Mathematica中如何對矩陣內元素並行計算?

首先有一個矩陣a,中心元素的值為alpha,其餘為eta. 稱大於等於alpha的值為「冰」,其餘為「水」。

L = 9; alpha = 0.501; beta = 0.3; gamma = 0.0001;
a = ConstantArray[beta, {L, L}];
a[[Ceiling[L/2], Ceiling[L/2]]] = alpha;

初始化a_1a_2

a1 = ParallelMap[If[# &>= alpha, # + gamma, 0] , a, {2}];
a2 = ParallelMap[If[# &< alpha, #, 0] , a, {2}];

然後掃一遍a中的元素,把「冰」和其周邊元素存入a_1,把剩餘的存入a_2,然後再在a_1中的非零元素上加上gamma(冰的增長率)。

Do[If[Total[
Boole[{a[[i, j]] &>= alpha, a[[i, j + 1]] &>= alpha,
a[[i, j - 1]] &>= alpha, a[[i + 1, j]] &>= alpha,
a[[i + 1, j + 1]] &>= alpha, a[[i + 1, j - 1]] &>= alpha,
a[[i - 1, j]] &>= alpha, a[[i - 1, j + 1]] &>= alpha,
a[[i - 1, j - 1]] &>= alpha}]] &>= 1,
a1[[i, j]] = a[[i, j]] + gamma; a2[[i, j]] = 0;,
a2[[i, j]] = a[[i, j]]; a1[[i, j]] = 0;], {i, 2, L - 1}, {j, 2,
L - 1}];

得到結果(當L=9時)。

a1 // MatrixForm
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0.3001 0.3001 0.3001 0 0 0
0 0 0 0.3001 0.5011 0.3001 0 0 0
0 0 0 0.3001 0.3001 0.3001 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
a2 // MatrixForm
0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3
0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3
0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3
0.3 0.3 0.3 0 0 0 0.3 0.3 0.3
0.3 0.3 0.3 0 0 0 0.3 0.3 0.3
0.3 0.3 0.3 0 0 0 0.3 0.3 0.3
0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3
0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3
0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3

結果是正確的,但是當L的值很大時,速度會變慢很多。

我嘗試用ParallelDo代替Do,但是有side-effect。

有沒有其他辦法並行計算呢?


應當避免在Mathematica中使用Do之類的函數。幾乎在所有情況下,Do都可以被其他函數替代,並且計算效率更高。

alpha = 0.501; beta = 0.3; gamma = 0.0001;
a = ReplacePart[ConstantArray[beta, {9, 9}], {5, 5} -&> alpha];

Block[{p1, p2},
p1 = UnitStep[a - alpha];
p2 = Sign@ListConvolve[BoxMatrix[1], p1, {{2, 2}}];
a1 = p2*(beta + gamma) + p1*(alpha - beta);
a2 = (1 - p2)*beta;]

p1挑選出了a中大於alpha的那些元素記1,其餘記0;

p2挑選出了a中任意相鄰元素大於alpha的那些元素記1,其餘記0。

ListConvolve可以用於快速的判斷相鄰元素的狀態。


推薦閱讀:

下面這個mathematica語句怎麼理解?
Mathematica導入牆外網頁數據失敗,軟體內如何實現科學上網?
理論物理學生如何用mathematica記錄筆記並進行管理?
Matlab 怎麼填充曲線相交的區域呢?
Mathematica如何導入某個csv或者excel文件的指定行和列?

TAG:演算法 | 數學 | WolframMathematica | 並行計算 |