I have defined an array of anonymous functions in side a function as shown below.
function test(x,y)
f={#(x,y) (3*y*x^2)
#(x,y) (x*y)
#(x,y) (x*2*y^2)
#(x,y) (2*x*y)}
res2=f{2}(x,y)-2*f{1}(x,y)
res3=f{3}(x,y)-5*f{2}(x,y)
res4=f{4}(x,y)-4*f{2}(x,y))
end
I want to obtain a 3 by 10 matrix via
x=2
y=linspace(0.0001,0.001,10)
for i=1:length(y)
final(i)=test(x,y(i));
end
However, I get an error stating there are too many input variables. How could I correct this?
function test(x,y)
This function returns nothing. So in your main code, you are asking too many output arguments.
You define functions that return as:
function [output1, output2 , ... , outputn]=f(input1, input2, ... , inputn)
Not sure in your case what you want, as your main loop only captures 1 output, yet inside the function you compute 3 variables.
Related
In Matlab page array provided a simple method to extend a scalar function $func$ to vector and matrix(and high dimensional tensor), i.e.
B = arrayfun(func,A)
However, when I attempted to do the same, it returned an error
function [output_matrix]=func(y1_matrix)
output_matrix = arrayfun( func_elementwise ,y1_matrix);
function [output_x]=func_elementwise(x1)
% a scalar function
...(Arguments that had been verified worked)
end
end
when I attempted to run the function, it returned
Not enough input arguments.
Error in func/func_elementwise
x1=mod(x1,2*pi)-pi;
Error in func
output_matrix = arrayfun( func_elementwise ,y1_matrix);
Could you tell me what went wrong? why arrayfun did not work for func_elementwise? (the attempted inputs for func were scalar and 1*N matrix, both did not work. )
In your code,
arrayfun(func_elementwise,y1_matrix)
you call the function func_elementwise without arguments:
func_elementwise
is the same as
func_elementwise()
You need to pass a function handle to arrayfun, like so:
arrayfun(#func_elementwise,y1_matrix)
In that case you need to pass func_elementwise as a function handle to arrayfunc:
arrayfun(#func_elementwise, y1_matrix)
Further details in Matlab Help:
https://www.mathworks.com/help/matlab/ref/arrayfun.html
https://www.mathworks.com/matlabcentral/answers/226399-arrayfun-with-a-function-that-takes-multiple-inputs
I have a use case as follows:
Inside F.m I have a function F that takes as its argument a 2 x 1 matrix x. F needs to matrix multiply the matrix kmat by x. kmat is a variable that is generated by a script.
So, what I did was set kmat to be global in the script:
global kmat;
kmat = rand(2);
In F.m:
function result = F(x)
global kmat;
result = kmat*x;
end
Then finally, in the script I have (x_0 has already been defined as an appropriate 2 x 1 matrix, and tstart and tend are positive integers):
xs = ode45(F, [tstart, tend], x_0);
However, this is causing the error:
Error using F (line 3)
Not enough input arguments.
Error in script (line 12)
xs = ode45(F, [tstart, tend], x_0);
What is going on here, and what can I do to fix it? Alternatively, what is the right way to pass kmat to F?
Firstly, the proper way to handle kmat is to make it an input argument to F.m
function result = F(x,kmat)
result = kmat*x;
end
Secondly, the input function to ode45 must be a function with inputs t and x (possibly vectors, t is the dependent variable and x is the dependent). Since your F function doesn't have t as an input argument, and you have an extra parameter kmat, you have to make a small anonymous function when you call ode45
ode45(#(t,x) F(x,kmat),[tstart tend],x_0)
If your derivative function was function result=derivative(t,x), then you simply do ode45(#derivative,[tstart tend],x_0) as Erik said.
I believe F in ode45(F,...) should be a function handle, i.e. #F. Also, you can have a look at this page of the MATLAB documentation for different methods to pass extra parameters to functions.
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]
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.
I'm currently coding a simulation in MATLAB and need some help in regards to an issue that I've been having.
I'm working on a problem where I have n separate anonymous function handles fi stored in cell array, each of which accepts a 1×1 numeric array xi and returns a 1×1 numeric array yi.
I'm trying to combine each of these anonymous function handles into a single anonymous function handle that accepts a single n×1 numeric array X and returns a single n×1 numeric array Y, where the i-th elements of X and Y are xi and yi = fi (xi), respectively.
As an example, let n = 2 and f_1, f_2 be two function handles that input and output 1×1 arrays and are stored in a cell array named functions:
f_1 = #(x_1) x_1^2
f_2 = #(x_2) x_2^3
functions = {f_1, f_2}
In this example, I basically need to be able to use f_1 and f_2 to construct a function handle F that inputs and outputs a 2×1 numeric array, like so:
F = #(x) [f_1(x(1,1)); f_2(x(2,1))]
The question is how to generalize this for an arbitrary number n of such functions.
It is difficult to define such a function using the inline #()-anonymous
syntax (because of the requirement for the function’s body to be
an expression).
However, it is possible to define a regular function that runs over
the items of a given vector and applies the functions from a given
cell array to those items:
function y = apply_funcs(f, x)
assert(length(f) == length(x));
y = x;
for i = 1 : length(f)
y(i) = feval(f{i}, x(i));
end
end
If it is necessary to pass this function as an argument to another
one, just reference it by taking its #-handle:
F = #apply_funcs
This can be solved using a solution I provided to a similar previous question, although there will be some differences regarding how you format the input arguments. You can achieve what you want using the functions CELLFUN and FEVAL to evaluate your anonymous functions in one line, and the function NUM2CELL to convert your input vector to a cell array to be used by CELLFUN:
f_1 = #(x_1) x_1^2; %# First anonymous function
f_2 = #(x_2) x_2^3; %# Second anonymous function
fcnArray = {f_1; f_2}; %# Cell array of function handles
F = #(x) cellfun(#feval,fcnArray(:),num2cell(x(:)));
Note that I used the name fcnArray for the cell array of function handles, since the name functions is already used for the built-in function FUNCTIONS. The colon operator (:) is used to turn fcnArray and the input argument x into column vectors if they aren't already. This ensures that the output is a column vector.
And here are a few test cases:
>> F([2;2])
ans =
4
8
>> F([1;3])
ans =
1
27
#you can try
f=#(x)[x(1)^2;x(2)^3]
>>f([1,2])
ans =
1
8
>>f([2,3])
ans =
4
27