Matlab: Detect number of input arguments for function handle from outside of the function - matlab

I begin with a symbolic function of one variable, calculate the symbolic derivatives of orders 1 through N, and then convert those symbolic functions into function handles and store the function handles in a cell array. I then evaluate each function handle at the same input value using a loop. The problem I have is that it is possible for one of the derivatives to be a constant (with higher order derivatives being zero, of course). As I was trying to give each function handle an input, I face the "Too many input arguments" error. I would like to be able to check, in advance, whether the function handle is a constant so I can avoid the error, but I can't figure out how to do that.
In case a small working example is helpful, I provide the following
symVar = sym('symVar');
startFunc = symVar^4 + symVar^3 + symVar^2;
derivesCell = cell(5);
for J=1:5
derivesCell(J) = {matlabFunction(diff(startFunc,symVar,J))};
end
cumSum = 0;
evalPoint = 2;
for J=1:5
cumSum = cumSum + derivesCell{J}(evalPoint);
end
Execution produces "Error using symengine>#()2.4e1
Too many input arguments."

tl;dr: You can do this with nargin:
>> nargin(derivesCell{5})
ans =
0
>> nargin(derivesCell{3})
ans =
1
Explanation:
Most people are familiar with the use of nargin as a "special variable" inside the function, but it can be used outside the context of a function definition, as a function that takes a function_handle argument, returning the number of input arguments that function handle takes. From the documentation:
NARGIN(FUN) returns the number of declared inputs for the
M-file function FUN. The number of arguments is negative if the
function has a variable number of input arguments. FUN can be
a function handle that maps to a specific function, or a string
containing the name of that function.

Related

Matlab parsing at run-time of function handles

