Strassen矩陣相乘演算法

2021-07-16 08:17:20 字數 2561 閱讀 6459

strassen的矩陣相乘方法是一種典型的分治演算法。目前為止,我們已經見過一些分治策略的演算法了,例如歸併排序和karatsuba大數快速乘法。現在,讓我再來看看分治策略的背後是什麼。

同動態規劃不同,在動態規劃中,為了得到最終的解決方案,我們經常需要把乙個大的問題「展開」為幾個子問題,但是這裡,我們會更多的談到如何把一些子解決方案組合到一起。這些子問題的解決方案是對等的,他們的歸併方式也是通過某種方式定義好的。

乙個典型的例子就是歸併排序演算法。在歸併排序中,我們有兩個有序陣列,我們想要這兩個陣列在合併之後仍然保持有序。當然了,在歸併排序中,最複雜的部分當屬自我合併,而原因在於,我們不得不傳遞兩個陣列,a和b,然後去比較每一「對」分別來自陣列a和陣列b的元素。有一點離題,但是,這是歸併排序的乙個弱點,雖然,它的最壞情況的時間複雜度是 o(n.log(n)),但是,快速排序卻往往是實踐中更為有效的排序方法,因為,它沒有「合併」的過程。快速排序僅僅把兩個子陣列連線到一起,請注意,在快速排序中,子陣列一般並不具有相同的長度,雖然他的最壞時間複雜度是o(n^2),但它的效能卻經常好於歸併排序。

在上文中,那個簡單的例子告訴我們:有時候如何合併兩個子問題並不是乙個簡單的事情。因此,當我們使用分治策略的時候,我們必須非常謹慎。

volker strassen是一位出生於2023年的德國數學家。他因為在概率論上的工作而廣為人知,但是在電腦科學和演算法領域,他卻因為矩陣相乘演算法而被大部分人認識,這個演算法目前仍然是比通用矩陣相乘演算法效能好的主要演算法之一。

strassen在2023年第一次發表關於這個演算法的文章,並證明了複雜度為n^3的演算法並不是最優演算法。實際上,strassen給出的解決方案只是更好一點點,但是,他的貢獻卻是巨大的,因為他的工作觸發了矩陣相乘領域更多的研究,比如複雜度為o(n^2,3737)的coppersmith-winograd演算法。

兩個矩陣 a[nxn] 和 b[nxn] 相乘的通用演算法是非常簡單的。雖然矩陣相乘比兩個數字相乘要複雜得多,而且也不滿足交換律,但它仍然非常簡單——同時也很慢。

讓我們先來定義一下什麼是a[nxn]矩陣。因為我們要說下nxn矩陣,讓我們先想象乙個有n行n列的方格網。在每一行和每一列的a[i][j],我們都有乙個值。

當然,作為乙個開發者,我們可以把乙個矩陣看成乙個二維陣列。

// php two-dimensional array

$a =

array(0

=>

array

($v1

,$v2

,$v3

,$v4),1

=>

array

($v5

,$v6

,$v7

,$v8),2

=>

array

($v9

,$v10

,$v11

,$v12

),);

不要忘記,乙個nxn的矩陣僅僅是矩陣中的一種情況,同樣的,我們可以有其他任何大小的nxm階矩陣(n <> m)。

然而,為了和另外的矩陣相乘,矩陣的大小是非常重要的,為什麼?

正如我上面提到的一樣,矩陣相乘和數字相乘並不一樣。首先,這個操作並不滿足交換律。

第二個問題是,你用來相乘a和b的方法。

僅僅因為這種方法只對nxn階矩陣有效,因此我們能看到把矩形矩陣相乘產生的問題。確實,這是不可能的,除非a矩陣的第二維和b矩陣的第一維相等。

不過好在我們現在正在討論的是具有相同維數的方形矩陣。

好的,現在我們知道如何把兩個方形矩陣相乘了(具有相同維數nxn),現在,讓我們一起去估算一下通用矩陣相乘演算法的時間複雜度。

我們知道a.b = c,當且僅當:

c[i

][j]=

sum(a[

i][k]

*b[k

][j])fork =

0..n

於是,我們有乙個n^3複雜度的操作。現在,讓我們盡力找乙個分治策略的演算法。

這個對於矩陣來說確實並不難,因為我們知道,乙個矩陣可以被分成很多更小的子矩陣。

現在,我們有什麼?

再一次——同樣的時間複雜度——我們有了8個乘積和4個和,那麼,計算量在哪?

當然, 為了得到更快的解決方案,我們不得不看一下strassen在1969做過的工作。他如下圖定義了p1, p2, p3, p4, p5, p6 和 p7。

正如我以上提到的,strassen演算法僅僅比通用矩陣相乘演算法好一點點。通用矩陣相乘演算法時間複雜度是o(n^3),然而strassen演算法複雜度則是o(n^2.80)。

你能在下圖觀察到,隨著n的變大,strassen演算法是如何比通用矩陣相乘演算法變得更有效率的。

雖然這個演算法看起來更接近純數學領域,而不是計算機領域。但在實際應用中,任何用到nxn陣列的地方,我們都可以從矩陣相乘演算法中獲益。

另一方面,strassen演算法並不比n^3複雜度的通用矩陣相乘演算法快很多。這很重要,因為對於乙個很小的n(通常n<45)來說,通用矩陣相乘演算法在實踐中往往是更好的選擇。然而,你可以從以上的中看到,對於n>100的情況來說,這兩個演算法的差別還是相當大的。

同時,當我們談到|v| = n的鄰接矩陣,以及一些依賴矩陣相乘的圖論演算法的時候,nxn陣列經常會在這些領域中使用。

strassen矩陣乘法 Strassen矩陣乘法

求矩陣a,b相乘的結果c 直接根據矩陣乘法的定義來遍歷計算。c 語言 void matrixmul int a,int b,int c,int m,int b,int n void test3 int b 3 2 int c 2 2 matrixmul int a,int b,int c,2,3,2...

矩陣乘法 之 strassen 演算法

一般情況下矩陣乘法需要三個for迴圈,時間複雜度為o n 3 現在我們將矩陣分塊如圖 來自mit演算法導論 一般演算法需要八次乘法 r a e b g s a f b h t c e d g u c f d h strassen將其變成7次乘法,因為大家都知道乘法比加減法消耗更多,所有時間複雜更高!...

演算法導論 矩陣乘法strassen演算法

矩陣運算在做科 算時是必不可少的,如果採用matlab來計算,這倒也容易。但是如果是自己寫c或者c 一般而言,需要做三次迴圈,其時間複雜度就是o n 3 上圖給出了我們一般會採用的方法,就是對應元素相乘和相加。如果把c a b進行分解,可以看出,這裡需要進行8次的乘法運算 分別是 r a e b g...