Creating a function handle for each element in a vector (Matlab) - matlab

I have a following issue. I am trying to create a function handle, which is a vector. In particular, I have something like this
EQ0 = #(W) m1.^2*(exp(W))-m2.^2
where m1 and m2 are the vectors of the same dimension. So, for each m1(i) and m2(i) I want to have a handle W(i). I need it in order to find those W(i)'s in the next step using fsolve in something looking like this
n=size(m1)
x0 = zeros(n);
Wbar = fsolve(EQ0,x0)
I have tried using arrayfun, but received a following error
EQ0 = arrayfun( #(W) m1.^2*(exp(W))-m2.^2, m1=m1e, m2=m2e)
Error: The expression to the left of the equals sign is not a valid target for an assignment.
Another attempt in using arrayfun resulted in this (here I just used m1 and m2 vectors directly, not as an inputs like in previous case)
EQ0 = arrayfun( #(W) m1.^2*(exp(W))-m2.^2,:)
Undefined variable arrayfun.
I am clearly missing something. I have looked on some feeds on arrayfun but it looks like my problem is somewhat different.
Any advice is appreciated.

So if I understood you right you want to have for each m1(i) or m2(i) a seperate function handle EQ0(i) which can operate with an vector W in the following way EQ0(i) = #(W) m1(i)^2*(exp(W))-m2(i)^2. Is this correct? If so you can create a cell-array of the same dimension as m1 with a function handle in each dimension:
EQ0 = cell(size(m1));
for ii = 1:numel(m1)
EQ0(ii) = {#(W) m1(ii)^2*exp(W)-m2(ii)^2};
end
EDIT:
Another option could be:
EQ0 = #(W)arrayfun(#(Wel,m1el,m2el)m1el^2*exp(Wel)-m2el^2,W,m1,m2);
fsolve(EQ0, W_Values)
Here m1, m2 should be defined beforehand. Otherwise you have to add them as arguments of the first anonymous function.
So by calling arrayfun(#(Wel, m1el, m2el)..., W, m1, m2) you do your elementwise calculations for the entries in W, m1, m2 defined by the anonymous function handle you have passed in the first argument of arrayfun. But since you want to define your W differently each time, you make an anonymous function of that arrayfun command, which takes W as an argument.

Related

Solve a matrix valued differential equation in Matlab

I am trying to solve a particular system of ODE's dF/dt = A*F, F_initial = eye(9). Being a Matlab novice, I am trying to somehow use the implemented ode45 function, and I found useful advises online. However, all of them assume A to be constant, while in my case the matrix A is a function of t, in other words, A changes with each time step.
I have solved A separately and stored it in a 9x9xN array (because my grid is t = 0:dt:2, N=2/dt is the number of time-steps, and A(:,:,i) corresponds to it's value at the i-th time step). But I can't implement this array in ode45 to eventually solve my ODE.
Any help is welcomed, and please tell me if I have missed anything important while explaining my problem. Thank you
First of all, F must be a column vector when using ode45. You won't ever get a result by setting F_initial = eye(9), you'd need F = ones(9,1).
Also, ode45 (documentation here, check tspan section) doesn't necessarily evaluate your function at the timesteps that you give it, so you can't pre-compute the A matrix. Here I'm going to assume that F is a column vector and A is a matrix which acts on it, which can be computed each timestep. If this is the case, then we can just include A in the function passed to ode45, like so:
F_initial = ones(9,1);
dt = 0.01;
tspan = 0:2/dt:2;
[t, F] = ode45(#(t,F) foo(t, F, Ainput), tspan, F_initial);
function f = foo(t, F, Ainput)
A = calculate_A(t, Ainput);
f = A*F;
end
function A = calculate_A(t, Ainput)
%some logic, calculate A based on inputs and timestep
A = ones(9,9)*sqrt(t)*Ainput;
end
The #(x) f(x,y) basically creates a new anonymous function which allows you to treat y as a constant in the calculation.
Hope this is helpful, let me know if I've misunderstood something or if you have other questions.

Using `lsqnonlin` with vector inputs

I have a question about using the lsqnonlin function.
In my case I have two functions:
f_1=#(t,x)sin(t+x.^2);
f_2=#(t,x)cos(x.^2)+3.*t.^2;
f = {f_1, f_2};
I want to find the values of the arguments t and x which would result in the least square error, defined as: f_1(t,x)^2+f_2(t,x)^2. In other words, argmin for LSE.
My code is as follow with initial guess [1,2]:
lsqnonlin(f,[1,2])
And I'm getting the error:
Error in lsqnonlin (line 196)
initVals.F = feval(funfcn{3},xCurrent,varargin{:});
Caused by:
Failure in initial objective function evaluation. LSQNONLIN cannot continue.
lsqnonlin can be used for vector function and vector input according to the documentation. I wonder how to prepare corresponding codes for it. Could anyone suggest the solution?
You are getting an error because lsqnonlin expects a scalar function handle that maps a vector to a vector, whereas you specify a cell array of function handles. To fix this, instead of a vector of functions outputting one scalar each, you need to rewrite it into a single function that accepts a vector of inputs and also outputs a vector:
f = #(xt)[sin(xt(2)+xt(1).^2), cos(xt(1).^2)+3.*xt(2).^2];
% xt = [x,t]
% f = [f_1(xt), f_2(xt)]
so f and xt are both vectors of 2 elements.
Then, the solver works:
lsqnonlin(f,[1,2])
ans =
1.6144 0.5354

ODE solver producing runtime error - not enough input arguments [duplicate]

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.

Matlab: Meaning of #(t)(costFunction(t, X, y)) from Andrew Ng's Machine Learning class

I have the following code in MATLAB:
% Set options for fminunc
options = optimset('GradObj', 'on', 'MaxIter', 400);
% Run fminunc to obtain the optimal theta
% This function will return theta and the cost
[theta, cost] = ...
fminunc(#(t)(costFunction(t, X, y)), initial_theta, options);
My instructor has explained the minimising function like so:
To specify the actual function we are minimizing, we use a "short-hand"
for specifying functions, like #(t)(costFunction(t, X, y)). This
creates a function, with argument t, which calls your costFunction. This
allows us to wrap the costFunction for use with fminunc.
I really cannot understand what #(t)(costFunction(t, X, y) means. What are the both ts are doing? What kind of expression is that?
In Matlab, this is called an anonymous function.
Take the following line:
f = #(t)( 10*t );
Here, we are defining a function f, which takes one argument t, and returns 10*t. It can be used by
f(5) % returns 50
In your case, you are using fminunc which takes a function as its first argument, with one parameter to minimise over. This could be called using
X = 1; y = 1; % Defining variables which aren't passed into the costFunction
% but which must exist for the next line to pass them as anything!
f = #(t)(costFunction(t, X, y)); % Explicitly define costFunction as a function of t alone
[theta, cost] = fminunc(f, 0, options);
This can be shortened by not defining f first, and just calling
[theta, cost] = fminunc(#(t)(costFunction(t, X, y)), 0, options);
Further reading
As mentioned in the comments, here is a link to generally parameterising functions.
Specifically, here is a documentation link about anonymous functions.
Just adding to Wolfie's response. I was confused as well and asked a similar question here:
Understanding fminunc arguments and anonymous functions, function handlers
The approach here is one of 3. The problem the anonymous function (1 of the 3 approaches in the link below) solves is that the solver, fminunc only optimizes one argument in the function passed to it. The anonymous function #(t)(costFunction(t, X, y) is a new function that takes in only one argument, t, and later passes this value to costFunction. You will notice that in the video lecture what was entered was just #costFunction and this worked because costFunction only took one argument, theta.
https://www.mathworks.com/help/optim/ug/passing-extra-parameters.html
I also had the same question. All thanks to the the link provided by Wolfie to understand paramterized and anonymous functions, I was able to clarify my doubts. Perhaps, you must have already found your answer but am explaining once again, for people who might develop this query in the mere future.
Let's say we want to derive a polynomial, and find its minimum/maximum value. Our code is:
m = 5;
fun = #(x) x^2 + m; % function that takes one input: x, accepts 'm' as constant
x = derive(fun, 0); % fun passed as an argument
As per the above code, 'fun' is a handle that points to our anonymous function, f(x)=x^2 + m. It accepts only one input, i.e. x. The advantage of an anonymous function is, one doesn't need to create a separate program for it. For the constant, 'm', it can accept any values residing in the current workspace.
The above code can be shortened by:
m = 5;
x = derive(#(x) x^2 + m, 0); % passed the anonymous function directly as argument
Our target is to find the global optimal,so i think the function here is to get a bounch of local minimal by change the alpha and compare with each other to see which one is the best.
to achive this you initiate the fminuc with value initial_theta
fminuc set t=initial_theta then compute CostFunction(t,X,y) which is equal to` CostFunction(initial_theta,X,y).you will get the Cost and also the gradient.
fminuc will compute a new_theta with the gradient and a alpha, then set t=new_theta and compute the Cost and gradient again.
it will loop like this until it find the local optimal.
Then it change the length of alpha and repeat above to get another optimal. At the end it will compare the optimals and return with the best one.

MATLAB Function (Solving an Error)

I have one file with the following code:
function fx=ff(x)
fx=x;
I have another file with the following code:
function g = LaplaceTransform(s,N)
g = ff(x)*exp(-s*x);
a=0;
b=1;
If=0;
h=(b-a)/N;
If=If+g(a)*h/2+g(b)*h/2;
for i=1:(N-1)
If=If+g(a+h*i)*h;
end;
If
Whenever I run the second file, I get the following error:
Undefined function or variable 'x'.
What I am trying to do is integrate the function g between 0 and 1 using trapezoidal approximations. However, I am unsure how to deal with x and that is clearly causing problems as can be seen with the error.
Any help would be great. Thanks.
Looks like what you're trying to do is create a function in the variable g. That is, you want the first line to mean,
"Let g(x) be a function that is calculated like this: ff(x)*exp(-s*x)",
rather than
"calculate the value of ff(x)*exp(-s*x) and put the result in g".
Solution
You can create a subfunction for this
function result = g(x)
result = ff(x) * exp(-s * x);
end
Or you can create an anonymous function
g = #(x) ff(x) * exp(-s * x);
Then you can use g(a), g(b), etc to calculate what you want.
You can also use the TRAPZ function to perform trapezoidal numerical integration. Here is an example:
%# parameters
a = 0; b = 1;
N = 100; s = 1;
f = #(x) x;
%# integration
X = linspace(a,b,N);
Y = f(X).*exp(-s*X);
If = trapz(X,Y) %# value returned: 0.26423
%# plot
area(X,Y, 'FaceColor',[.5 .8 .9], 'EdgeColor','b', 'LineWidth',2)
grid on, set(gca, 'Layer','top', 'XLim',[a-0.5 b+0.5])
title('$\int_0^1 f(x) e^{-sx} \,dx$', 'Interpreter','latex', 'FontSize',14)
The error message here is about as self-explanatory as it gets. You aren't defining a variable called x, so when you reference it on the first line of your function, MATLAB doesn't know what to use. You need to either define it in the function before referencing it, pass it into the function, or define it somewhere further up the stack so that it will be accessible when you call LaplaceTransform.
Since you're trying to numerically integrate with respect to x, I'm guessing you want x to take on values evenly spaced on your domain [0,1]. You could accomplish this using e.g.
x = linspace(a,b,N);
EDIT: There are a couple of other problems here: first, when you define g, you need to use .* instead of * to multiply the elements in the arrays (by default MATLAB interprets multiplication as matrix multiplication). Second, your calls g(a) and g(b) are treating g as a function instead of as an array of function values. This is something that takes some getting used to in MATLAB; instead of g(a), you really want the first element of the vector g, which is given by g(1). Similarly, instead of g(b), you want the last element of g, which is given by g(length(g)) or g(end). If this doesn't make sense, I'd suggest looking at a basic MATLAB tutorial to get a handle on how vectors and functions are used.