31.12.2014 Aufrufe

Drei divide-and-conquer Algorithmen 1 Karatsuba-Multiplikation von ...

Drei divide-and-conquer Algorithmen 1 Karatsuba-Multiplikation von ...

Drei divide-and-conquer Algorithmen 1 Karatsuba-Multiplikation von ...

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

<strong>Drei</strong> <strong>divide</strong>-<strong>and</strong>-<strong>conquer</strong> <strong>Algorithmen</strong><br />

1 <strong>Karatsuba</strong>-<strong>Multiplikation</strong> <strong>von</strong> Polynomen<br />

(und <strong>von</strong> ganzen Zahlen)<br />

Die <strong>Multiplikation</strong> zweier Polynome<br />

f(x) = 2n−1 ∑<br />

i=0<br />

f i x i , g(x) = 2n−1 ∑<br />

j=0<br />

g j x j<br />

vom Grad deg f, deg g < 2n wird zurückgeführt auf die drei<br />

<strong>Multiplikation</strong>en <strong>von</strong> Polynomen, deren Grad < n ist:<br />

f(x) = a(x) + x n b(x)<br />

g(x) = c(x) + x n d(x)<br />

f(x)g(x) = a(x)c(x) + x n (a(x)d(x) + b(x)c(x)) + x 2n b(x)d(x)<br />

wobei<br />

= u(x) + x n (w(x) − u(x) − v(x)) + x 2n v(x)<br />

u(x) := a(x)c(x)<br />

v(x) := b(x)d(x)<br />

w(x) := (a(x) + b(x))(c(x) + d(x))<br />

Für die rekursive Anwendung dieser Idee im Maple-Programm<br />

karatsuba wird angenommen, daß n eine Potenz <strong>von</strong> 2 ist,<br />

d.h. deg f, deg g < 2 m . Der Parameter m wird im rekursiven<br />

Programm mitgeführt. Startet man mit beliebigen input-<br />

Polynomen, so wird in kara mult das kleinste m bestimmt,<br />

sodaß diese Annahmen zutreffen.<br />

Idee und Programm sind auf <strong>Multiplikation</strong> <strong>von</strong> ganzen<br />

Zahlen zu übertragen.<br />

1


karatsuba := proc(f,g,x,m)<br />

local a,b,c,d,u,v,w,deg;<br />

if m=0 then RETURN(f*g) fi;<br />

deg := 2^(m-1);<br />

a := sum(’coeff(f,x,i)*x^i’,’i’=0..deg-1);<br />

b := sum(’coeff(f,x,i+deg)*x^i’,’i’=0..deg-1);<br />

c := sum(’coeff(g,x,i)*x^i’,’i’=0..deg-1);<br />

d := sum(’coeff(g,x,i+deg)*x^i’,’i’=0..deg-1);<br />

u := karatsuba(a,c,x,m-1);<br />

v := karatsuba(b,d,x,m-1);<br />

w := karatsuba(a+b,c+d,x,m-1);<br />

RETURN(exp<strong>and</strong>(u+(w-u-v)*x^deg+v*x^(2*deg)));<br />

end;<br />

kara_mult := proc(f,g,var)<br />

local df,dg,bound;<br />

df := degree(f,var);<br />

dg := degree(g,var);<br />

bound := ceil(simplify(log[2](max(df,dg)+1)));<br />

karatsuba(f,g,var,bound);<br />

end;<br />

Komplexitätsanalyse (für n = 2 m ):<br />

t(n) :=<br />

⎧<br />

⎨<br />

⎩<br />

Anzahl der Additionen und <strong>Multiplikation</strong>en im<br />

Koeffizientenbereich bei input-Grad < n<br />

t(2n) = 3 · t(n) + Θ(n) ,<br />

t(1) = Θ(1)<br />

2


⇒ t(n) ∈ Θ(n log 2 3 )<br />

3


2 Sortieren durch Verschmelzen: mergesort<br />

Die Idee <strong>von</strong> mergesort ist einfach: ist eine Liste A[1..n]<br />

der Länge n zu sortieren, so zerlegt man diese in Teillisten<br />

B := A[1..⌊n/2⌋] und C := A[⌊n/2⌋+1..n], sortiert die beiden<br />

separat (durch rekursive Anwendung eben dieser Idee)<br />

und produziert durch “Verschmelzen” (merging) beider Listen<br />

das Resultat. Das merging ist ein einfacher Vorgang,<br />

bei dem aus den aktuellen Resten der beiden sortierten Teillisten<br />

das jeweils kleinste Element durch einen Vergleich gefunden,<br />

entfernt und in die Resultatsliste geschrieben wird.<br />

Das Maple-Programm merge ist der Übersichtlichkeit wegen<br />

rekursiv geschrieben.<br />

merge := proc(A:list(integer),B:list(integer))<br />

local a,b;<br />

a := nops(A);<br />

b := nops(B);<br />

if a=0 then RETURN(B) fi;<br />

if b=0 then RETURN(A) fi;<br />

if op(1,A)


mergesort := proc(A:list(integer))<br />

local B,C,length,half;<br />

length := nops(A);<br />

half := floor(length/2);<br />

if length < 2 then RETURN(A) else<br />

B := [op(1..half,A)];<br />

C := [op(half+1..length,A)];<br />

RETURN(merge(mergesort(B),mergesort(C)));<br />

fi;<br />

end;<br />

mergesort reduziert das Sortierproblem für eine Liste der<br />

