Die Klassen P und NP

Zeitkomplexität des Euler-Problems und des Hamilton-Problems

Die Zeitkomplexität eines Problems wird durch eine untere Schranke für Kostenfunktionen von Algorithmen zur Lösung des Problems beschrieben.

Oft ist man nicht in der Lage, solche Schranken für Kostenfunktionen anzugeben. Man beschränkt sich dann darauf, das Problem einer Komplexitätsklasse zuzuordnen.

Beim Euler-Problem haben wir gezeigt, dass es mit einem Algorithmus mit quadratischer Zeitkomplexität gelöst werden kann. Das Euler-Problem gehört also zur Klasse P der Probleme, die mit einem polynomialen Algorithmus gelöst werden können.

Anders verhält es sich beim Hamilton-Problem. Die beiden hier vorgestellten Lösungsalgorithmen haben eine exponentielle Zeitkomplexität. Alle weiteren Lösungsalgorithmen, die bisher entwickelt worden sind, haben ebenfalls eine exponentielle Zeitkomplexität. Ob es Lösungsalgorithmen für das Hamilton-Problem gibt, die eine polynomiale Zeitkomplexität aufweisen, ist nicht bekannt. Es ist also noch offen, ob das Hamilton-Problem zur Klasse P gehört oder nicht. Man vermutet aufgrund der vielen negativen Ergebnisse, dass es wohl nicht zu P gehört.

Nicht-deterministische Algorithmen mit polynomialer Komplexität

Interessante Ergebnisse erhält man, wenn man den Algorithmusbegriff etwas aufweicht. Bei einem Algorithmus haben wir bisher immer vorausgesetzt, dass er deterministisch in dem Sinne ist, dass der nächste Ausführungsschritt immer genau feststeht. Wenn man diese Voraussetzung weglässt, gelangt man zu den nichtdeterministen Algorithmen. Es zeigt sich, dass sich etliche Probleme mit noch nicht geklärter Komplexität mit nichtdeterministischen Algorithmen lösen lassen, die eine polynomiale Komplexität haben. Zu diesen Problemen gehört auch das Hamilton-Problem.

Wir verdeutlichen im Folgenden, dass das Hamilton-Problem mit einem polynomialen nichtdeterministischen Algorithmus gelöst werden kann.

ALGORITHMUS hamiltonkreis_nichtdeterministisch
    Übergabe: Graph, dargestellt mit Nachbarschaftslisten
    # erzeuge nichtdeterministisch einen Rundreisekandidaten
    lege einen startKnoten fest
    weg = [startknoten]
    n = Anzahl der Knoten des Graphen
    restKnoten = Liste mit allen Knoten außer dem startKnoten
    WIEDERHOLE n-1 mal:
        naechsterKnoten = restKnoten[0] | restKnoten[1] | ... | restKnoten[n-2]
        weg = weg + [naechsterKnoten]
    weg = weg + [startKnoten]
    # überprüfe den Rundreisekandidaten
    hamiltonkreisExistiert = True
    FÜR i von 1 BIS n-1:
        WENN weg[i] kein Nachbar von weg[i-1] ist oder
             weg[i] bereits in [weg[0], ..., weg[i-1]] vorkommt:
            hamiltonkreisExistiert = False
    WENN weg[n] kein Nachbar von weg[n-1] ist:
        hamiltonkreisExistiert = False
    Rückgabe: hamiltonkreisExistiert

Die nichtdeterministische Stelle im Algorithmus ist die Zuweisung naechsterKnoten = restKnoten[0] | restKnoten[1] | ... | restKnoten[n-2]. Der senkrechte Strich soll hier bedeuten, dass entweder restKnoten[0] oder restKnoten[1] oder ... oder restKnoten[n-2] als Wert bei der Zuweisung genommen wird. Hier ist also nicht eindeutig festgelegt, welche Zuweisung zum Zuge kommt.

Der nichtdeterministische Algorithmus hat eine polynomiale Komplexität. Bei der (nichtdeterministischen) Erzeugung des Weges wird die Liste weg insgesamt n-mal erweitert. Bei der Überprüfung des Weges muss n-mal getestet werden, ob aufeinanderfolgende Knoten eine Kante des Graphen bilden. Hierzu muss jeweils maximal n-mal getestet werden, ob ein Knoten nicht bereits unter den Vorgängerknoten des Weges vorkommt. Insgesamt ergibt sich eine quadratische Komplexität.

Das Hamilton-Problem gehört also zur Klasse NP aller Probleme, die mit einem nichtdeterministischen Algorithmus mit polynomialer Komplexität gelöst werden können.

Nichtdeterministische Algorithmen werden in der Praxis nicht benutzt - hier muss immer alles eindeutig geregelt sein. Warum solche nichtdeterminischen Algorithmen dennoch interessant sind, soll im nächsten Abschnitt geklärt werden.

X

Fehler melden

X

Suche