My Question: Given a function handle, does matlab parse the string each time it needs to evaluate it, or just once and then it caches it?
Example
Consider the ingenious function
function [] = foo(func)
for j=1:1e4
func(j);
end
and the script
func1 = #(x) 5*abs(x)^2
function foo(func1);
At run-time, Matlab needs to interpret #(x) 5*abs(x)^2 as a function. In this example, does it do it once, or a thousand times?
First of all #(x)cos(x) is not a string, it is an anonymous function declaration. When you create an anonymous function, MATLAB essentially creates a function object which contains all of the information it needs to run. This anonymous function can then be passed around to various functions or even saved to a file. As such, it is only constructed once and evaluated many times.
When evaluated, MATLAB does not do any caching, so calling the same anonymous function with the same inputs many times causes the contents of the anonymous function to be evaluated each time.
If you want to get more information about your anonymous function, including the local workspace of the function, you can use the functions function
f = #(x)cos(x);
functions(f)
% function: '#(x)cos(x)'
% type: 'anonymous'
% file: ''
% workspace: {[1x1 struct]}
% within_file_path: '__base_function'
That being said, in your example, it could really be reduced to a function handle rather than an anonymous function since you pass all input arguments directly to cos without modifying them. As you can see, this has a different internal representation and from some preliminary benchmarks, it seems to be marginally faster.
f = #cos
functions(f)
% function: 'cos'
% type: 'simple'
% file: ''
And a quick benchmark
function benchit
fprintf('Anonymous function: %0.4f\n', timeit(#option1));
fprintf('Function handle: %0.4f\n', timeit(#option2));
end
function option2()
f = #(x)cos(x);
for k = 1:10000
f(k);
end
end
function option1()
f = #cos;
for k = 1:10000
f(k);
end
end
And the results (not really a huge difference)
Anonymous function: 0.0056
Function handle: 0.0049
A few more things
When creating the anonymous function, the anonymous function declaration must still adhere to all of MATLAB's standard syntax rules otherwise it won't be created. For example, the following would throw an error during anonymous function creation since it is invalid syntax
func = #(x)thing]
Error: Unbalanced or unexpected parenthesis or bracket.
When you evaluate an anonymous function (after it's successful creation), it's just like evaluating any other function in that the anonymous function can throw an error and the error depends upon the input.
func = #(x) x + [1 2];
func([3 4])
% 4 6
% Now we're going to pass an array that isn't 1 x 2
func([5 6 7])
Matrix dimensions must agree.
Error in #(x)x+[1,2]

Create function with given number of input arguments

Here's the situation:
I need to create a function that takes a function handle fun which is of CONSTANT input-length (that is nargin(fun)>=0), does some transformation on the inputs and then calls fun.
Pseudo-Code:
function g = transformFun(fun)
n = nargin(fun);
g = #(v_1, ..., v_n) ...
% ^ NOT REAL MATLAB - THE MAIN PROBLEM
fun(someCalculationsWithSameSizeOfOutput(v_1,...v_n){:});
% CAN BE ACHIEVED WITH TEMPORARY CELL IN HELPER FUNCTION ^
end
Now the problem: the output function's handle (g = transformFun(concreteFun)) is then passed to other code that relies on the fact that the function is of constant length (assumes nargin(g)>=0), thus a variable-input-length function is unacceptable (the "easy" solution).
This transformation is called with many functions with every possible number of arguments (n is unbounded), so covering a finite number of possibilities is also not possible.
Is there a (simple?) way to achieve that?
[I've searched the internet for a few hours and could only come up with a nasty hack involving the deprecated inline function, which I couldn't make work; maybe I have the wrong terminology].
So typically you could use varargin to handle this sort of thing, but since you need nargin(g) to return the actual number of inputs it's a little trickier.
You could use str2func to create the anonymous function as a string and then convert it to a function handle.
% Create a list or arguments: x1, x2, x3, x4, ...
args = sprintf('x%d,', 1:nargin(func));
args(end) = '';
% Place these arguments into a string which indicates the function call
str = sprintf('#(%s)fun(someCalculationsWithSameSizeOfOutput(%s))', args, args);
% Now create an anonymous function from this string
g = str2func(str);
Based on the attrocity above, it may be worth considering an alternative way of dealing with your function handles.

Symbolic diff in matlab should return vector

If I have a symbolic function p(r,s) = r^3 in MATLAB, I obtain the derivatives dp/dr = 3r^2 and dp/ds = 0, but my goal is to use matlabFunction to convert these expressions to function handles, with vector inputs (r,s). I want something similar to zeros(size(s)), for the derivative dp/ds so I don't obtain a scalar output if my input (r,s) is a vector.
This code I tried:
syms r s
p = r^3
dpds = diff(p,s)
gives a scalar zero not variable size zero, i.e scalar output if we have vector input.
This is the nature of how matlabFunction works. If you provide an equation that has no independent variables as part of the equation, it will default to giving you an anonymous function with no inputs and give you a scalar result.
For example:
>> syms r s;
>> p = r^3;
>> dpds = diff(p,s);
>> dpdsFunc = matlabFunction(dpds)
dpdsFunc =
#()0.0
This will only give you a single scalar value each time. This also applies to any scalar function that gives a non-zero output. If you'd like to override this behaviour and give a variable length of this scalar that is dependent on the length of the input, you can first detect if there are any input variables in the function by checking how many variables there are. You can use symvar for that. You would check if this array has a length of 0, and if it does, you override the function.
Something like this comes to mind:
syms r s;
p = r^3;
dpds = diff(p,s);
if numel(symvar(dpds)) == 0
dpdsFunc = #(s) ones(size(s))*double(dpds); %// Thanks Daniel!
else
dpdsFunc = matlabFunction(dpds);
end
This should achieve what you want.
Minor Note
I actually think this variable length of zeroes business is something that should be put into MATLAB by default, rather than defaulting to a single value. It makes vectorizing code a lot easier. I'm tempted to submit a feature request to MathWorks in the future.

Why does MATLAB throw a "too many output arguments" error when I overload subsref (subscripted reference)?

As a toy example, I have a class that simply wraps a vector or matrix in an object and includes a timestamp of when it was created. I'm trying to overload subsref so that
() referencing works exactly as it does with the standard vector and matrix types
{} referencing works in exactly the same way as () referencing (nothing to do with cells in other words)
. referencing allows me to access the private properties of the object and other fields that aren't technically properties.
Code:
classdef TimeStampValue
properties (Access = private)
time;
values;
end
methods
%% Constructor
function x = TimeStampValue(values)
x.time = now();
x.values = values;
end
%% Subscripted reference
function x = subsref(B, S)
switch S.type
case '()'
v = builtin('subsref', B.values, S);
x = TimeStampValue(v);
case '{}'
S.type = '()';
v = builtin('subsref', B.values, S);
x = TimeStampValue(v);
case '.'
switch S.subs
case 'time'
x = B.time;
case 'values'
x = B.values;
case 'datestr'
x = datestr(B.time);
end
end
end
function disp(x)
fprintf('\t%d\n', x.time)
disp(x.values)
end
end
end
However brace {} referencing doesn't work. I run this code
clear all
x = TimeStampValue(magic(3));
x{1:2}
and I get this error:
Error using TimeStampValue/subsref
Too many output arguments.
Error in main (line 3)
x{1:2}
MException.last gives me this info:
identifier: 'MATLAB:maxlhs'
message: 'Too many output arguments.'
cause: {0x1 cell}
stack: [1x1 struct]
which isn't helpful because the only thing in the exception stack is the file containing three lines of code that I ran above.
I placed a breakpoint on the first line of the switch statement in subsref but MATLAB never reaches it.
Whats the deal here? Both () and . referencing work as you would expect, so why doesn't {} referencing work?
When overloading the curly braces {} to return a different number of output arguments than usual, it is also necessary to overload numel to return the intended number (1, in this case). UPDATE: As of R2015b, the new function numArgumentsFromSubscript was created to be overloaded instead of numel. The issue remains the same, but this function should be overloaded instead of numel as I describe in the original answer below. See also the page "Modify nargout and nargin for Indexing Methods". Excerpt:
When a class overloads numArgumentsFromSubscript, MATLAB calls this method instead of numel to compute the number of arguments expected for subsref nargout and subsasgn nargin.
If classes do not overload numArgumentsFromSubscript, MATLAB calls numel to compute the values of nargout or nargin.
More explanation of the underlying issue (need to specify number of output arguments) follows.
Original answer (use numArgumentsFromSubscript instead of numel for R2015b+)
To handle the possibility of a comma separated list of output arguments when indexing with curly braces, MATLAB calls numel to determine the number of output arguments from the size of the input indexes (according to this MathWorks answer). If the number of output arguments in the definition of overloaded subsref is inconsistent with (i.e. less than) the number provided by numel, you get the "Too many output arguments" error. As stated by MathWorks:
Therefore, to allow curly brace indexing into your object while returning a number of arguments INCONSISTENT with the size of the input, you will need to overload the NUMEL function inside your class directory.
Since x{1:2} normally provides two outputs (X{1},X{2}), the definition function x = subsref(B, S) is incompatible for this input. The solution is to include in the class a simple numel method to overload the builtin function, as follows:
function n = numel(varargin)
n = 1;
end
Now the {} indexing works as intended, mimicking ():
>> clear all % needed to reset the class definition
>> x = TimeStampValue(magic(3));
>> x(1:2)
ans =
7.355996e+05
8 3
>> x{1:2}
ans =
7.355996e+05
8 3
However, overloading curly braces in this manner is apparently a "specific type of code that we [MathWorks] did not expect customers to be writing". MathWorks recommends:
If you are designing your class to output only one argument, it is not recommended that you use curly brace indexing that requires you to overload NUMEL. Instead, it is recommended you use smooth brace () indexing.
UPDATE: Interestingly, the R2015b release notes state:
Before MATLAB release R2015b, MATLAB incorrectly computed the number of arguments expected for outputs from subsref and inputs to subsasgn for some indexing expressions that return or assign to a comma-separated list.
With release R2015b, MATLAB correctly computes the values of nargout and nargin according to the number of arguments required by the indexing expression.
So perhaps this is now fixed?
An alternative solution that comes to mind is to change function x = subsref(B, S) to function varargout = subsref(B, S) and adding varargout=cell(1,numel(B)); varargout{1} = x;. As Amro noted in comments, pre-allocating the cell is necessary to avoid an error about an unassigned argument.
I just ran into the same problem. What's even worse, is that the number of output arguments is enforced to be equal to what numel() returns not only for the curly braces {}, but also for the dot . operation.
This means that if numel() is overridden to return the usual prod(size(obj)), it becomes impossible to access any properties of the underlying object (such as x.time in the above example), as subsref() is then expected to return multiple outputs.
But if numel() just returns 1 instead, it does not match prod(size(obj)), which is what most code working with numeric values or based on reshape() expects. In fact, the MATLAB editor's balloon help immediately suggests that 'NUMEL(x) is usually faster than PROD(SIZE(x))', which suggest that they are equivalent, but apparently are not.
A possible solution would be to make numel() return prod(size(obj)) and write explicit getter/setter functions for all these properties, e.g.,
x.get_time()
in the example above. This seems to work, because method calls apparently get resolved before subsref() gets called. But then if one of the properties is a matrix it cannot be directly indexed any more because Matlab doesn't understand chained indexing, i.e., instead of writing
x.matrix(1,:)
one would have to write
m = x.get_matrix();
m(1,:)
which is ugly to say the least.
This is starting to get a bit frustrating. I still hope I've just overlooked something obvious, I can't believe that this is how it's supposed to work.
This solution seems to work in 2014b (but not entirely certain why)
classdef TestClass < handle
methods
function n = numel(~,varargin)
n = 1;
end
function varargout = subsref(input,S)
varargout = builtin('subsref',input,S);
end
function out = twoOutputs(~)
out = {}; out{1} = 2; out{2} = 3;
end
end
end
Then via the command window
>> testClass = TestClass();
>> [a,b] = testClass.twoOutouts()
a =
2
b =
3
I am working on a class to handle polynomials and polynomial matrices. I was having the same dificulty because I want different behaviors for the '.' indexing in the cases of scalar polynomials and polynomial matrices.
In my case I want P.coef to return a vector of coefficients if P is a scalar polynomial. If P is a polynomial matrix, P.coef must return a cell array of the same size of P, in which the cell {i,j} contains the coefficient vector of the polynomial P(i,j).
The problem appeared when P.coef was used with a matrix. My desired behavior returns only one object as an answer, but Matlab is expecting the function to return numel(P) objects.
I found a very simple solution. When declaring subsref, I used one mandatory output and a varargout:
function [R,varargout] = subsref(P,S)
The body of the function defines R as needed, according to my design. And at the very end of the function I added:
varargout(1:nargout-1) = cell(1,nargout-1);
To just return empty matrices as the extra outputs that Matlab wants.
This should create no problem if the function is always called with a single output argument, e.g., as in R = P.coef. If the function is called without assigning, the user will see numel(P)-1 empty matrices, which is really not a big deal. Anyway, the user is warned about this in the function help.

fminsearch with vector inputs

I want to minimize this function:
function [GCV2]=GCV(y,x,k)
[n, p]=size(x);
A=(x'*x+k*eye(p));
A=A\x';
A=x*A;
I_mat=eye(n);
num2=(I_mat-A);
num2=num2*y;
num2=norm(num2);
num2=num2^2;
num2=num2/n;
%(norm((I_mat-A)*y)^2)/n;
den2=(I_mat-A);
den2=trace(den2);
den2=den2/n;
den2=den2^2;
GCV2=num2/den2;
end
The x and y values are 13-by-4) and 13-by-1 arrays, respectively, and these values are already defined in the Matlab workspace. I want to optimize on the k value so that the function value GCV is minimized.
The parameter being optimized as well as the output are scalar so fminsearch should be appropriate.
But I can't get it to run?
I've tried several methods, the latest being:
k_min = fminsearch(#GCV,(x;y;0));
??? k_min = fminsearch(#GCV,(x;y;0));
|
Error: Unbalanced or unexpected parenthesis or bracket.
What am I doing wrong?
Looks like you're learning about anonymous functions. fminsearch minimizes a single variable (which may be a vector). Your objective function must therefore have only one input. You have a function, GCV, that takes three inputs. Two are static and are defined in the workspace outside of the minimization, while k is the one to be minimized. To create a function with one input from GCV, you can use any anonymous function, taking care to specify which variables are parameters:
x = ...
y = ...
k0 = 0;
k_min = fminsearch(#(k)GCV(y,x,k),k0);
The second input to fminsearch is the starting parameter (i.e. k0), so specify a starting value of k. Then you can define an anonymous helper function and optimize on that:
>> % define x,y
>> GCVk = #(k) GCV(y,x,k);
>> k0 = 0;
>> k_min = fminsearch(GCVk,k0)
There is probably another way to do this, but this is one of the listed ways of passing additional parameters for the optimizer.
And since there are no bonus points for being first, how about humor. Let's have an example:
>> x=1; y=1;
>> GCVk = #(k) x+y+k; k0=0;
>> k_min = fminsearch(GCVk,k0)
Exiting: Maximum number of function evaluations has been exceeded
- increase MaxFunEvals option.
Current function value: -316912650057057490000000000.000000
k_min =
-3.1691e+26
Found it - the lowest number (minus 2) in the world! Profit?