How does one pass a function with some fixed argument as an argument in MATLAB - matlab

I want to pass a function that has arguments to another function that takes the function handler (pointer) as an argument, but some of the arguments to the function handler need to be fixed. How does one do this in MATLAB?
Concretely I want to minimize a function h(eta) using fminsearch(fun,x0). One obvious issue is that if I pass all the arguments in x0 it will minimize it with respect to all the arguments but that isn't what I want to do. What I really want to do is instead:
I have tried the following and it seems to work as far as I tested it:
function [ h ] = function_returner( x )
%
t = -10000;
h = #(eta)-10*x + t + eta^2;
end
and the script to test it:
h = function_returner(0);
h(3) %-9991
[x,fval,exitflag] = fminsearch(h,[10]) %returns [0, -10000, 1]
returns the correct minimum and the correct value of x at which the minimum is obtained. The thing that I wanted to make sure is that the variables that are fixed of h indeed remain fixed after I returned the function handler. i.e. if h is passed around, how does one make sure that the variables don't change value just because they go into an environment that has the same variables names as in the function handler?
I also wrote:
x = inf;
t = inf;
eta = inf;
h = function_returner(0);
h(3) %-9991
[x,fval,exitflag] = fminsearch(h,[10]) %returns [0, -10000, 1]
and it seems to go unaffected (i.e. it works as I want it to work). But just to be on the safe side, I was hoping there was not a some weird edge condition that this doesn't work.

You are worrying unnecessarily. :-) The thing is, when you create an anonymous function, all the outer variables that are used for its definition are frozen, so you don't need to worry that the function will change behavior behind your back via modified parameters. To test this, try this script:
a = 1;
b = 2;
f = #(u,v) u*a + v*b;
x = f(1,1); %// x is 3 = 1*1 + 1*2
a = 2;
b = 3;
g = #(w) f(w,a)
y = g(1); %// y is 5 = f(1,2) = 1*1 + 2*2

Related

How to write the following function so that gradient can be found before putting the variable values

function [y] = sumsqu(xx)
d = length(xx);
sum = 0;
for ii = 1:d
xi = xx(ii);
sum = sum + ii*xi^2;
end
y = sum;
end
Above is the code for d variables. Whenever I call the function I get the sum as expected. Now I want to find the numerical gradient of the function. But since the function is returning a scalar value, gradient returns 0 obviously. What can I do so that gradient first evaluates in its variable form then return an array corresponding to [x1 x2 x3....xd]?
As you can see in the picture, I want it in that order. And I also want d as a variable so that code can be generic. Hope you understood my problem.
Your function does exactly this:
y = sum(xx.^2 .* (1:numel(xx)));
The derivatives then are:
y = 2*xx .* (1:numel(xx));
(according to the hand-written equations).
You should avoid using sum as a variable name, you can see above that it is an important function, if you assign a value to sum, you hide the function and can no longer use it.
For your specific function, you can calculate the gradient analytically like:
g = 2*(1:length(xx)).*xx;
You can also replace the call for length(xx) by d if it is given.

Two functions in Matlab to approximate integral - not enough input arguments?

I want to write a function that approximates integrals with the trapezoidal rule.
I first defined a function in one file:
function[y] = integrand(x)
y = x*exp(-x^2); %This will be integrand I want to approximate
end
Then I wrote my function that approximates definite integrals with lower bound a and upper bound b (also in another file):
function [result] = trapez(integrand,a,b,k)
sum = 0;
h = (b-a)/k; %split up the interval in equidistant spaces
for j = 1:k
x_j = a + j*h; %this are the points in the interval
sum = sum + ((x_j - x_(j-1))/2) * (integrand(x_(j-1)) + integrand(x_j));
end
result = sum
end
But when I want to call this function from the command window, using result = trapez(integrand,0,1,10) for example, I always get an error 'not enough input arguments'. I don't know what I'm doing wrong?
There are numerous issues with your code:
x_(j-1) is not defined, and is not really a valid Matlab syntax (assuming you want that to be a variable).
By calling trapez(integrand,0,1,10) you're actually calling integrand function with no input arguments. If you want to pass a handle, use #integrand instead. But in this case there's no need to pass it at all.
You should avoid variable names that coincide with Matlab functions, such as sum. This can easily lead to issues which are difficult to debug, if you also try to use sum as a function.
Here's a working version (note also a better code style):
function res = trapez(a, b, k)
res = 0;
h = (b-a)/k; % split up the interval in equidistant spaces
for j = 1:k
x_j1 = a + (j-1)*h;
x_j = a + j*h; % this are the points in the interval
res = res+ ((x_j - x_j1)/2) * (integrand(x_j1) + integrand(x_j));
end
end
function y = integrand(x)
y = x*exp(-x^2); % This will be integrand I want to approximate
end
And the way to call it is: result = trapez(0, 1, 10);
Your integrandfunction requires an input argument x, which you are not supplying in your command line function call

MATLAB function handles and parameters