Länge n auf zwei Sortierprobleme (etwa) halber Größe und<br />

linearen Zusatzaufw<strong>and</strong> für Verschmelzen und overhead<br />

Komplexitätsanalyse (für n = 2 m ):<br />

t(2n) :=<br />

⎧<br />

⎨<br />

⎩<br />

Anzahl der Vergleichsoperationen + overhead für<br />

Listen der Länge n<br />

t(2n) = 2 · t(n) + Θ(n) ,<br />

t(1) = Θ(1)<br />

⇒ t(n) ∈ Θ(n log 2 n)<br />

5


3 Strassens Matrix-<strong>Multiplikation</strong><br />

Ausgangspunkt: die <strong>Multiplikation</strong> <strong>von</strong> zwei (2×2)-Matrizen<br />

(über irgendeinem (!) Ring) läßt sich mit 7 <strong>Multiplikation</strong>en<br />

im Koeffizientenbereich ausführen — statt mit 8 <strong>Multiplikation</strong>en<br />

nach “Schulmethode”:<br />

⎛<br />

⎝ a 11 a 12<br />

a 21<br />

⎞ ⎛<br />

⎠<br />

a 22<br />

⎝ b 11 b 12<br />

b 21<br />

⎞<br />

⎠ =<br />

b 22<br />

=<br />

d ⎝ 11 d 12<br />

d 21<br />

Man berechnet zunächst 7 Produkte<br />

⎛<br />

a ⎞<br />

⎝ 11b 11 + a 12 b 21 a 11 b 12 + a 12 b 22 ⎠<br />

a 21 b 11 + a 22 b 21 a 21 b 12 + a 22 b 22<br />

⎛<br />

⎞<br />

⎠<br />

d 22<br />

c 1 = (a 12 − a 22 )(b 21 + b 22 )<br />

c 2 = (a 11 + a 22 )(b 11 + b 22 )<br />

c 3 = (a 11 − a 21 )(b 11 + b 12 )<br />

c 4 = (a 11 + a 12 ) b 22<br />

c 5 = a 11 (b 12 − b 22 )<br />

c 6 = a 22 (b 21 − b 11 )<br />

c 7 = (a 21 + a 22 ) b 11<br />

und danach die d 11 , . . . , d 22 durch<br />

d 11 = c 1 + c 2 − c 4 + c 6 d 12 = c 4 + c 5<br />

d 21 = c 6 + c 7 d 22 = c 2 − c 3 + c 5 − c 7<br />

Der Witz der (rekursiven) Angelegenheit: die Koeffizienten<br />

a ij , b i,j , . . . können selbst wieder Matrizen sein, d.h.<br />

Reduktion einer Matrixmultiplikation für zwei (2n × 2n)-<br />

Matrizen auf 7 Matrixmultiplikationen <strong>von</strong> (n × n)-Matrizen,<br />

dazu 18 Additionen/Subtraktionen <strong>von</strong> (n × n)-Matrizen<br />

6


strassen := proc(A:matrix,B:matrix,m)<br />

local dim,A11,A12,A21,A22,<br />

B11,B12,B21,B22,<br />

C1,C2,C3,C4,C5,C6,C7,<br />

D11,D12,D21,D22;<br />

if m=0 then RETURN(evalm(A&*B)) fi;<br />

dim := 2^(m-1);<br />

A11 := submatrix(A,1..dim,1..dim);<br />

A12 := submatrix(A,1..dim,dim+1..2*dim);<br />

A21 := submatrix(A,dim+1..2*dim,1..dim);<br />

A22 := submatrix(A,dim+1..2*dim,dim+1..2*dim);<br />

B11 := submatrix(B,1..dim,1..dim);<br />

B12 := submatrix(B,1..dim,dim+1..2*dim);<br />

B21 := submatrix(B,dim+1..2*dim,1..dim);<br />

B22 := submatrix(B,dim+1..2*dim,dim+1..2*dim);<br />

C1 := strassen(evalm(A12-A22),evalm(B21+B22),m-1);<br />

C2 := strassen(evalm(A11+A22),evalm(B11+B22),m-1);<br />

C3 := strassen(evalm(A11-A21),evalm(B11+B12),m-1);<br />

C4 := strassen(evalm(A11+A12),B22,m-1);<br />

C5 := strassen(A11,evalm(B12-B22),m-1);<br />

C6 := strassen(A22,evalm(B21-B11),m-1);<br />

C7 := strassen(evalm(A21+A22),B11,m-1);<br />

D11 := evalm(C1+C2-C4+C6);<br />

D12 := evalm(C4+C5);<br />

D21 := evalm(C6+C7);<br />

D22 := evalm(C2-C3+C5-C7);<br />

RETURN(stack(concat(D11,D12),concat(D21,D22)));<br />

end;<br />

7


Komplexitätsanalyse (für n = 2 m ):<br />

t(n) :=<br />

⎧<br />

⎪⎨<br />

⎪⎩<br />

Anzahl der arithmetischen Operationen im Koeffizientenbereich<br />

für die <strong>Multiplikation</strong> <strong>von</strong> zwei<br />

(n × n)-Matrizen<br />

t(2n) = 7 · t(n) + 18 · n 2 , t(1) = 1<br />

⇒ t(n) ∈ Θ(n log 2 7 )<br />

Beachte: log 2 7 = 2.81 . . . !<br />

Siehe Kapitel 31.2 in Cormen/Leiserson/Rivest für<br />

einen Rekonstruktionsversuch der Strassenschen Idee.<br />

8

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!