2012-02-17 42 views
1

這只是一個出於興趣而提出的問題。假設我有一個接受方矩陣和輸出方矩陣相同大小的二進制函數(或更一般地,它的輸入的類型和大小相同,其輸出的類型和大小):在matlab中將雙輸入函數轉換爲可變長度輸入函數的巧妙方法

function C = myfunc(A,B) 

一個例子是mtimes funcion。有哪些不同和巧妙的把這個變成一個可變長度的輸入功能

function C = myfunc_multi(varargin) 

這樣

myfunc(A{1},myfunc(A{2},myfunc(A{3},...myfunc(A{end-1},A{end})...))) == 
    myfunc_multi(A{:}) 

的方法呢?

這是已經到了我的第一個通用的解決方案(編輯:除了遞歸或循環):

function C = multioutput(functionhandle, varargin) 
    n = length(varargin); 
    funcstr = functiontostring(functionhandle); 
    str = regexprep(arrayfun(@num2str,1:n-1),'(.)',[funcstr '(varargin{$1},']); 
    C = eval(sprintf('%svarargin{%d}%s',str,n,repmat(')',1,n-1))); 
end 

,那麼你可以用一些測試它像

A = {rand(3) rand(3) rand(3) rand(3) rand(3)}; 
multioutput(@mtimes,A{:})-A{1}*A{2}*A{3}*A{4}*A{5} 

進行測試。你能想到的其他方式?

+3

對不起,但通過複雜的使用arrayfun避免了簡單的循環,regexprep和eval只是愚蠢的。學會在適當的時候編寫簡單的代碼。這裏的循環就是這樣。這種混亂在評估中不會浪費時間,但是如果您需要調試它 - 確實是一團糟。 – 2012-02-17 22:20:35

+0

另外,我建議不要使用遞歸(因爲你提到它)。浪費時間和記憶。 – yuk 2012-02-17 22:45:54

+1

@ woodchips,@ yuk:正如我所說,這個問題出於興趣。與任何編程語言一樣,我喜歡看到整潔的技巧,以及可以完成事情的迂迴或意想不到的方式。我更多地考慮[IOCCC](http://en.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest)的實際情況。當我實際使用Matlab進行計算時,我寫了「簡單代碼」。 – 2012-02-18 15:13:37

回答

5

可能沒有理由避免顯而易見的遞歸構造。它很簡單,易於閱讀和維護,並且應該具有相當不錯的性能。

function out = aggregate_inputs(fHandle, varargin) 
if nargin>3 
    out = fHandle(varargin{1},aggregate_inputs(fHandle,varargin{2:end})); 
elseif nargin <= 3 
    out = fHandle(varargin{:}); 
end 

不太優雅,但(可能*)需要較少的內存是循環結構

function accumulate = aggregate_inputs(fHandle,varargin) 
if nargin<=3 
    accumulate = fHandle(varargin{:}); 
else 
    accumulate = fHandle(varargin{end-1},varargin{end}); 
    for ix = (length(varargin)-2):-1:1 
     acumulate = fHandle(varargin{ix}, accumulate); 
    end 
end 

當然,你的問題取出考慮這些構造...所以不是一個真正的好這樣做,我可以看到。


爲了使哲學蠟一分鐘,確實很多Matlab操作可以通過使用矢量化調用更快得多。有時這被解釋爲「不惜一切代價避免循環」。但是,通過調用cellfun,arrayfun或(please no)eval來避免循環通常不會提高性能。有時候,出於其他原因是正確的做法......但它並沒有幫助「矢量化代碼以使其更快」。


*的「也許」上面很簡單,因爲我不知道Matlab的懶惰寫入時複製以及其他優化如何將阻止內存使用這似乎是與遞歸解決方案的潛在危險。

+0

我可能很容易被認爲是不正確的,但我假設你的意思是寫出'out = fhandle(varargin {1},aggregate_inputs(fHandle,varargin {2:en​​d}))'作爲第一個函數的遞歸步驟。 – Nigel 2013-07-19 21:12:43

+0

我認爲你是對的。更新。 – Pursuit 2013-07-19 21:22:19