How to get all outputs (MatLab)? - matlab

Suppose I have a function that gives out unknown number of output arguments (it depends on input,thus change through the loops). How to get all of them?
nargout doesn't help as the function uses varargout (the result is -1)
And of course I can't rewrite the function, otherwise the question wouldn't arise :- )

Well, thanks to all partisipated in discussion. Summing up, it seems the problem has no general solution, because MatLab itself estimates the number of desired outputs before the function call to use inside it. Three cases can be pointed out though:
1) The funcrion doesn't have varargout in definition, thus nOut=nargout(#fcn) returns positive number.
Then nOut is an actual number of outputs and we can use a cell array and a column list trick.
X=cell(1,nOut);
[X{:}]=fcn(inputs);
2) The funcrion has varargout in definition, thus nOut=nargout(#fcn) returns negative number. However some correlation with inputs can be found (like length(varargin)=length(varargout)).
Then we can calculate the resulting nOut from inputs and perform the above column list trick.
3) You know the fcn developer.
Ask him fot assistance. For example to make the function's output to be a cell array.

One of ways I usually use in this case is to store all outputs in a cell array inside the function. Getting the cell array outside the function's body, you might investigate its length and other properties.

Here is how you could deal with the problem in general. I didn't mention this solution earlier because... it is horrible.
Suppose a function can have 1 or 2 output arguments:
try
[a, b] = f(x)
catch
a = f(x)
end
Of course it is possible to do this for any number of output arguments, but you really don't want to.

Related

How to write an anonymous function with a variable number of output arguments?

