fla*_*awr 6 matlab anonymous-function variadic-functions function-handle output
使用deal我们可以编写具有多个输出参数的匿名函数,例如
minmax = @(x)deal(min(x),max(x));
[u,v] = minmax([1,2,3,4]); % outputs u = 1, v = 4
Run Code Online (Sandbox Code Playgroud)
但是如果你想为优化函数提供一个具有渐变的函数,那么fminunc这不起作用.该函数 (编辑:这不是真的,你只需要指定你是否真的想要使用渐变,使用例如fminunc有时会调用输入函数,有时会调用两个输出参数.optimset('SpecifyObjectiveGradient',true).然后在一次调用中它总是要求相同数量的参数.)
我们必须提供类似的东西
function [f,g] = myFun(x)
f = x^2; % function
g = 2*x; % gradient
Run Code Online (Sandbox Code Playgroud)
可以使用一个或两个输出参数调用.
那么有没有办法在不使用function关键字的情况下进行同样的内联?
是的,它涉及一个关于递归匿名函数的问题中使用的技术.首先,我们定义一个辅助函数
helper = @(c,n)deal(c{1:n});
Run Code Online (Sandbox Code Playgroud)
它接受c可能输出的单元数组以及一个n表示我们需要多少输出的整数.要编写我们的实际函数,我们只需要定义单元格数组并将nargout(预期输出参数的数量)传递给helper:
myFun = @(x)helper({x^2,2*x,2},nargout);
Run Code Online (Sandbox Code Playgroud)
这现在在调用时非常有效fminunc:
x = fminunc(myFun,1);
Run Code Online (Sandbox Code Playgroud)
该OP的解决方案是因为它的简洁好的,有用在许多情况下。
但是,它有一个主要缺点,那就是它的可扩展性比其他方式差。提出这项声明是因为{x^2,2*x,2}评估了所有函数(),无论是否需要将它们用作输出-当请求少于3个输出时,这将导致“浪费”的计算时间和内存消耗。
在此问题的示例中,这不是问题,因为函数及其派生函数很容易计算,并且输入x是标量,但是在不同情况下,这可能是一个非常现实的问题。
我提供的是一个修改后的版本,尽管较丑陋,但可以避免上述问题,并且更通用一些:
funcs_to_apply = {@(x)x.^2, @(x)2*x, @(x)2};
unpacker = @(x)deal(x{:});
myFun = @(x)unpacker(cellfun(@(c)feval(c,x),...
funcs_to_apply(1:evalin('caller','nargout')),...
'UniformOutput',false)...
);
Run Code Online (Sandbox Code Playgroud)
笔记:
cellfun,evalin以及feval。'UniformOutput'论点是只增加使输出cellfun是细胞(可以是“解包”的逗号分隔的列表,我们可以在已经包裹它num2cell代替)。evalin是必需的技巧,因为在myFun范围内,我们不知道从中请求了多少输出unpacker。eval各种形式(此处evalin为:),但在这种情况下,我们确切知道呼叫者是谁,这是安全的操作。