Fragen zur amortisierten Analyse

7

Als Vorbereitung einer Prüfung über Algorithmen und Komplexität löse ich derzeit alte Übungen. Ein Konzept, mit dem ich bereits zu kämpfen hatte, als ich es zum ersten Mal sah, ist das Konzept der amortisierten Analyse. Was ist eine amortisierte Analyse und wie geht das? In unseren Vorlesungsunterlagen heißt es, dass "die amortisierte Analyse Grenzen für die" durchschnittliche Zeit "gibt, die für eine bestimmte Operation benötigt wird, und auch eine Grenze für den schlimmsten Fall". Das klingt wirklich nützlich, aber wenn es um Beispiele geht, habe ich keine Ahnung, was ich tun muss, und selbst nachdem ich die Beispiellösung gelesen habe, habe ich keine Ahnung, was sie tun.

Addieren wir 1 in Basis 2, dh 0, 1, 10, 11, 100, 101, 110, 111, 1000, ... Zeigen Sie anhand der amortisierten Analyse, dass in jedem Schritt nur konstant amortisiert viele Bits geändert werden müssen.

(Die Übung ist ursprünglich auf Deutsch, daher entschuldige ich mich für meine möglicherweise nicht ganz genaue Übersetzung.)

Nun definiert zunächst die Standardlösung ϕ(ich): =c#{1 Bit in der Binärdarstellung}} für eine Konstante c>0. Ich denke, dies ist die sogenannte potenzielle Funktion, die irgendwie den übermäßigen Zeiteinheiten entspricht (aber ich habe keine Ahnung, warum ich mir diese spezielle Definition einfallen lassen würde). Vorausgesetzt, wir müssen uns ändernm Bits in der ich-th Schritt. Ein solcher Schritt hat immer die Form

011m100m.

Diese Aussage ist für mich verständlich, aber ich sehe die Motivation dahinter wieder nicht. Dann kommen sie aus dem Nichts auf eine "Schätzung".

ein(ich)=m+c(ϕ(ich)- -ϕ(ich- -1))=m+c(- -m+2)

und sie sagen das für c=1, wir bekommen ein(ich)=2 Das mussten wir zeigen.

Was ist gerade passiert? Was istein(ich)? Warum können wir wählenc=1? Wenn ich zeigen muss, dass in jedem Schritt nur ständig amortisiert viele "Zeiteinheiten" benötigt werden, bedeutet das im Allgemeinen, dass ich das zeigen mussa(i) ist konstant?

Es gibt noch ein paar andere Übungen zur amortisierten Analyse und ich verstehe sie auch nicht. Ich dachte, wenn mir jemand bei dieser helfen könnte, könnte ich die anderen Übungen noch einmal versuchen und vielleicht hilft mir das, das Konzept wirklich zu verstehen.

Vielen Dank im Voraus für jede Hilfe.

Huy
quelle
Hast du in ein Lehrbuch geschaut? Dies ist das Standardbeispiel und sollte in jedem guten Buch auseinander genommen und erklärt werden.
Raphael
@ Raphael, IIRC Dies ist aus Kapitel 17 von CLRS.
Kaveh

Antworten:

5

Lassen ai die amortisierten Betriebskosten sein i, ci die tatsächlichen Betriebskosten sein i, und Di die Datenstruktur nach dem Betrieb ich. Die fortgeführten Anschaffungskosten eines Vorgangs sind definiert als

ai:=ci+Φ(Di)Φ(Di1).
Sie nehmen normalerweise Folgendes an
  1. Das Potenzial ist also immer positiv :iΦ(Di)0,
  2. Am Anfang ist das Potential 0, das heißt Φ(D0)=0.

Diese beiden Annahmen sind nicht immer notwendig, werden jedoch häufig verwendet und erleichtern das Leben. Jetzt können Sie das Potenzial zu Kosten berücksichtigen, die bereits durch frühere Vorgänge bezahlt wurden.

Um diese Definition zu rechtfertigen, berücksichtigen Sie die kumulierten Kosten aller Operationen. Wir erhalten die folgende Teleskopsumme

