Ich weiß, dass Knapsack
das NP-vollständig ist, während es von DP gelöst werden kann. Sie sagen, dass die DP-Lösung ist pseudo-polynomial
, da sie in der "Länge der Eingabe" exponentiell ist (dh die Anzahl der Bits, die zum Codieren der Eingabe erforderlich sind). Leider habe ich es nicht verstanden. Kann pseudo-polynomial
mir jemand das langsam erklären ?
87
Antworten:
Die Laufzeit ist O (NW) für einen unbeschränkten Knapsackproblems mit N Artikeln und Tornister der Größe W. W in der Länge des Eingangs nicht Polynom ist aber, das ist , was es macht Pseudo -polynomial.
Betrachten Sie W = 1.000.000.000.000. Es werden nur 40 Bits benötigt, um diese Zahl darzustellen, also Eingabegröße = 40, aber die Rechenlaufzeit verwendet den Faktor 1.000.000.000.000, der O (2 40 ) ist.
Die Laufzeit wird also genauer als O (N.2 Bits in W ) bezeichnet, was exponentiell ist.
Siehe auch:
quelle
Bei den meisten unserer Probleme haben wir es mit großen Listen von Zahlen zu tun, die bequem in Standard-Int / Float-Datentypen passen. Aufgrund der Art und Weise, wie die meisten Prozessoren dafür ausgelegt sind, 4-8-Byte-Zahlen gleichzeitig ohne zusätzliche Kosten zu verarbeiten (im Verhältnis zu Zahlen, die beispielsweise in 1 Byte passen), kommt es selten zu einer Änderung der Laufzeit durch Skalieren unserer Zahlen oder Innerhalb von Bereichen, auf die wir bei realen Problemen stoßen - der dominierende Faktor bleibt also nur die schiere Menge an Datenpunkten, die n oder m Faktoren, die wir gewohnt sind.
(Sie können sich vorstellen, dass die Big-O-Notation einen konstanten Faktor verbirgt, der 32 oder 64 Bit pro Datum aufteilt und nur die Anzahl der Datenpunkte belässt, wenn jede unserer Zahlen in so viele Bits oder weniger passt )
Versuchen Sie jedoch, mit anderen Algorithmen zu überarbeiten, um auf Datensätze mit großen Ints zu reagieren - Zahlen, für deren Darstellung mehr als 8 Byte erforderlich sind - und sehen Sie, was dies für die Laufzeit bedeutet. Die Größe der beteiligten Zahlen macht auch bei anderen Algorithmen wie der binären Sortierung immer einen Unterschied, wenn Sie über den Sicherheitspuffer hinaus expandieren, den herkömmliche Prozessoren uns "kostenlos" geben, indem sie 4-8-Byte-Stapel verarbeiten.
Der Trick mit dem von uns diskutierten Knapsack-Algorithmus besteht darin, dass er (im Vergleich zu anderen Algorithmen) ungewöhnlich empfindlich auf die Größe eines bestimmten Parameters W reagiert. Wenn Sie W ein Bit hinzufügen, verdoppeln Sie die Laufzeit des Algorithmus. Wir haben diese dramatische Reaktion auf Wertänderungen in anderen Algorithmen vor diesem nicht gesehen, weshalb es so aussieht, als würden wir Knapsack anders behandeln - aber das ist eine echte Analyse dessen, wie es nicht-polynomisch reagiert zu Änderungen in der Eingabegröße.
quelle
Die Laufzeit des Rucksackalgorithmus ist nicht nur an die Größe der Eingabe (n - die Anzahl der Elemente) gebunden, sondern auch an die Größe der Eingabe (W - die Rucksackkapazität) O (nW), die exponentiell ist im Computer binär dargestellt (2 ^ n). Die Rechenkomplexität (dh wie die Verarbeitung innerhalb eines Computers durch Bits erfolgt) betrifft nur die Größe der Eingaben, nicht deren Größen / Werte .
Ignorieren Sie die Wert- / Gewichtsliste für einen Moment. Angenommen, wir haben eine Instanz mit Rucksackkapazität 2. W würde zwei Bits in den Eingabedaten benötigen. Jetzt werden wir die Rucksackkapazität auf 4 erhöhen und den Rest der Eingabe beibehalten. Unsere Eingabe ist nur um ein Bit gewachsen, aber die Rechenkomplexität hat sich verdoppelt. Wenn wir die Kapazität auf 1024 erhöhen, hätten wir nur 10 Bits der Eingabe für W anstelle von 2, aber die Komplexität hat sich um den Faktor 512 erhöht. Die zeitliche Komplexität wächst exponentiell in der Größe von W in binärer (oder dezimaler) Darstellung .
Ein weiteres einfaches Beispiel, das mir geholfen hat, das Pseudo-Polynom-Konzept zu verstehen, ist der naive Primalitätstest-Algorithmus. Für eine gegebene Zahl n prüfen wir, ob sie durch jede ganze Zahl im Bereich 2..√n gleichmäßig geteilt wird, sodass der Algorithmus √ (n - 1) Schritte ausführt. Aber hier ist n die Größe der Eingabe, nicht ihre Größe.
Im Gegensatz dazu wird die Suche in einem Array nach einem bestimmten Element in Polynomzeit ausgeführt: O (n). Es dauert höchstens n Schritte und hier ist n die Größe der Eingabe (die Länge des Arrays).
[ siehe hier ]
Berechnung der zum Speichern der Dezimalzahl erforderlichen Bits
quelle
Ich verstehe das so, dass die Kapazität O (W) gewesen wäre, wenn die Kapazitätseingabe ein Array von [1,2, ..., W] gewesen wäre , das eine Größe von W hat. Die Kapazitätseingabe ist dies jedoch nicht ein Array von Zahlen, es ist stattdessen eine einzelne Ganzzahl. Bei der zeitlichen Komplexität geht es um die Beziehung zur Größe der Eingabe. Die Größe einer Ganzzahl ist NICHT der Wert der Ganzzahl, sondern die Anzahl der Bits, die sie darstellen. Wir konvertieren diese ganze Zahl W später in ein Array [1,2, ..., W] im Algorithmus, was dazu führt, dass die Leute fälschlicherweise denken, W sei die Größe, aber dieses Array ist nicht die Eingabe, sondern die ganze Zahl selbst.
Stellen Sie sich die Eingabe als "ein Array von Dingen" und die Größe als "wie viele Dinge in dem Array" vor. Die Elementeingabe ist tatsächlich ein Array von n Elementen im Array, also Größe = n. Die Kapazitätseingabe ist KEIN Array von W-Zahlen , sondern eine einzelne Ganzzahl , die durch ein Array von Protokollbits (W) dargestellt wird. Erhöhen Sie die Größe um 1 (Hinzufügen von 1 aussagekräftigem Bit). W verdoppelt sich, sodass sich die Laufzeit verdoppelt, daher die exponentielle Zeitkomplexität.
quelle