在matlab中将双输入函数转换为可变长度输入函数的巧妙方法

Ian*_*cks 1 matlab arguments function

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

function C = myfunc(A,B)
Run Code Online (Sandbox Code Playgroud)

一个例子是mtimes funcion.有什么不同和聪明的方法将其变成可变长度输入功能

function C = myfunc_multi(varargin)
Run Code Online (Sandbox Code Playgroud)

这样的

myfunc(A{1},myfunc(A{2},myfunc(A{3},...myfunc(A{end-1},A{end})...))) == 
    myfunc_multi(A{:})
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

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

测试它.您还能想到其他任何方式吗?

Pur*_*uit 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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

当然,你的问题从考虑中删除了那些结构......所以我看不到真正的好方法.


为了使哲学成为一分钟,通过使用向量化调用,可以更快地制作许多Matlab操作.有时这被解释为"不惜一切代价避免循环".但是,通过调用cellfun,arrayfun或(请不)eval来避免循环通常不会提高性能.有时候出于其他原因这是正确的做法......但它无助于"将代码矢量化以使其更快".


*上面的"或许"仅仅是因为我不确定Matlab的懒惰写入和其他优化会如何阻止内存使用,这似乎是递归解决方案的潜在危险.