I have a function called objective in Matlab I evaluate by writing [f, df] = objective(x, {#fun1, #fun2, ..., #funN}) in a script. The functions fun1, fun2, ..., funN have the format [f, df] = funN(x).
Inside objective I want to, for each input in my cell array called fun, evaluate the given functions using the Matlab built-in function feval as:
function [f, df] = objective(x, fun)
f = 0;
df = 0;
for i = 1:length(fun)
fhandle = fun(i);
[fi, dfi] = feval(fhandle, x);
f = f + fi;
df = df + dfi;
end
end
I get the following error evaluating my objective.
Error using feval
Argument must contain a string or function_handle.
I do not get how to come around this error.
You need to reference the elements of fun using curly braces
fhandle = fun{i};
PS
It is better not to use i and j as variable names in Matlab
Alternatively, a solution using cellfun.
A more elegant approach using cellfun
function [f df] = objective( x, fun )
[f, df] = cellfun( #(f) f(x), fun );
f = sum(f);
df = sum(df);
Note the kinky use of cellfun - the cellarray is the fun rather than the data ;-)
Related
I found this octave function, that returns a tuple in octave:
function [ret] = g(x)
ret(1, 1) = cos(x)
ret(1, 2) = sin(x)
end
I don't get the brackets why for [ret], as we are returning one variable, can you explain please? Because ret is a vector, and why vector inside a vector.
The square brackets there don’t form a vector, they collect the output variables. It is part of the function signature.
function [ret] = … is exactly the same as function ret = …. That is, the brackets are optional when there is a single return variable.
The same is true when there are no return variables, function [] = name(…) is the same as function name(…).
Say I have a two classes and a procedure that modifies either class in the same manner. How do I specify that a parameter can be either class (instead of rewriting or overloading the function for each class)? A simple example:
type
Class1[T] = object
x: T
Class2[T] = object
x: T
y: T
# this works fine
proc echoX[T](c: Class1[T]|Class2[T]) =
echo c.x
# this does not work
proc addToX[T](c: var Class1[T]|Class2[T], val: T) =
c.x += val
var c1: Class1[int]
var c2: Class2[int]
# this works fine
echoX(c1)
echoX(c2)
# this does not work
addToX(c1, 10)
addToX(c2, 100)
I get the following error.
Error: for a 'var' type a variable needs to be passed
If I use a separate procedure for each class, things work fine.
proc addToX[T](c: var Class1[T], val: T) =
c.x += val
proc addToX[T](c: var Class2[T], val: T) =
c.x += val
This is just a simple example where it's easy to rewrite the function. But I'm looking to do this for more complex classes and procedures. In some cases inheritance might be appropriate, but it doesn't seem like Nim classes can be passed as variables to procedures in place of the base class.
A bracket fixes this problem, otherwise the var just applies to Class1[T]:
proc addToX[T](c: var (Class1[T]|Class2[T]), val: T) =
You may run into another compiler bug with this later: https://github.com/nim-lang/Nim/issues/1385
Maybe in your use case object variantes or inheritance and methods will work better.
If I call a matlab function with:
func(1,2,3,4,5)
it works perfectly.
But if I do:
a=[1,2,3,4,5] %(a[1;2;3;4;5] gives same result)
then:
func(a)
gives me:
??? Error ==> func at 11
Not enough input arguments.
Line 11 in func.m is:
error(nargchk(5, 6, nargin));
I notice that this works perfectly:
func(a(1),a(2),a(3),a(4),a(5))
How can I use the vector 'a' as a parameter to a function? I have another function otherfunc(b) which returns a, and would like to use its output as a paramater like this func(otherfunc(b)).
Comma-seperated lists
(CSL) can be passed to functions as parameter list,
so what you need is a CSL as 1,2,3,4,5 constructed from an array.
It can be generated using cell array like this:
a=[1,2,3,4,5];
c = num2cell(a);
func(c{:});
Maybe you could try with nargin - a variable in a function that has the value of the number of input arguments. Since you have a need for different length input, I believe this can best be handled with varargin, which can be set as the last input variable and will then group together all the extra input arguments..
function result = func(varargin)
if nargin == 5: % this is every element separately
x1 = varargin{1}
x2 = varargin{2}
x3 = varargin{3}
x4 = varargin{4}
x5 = varargin{5}
else if nargin == 1: % and one vectorized input
[x1 x2 x3 x4 x5] = varargin{1}
I've written x1...x5 for your input variables
Another method would be to create a separate inline function. Say you have a function f which takes multiple parameters:
f = f(x1,x2,x3)
You can call this with an array of parameter values by defining a separate function g:
g = #(x) f(x(1),x(2),x(3))
Now, if you have a vector of parameters values v = [1,2,3], you will be able to call f(v(1),v(2),v(3)) using g(v).
Just make the function take a single argument.
function result = func(a)
if ~isvector(a)
error('Input must be a vector')
end
end
Since arguments to functions in Matlab can themselves be vectoes (or even matrices) you cannot replace several arguments with a single vector.
If func expects 5 arguments, you cannot pass a single vector and expect matlab to understand that all five arguments are elements in the vector. How can Matlab tell the difference between this case and a case where the first argument is a 5-vector?
So, I would suggest this solution
s.type = '()';
s.subs = {1:5};
func( subsref( num2cell( otherfunc(b) ), s ) )
I'm not sure if this works (I don't have matlab here), but the rationale is to convert the 5-vector a (the output of otherfunc(b)) into a cell array and then expand it as 5 different arguments to func.
Please not the difference between a{:} and a(:) in this subsref.
You could create a function of the following form:
function [ out ] = funeval( f, x )
string = 'f(';
for I = 1:length(x)
string = strcat( string, 'x(' , num2str(I), '),' );
end
string( end ) = ')';
out = eval( string );
end
In which case, funeval( func, a ) gives the required output.
Use eval:
astr = [];
for i=1:length(a)
astr = [astr,'a(',num2str(i),'),']; % a(1),a(2),...
end
astr = astr(1:end-1);
eval(['func(' astr ');']);
When I pass a function (let's call it f) into my Base function , the Base function doesn't recognize
the f function , without using '' quotes , here's the code :
function y = test(a, b, n ,f)
if ( rem(n,2) ~= 0 )
error ( 'n is not even' )
end
% create a vector of n+1 linearly spaced numbers from a to b
x = linspace ( a, b, n+1 );
for i = 1:n+1
% store each result at index "i" in X vector
X(i) = feval ( f, x(i) );
end
y=sum(X);
end
And this is f.m :
function [y] = f (x)
y = 6-6*x^5;
When I run from command line with quotes :
>> [y] = test(0,1,10,'f')
y =
52.7505
but when I remove them :
>> [y] = test(0,1,10,f)
Error using f (line 2)
Not enough input arguments.
Where is my mistake ? why can't I execute [y] = test(0,1,10,f) ?
Thanks
The function feval expects either the function name (i.e., a string) or a function handle as input. In your code, f is neither a name, nor a handle. Use either the string 'f' or the handle #f when calling your base function test.
If, as posted in the comments, function handles are not allowed per assignment in the call to the base function, you can still use the function handle to create a string with the name of the function. This functionality is provided by the function func2str:
functionName = func2str(#f);
test(0,1,10,functionname);
Try passing #f as the argument instead of 'f', and also change the line to
X(i) = f(x(i));
The thing is that just f is not a function handle. Also there's no need to use feval in this case.
Consider a function varargout = foo(varargin). I know how to format a comma separated list so we can generate varargin automatically. E.g. [x y z] = ndgrid(-1:1,-1:1,-1:1) is equivalent to:
inp = repmat({-1:1},[1 3]);
[x y z] = ndgrid(inp{:});
My question is: how do I obtain the output (x,y,z in the example) automatically? I.e.,
out = ndgrid(inp{:});
PS: I would like to avoid using eval.
It looks like this should work:
out = cell(size(inp));
[out{:}] = ndgrid(inp{:});