Python演算法 矩陣鏈乘法

2022-03-15 11:14:37 字數 2926 閱讀 6387

題目解析參考:【動態規劃】矩陣鏈乘法

矩陣乘法是乙個滿足結合律的運算。顯然,對於矩陣a、b、c來說,(ab)c 與 a(bc) 是等價的,我們可以根據自己的心情選擇任意的運算順序,總之,結果都是一樣的。

糟糕的是,對計算機來說可不是這麼回事,若我們假定矩陣 a=[10,20], b=[20,30], c=[30,40],那麼在以下兩種運算順序中,標量相乘的次數是天差地別:

(ab)c = 10*20*30 + 10*30*40 = 18000

a(bc) = 20*30*40 + 10*20*40 = 32000

為了計算表示式,我們可以先用括號明確計算次序,然後利用標準的矩陣相乘演算法進行計算。

完全括號化(fully parenthesized):它是單一矩陣,或者是兩個完全括號化的矩陣乘積鏈的積。

例如如果有矩陣鏈為,則共有5種完全括號化的矩陣乘積鏈。

(a1(a2(a3a4)))

(a1((a2a3)a4))

((a1a2)(a3a4))

((a1(a2a3))a4)

((a1(a2a3))a4)

對矩陣鏈加括號的方式會對乘積運算的代價產生巨大影響。我們先來分析兩個矩陣相乘的代價。下面的偽**的給出了兩個矩陣相乘的標準演算法,屬性rows和columns是矩陣的行數和列數。

matrix-multipkly(a,b)

if a.columns≠b.rows

error "incompatible dimensions"

else let c be a new a.rows×b.columns matrix

for i = 1 to a.rows

for j = 1 to b.columns

c(ij)=0

for k = 1 to a.columns

c(ij)=c(ij)+a(ik)*b(kj)

return c

兩個矩陣a和b只有相容(compatible),即a的列數等於b的行數時,才能相乘。如果a是p×q的矩陣,b是q×r的矩陣,那麼乘積c是p×r的矩陣。計算c所需要時間由第8行的標量乘法的次數決定的,即pqr。

以矩陣鏈為例,來說明不同的加括號方式會導致不同的計算代價。假設三個矩陣的規模分別為10×100、100×5和5×50。

如果按照((a1a2)a3)的順序計算,為計算a1a2(規模10×5),需要做10*100*5=5000次標量乘法,再與a3相乘又需要做10*5*50=2500次標量乘法,共需7500次標量乘法。

如果按照(a1(a2a3))的順序計算,為計算a2a3(規模100×50),需100*5*50=25000次標量乘法,再與a1相乘又需10*100*50=50000次標量乘法,共需75000次標量乘法。因此第一種順序計算要比第二種順序計算快10倍。

矩陣鏈乘法問題(matrix-chain multiplication problem)可描述如下:給定n個矩陣的鏈,矩陣ai的規模為p(i-1)×p(i) (1<=i<=n),求完全括號化方案,使得計算乘積a1a2...an所需標量乘法次數最少。

因為括號方案的數量與n呈指數關係,所以通過暴力搜尋窮盡所有可能的括號化方案來尋找最優方案是乙個糟糕策略。我們可以使用遞迴關係來找到我們需要的最優解法,首先,我們要用乙個函式mcm來得到最小標量相乘次數,那麼mcm也可用來定義在所有情況下的最優子段。再使用動態規劃和備忘錄法即可得到結果。

應用動態規劃方法

下面用動態規劃方法來求解矩陣鏈的最優括號方案,我們還是按照之前提出的4個步驟進行:

1.刻畫乙個最優解的結構特徵

2.遞迴地定義最優解的值

3.計算最優解的值,通常採用自底向上的方法

4.利用計算出的資訊構造乙個最優解

def mult(chain):

n = len(chain)

# single matrix chain has zero cost

aux =

print(aux)

# i: length of subchain(子鏈)

for i in range(1, n):

# j: starting index of subchain

for j in range(0, n - i):

best = float('inf') #inf is infinite(無窮大)

# k: splitting point of subchain

for k in range(j, j + i):

# multiply subchains at splitting point

lcost, lname, lrow, lcol = aux[j, k]

rcost, rname, rrow, rcol = aux[k + 1, j + i]

cost = lcost + rcost + lrow * lcol * rcol

var = '(%s%s)' % (lname, rname)

print(cost, var)

# pick the best one

if cost < best:

best = cost

aux[j, j + i] = cost, var, lrow, rcol

print(aux)

return dict(zip(['cost', 'order', 'rows', 'cols'], aux[0, n - 1]))

6000 (ab)

24000 (bc)

32000 (a(bc))

18000 ((ab)c)

演算法導論 矩陣鏈乘法

問題描述 給定有n個連乘矩陣的維數,要求計算其採用最優計算次序時所用的乘法次數,即所要求計算的乘法次數最少。例如,給定三個連乘矩陣的維數分別是10 100,100 5和5 50,採用 a1a2 a3,乘法次數為10 100 5 10 5 50 7500次,而採用a1 a2a3 乘法次數為100 5 ...

矩陣鏈乘法問題 (演算法)

一 概述 以兩個矩陣相乘為例,a1 a2,a1和a2為兩個矩陣,假設a1的行列數是p q,a2的行列數是q r。注意這裡由於是a1乘以a2,所以a1的列數要等於a2的行數,否則無法做矩陣乘法,滿足上述條件的矩陣,我們稱之為 相容 的。那麼對於a1 a2而言,我們需要分別執行p r次對應a1的行元素乘...

矩陣鏈乘法

設m i j 為計算矩陣ai.j所需標量乘法運算次數的最小值。對整個問題計算ai.n的最小代價就是m i,n 使用輔助表是s 1.n,1.n 來記錄計算m i,j 時取得最優代價處k的值。k是裂開的位置。include define n 6 void matrix int p,int m n 1 i...