Das Prinzip vom Teilen und Herrschen

Werbung
Das Prinzip vom Teilen und Herrschen
Parameter eines Divide&Conquer–Algorithmus
Bei einem Ansatz mit Divide and Conquer wird das Gesamtproblem in kleinere Teilprobleme aufgeteilt, diese dann (in der Regel rekursiv) gelöst und danach die Gesamtlösung aus den Lösungen der
Teilprobleme zusammengesetzt. Um zu einer effizienten Lösung zu kommen, sollte bei jeder Aufspaltung die Anzahl der neuen Teilprobleme konstant sein (im Standardfall zwei, allgemein a ∈ N+ ) und
die Größe der neuen Teilprobleme um einen konstanten Faktor c < 1 abnehmen (z.B. Halbierung der
Größe, allgemein c = 1b für ein b > 1 aus Q). Ist n die ursprüngliche Problemgröße und stellt man die
Aufspaltungen der betrachteten Probleme bis zu den Rekursionsankern in einem Baum dar, dann hat
dieser Baum eine Höhe h ≤ dlogb ne und jeder innere Knoten hat höchstens a Kinder. Damit hat man
bereits eine Übersicht, wie viele Teilungsaufrufe für welche Problemgrößen erfolgen, aber um die
Gesamtlaufzeit abschätzen zu können fehlt noch ein wesentlicher Aspekt, nämlich die Kosten f (n),
um ein Problem der Größe n zuerst in a Teilprobleme der Größe n/b aufzuteilen und dann aus den a
Teillösungen die Lösung des ursprünglichen Problems zu berechnen.
Betrachten wir dazu die zwei bekannten Beispiele:
1. Beim Merge–Sort ist a = 2 und
b = 2 (eigentlich reicht das nicht ganz, denn bei ungeradem
n hat eine Teilliste die Länge 2n > n2 , aber man kann zeigen, dass solche Rundungseffekte
vernachlässigbar sind). Das Aufteilen erfolgt in konstanter Zeit, das Mischen der zwei sortierten
Teillisten in linearer Zeit, d.h. insgesamt f (n) ∈ Θ(n).
2. Bei der Binärsuche unterteilt man in zwei Bereiche, aber sucht entweder nur auf der linken
oder nur auf der rechten Seite weiter, behandelt also ein Teilproblem halber Größe. Daraus
folgt a = 1, b = 2 und f (n) ∈ Θ(1), denn das Aufteilen (also die Entscheidung für die richtige
Seite) erfordert konstante Zeit und das Ergebnis des rekursiven Aufrufs muss nur nach oben
weitergereicht werden.
Die folgende Abbildung zeigt den Rekursionsbaum mit den Parametern a = 3 und b = 2 für eine
Eingabe der Größe n = 8. Die Zahlen in den Knoten des Baums repräsentieren die Problemgrößen.
8
4
2
2
1
1
4
1
1
1
2
1
1
1
2
2
1
1
1
4
1
1
1
2
1
1
1
2
2
1
1
1
1
1
1
2
1
1
1
1
Sind die Parameter a, b und f (n) eines Divide&Conquer–Algorithmus bekannt, dann ergibt sich für
die Gesamtlaufzeit (unter der vereinfachenden Annahme, dass n/b ganzzahlig ist) die Rekursion
T (n) ≤ a · T (n/b) + f (n).
Wünschenswert wäre eine direkte (nichtrekursive) Beschreibung der Laufzeit in Abhängigkeit von
den drei Parametern. Der folgende Satz zeigt auf, wie man diese Rekursion in drei wichtigen Fällen
1
auflösen kann. Da diese drei Fälle die meisten realen Anwendungssituationen abdecken, hat der Satz
dem ehrenvollen Namen ‘Mastertheorem’ bekommen. Wir werden sehen, dass sich die bekannten
Laufzeiten T1 (n) ∈ Θ(n log n) für Merge–Sort und T2 (n) ∈ Θ(log n) für die Binärsuche unmittelbar
aus den Satz ableiten lassen.
Offen bleiben nur solche Rekursionen, in denen die Funktion f (n) ein sehr konfuses Verhalten aufweist.
Das Mastertheorem
Satz: Seien a ≥ 1 und b > 1 Konstanten, f (n) eine Funktion mit nichtnegativen Werten und gelte die
Rekursion
T (n) = a · T (n/b) + f (n),
wobei n/b für bn/bc oder dn/be stehen kann, und sei T(1) eine positive Konstante. Dann gelten für
T (n) die folgenden asymptotischen Schranken:
1. Ist f (n) ∈ O nlogb a−ε für ein ε > 0, dann ist T (n) ∈ Θ nlogb a
2. Ist f (n) ∈ Θ nlogb a , dann ist T (n) ∈ Θ nlogb a · log n
3. Ist f (n) ∈ Ω nlogb a+ε für ein ε > 0 sowie a · f (n/b) ≤ d · f (n) für eine Konstante 0 < d < 1
und geügend große n, dann ist T (n) ∈ Θ ( f (n))
Beweisidee: Der vollständige Beweis dieses Satzes ist sehr umfangreich allein durch die Fallunterscheidung (drei obere und drei untere Schranken) und darüber hinaus technisch aufwändig in den
Details (durch das Auf- und Abrunden bei der Division). Deshalb wollen wir hier nur die Grundidee
vorstellen. Zur Vereinfachung setzen wir a und b ganzzahlig voraus und nehmen an, dass n eine
ganzzahlige Potenz von b ist (oder anders gesagt, dass logb n eine natürliche Zahl ist). In diesem
Fall kann man die Rekursion durch wiederholte Anwendung vollständig ‘ausrollen’ bis man bei der
Verankerung für n = 1 angekommen ist:
T (n) =
f (n) + a · T (n/b)
=
f (n) + a · f (n/b) + a2 T (n/b2 ) = . . .
=
f (n) + a · f (n/b) + a2 f (n/b2 ) + a3 f (n/b3 ) + . . . + a(logb n)−1 · f (b) + alogb n · T (1)
(logb n)−1
=
∑
a j · f (n/b j ) +Θ nlogb a
j=0
|
{z
=g(n)
}
Da man den zweiten Summanden Θ nlogb a in allen drei Fällen bereits gut in die Behauptung einbinden kann, und in dieser im Fall 1 bereits die untere Schranke begründet, kommt es nur noch darauf
an, Begründungen für den ersten Summanden (den wir kurz g(n) genannt haben) zu finden. Es bleibt
also Folgendes zu zeigen:
• In Fall 1 ist g(n) ∈ O nlogb a ;
• In Fall 2 ist g(n) ∈ Θ nlogb a · log n ;
• In Fall 3 ist g(n) ∈ Θ( f (n)).
2
Das werden wir nicht im Detail machen. Der Trick besteht darin, zu Ungleichungen überzugehen, in
logb a +− ε
denen man f (n/b j ) je nach Fall durch einen Ausdruck der Form C · bnj
substituieren kann. Mit
Hilfe der Summenformel für geometrische Reihen kommt man dann letztlich zu den Behauptungen.
Zurück zu unseren zwei Standardbeispielen. Wir können nun leicht nachrechnen, dass für Merge-Sort
der zweite Fall vorliegt:
Wegen logb a = log2 2 = 1 und f (n) ∈ Θ(n) = Θ(n1 )) folgt T1 (n) ∈ Θ(n log n).
Für die Binärsuche liegt mit logb a = log2 1 = 0 und f (n) ∈ Θ(1) = Θ(n0 )) auch der zweite Fall vor.
Somit erhalten wir T1 (n) ∈ Θ(n0 log n) = Θ(log n).
Unser nächster Algorithmus ist ein Anwendungsbeispiel für einen anderen Fall des Mastertheorems.
Schnelle Multiplikation von n-stelligen Zahlen
Multipliziert man zwei n-stellige Zahlen mit der
der Schulmethode (wie nebenstehend an einem
Beispiel demonstriert), so sind dazu n2 elementare
Multiplikationen und n2 elementare Additionen
notwendig.
2
3 6
1 4 5
1 8 3
7
1
2
0
4
2 5 · 2 5 3
7 5
5
2 5
Es stellt sich die Frage, ob (und wenn ja, dann wie) man dieses Problem auch mit kleinerem Aufwand
lösen kann. Der Einwand, dass diese Frage uninteressant ist, weil ein moderner Prozessor mit 64–Bit–
Architektur auch zwei jeweils 9-stellige Dezimalzahlen in einem Takt multiplizieren kann, mag für
diese Standardanwendungen berechtigt sein, verliert aber sein Gewicht, wenn man an kryptographische Anwendungen mit 100 und mehr Dezimalstellen denkt. In diesem Fall würde man die großen
Zahlen in kleinere Einheiten mit z.B. 32 Bit zerlegen und den Begriff der elementaren Operation auf
diese Einheiten beziehen.
Zunächst ist klar, dass die Addition von zwei n-stelligen Zahlen mit O(n) elementaren Additionen
möglich ist (durch die O-Notation wird auch die Addition der Überträge berücksichtigt). Für die Multiplikation wollen wir mit einem rekursiven Divide&Conquer–Ansatz arbeiten und gehen zunächst
davon aus, dass n eine gerade Zahl ist, und dass wir bereits über eine Methode zur Multplikation von
zwei (n/2)–stelligen Zahlen verfügen. Sei d die Basis der Darstellung (also z.B. 2, 10 oder 232 ) und
x, y die beiden n-stelligen Zahlen. Wir betrachten die (n/2)–stelligen Zahlen x0 , x1 , y0 , y1 der Zerlegung von x und y, d.h. x = x1 · d n/2 + x0 und y = y1 · d n/2 + y0 . Daraus folgt
z = x · y = x1 · d n/2 + x0 · y1 · d n/2 + y0 = x1 · y1 ·d n + (x1 · y0 + x0 · y1 ) ·d n/2 + x0 · y0
| {z }
| {z }
|
{z
}
=z2
=z1
=z0
Da die Multiplikation mit den Potenzen von d höchstens lineeare Kosten verursacht (einfach Nullen
anhängen), kann man die Laufzeit T (n) durch vier Multiplikationen von (n/2)–stelligen Zahlen und
drei Additionen von Zahlen mit höchstens 2n Stellen abschätzen, d.h.
T (n) ≤ 4 · T (n/2) + f (n)
mit
f (n) ∈ O(n).
Wir können das Mastertheorem mit a = 4 und b = 2 anwenden. Wenn wir ε = 1 setzen, ist f (n) ∈
O(nlogb a−ε ). Das ist also der erste Fall des Mastertheorems und ergibt T (n) ∈ O(nlogb a ) = O(n2 ),
3
womit man die Schulmethode offensichtlich noch nicht verbessert hat. Der entscheidende Trick besteht darin, eine der vier Multiplikationen einzusparen auf Kosten von zusätzlichen, aber billigeren
Additionen bzw. Subtraktionen.
Wir setzen x0 = x1 + x0 und y0 = y1 + y0 und berechnen rekursiv z0 = x0 · y0 und z2 = x1 · y1 (wie vorher)
sowie z0 = x0 · y0 . Folgendes kann nun leicht nachgerechnet werden:
z = x · y = x1 · d n/2 + x0 · y1 · d n/2 + y0 = z2 · d n + (z0 − z2 − z0 ) · d n/2 + z0 .
Daraus ergibt sich T (n) ≤ 3 · T (n/2) + f (n) mit f (n) ∈ O(n) als neue Laufzeitrekursion.
Wegen log2 3 = 1.58 . . . kann man mit ε = 0.1 die obere Schranke f (n) ∈ O(nlogb a−ε ) ableiten. Somit
können wir wieder den ersten Fall des Mastertheorems anwenden und erhalten T (n) ∈ O(nlog2 3 ) und
damit auch T (n) ∈ O(n1.59 ).
Der hier beschriebene Trick war nur ein erster Schritt zu einem schnellen Multiplikationsverfahren.
Durch Nutzung der schnellen diskreten Fourier–Transformation und dem Einsatz von Methoden aus
der Zahlentheorie gelang es Schönhage und Strassen, die Laufzeit noch einmal entscheidend zu verbessern auf O(n log n log log n).
Mit ähnlichen Ideen wurden auch schnelle Verfahren zur Multiplikation von Matrizen entwickelt: Der
erste Schritt dazu war die Reduktion der Anzahl von elementaren Multiplikationen bei der Multiplikation von zwei 2 × 2–Matrizen von 8 auf 7.
4
Herunterladen