Problem nawiasowania ciągu macierzy

Problem nawiasowania ciągu macierzy – problemem znalezienia takiego nawiasowania iloczynu macierzy A 0 , A 1 , , A n , {\displaystyle A_{0},A_{1},\dots ,A_{n},} by zminimalizować łączny koszt wszystkich mnożeń. Nawiasowanie takie nazywa się optymalnym. Mówimy, że iloczyn macierzy A 0 A 1 A n {\displaystyle A_{0}\cdot A_{1}\cdot \ldots \cdot A_{n}} ma ustalone nawiasowanie, jeżeli tworzy go pojedyncza macierz lub iloczyn dwóch iloczynów macierzy o ustalonym nawiasowaniu.

Przykład ustalonych nawiasowań

Niech A 0 , A 1 , A 2 , A 3 {\displaystyle A_{0},A_{1},A_{2},A_{3}} będzie ciągiem macierzy. Ich iloczyn ma następujące ustalone nawiasowania:

( ( ( A 0 A 1 ) A 2 ) A 3 ) {\displaystyle (((A_{0}\cdot A_{1})\cdot A_{2})\cdot A_{3})}
( ( A 0 ( A 1 A 2 ) ) A 3 ) {\displaystyle ((A_{0}\cdot (A_{1}\cdot A_{2}))\cdot A_{3})}
( ( A 0 A 1 ) ( A 2 A 3 ) ) {\displaystyle ((A_{0}\cdot A_{1})\cdot (A_{2}\cdot A_{3}))}
( A 0 ( ( A 1 A 2 ) A 3 ) ) {\displaystyle (A_{0}\cdot ((A_{1}\cdot A_{2})\cdot A_{3}))}
( A 0 ( A 1 ( A 2 A 3 ) ) ) {\displaystyle (A_{0}\cdot (A_{1}\cdot (A_{2}\cdot A_{3})))}

Nawiasowanie a koszt obliczenia iloczynu macierzy

Wybór nawiasowania może mieć znaczący wpływ na liczbę operacji potrzebnych do obliczenia iloczynu macierzy – koszt pomnożenia dwóch macierzy o wymiarach odpowiednio a × b {\displaystyle a\times b} i b × c {\displaystyle b\times c} wynosi O ( a b c ) {\displaystyle O(a\cdot b\cdot c)} (dokładnie – wymaga a b c {\displaystyle a\cdot b\cdot c} mnożeń skalarnych).