ich=1neinich=ich=1n(cich+Φ(D.ich)- -Φ(D.ich- -1))=Φ(D.n)- -Φ(D.0)+ich=1ncichich=1ncich.
Sie sehen also, dass die Summe der fortgeführten Anschaffungskosten die tatsächlichen Gesamtkosten übersteigt. Daher geben die fortgeführten Anschaffungskosten eine Obergrenze.

Ich habe die Verwendung der nicht gesehen cin deiner Formel. Aber diec kann einfach zur potentiellen Funktion hinzugefügt werden Φ. Denken Sie also an diec als ein Faktor, der das Potenzial gewichtet und die Funktion neu definiert Φ Sie können es loswerden.

Also, um Ihre konkreten Fragen zu beantworten. ein(ich) bezeichnet die fortgeführten Anschaffungskosten für die ichth Operation, das sind die tatsächlichen Kosten in einer Abfolge von Operationen, die dem Betrieb belastet werden ich. Dascist ein positiver Faktor, den Sie auswählen können. Und derein(ich)s sind im Allgemeinen nicht konstant (sie sind in Ihrem Beispiel) - Sie müssen nichts für die zeigen ein(ich) Kosten, die Werte ein(ich) sind das Ergebnis Ihrer Analyse.

Da Sie anscheinend Deutsch sprechen, können Sie sich auch meine Deutschnotizen zur möglichen Funktion ansehen .

A.Schulz
quelle
4

Die mögliche Funktionsmethode ist kompliziert, Ihr Beispiel ist einfach. Die Anzahl der geänderten Bits beträgt 1 ungefähr die Hälfte der Zeit, 2 ungefähr ein Viertel der Zeit, 3 ungefähr ein Achtel der Zeit und so weiter. Dies liegt daran, dass die Anzahl der geänderten Bits ab 0 1,2,1,3,1,2,1,4 usw. beträgt (Sie erhalten das Muster). Die durchschnittliche Anzahl der geänderten Bits ist also

k=1k2k=k=1l=k12l=k=112k- -1=2.
Yuval Filmus
quelle
1
Ich bin nicht der Meinung, dass die mögliche Funktionsmethode kompliziert ist. Konzeptionell ist es sehr einfach. Es kann jedoch schwierig sein, die richtige potenzielle Funktion für ein bestimmtes Problem zu finden.
A.Schulz
1
Ich bin damit einverstanden, dass dies der beste Weg ist, es zu sehen, aber es ist besser, wenn Sie eine Reihe von Formularen annehmen 2nund sehen, dass sich das erste Bit jedes Mal ändert, das zweite Bit jedes andere, das dritte Bit jedes vierte usw.
Pål GD
3

Die amortisierte Analyse behandelt die Laufzeitkosten eines Vorgangs als Durchschnitt über eine Folge von Vorgängen. Dies ähnelt dem Finanzkonzept der Amortisation - ein einziger Pauschalbetrag wie ein Darlehen wird über einen bestimmten Zeitraum abgeschrieben . Dies legt beispielsweise eine monatliche Zahlung fest, obwohl der Kapitalbetrag immer kleiner wird.

Auf diese Weise ist eine amortisierte Laufzeit eine Art Durchschnitt, obwohl sie nicht mit einer durchschnittlichen Laufzeit identisch ist, die eine probabilistische Analyse einer Verteilung von Eingaben umfasst.

Es gibt drei Standardtechniken für die Durchführung der amortisierten Analyse: (1) die aggregierte Methode, (2) die Rechnungslegungsmethode und (3) die potenzielle Methode. Letzteres sehen Sie in Ihren Vorlesungsunterlagen, und das verwendet A. Schulz in seiner Antwort. Es ist auch etwas komplizierter.

Ich möchte Sie auf JeffEs ausgezeichnete Vorlesungsunterlagen verweisen, die eine Erläuterung aller drei Techniken enthalten, beginnend mit dem oft zitierten Beispiel (und dem Beispiel, auf das Sie gestoßen sind) für das Inkrementieren eines Binärzählers. Es zeigt, dass die fortgeführten Anschaffungskosten einer Inkrementierungsoperation betragenÖ(1) wenn über eine Folge solcher Operationen gemittelt, obwohl die Laufzeit im ungünstigsten Fall ist Ö(Logn).

