在matlab中将双输入函数转换为变长输入函数的巧妙方法 [英] Clever ways of turning a two-input function into a variable-length-input function in matlab

查看:36
本文介绍了在matlab中将双输入函数转换为变长输入函数的巧妙方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这只是一个出于兴趣的问题.假设我有一个二元函数,它接受方阵并输出相同大小的方阵(或者更一般地说,它的输入类型和大小与其输出类型和大小相同):

This is just a question out of interest. Suppose I have a binary function that accepts square matrices and outputs square matrices of the same size (or more generally, it's input type and size are the same as its output type and size):

function C = myfunc(A,B)

一个例子是 mtimes 函数.有什么不同的聪明的方法可以把它变成一个可变长度的输入函数

An example would be the mtimes funcion. What are some different and clever ways of turning this into a variable length input function

function C = myfunc_multi(varargin)

这样

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

?

这是我想到的第一个通用解决方案(除了递归或循环):

This is the first general solution that has come to me (edit: besides recursion or a loop):

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

然后你可以用类似的东西来测试它

then you can test it with something like

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

来测试一下.你还能想到其他方法吗?

to test it. Any other ways you can think of?

推荐答案

可能没有充分的理由避免明显的递归构造.它简单,易于阅读和维护,并且应该具有不错的性能.

There is probably no good reason to avoid the obvious recursive construct. It is simple, easy to read and maintain, and should have pretty good performance.

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

不太优雅,但是(也许*)需要更少的内存是循环结构

Not quite as elegant, but (perhaps*) requiring less memory is the loop construct

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

当然,您的问题从考虑中排除了这些结构......所以我认为没有什么好的方法可以做到这一点.

Of course, your question removed those constructs from consideration ... so there's not really a good way to do it that I can see.

顺便说一句,使用矢量化调用可以更快地进行许多 Matlab 操作,这是事实.有时这被解释为不惜一切代价避免循环".但是,避免调用 cellfun、arrayfun 或(请不要)eval 的循环通常不会提高性能.有时出于其他原因这样做是正确的……但这无助于向量化您的代码以使其更快".

To wax philosophical for a minute, it is true that many Matlab operations can be made much much faster by using vectorized calls. Sometimes this is interpreted as "avoid loops at all costs". However, avoiding loops with calls to cellfun, arrayfun, or (please no) eval, does not usually increase performance. Sometimes it is the right thing to do for other reasons ... but it does not help "vectorize your code to make it faster".

*上面的也许"仅仅是因为我不确定 Matlab 的惰性写时复制和其他优化在多大程度上可以防止内存使用,这似乎是递归解决方案的潜在危险.

*The "perhaps" above is simply because I'm not sure how well Matlab's lazy copy-on-write and other optimizations would prevent the memory usage which seems like a potential hazard with the recursive solution.

这篇关于在matlab中将双输入函数转换为变长输入函数的巧妙方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