When I type help gmres in MATLAB I get the following example:
n = 21; A = gallery('wilk',n); b = sum(A,2);
tol = 1e-12; maxit = 15;
x1 = gmres(#(x)afun(x,n),b,10,tol,maxit,#(x)mfun(x,n));
where the two functions are:
function y = afun(x,n)
y = [0; x(1:n-1)] + [((n-1)/2:-1:0)'; (1:(n-1)/2)'].*x+[x(2:n); 0];
end
and
function y = mfun(r,n)
y = r ./ [((n-1)/2:-1:1)'; 1; (1:(n-1)/2)'];
end
I tested it and it works great. My question is in both those functions what is the value for x since we never give it one?
Also shouldn't the call to gmres be written like this: (y in the #handle)
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
Function handles are one way to parametrize functions in MATLAB. From the documentation page, we find the following example:
b = 2;
c = 3.5;
cubicpoly = #(x) x^3 + b*x + c;
x = fzero(cubicpoly,0)
which results in:
x =
-1.0945
So what's happening here? fzero is a so-called function function, that takes function handles as inputs, and performs operations on them -- in this case, finds the root of the given function. Practically, this means that fzero decides which values for the input argument x to cubicpoly to try in order to find the root. This means the user just provides a function - no need to give the inputs - and fzero will query the function with different values for x to eventually find the root.
The function you ask about, gmres, operates in a similar manner. What this means is that you merely need to provide a function that takes an appropriate number of input arguments, and gmres will take care of calling it with appropriate inputs to produce its output.
Finally, let's consider your suggestion of calling gmres as follows:
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
This might work, or then again it might not -- it depends whether you have a variable called x in the workspace of the function eventually calling either afun or mfun. Notice that now the function handles take one input, y, but its value is nowhere used in the expression of the function defined. This means it will not have any effect on the output.
Consider the following example to illustrate what happens:
f = #(y)2*x+1; % define a function handle
f(1) % error! Undefined function or variable 'x'!
% the following this works, and g will now use x from the workspace
x = 42;
g = #(y)2*x+1; % define a function handle that knows about x
g(1)
g(2)
g(3) % ...but the result will be independent of y as it's not used.

Matlab Defining A Function That Has Vector As An Input

I was given a simple exercise by my professor, which is to define a cerrtain function. Here is my function
function [a,b,c] = PHUN([x,y],[z,t,w])
a = x
b = ((y+z)^2)*t
c = z/w + x
However, matlab states that I am using invalid syntax in the first line. So, I figured, perhaps there is a particular way in which vector inputs are supposed to be typed. I have attempt several searches on defining functions with vector inputs (or arguments), but have not been successful. I was wondering if someone could possibly help me.
You can pass vectors as arguments in the same way you pass variables. Then access them in the function body appropriately. Your function could be re-written as follows:
function [a,b,c] = PHUN(X,Y)
a = X(1)
b = ((X(2)+Y(1))^2)*Y(2)
c = Y(1)/Y(3) + X(1)
Or if you want to keep the original variables:
function [a,b,c] = PHUN(X,Y)
Z = num2cell([X,Y]);
[x,y,z,t,w] = Z{:};
a = x
b = ((y+z)^2)*t
c = z/w + x

Embedded Matlab: Problem with persistent variables

I wrote some function, that makes use of persistent variables, for example:
function y = integrator(x, t)
persistent yr; %result
...
and then, if I call it only once in a cycle, everything works fine:
x = integrator(x_dot, t);
but if I want to call it twice with different arguments, it will give wrong results:
x = integrator(x_dot, t);
y = integrator(y_dot, t);
This is not unexpected, but how can I deal with that? Use something different (non-persistent) variables or what?
I'm used to deal mostly with Simulink and the solution is not obvious to me.
You could use a closure for this:
function integrator_handle = make_integrator(yr)
function y = integrator(x, t)
y = x + yr;
yr = yr + 1;
end
integrator_handle = #integrator; % (1)
end
To use:
>> integrator1 = make_integrator(0); % 0 is the initial value for yr
>> integrator2 = make_integrator(1);
integrator1 and integrator2 are now stateful function handles, essentially closures that have captured the state of yr as it was at the point where the function handle was created (the line marked with the comment "% (1)"). They can be invoked using parenthesis-indexing, which looks just like function invocation:
y = integrator1(x, t);
Any modifications to yr during the execution of the function handle will be retained with the function handle, so in my example above, yr will keep incrementing by one each time an integrator is called, but only for that particular instance of the integrator.
The best solution would change what you have to something like:
function [y, yr] = integrator(x, t, yr)
if nargin < 3
yr = []; % will behave identically to persistent when yr is not given
end
Now you can make repeated calls as:
[x,xr] = integrator(x, t);
[x,xr] = integrator(x, t, xr);
[y,yr] = integrator(x, t);
[y,yr] = integrator(x, t, yr);
Though I wouldn't recommend it, there is a way to keep your current implementation and nearly achieve your desired result. It's possible to clear persistent variables by clearing the function. This will allow you to "reset" the persistent variable, which means this sequence of calls should work:
x = integrator(x_dot, t);
clear integrator;
y = integrator(y_dot, t);
But note that this will likely not produce the expected result when calling
x = integrator(x_dot, t);
clear integrator;
y = integrator(y_dot, t);
clear integrator;
x = integrator(x_dot, t);
Whereas in the solution I suggest first you can call
[x,xr] = integrator(x, t);
[y,yr] = integrator(x, t);
[x,xr] = integrator(x, t, xr);
[y,yr] = integrator(x, t, yr);
and the results will maintain state as expected.
You could just send and return the yr variable to the function each time. For your code above you would need to have a x_yr variable and a y_yr variable. It may not be very elegant, but it would work.
If you only want two instances of this function (as above with x and y) then you could make two functions that are identical except in name like xintegrator and yintegrator. Or, you could have yr be an array and have a parameter sent when calling integrator specifying which value in the array to use.