Eine weitere Ressource wäre Kapitel 17 von [CLRS01] , das mit einem anderen gängigen Beispiel beginnt, einem Stapel mit einer "Multi-Pop" -Operation .

David
quelle
2

Ich denke, die Problemstellung ist klarer, wenn Sie sie als einen Zähler betrachten, der bei 0 beginnt und eine Operation hat, die den Wert um eins erhöht. Jedes Mal, wenn der Zähler Ihres Problems erhöht wird, wird genau ein Bit umgedreht und null oder mehr Bits werden umgedreht. Die mögliche Funktion des Beispielproblems ist nicht so aus heiterem Himmel, wie Sie vielleicht denken. Der Schlüssel zur Sache ist, dass nur ein Bit, das zuvor eingeschaltet wurde, ausgeschaltet werden kann. Jedes Mal, wenn wir eine Inkrementierungsoperation ausführen und ein Bit einschalten, speichern wir eine Zeiteinheit auf unserem "Sparkonto" (der potenziellen Funktion), mit der wir dieses Bit später ausschalten können.

Dies liegt daran, dass Sie beim Inkrementieren des Zählers zuerst das Bit ganz rechts betrachten. Wenn es ausgeschaltet ist, schalten Sie es ein. Wenn es eingeschaltet ist, schalten Sie es aus und sehen sich das Bit eine Position links an. Wenn es ausgeschaltet ist, schalten Sie es ein und halten Sie an. Wenn es eingeschaltet ist, schalten Sie es aus und sehen Sie sich das Bit links von diesem Bit an. Die Anzahl der Bits, die Sie in einer Operation umdrehen, entspricht also der Position des ersten 0-Bits von rechts.

Zu Beginn sind sowohl der Zähler als auch die Potentialfunktion 0. Nach einer Inkrementoperation ist der Zähler 1 und die Potentialfunktion ebenfalls 1. Wenn wir erneut inkrementieren, wird der Zähler zu 10. Die Potentialfunktion bleibt 1. Nach einem weiteren Schritt ist der Zähler 11 und die Potentialfunktion 2. Wenn wir den Zähler erneut inkrementieren würden, müssten wir 3 Bits umdrehen, um von 011 zu gehen Dazu müssen wir einen Teil des Potentials nutzen und erhalten ein neues Potential von 1. Der Trick besteht darin, dass die Gesamtzahl der bisher tatsächlich umgedrehten Bits plus der Potentialfunktion immer dem Zweifachen der Anzahl von entspricht Inkrementierungsoperationen. Da die potenzielle Funktion niemals negativ ist, wird die Gesamtzahl der Bitflips nachn Inkrementierungsoperationen sind höchstens 2n, so wird jede Operation amortisiert 2 Bitflips.

Ein weiteres sehr gutes Beispiel ist die Array-Liste. Hier haben wir eine Liste (die das Durchlaufen aller Elemente und das Hinzufügen eines neuen Elements unterstützt), die durch Speichern der Elemente in einem Array implementiert wird. Das Array beginnt zunächst recht klein (z. B. 2 Stellen). Wenn wir ein Element hinzufügen, wird es im Array gespeichert. Wenn wir das dritte Element hinzufügen möchten, ist im Array kein Platz mehr vorhanden. Um dem entgegenzuwirken, erstellen wir ein neues Array mit doppelter Größe und kopieren alle Elemente aus dem ursprünglichen Array. Dies kann sehr lange dauern (linear in der Anzahl der Elemente), aber die amortisierte Analyse zeigt, dass jede Additionsoperation nur eine konstante Zeit benötigt. Die Array-Liste funktioniert in der realen Welt sehr gut (viel besser als die verknüpfte Liste). Jede Operation kann in konstanter Zeit durchgeführt werden, mit der Einschränkung, dass eine Operation gelegentlich viel länger dauert.

Tom van der Zanden
quelle