Analyse von Algorithmen


Im Informatik, das Analyse von Algorithmen ist der Prozess des Findens des Rechenkomplexität von Algorithmen - Zeit, Speicher oder anderen Ressourcen, die erforderlich sind richtet sie hin. Normalerweise beinhaltet dies die Bestimmung a Funktion Das bezieht die Größe der Eingabe eines Algorithmus auf die Anzahl der Schritte, die er unternimmt (Iss Zeitkomplexität) oder die Anzahl der von ihnen verwendeten Speicherorte (ITS (ITS) Raumkomplexität). Ein Algorithmus soll effizient sein, wenn die Werte dieser Funktion gering sind oder langsam im Vergleich zu einem Wachstum der Größe des Eingangs wachsen. Unterschiedliche Eingaben derselben Größe können dazu führen, dass der Algorithmus unterschiedlich verhalten wird. Bester, schlimmster und durchschnittlicher Fall Beschreibungen können alle von praktischem Interesse sein. Wenn nicht anders angegeben, ist die Funktion, die die Leistung eines Algorithmus beschreibt, normalerweise eine obere Grenze, bestimmt aus den schlimmsten Falleingaben zum Algorithmus.
Der Begriff "Analyse von Algorithmen" wurde durch geprägt Donald Knuth.[1] Die Algorithmusanalyse ist ein wichtiger Bestandteil eines breiteren Computerkomplexitätstheorie, was theoretische Schätzungen für die Ressourcen liefert, die von jedem Algorithmus benötigt werden, der eine gegebene Lösung löst Rechenproblem. Diese Schätzungen geben einen Einblick in angemessene Richtungen der Suche nach effiziente Algorithmen.
Bei der theoretischen Analyse von Algorithmen ist es üblich, ihre Komplexität im asymptotischen Sinne zu schätzen, d. H. Die Komplexitätsfunktion für willkürlich große Eingabe. Big O Notation, Big-Omega-Notation und Big-Theta Notation werden an dieses Ende gewöhnt. Zum Beispiel, binäre Suche soll in einer Reihe von Schritten laufen proportional zum Logarithmus der Größe n der sortierten Liste, die gesucht wird oder in O(Protokoll n), umgangssprachlich " logarithmische Zeit". Normalerweise asymptotisch Schätzungen werden verwendet, weil unterschiedlich Implementierungen Der gleiche Algorithmus kann sich in der Effizienz unterscheiden. Die Effizienz von zwei "vernünftigen" Implementierungen eines bestimmten Algorithmus beziehen sich jedoch durch einen konstanten multiplikativen Faktor, der als a Versteckte Konstante.
Exakte (nicht asymptotische) Effizienzmessungen können manchmal berechnet werden, aber sie erfordern normalerweise bestimmte Annahmen in Bezug auf die bestimmte Implementierung des Algorithmus, genannt Berechnungsmodell. Ein Berechnungsmodell kann in Bezug auf eine definiert werden abstrakter Computer, z.B. Turing Maschineund/oder postulieren, dass bestimmte Vorgänge in der Einheitszeit ausgeführt werden. Zum Beispiel, wenn die sortierte Liste, auf die wir binäre Suche anwenden n Elemente, und wir können garantieren, dass jede Suche eines Elements in der Liste in der Einheitszeit und dann höchstens durchgeführt werden kann Protokoll2(n) + 1 Es werden Zeiteinheiten benötigt, um eine Antwort zurückzugeben.
Kostenmodelle
Zeiteffizienzschätzungen hängen davon ab, was wir als Schritt definieren. Damit die Analyse für die tatsächliche Laufzeit passen, muss die für die Durchführung eines Schritts erforderliche Zeit garantiert durch eine Konstante begrenzt werden. Man muss hier vorsichtig sein; Zum Beispiel zählen einige Analysen eine Zugabe von zwei Zahlen als einen Schritt. Diese Annahme ist in bestimmten Kontexten möglicherweise nicht gerechtfertigt. Wenn beispielsweise die Zahlen, die an einer Berechnung beteiligt sind, willkürlich groß sein können, kann die von einer einzelnen Zugabe erforderliche Zeit nicht mehr als konstant angesehen werden.
Im Allgemeinen werden zwei Kostenmodelle verwendet:[2][3][4][5][6]
- das einheitliches Kostenmodell, auch genannt einheitliche Kostenmessung (und ähnliche Variationen) weist jedem Maschinenbetrieb konstante Kosten zu, unabhängig von der Größe der beteiligten Zahlen
- das Logarithmischer Kostenmodell, auch genannt logarithmische Kostenmessung (und ähnliche Variationen) weist jedem Maschinenbetrieb proportional zur Anzahl der beteiligten Bits zu Kosten zu
Letzteres ist umständlicher zu bedienen und wird daher nur bei Bedarf verwendet, zum Beispiel bei der Analyse von willkürliche Präzisionsarithmetik Algorithmen, wie die in verwendeten in Kryptographie.
Ein entscheidender Punkt, der häufig übersehen wird dachte möglich.[7]
Laufzeitanalyse
Die Laufzeitanalyse ist eine theoretische Klassifizierung, die den Anstieg der Erhöhung schätzt und vorwegnimmt Laufzeit (oder Laufzeit oder Ausführungszeit) von Algorithmus wie es Eingangsgröße (Normalerweise als bezeichnet als n) steigt. Laufzeiteffizienz ist ein Thema von großem Interesse an Informatik: EIN Programm kann Sekunden, Stunden oder sogar Jahre dauern, bis die Ausführung abgeschlossen ist, je nachdem, welcher Algorithmus es implementiert. Während Software -Profilerstellung Techniken können verwendet werden, um die Laufzeit eines Algorithmus in der Praxis zu messen. Sie können nicht für alle unendlich viele mögliche Eingaben zeitliche Daten bereitstellen. Letzteres kann nur durch die theoretischen Methoden der Laufzeitanalyse erreicht werden.
Mängel empirischer Metriken
Da sind Algorithmen Plattformunabhängig (d. H. Ein gegebener Algorithmus kann in einem willkürlichen Umfang implementiert werden Programmiersprache auf einem willkürlichen Computer ein willkürliches Ausführen Betriebssystem) Es gibt zusätzliche erhebliche Nachteile bei der Verwendung eines empirisch Ansatz, um die vergleichende Leistung eines bestimmten Satzes von Algorithmen zu messen.
Nehmen Sie als Beispiel ein Programm, das einen bestimmten Eintrag in a ansieht sortiert aufführen von Größe n. Angenommen, dieses Programm wurde auf dem Computer A implementiert, eine hochmoderne Maschine mit a Lineare Suche Algorithmus und auf dem Computer B, eine viel langsamere Maschine mit A binärer Suchalgorithmus. Benchmark -Test Auf den beiden Computern, die ihre jeweiligen Programme ausführen, sehen möglicherweise etwas wie folgt aus:
n (Listengröße) | Computer eine Laufzeit (in Nanosekunden)) | Computer b Laufzeit (in Nanosekunden)) |
---|---|---|
16 | 8 | 100.000 |
63 | 32 | 150.000 |
250 | 125 | 200.000 |
1.000 | 500 | 250.000 |
Basierend auf diesen Metriken wäre es leicht, zu dem Schluss zu springen, dass Computer a Führt einen Algorithmus aus, der in der Effizienz weit überlegen ist Computer b. Wenn jedoch die Größe der Eingabeliste auf eine ausreichende Zahl erhöht wird, wird diese Schlussfolgerung dramatisch nachgewiesen: fehlerhaft:
n (Listengröße) | Computer eine Laufzeit (in Nanosekunden)) | Computer b Laufzeit (in Nanosekunden)) |
---|---|---|
16 | 8 | 100.000 |
63 | 32 | 150.000 |
250 | 125 | 200.000 |
1.000 | 500 | 250.000 |
... | ... | ... |
1.000.000 | 500.000 | 500.000 |
4.000.000 | 2.000.000 | 550.000 |
16.000.000 | 8.000.000 | 600.000 |
... | ... | ... |
63.072 × 1012 | 31.536 × 1012 ns, oder 1 Jahr | 1.375.000 ns, oder 1,375 Millisekunden |
Computer A, Ausführen des linearen Suchprogramms, zeigt a linear Wachstumsrate. Die Laufzeit des Programms ist direkt proportional zu seiner Eingangsgröße. Verdoppelt die Eingangsgröße verdoppelt die Laufzeit, vervierfacht die Eingangsgröße, die die Laufzeit vervierfacht und so weiter. Andererseits zeigt Computer B, das das Binär -Suchprogramm ausführt, A. logarithmisch Wachstumsrate. Veneviertel der Eingangsgröße erhöht die Laufzeit nur um eine konstante Menge (in diesem Beispiel 50.000 ns). Obwohl Computer A angeblich eine schnellere Maschine ist, wird Computer B in der Laufzeit unvermeidlich übertreffen, da ein Algorithmus mit einer viel langsameren Wachstumsrate ausgeführt wird.
Wachstumsaufträge
Informell kann gesagt werden, dass ein Algorithmus eine Wachstumsrate in der Reihenfolge von a aufweisen kann Mathematische Funktion Wenn über eine bestimmte Eingangsgröße hinaus n, die Funktion f(n) mal eine positive Konstante liefert eine Obergrenze oder Grenze Für die Laufzeit dieses Algorithmus. Mit anderen Worten, für eine bestimmte Eingangsgröße n größer als manche n0 und eine Konstante cDie Laufzeit dieses Algorithmus wird niemals größer als c × f(n). Dieses Konzept wird häufig mit Big O -Notation ausgedrückt. Zum Beispiel seit der Laufzeit von Sortieren durch Einfügen wächst quadratisch Wenn die Eingangsgröße zunimmt O(n2).
Big o Notation ist eine bequeme Möglichkeit, die auszudrücken Worst-Case-Szenario Für einen bestimmten Algorithmus kann er auch zum Ausdruck des Durchschnittsfalls verwendet werden-zum Beispiel das Worst-Case-Szenario für schnelle Sorte ist O(n2), aber die Durchschnittsfall-Laufzeit ist O(n Protokoll n).
Empirische Wachstumsordnungen
Angenommen, die Laufzeit folgt der Machtregel, t ≈ Knader Koeffizient a kann gefunden werden [8] durch empirische Messungen der Laufzeit {t1, t2} an einigen Problemen in Problemgröße {n1, n2} und Berechnung t2/t1 = (n2/n1)a so dass a = log (log (t2/t1)/Protokoll(n2/n1). Mit anderen Worten, dies misst die Steigung der empirischen Linie auf der Log -Log -Diagramm der Laufzeit vs. Eingangsgröße zu einem gewissen Größenpunkt. Wenn die Reihenfolge des Wachstums tatsächlich der Leistungsregel folgt (und so ist die Linie des Protokoll -Log -Diagramms tatsächlich eine gerade Linie), der empirische Wert von bleibt in verschiedenen Bereichen konstant, und wenn nicht, ändert sich sie (und die Linie ist eine gekrümmte Linie) - aber es könnte immer noch zum Vergleich von zwei gegebenen Algorithmen in Bezug auf ihre dienen Empirische lokale Wachstumsordnungen Verhalten. Auf die obige Tabelle angewendet:
n (Listengröße) | Computer eine Laufzeit (in Nanosekunden)) | Lokale Wachstumsordnung (n^_) | Computer b Laufzeit (in Nanosekunden)) | Lokale Wachstumsordnung (n^_) |
---|---|---|---|---|
15 | 7 | 100.000 | ||
65 | 32 | 1.04 | 150.000 | 0,28 |
250 | 125 | 1.01 | 200.000 | 0,21 |
1.000 | 500 | 1.00 | 250.000 | 0,16 |
... | ... | ... | ||
1.000.000 | 500.000 | 1.00 | 500.000 | 0,10 |
4.000.000 | 2.000.000 | 1.00 | 550.000 | 0,07 |
16.000.000 | 8.000.000 | 1.00 | 600.000 | 0,06 |
... | ... | ... |
Es ist deutlich zu erkennen, dass der erste Algorithmus eine lineare Wachstumsreihenfolge aufweist, die der Machtregel tatsächlich entspricht. Die empirischen Werte für die zweite verringern sich rasch, was darauf hindeutet, dass eine andere Wachstumsregel folgt und auf jeden Fall viel geringere lokale Wachstumsordnungen (und sich weiter verbessert), empirisch als die erste.
Bewertung der Laufzeitkomplexität
Die Laufzeitkomplexität für das Worst-Case-Szenario eines bestimmten Algorithmus kann manchmal bewertet werden, indem die Struktur des Algorithmus untersucht und einige vereinfachende Annahmen gestellt werden. Folgendes berücksichtigen Pseudocode:
1 Holen Sie sich eine positive Ganzzahl N von der Eingabe 2 wenn n> 10 3 drucken "Das könnte eine Weile dauern ..." 4 zum I = 1 zu n 5 zum J = 1 zu i 6 drucken i * j 7 drucken "Fertig!"
Ein bestimmter Computer wird a nehmen diskrete Zeitspanne jeden der ausführen Anweisungen mit der Durchführung dieses Algorithmus beteiligt. Die bestimmte Zeitspanne für die Durchführung einer bestimmten Anweisung variiert je nachdem, welche Anweisung ausgeführt wird und welcher Computer sie ausführt, aber auf einem konventionellen Computer wird dieser Betrag jedoch sein deterministisch.[9] Sagen Sie, dass die in Schritt 1 durchgeführten Aktionen als Zeit in Betracht gezogen werden T1, Schritt 2 verwendet Zeit T2, und so weiter.
Im obigen Algorithmus werden die Schritte 1, 2 und 7 nur einmal ausgeführt. Für eine Worst-Case-Bewertung sollte angenommen werden, dass auch Schritt 3 ausgeführt wird. Somit beträgt die Gesamtzeit für die Ausführung der Schritte 1-3 und Schritt 7:
Das Schleifen In den Schritten 4 sind 5 und 6 schwieriger zu bewerten. Der äußere Schleifentest in Schritt 4 wird ausgeführt ( n + 1) mal (beachten Sie, dass ein zusätzlicher Schritt erforderlich ist, um die für die Schleife zu beenden, daher n + 1 und nicht n -Ausführungen), der sich verbraucht T4( n + 1) Zeit. Die innere Schleife dagegen wird vom Wert von j gesteuert, was Iteraten von 1 bis i. Beim ersten Durchgang durch die äußere Schleife iteriert J von 1 bis 1: Die innere Schleife macht einen Pass, so T6 Zeit, und der innere Schleifentest (Schritt 5) verbraucht 2T5 Zeit. Während des nächsten Durchgangs durch die äußere Schleife iteriert J von 1 bis 2: Die innere Schleife macht zwei Pässe, soT6 Zeit, und der innere Schleifentest (Schritt 5) verbraucht 3T5 Zeit.
Insgesamt kann die Gesamtzeit, die zum Ausführen des inneren Schleifenkörpers erforderlich ist arithmetischer Fortschritt:
welches sein kann berücksichtigt[10] wie
Die Gesamtzeit, die zum Ausführen des Außenschleifstests erforderlich ist, kann ähnlich bewertet werden:
was als berücksichtigt werden kann wie
Daher ist die Gesamtlaufzeit für diesen Algorithmus:
das reduziert sich auf
Als ein FaustregelMan kann davon ausgehen, dass der Begriff mit der höchsten Ordnung in einer bestimmten Funktion seine Wachstumsrate dominiert und somit seine Laufzeitreihenfolge definiert. In diesem Beispiel n2 ist der Begriff mit höchster Ordnung, so dass man das schließen kann f(n) = O(n2). Formal kann dies wie folgt nachgewiesen werden:
Beweise das
Lassen k eine Konstante größer sein als oder gleich [T1..T7]
Deswegen
Mehr elegant Der Ansatz zur Analyse dieses Algorithmus wäre, dies zu erklären [T1..T7] sind alle gleich einer Zeiteinheit in einem System von Einheiten, so dass eine Einheit größer oder gleich den tatsächlichen Zeiten für diese Schritte ist. Dies würde bedeuten, dass die Laufzeit des Algorithmus wie folgt zusammenbricht:[11]
Wachstumsrate Analyse anderer Ressourcen
Die Methodik der Laufzeitanalyse kann auch zur Vorhersage anderer Wachstumsraten verwendet werden, wie z. B. Konsum von Speicherraum. Betrachten Sie beispielsweise den folgenden Pseudocode, der die Speicherverwendung durch ein Programm basierend auf der Größe von a verwaltet und verwaltet Datei Welches Programm verwaltet:
während Die Datei ist noch geöffnet: Lassen n = Größe der Datei zum alle 100.000 Kilobytes Erhöhung der Dateigröße Verdoppeln Sie die Menge an Speicher reserviert
In diesem Fall wird der Speicher mit einer Dateigröße n bei A konsumiert exponentielles Wachstum Rate, die Ordnung ist O(2n). Dies ist eine extrem schnelle und wahrscheinlich unüberschaubare Wachstumsrate für den Verbrauch des Gedächtnisses Ressourcen.
Relevanz
Die Algorithmusanalyse ist in der Praxis wichtig, da die zufällige oder unbeabsichtigte Verwendung eines ineffizienten Algorithmus die Systemleistung erheblich beeinflussen kann. In zeitempfindlichen Anwendungen kann ein Algorithmus zu lange, um zu laufen, seine Ergebnisse veraltet oder nutzlos machen. Ein ineffizienter Algorithmus kann auch eine unwirtschaftliche Menge an Rechenleistung oder Speicher erfordern, um ihn erneut zu betreiben, und macht ihn erneut praktisch nutzlos.
Konstante Faktoren
Die Analyse von Algorithmen konzentriert sich typischerweise auf die asymptotische Leistung, insbesondere auf elementarer Ebene, aber in praktischen Anwendungen sind konstante Faktoren wichtig, und die Daten in der Praxis sind in der Praxis immer begrenzt. Die Grenze ist in der Regel die Größe des adressierbaren Speichers, also auf 32-Bit-Maschinen 232 = 4 gib (größer wenn Segmentierter Speicher wird verwendet) und auf 64-Bit-Maschinen 264 = 16 EIB. Bei einer begrenzten Größe kann eine Wachstumsreihenfolge (Zeit oder Raum) durch einen konstanten Faktor ersetzt werden, und in diesem Sinne sind alle praktischen Algorithmen O(1) für eine ausreichend große Konstante oder für kleine Daten.
Diese Interpretation ist in erster Linie nützlich für Funktionen, die extrem langsam wachsen: (binär) Iteratter Logarithmus (Protokoll*) ist weniger als 5 für alle praktischen Daten (265536 Bits); (binär) log-log (log log log n) ist weniger als 6 für praktisch alle praktischen Daten (264 Bits); und binäres Protokoll (Protokoll n) ist weniger als 64 für praktisch alle praktischen Daten (264 Bits). Ein Algorithmus mit nicht konstantem Komplexität kann dennoch effizienter sein als ein Algorithmus mit konstanter Komplexität für praktische Daten, wenn der Overhead des konstanten Zeitalgorithmus zu einem größeren konstanten Faktor führt, z. B. kann man haben so lange wie und .
Für große Daten kann lineare oder quadratische Faktoren nicht ignoriert werden, aber für kleine Daten kann ein asymptotisch ineffizienter Algorithmus effizienter sein. Dies wird besonders in verwendet Hybridalgorithmen, wie Timsort, die einen asymptotisch effizienten Algorithmus verwenden (hier Zusammenführen, sortierenmit zeitlicher Komplexität ), aber wechseln Sie zu einem asymptotisch ineffizienten Algorithmus (hier Sortieren durch Einfügenmit zeitlicher Komplexität ) für kleine Daten, da der einfachere Algorithmus bei kleinen Daten schneller ist.
Siehe auch
- Amortisierte Analyse
- Analyse paralleler Algorithmen
- Asymptotische rechnerische Komplexität
- Bester, schlimmster und durchschnittlicher Fall
- Big O Notation
- Computerkomplexitätstheorie
- Master -Theorem (Analyse von Algorithmen)
- NP-Complete
- Numerische Analyse
- Polynomzeit
- Programmoptimierung
- Profilerstellung (Computerprogrammierung)
- Skalierbarkeit
- Geglättete Analyse
- Terminierungsanalyse - Das Unterproblem der Überprüfung, ob ein Programm überhaupt endet
- Zeitkomplexität - Enthält Wachstumsbestellverträge für gemeinsame Algorithmen
- Informationsbasierte Komplexität
Anmerkungen
- ^ "Knuth: Neueste Nachrichten". 28. August 2016. archiviert von das Original am 28. August 2016.
- ^ Alfred V. Aho; John E. Hopcroft; Jeffrey D. Ullman (1974). Das Design und die Analyse von Computeralgorithmen. Addison-Wesley Pub. Co. ISBN 9780201000290., Abschnitt 1.3
- ^ Juraj Hromkovič (2004). Theoretische Informatik: Einführung in Automaten, Berechnung, Komplexität, Algorithmik, Randomisierung, Kommunikation und Kryptographie. Springer. S. 177–178. ISBN 978-3-540-14015-3.
- ^ Giorgio Ausiello (1999). Komplexität und Näherung: Kombinatorische Optimierungsprobleme und deren Annäherungseigenschaften. Springer. S. 3–8. ISBN 978-3-540-65431-5.
- ^ Wegener, Ingo (2005), Komplexitätstheorie: Untersuchung der Grenzen effizienter Algorithmen, Berlin, New York: Springer-Verlag, p. 20, ISBN 978-3-540-21045-0
- ^ Robert Endre Tarjan (1983). Datenstrukturen und Netzwerkalgorithmen. SIAM. S. 3–7. ISBN 978-0-89871-187-5.
- ^ Beispiele für den Abstraktionspreis?, cstheory.Stackexchange.com
- ^ Wie man O-Missbrauch und Bestechungsgelder vermieden Archiviert 2017-03-08 bei der Wayback -Maschine, im Blog "Gödels verlorener Brief und P = NP" von R. J. Lipton, Professor für Informatik bei Georgia Tech, erzählte Idee von Robert Sedgebick
- ^ Dies ist jedoch bei a jedoch nicht der Fall Quantencomputer
- ^ Es kann durch nachgewiesen werden Induktion das
- ^ Dieser Ansatz vernachlässigt im Gegensatz zum obigen Ansatz die ständige Zeit, die durch die Schleifentests verbraucht wird, die ihre jeweiligen Schleifen beenden, aber es ist trivial zu beweisen, dass eine solche Auslassung das Endergebnis nicht beeinflusst
Verweise
- Sedgewick, Robert; Flajolet, Philippe (2013). Eine Einführung in die Analyse von Algorithmen (2. Aufl.). Addison-Wesley. ISBN 978-0-321-90575-8.
- Greene, Daniel A.; Knuth, Donald E. (1982). Mathematik zur Analyse von Algorithmen (Zweite Ausgabe). Birkhäuser. ISBN 3-7643-3102-x.
- Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L. & Stein, Clifford (2001). Einführung in Algorithmen. Kapitel 1: Grundlagen (zweite Ausgabe). Cambridge, MA: MIT Press und McGraw-Hill. S. 3–122. ISBN 0-262-03293-7.
- Sedgewick, Robert (1998). Algorithmen in C, Teile 1-4: Grundlagen, Datenstrukturen, Sortieren, Suche (3. Aufl.). Lesen, MA: Addison-Wesley Professional. ISBN 978-0-201-31452-6.
- Knuth, Donald. Die Kunst der Computerprogrammierung. Addison-Wesley.
- Goldreich, Oded (2010). Computerkomplexität: Eine konzeptionelle Perspektive. Cambridge University Press. ISBN 978-0-521-88473-0.
Externe Links
-
Medien im Zusammenhang mit der Analyse von Algorithmen bei Wikimedia Commons