2011-09-09 154 views
2

我有雙重求和 = 1:中號Ñ = 1:Ñ用於與座標RHO極性點,ž向量化MATLAB函數

Double summ over m and n

我寫過它的向量化符號:

N = 10; 
M = 10; 
n = 1:N; 
m = 1:M; 

rho = 1; 
phi = 1; 
z = 1; 

summ = cos (n*z) * besselj(m'-1, n*rho) * cos(m*phi)'; 

現在我需要座標重寫該功能用於接收向量(列)RHOž。我嘗試了arrayfun,cellfun,簡單的循環 - 它們對我來說太慢了。我知道「MATLAB數組操作技巧和技巧」,但作爲MATLAB初學者,我無法理解repmat和其他功能。

任何人都可以提出矢量化解決方案嗎?

+0

可以:結果與先前一致你詳細說明每個變量的維度。即'rho'是'1xA'等,以及您期望輸出的尺寸。首先,這有助於我們幫助你,其次,這可以幫助你自己,因爲在使用MATLAB時首先要考慮適當的尺寸。 – Egon

回答

1

我覺得你的代碼已經好矢量(對於nm)。如果你希望這個函數也接受一個數組值rho/phi/z值,我建議你簡單地在for循環中處理值,因爲我懷疑任何進一步的矢量化都會帶來顯着的改進(加上代碼將更難以閱讀)。儘管如此,在下面的代碼中,我試圖通過對BESSELJ和COS函數進行一次調用(我將每個行/矩陣/第三維中的列)。他們的乘法還是done in a loop(ARRAYFUN是精確的):

%# parameters 
N = 10; M = 10; 
n = 1:N; m = 1:M; 

num = 50; 
rho = 1:num; phi = 1:num; z = 1:num; 

%# straightforward FOR-loop 
tic 
result1 = zeros(1,num); 
for i=1:num 
    result1(i) = cos(n*z(i)) * besselj(m'-1, n*rho(i)) * cos(m*phi(i))'; 
end 
toc 

%# vectorized computation of the components 
tic 
a = cos(bsxfun(@times, n, permute(z(:),[3 2 1]))); 
b = besselj(m'-1, reshape(bsxfun(@times,n,rho(:))',[],1)');    %' 
b = permute(reshape(b',[length(m) length(n) length(rho)]), [2 1 3]); %' 
c = cos(bsxfun(@times, m, permute(phi(:),[3 2 1]))); 
result2 = arrayfun(@(i) a(:,:,i)*b(:,:,i)*c(:,:,i)', 1:num);   %' 
toc 

%# make sure the two results are the same 
assert(isequal(result1,result2)) 

我沒有使用TIMEIT功能(提供了更多的公平計時)其他基準測試。

0.0062407 # elapsed time (seconds) for the my solution 
0.015677  # elapsed time (seconds) for the FOR-loop solution 

注意,當你增加輸入向量的大小,這兩種方法會開始有類似的時序(for循環,甚至贏得一些場合)

+0

非常感謝。你的代碼工作速度超快。我將保留這段代碼作爲'bsxfun'和'permute'的例子。我嘗試用for循環替換arrayfun,並且獲得了更快的代碼2-10倍。看起來'arrayfun'和'cellfun'比普通的for循環慢。 – N0rbert

0

您需要創建兩個矩陣,說m_n_因此,通過選擇每個矩陣的元素i,j你會得到兩個mn所需的索引。

大多數MATLAB函數接受矩陣和向量並逐個計算它們的結果。因此,要產生一個雙重和,您可以並行計算總和的所有元素f(m_, n_)並對它們進行求和。

在你的情況(注意.*運營商進行矩陣的元素方式乘法)

N = 10; 
M = 10; 
n = 1:N; 
m = 1:M; 

rho = 1; 
phi = 1; 
z = 1; 

% N rows x M columns for each matrix 
% n_ - all columns are identical 
% m_ - all rows are identical 
n_ = repmat(n', 1, M); 
m_ = repmat(m , N, 1); 

element_nm = cos (n_*z) .* besselj(m_-1, n_*rho) .* cos(m_*phi); 
sum_all = sum(element_nm(:)); 
+0

你好,nimrodm!謝謝您的回答。但這不是我的意思。我的意思是,* rho *,* phi *,* z *將是向量,即rho = 0:4,phi = 0:4,z = 0:4。你的代碼不接受這些變量的向量。它給出了與我的代碼相同的結果(對於標量值* rho *,* phi *和* z *),但執行速度比我的慢620倍。我的變體意味着{行N} * {矩陣N * M} * {col M} = {標量}。這就是爲什麼我沒有使用元素明智的運算符(如。*)。 – N0rbert