Multiple outputs from anonymous function

I have a function of the following form
function [out1, out2] = demo_fcn( in )
out1 = in(1);
out2 = in(2);
end
which gets called by
[out1, out2] = @(x) demo_fcn(x);
but anonymous functions are not allowed more than one outputs. This is clearly a simplified example, the application is for a nonlinear programming problem where out1 is the objective function and out2 is the gradient calculation. I am not sure how I can structure this differently or in a way which is acceptable by MATLAB syntax.
Note the error messge is
Only functions can return multiple values.

3 comentarios

Stephen23
Stephen23 el 10 de Dic. de 2019
Editada: Stephen23 el 10 de Dic. de 2019
"...which gets called by [out1, out2] = @(x) demo_fcn(x);"
But what you show is not calling any function: that line appears to be a syntactically-incorrect anonymous function definition... but it certainly does not call any function.
Is that really the code that you are trying? If so, then it appears that you might be getting confused between defining the function handle and calling the function handle.
"...but anonymous functions are not allowed more than one outputs."
Who told you that? Two output arguments worked perfectly when I tried just now:
>> fun = @(x) size(x);
>> [R,C] = fun(ones(2,3))
R =
2
C =
3
Morten Nissov
Morten Nissov el 10 de Dic. de 2019
Editada: Morten Nissov el 10 de Dic. de 2019
I mean the error message did, but I can see i may have misunderstood it.
The purpose of the code is that I need to calculate an objective function and it's gradients with respect to an unknown value "u' such that the optimizer can solve for this "u".
For example my earlier implementation when I only required the objective function and not the gradients was
objfun = @(x) get_obj(x)
I guess the problem is I'm not quite sure how to adapt the previous version above to also create and output the gradients.
Edit: The intention is to use this in conjunction with fmincon by the way.
Guillaume
Guillaume el 10 de Dic. de 2019
So, I'm a bit unclear on what you are asking.
As pointed out by Stephen, anonymous functions can return more than one output (as long as the function delegates the actual processing to a function that returns more than one output).
Yes, some functions such as your demo_fun can't be implemented as an anonymous function since it's made of two statements and anonymous functions in matlab are limited to one non-branching statement. However, you're never forced to use anonymous functions, they're just syntactic sugar that can always be replaced by named functions. You can pass a handle to your demo_fun to fmincon and others, so why can't you use demo_fun as you have written it?

Iniciar sesión para comentar.

Respuestas (5)

Pritesh Mody
Pritesh Mody el 4 de Mayo de 2022
Editada: Pritesh Mody el 4 de Mayo de 2022

1 voto

The built-in "deal" function allows this. There is an example in the help for deal.
Star Strider
Star Strider el 10 de Dic. de 2019
One option is to have the two outputs to one vector, then separate them in a subsequent assignment:
demo_fcn = @(in) [in(1) in(2)];
in = rand(2,1)
Out = demo_fcn(in)
Out1 = Out(1)
Out2 = Out(2)
This works, however I cannot tell if it does what you want it to do.

3 comentarios

This doesn't quite do what I want, I should maybe explain the problem a little more clearly.
The demo_fcn in question is meant to be calculating the objective function as well as its gradients for the unknown variable x such that it can be solved using a nonlinear minimizer like fmincon.
A more concrete example would probably have been
psi = @(u) objfun(u)
function [ psi ] = objfun( u )
psi = sum(u.^2)
end
where this is the original function and I would like to expand it to also return a calculation for the gradients of psi, resembling
[psi, grad_psi] = @(u) objfun(u)
function [ psi,grad_psi ] = objfun( u )
psi = sum(u.^2)
grad_psi = diff(psi,u); % poor example of gradient fcn; but same purpose
end
Star Strider
Star Strider el 10 de Dic. de 2019
O.K.
The approach I used would clearly not allow concatenation such as that unless the outputs of the two sub-functions were in cell arrays. That adds the additional complication of recovering the double array from the cell array, however that is not diffcult.
I encourage you to experiment with that approach.
Benjamin
Benjamin el 13 de Nov. de 2024
Was this solved in the end? I'm trying to implement the same code.

Iniciar sesión para comentar.

gotjen
gotjen el 25 de Jun. de 2021
Editada: Walter Roberson el 4 de Mayo de 2022
Hey Morten, even though its years later I want to give you my solution to this problem. I use the matlab function disperse ( https://www.mathworks.com/matlabcentral/fileexchange/33866-disperse ) which is availble on the File Exchange but should absoutely become a built in function.
disperse splits arrays into multiple output arguments. You can use it to conveniently get multple outputs from an anonymous function
f = @(x) disperse( [x, 2*x] )
[a, b] = f(1:10)
% a = [ 1 2 ... 10 ];
% b = [ 2 4 ... 20 ];
Nice pet example but lets do something useful with it.
Say we have a structure array, and we want to get the 3rd element from two vector members of that structure. We want to get them out as two arrays
% data is some large data structure we use to pass around parameters for
% our model.
[A, B] = arrayfun( @(s) disperse([ s.wavelength(3), s.absorption(3)]), data);
This one-liner avoids some ugly for-loop when all we want to do is slice our data structure in an unusual way.

1 comentario

One-liner without any third party functions:
f = @(x) deal(x, 2*x);
[a, b] = f(1:10)
a = 1×10
1 2 3 4 5 6 7 8 9 10
b = 1×10
2 4 6 8 10 12 14 16 18 20

Iniciar sesión para comentar.

Renwen Lin
Renwen Lin el 18 de Dic. de 2022
try this
@(x1,x2)deal(x1+1,x2+1)
% T2 = grouptransform_easy(T, {'HA','HB'},@(x1,x2)deal(x1+1,x2+1),{'Grade','Name'},["Province","City"]);
When you define an anonymous function, assign it to one output.
f = @(x) svd(x, "econ") % Define f
f = function_handle with value:
@(x)svd(x,"econ")
When you call an anonymous function you can call it with however many outputs you want (that the code inside the anonymous function supports.) So since svd can return up to three ouptuts:
A = [1 2 3 4; 5 6 7 8; 9 10 11 12];
[U, S, V] = f(A) % Call f
U = 3×3
-0.2067 -0.8892 0.4082 -0.5183 -0.2544 -0.8165 -0.8298 0.3804 0.4082
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
S = 3×3
25.4368 0 0 0 1.7226 0 0 0 0.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
V = 4×3
-0.4036 0.7329 0.5110 -0.4647 0.2898 -0.8283 -0.5259 -0.1532 0.1236 -0.5870 -0.5962 0.1937
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[checkU, checkS, checkV] = svd(A, "econ") % Show that f did call svd with 3 outputs
checkU = 3×3
-0.2067 -0.8892 0.4082 -0.5183 -0.2544 -0.8165 -0.8298 0.3804 0.4082
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
checkS = 3×3
25.4368 0 0 0 1.7226 0 0 0 0.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
checkV = 4×3
-0.4036 0.7329 0.5110 -0.4647 0.2898 -0.8283 -0.5259 -0.1532 0.1236 -0.5870 -0.5962 0.1937
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
This code from the original question didn't work because it tried to specify multiple outputs when defining the function and that won't work. [I'm commenting it out so it doesn't error when I run the code in my answer.]
% [out1, out2] = @(x) demo_fcn(x);

Categorías

Más información sobre Creating and Concatenating Matrices en Centro de ayuda y File Exchange.

Productos

Versión

R2019a

Etiquetas

Preguntada:

el 10 de Dic. de 2019

Respondida:

el 13 de Nov. de 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by