Niech dane będą trzy macierze A 0 , A 1 , A 2 {\displaystyle A_{0},A_{1},A_{2}} o rozmiarach odpowiednio 2×20, 20×1 i 1×10. Dla nawiasowania ( ( A 0 A 1 ) A 2 ) {\displaystyle ((A_{0}\cdot A_{1})\cdot A_{2})} koszty wyniosą:

  • obliczenie iloczynu A = A 0 A 1 {\displaystyle A^{'}=A_{0}\cdot A_{1}} – koszt 2 20 1 = 40 {\displaystyle 2\cdot 20\cdot 1=40} mnożeń; macierz A {\displaystyle A^{'}} ma rozmiary 2×1;
  • obliczenie iloczynu A A 2 {\displaystyle A^{'}\cdot A_{2}} – koszt 2 1 10 = 20 {\displaystyle 2\cdot 1\cdot 10=20} mnożeń;
  • razem: 40 + 20 = 60 {\displaystyle 40+20=60} mnożeń skalarnych.

Dla tych samych macierzy, ale nawiasowania ( A 0 ( A 1 A 2 ) ) , {\displaystyle (A_{0}\cdot (A_{1}\cdot A_{2})),} koszty wyniosą:

  • obliczenie iloczynu A = A 1 A 2 {\displaystyle A^{''}=A_{1}\cdot A_{2}} – koszt 20 1 10 = 200 {\displaystyle 20\cdot 1\cdot 10=200} mnożeń; macierz A {\displaystyle A^{''}} ma rozmiary 20×10;
  • obliczenie iloczynu A 0 A {\displaystyle A_{0}\cdot A^{''}} – koszt 2 20 10 = 400 {\displaystyle 2\cdot 20\cdot 10=400} mnożeń;
  • razem: 200 + 400 = 600 {\displaystyle 200+400=600} mnożeń skalarnych.

Przewaga pierwszego nawiasowania jest oczywista.

Własność optymalnej podstruktury

Można wykazać, że problem nawiasowania macierzy wykazuje własność optymalnej podstruktury.

Dowód

Załóżmy, że dla optymalnego nawiasowania macierzy A i , A i + 1 , , A j {\displaystyle A_{i},A_{i+1},\dots ,A_{j}} występuje podział między A p {\displaystyle A_{p}} i A p + 1 {\displaystyle A_{p+1}} oraz, niewprost, że dla tego nawiasowania nawiasowanie A i , A i + 1 , , A p {\displaystyle A_{i},A_{i+1},\dots ,A_{p}} nie jest optymalne. Wówczas można by w nawiasowaniu A i , A i + 1 , , A j {\displaystyle A_{i},A_{i+1},\dots ,A_{j}} „podmienić” nawiasowanie A i , A i + 1 , , A p {\displaystyle A_{i},A_{i+1},\dots ,A_{p}} na optymalne, w wyniku czego otrzymalibyśmy nowe nawiasowanie A i , A i + 1 , , A j {\displaystyle A_{i},A_{i+1},\dots ,A_{j}} lepsze od optymalnego – sprzeczność.

Rozwiązanie problemu nawiasowania macierzy

Problem nawiasowania ciągu macierzy można łatwo rozwiązać, stosując algorytm dynamiczny. Definiujemy koszt optymalnego nawiasowania jako funkcję optymalnych rozwiązań podproblemów.

Niech k [ i ] [ j ] {\displaystyle k[i][j]} oznacza minimalny koszt wymnożenia macierzy A i , A i + 1 , , A j {\displaystyle A_{i},A_{i+1},\dots ,A_{j}} o rozmiarach odpowiednio a i × a i + 1 , a i + 1 × a i + 2 , , a j × a j + 1 . {\displaystyle a_{i}\times a_{i+1},a_{i+1}\times a_{i+2},\dots ,a_{j}\times a_{j+1}.}
k [ i ] [ j ] {\displaystyle k[i][j]} może być zdefiniowane następująco:

  • k [ i ] [ i ] {\displaystyle k[i][i]} – nawiasowanie tylko jednej macierzy – k [ i ] [ i ] = 0 {\displaystyle k[i][i]=0}
  • k [ i ] [ j ] {\displaystyle k[i][j]} – nawiasowanie to musi wyznaczać punkt podziału p {\displaystyle p} taki, że (zgodnie z podpunktem o własności optymalnego nawiasowania) A i , , A p {\displaystyle A_{i},\dots ,A_{p}} i A p + 1 , , A j {\displaystyle A_{p+1},\dots ,A_{j}} są optymalnymi rozwiązaniami podproblemów. Wtedy k [ i ] [ j ] {\displaystyle k[i][j]} jest równe sumie minimalnych kosztów obliczenia A i , , A p {\displaystyle A_{i},\dots ,A_{p}} i A p + 1 , , A j {\displaystyle A_{p+1},\dots ,A_{j}} oraz kosztu pomnożenia macierzy wynikowych tych podrozwiązań:
k [ i ] [ j ] = min i m < j { k [ i ] [ m ] + k [ m + 1 ] [ j ] + a i a m + 1 a j + 1 } {\displaystyle k[i][j]=\min _{i\leqslant m<j}\{k[i][m]+k[m+1][j]+a_{i}\cdot a_{m+1}\cdot a_{j+1}\}}