Using deal we can write anonymous functions that have multiple output arguments, like for example
minmax = #(x)deal(min(x),max(x));
[u,v] = minmax([1,2,3,4]); % outputs u = 1, v = 4
But if you want to provide a function with its gradient to the optimization function fminunc this does not work. The function fminunc calls the input function sometimes with one and sometimes with two output arguments. (EDIT: This is not true, you just have to specify whether you actually want to use the gradient or not, using e.g. optimset('SpecifyObjectiveGradient',true). Then within one call it always asks for the same number of arguments.)
We have to provide something like
function [f,g] = myFun(x)
f = x^2; % function
g = 2*x; % gradient
which can be called with one or two output arguments.
So is there a way to do the same inline without using the function keyword?
Yes there is, it involves a technique used in this question about recursive anonymous functions. First we define a helper function
helper = #(c,n)deal(c{1:n});
which accepts a cell array c of the possible outputs as well as an integer n that says how many outputs we need. To write our actual function we just need to define the cell array and pass nargout (the number of expected output arguments) to helper:
myFun = #(x)helper({x^2,2*x,2},nargout);
This now works perfectly when calling fminunc:
x = fminunc(myFun,1);
The OP's solution is good in that it's concise and useful in many cases.
However, it has one main shortcoming, in that it's less scalable than otherwise possible. This claim is made because all functions ({x^2,2*x,2}) are evaluated, regardless of whether they're needed as outputs or not - which results in "wasted" computation time and memory consumption when less than 3 outputs are requested.
In the example of this question this is not an issue because the function and its derivatives are very easy to compute and the input x is a scalar, but under different circumstances, this can be a very real issue.
I'm providing a modified version, which although uglier, avoids the aforementioned problem and is somewhat more general:
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)...
);
Notes:
The additional functions I use are cellfun, evalin and feval.
The 'UniformOutput' argument was only added so that the output of cellfun is a cell (and can be "unpacked" to a comma-separated list; we could've wrapped it in num2cell instead).
The evalin trick is required since in the myFun scope we don't know how many outputs were requested from unpacker.
While eval in its various forms (here: evalin) is usually discouraged, in this case we know exactly who the caller is and that this is a safe operation.

bsxfun() Invalid output dimensions

I have a function that takes upto seven arguments and returns a row vector. The first three arguments are vectors (column, column, row) and the remaining four are optional scalars.
I want to use bsxfun() to apply the function to a vector of its last argument. Below is my attempt to do that.
o = #(m,pulse,N0,samples_per_pulse,sample_select,filter,channel_cutoff) ELE452Functions.EvaluateBER(m,pulse,N0,samples_per_pulse,sample_select,filter,channel_cutoff);
oo = #(m,pulse,N0,samples_per_pulse,sample_select,filter,channel_cutoff) bsxfun(#(N0,channel_cutoff) o(m,pulse,N0,samples_per_pulse,sample_select,filter,channel_cutoff), N0' , channel_cutoff);
when I try to call the function with a vector, oo(m,pulse,N0,1,1,1,[0.5 0.2]); for example, I get this error:
Error using bsxfun
Invalid output dimensions.
I am not experienced in using bsxfun and I tried to follow the documentation.
Update:
May be this is a clearer way to ask my question:
I want to use bsxfun to rewrite (improve) the code below with out a loop.
for i=1:length(channel_normalized_cuttoffs)
BER_LPchannel(i,:) = ELE452Functions.EvaluateBER(m,pulse,N0,1,1,1,channel_normalized_cuttoffs(i));
end
The idea behind bsxfun is to evaluate a certain function for all possible combinations of two elements (b in bsxfun stands for binary), each coming from one of the arrays. (NB: This is valid if you use it with a row and a column vector. But bsxfun can also do more.)
What you want to achieve is simply: For all entries of a single array, evaluate a function.
So bsxfun is just not the correct choice here.
You could use arrayfun instead, but this still may not perform a lot better than your original for loop, as it looks like the Matlab JIT Compiler would be able to optimize most of it, considering it's simplicity.
As I don't have the code of your function, I'm not able to test it, but your solution might look a lot like this:
evalBER = #(CNcutoffi) ELE452Functions.EvaluateBER(m,pulse,N0,1,1,1,CNcutoffi);
BER_LPchannel = arrayfun(evalBER, channel_normalized_cuttoffs, 'UniformOutput', false)

Number of outputs from constant anonymous function (anonymous function not known a priori)

This question may initially appear similar to this other question but my situation is a little bit different.
I have a function 'deriv' that takes a symbolic expression as its input, then takes the first derivative of that symbolic expression. That derivative is then converted into an anonymous function using matlabFunction(), and is then evaluated over an array of points. I also use the anonymous function later in some other code.
The problem I'm having is that sometimes the input symbolic expression happens to be linear, and thus the derivative is constant; therefore the anonymous function is also a constant. When I evaluate the anonymous function over the array of points, I only get one output instead of an array of outputs.
Here's some code showing what I'm doing. For the sake of simplicity here, let's assume that the symbolic input expressions will involve only one symbolic variable called q.
function[derivFun,derivVals] = deriv(input)
derivSym = diff(input,q);
derivFun = matlabFunction(derivSym,'vars',q);
evalPoints = [1;2;3;4;5]; %in my true application, a much larger array
derivVals = derivFun(evalPoints);
end
So if the input is q^2, then the output derivVals will be [2;4;6;8;10]. But if the input happens to be, say, 3*q, then derivVals will be 3 (just a single scalar). What I'd like is for derivVals to be [3;3;3;3;3].
That is, I'd like derivVals to be the same size as evalPoints even if the input function happens to be linear (or constant). And I don't know ahead of time what the input expression will be.
Can anyone give suggestions for a scheme that would do that? I understand that a constant anonymous function will just return a single constant scalar, regardless of the size of its input. What I'm hoping for is perhaps some way to recognize when the anonymous function is constant and then still cause derivVals to be the same size as evalPoints.
I know that I could use a for loop to evaluate derivFun for every row of evalPoints, but I'd like to avoid using such a loop if possible.
Thank you for your time and consideration.
I think that this is a slightly simpler solution. The issue is that you're using matlabFunction, which simplifies down the equations and doesn't allow much customization. However, you can create an anonymous function of an anonymous function. Just add the this line right after your matlabFunction line:
derivFun = #(evalPoints)derivFun(evalPoints)+zeros(size(evalPoints));
This only evaluates the original derivFun once. However, I do like you symvar solution (just remember that adding zeros is always better than multiplying ones).
Not 100% sure I got the problem correctly.
Would this solve your issue?:
if isscalar(derivVals)
derivVals = repmat(derivVals, size(evalPoints));
end

When using a multiple-output matlab function, do i need to callback all variables?

When using a multiple-output matlab function, do i need to callback all variables? or can I just take the first two variables? (if so..is it not recommended?)
lets say in function.m
[a, b, c] = function( )
in main.m
[var1, var2] = function;
When calling (almost) any function in matlab you can request fewer outputs than it specifies. So, yes the example you give should work perfectly fine.
There are some clever things you can do with this, such as using nargout within a function to see how many output arguments have been requested and only calculating the values that have been requested as an optimisation trick.
It depends on the definition of the function, and exactly which of the outputs you want to get.
Not all the function allow to do it, you can find all the options for each function in the beginning of the help documentation on the specific function.
If you want only the 2nd, or 3rd outputs, and you want also to save the computation-time of the results that does not interesting, you can use ~ option, like this (for versions 2009b and later):
[~, var1, var2]=function
Many functions allow for options to passed that change how the function behaves. I used/wrote various numerical solving functions a bit and one that nice amount of option, for instance is the LSMR function(s).
Otherwise, if you can manipulate the original either introduce an input(s) to do so before or at the end with an inline subroutine to generate the outputs you want.
Or if you can't it will return as either a cell array or a vector and you can pass an anonymous function to generate the desired outputs that way.
Really, can be done many ways. Very contextual.

Capture all possible outputs based on variable number of inputs.

I would like Matlab to return all the outputs from a variable input function. For instance,
[varargout]=cpd_intersect(varargin{:});
This only returns the last output but I know the function is defined to give multiple outputs.
Instead of defining dummy variables A, B , C etc in [A,B,C...]=pd_intersect(varargin{:}). I would like something like a cell to store all the output values based on the input number of values. I hope this makes sense. Many thanks in advance.
I know this is late, but I think this is what you want:
function [varargout] = myfun(f, varargin)
% apply f to args, and return all its outputs
[ x{1:nargout(f)} ] = f(varargin{:}); % capture all outputs into a cell array
varargout = x; % x{:} now contains the outputs of f
The insight here is that
NARGOUT can operate on functions and returns their maximum number of outputs
using [ X{1:2} ] = ...on the left hand side when X is undefined, is equivalent to doing [ X{1} X{2} ] = ..., and can capture 2 separate outputs into individual variables.
Two points to note:
this works for anonymous functions too! e.g. #(x)eig(x)
it won't work for functions that use varargout, i.e. functions with truly variable numbers of outputs. If this is the case then there should be a way to calculate how many outputs you are going to have, e.g. using nargin.
PS I learnt this from #gnovice, If a MATLAB function returns a variable number of values, how can I get all of them as a cell array?
You can do this by returning a cell array
I see you cannot force a variable comma separated output list in Matlab. Pity. It would be useful. It seems I have to explicitly assign each output. This sucks since I do not know beforehand the number of outputs I will get.