How to fix nan in anonymous function? - matlab

Suppose I have a function f(x) defined, which gives nan when it is very large, say x>100. Fortunately, when x>100, I can replace f by another function g. So I would like to define:
h = #(x)isnan(f(x)).*f(x)+isnan(f(x)).*g(x)
However, when I substitute h(1001), it gives nan. Is it possible to define h so that it gives g(1001) instead of nan? The only restriction is that I need to have anonymous function h for later use, say I would like to use it in integration, i.e., integral(h,0,inf).
Example: Suppose I have a function:
f = #(x)x.*1./x
This function is very easy and must be 1. I construct a function:
g = #(x)isnan(f(x)).*0+isnan(f(x)).*1
How to make g to be well defined so that I can still evaluate integral(g,-1,1)? For this example, I know I can evaluate it easily, but my restriction is that I need to define anonymous function g and use integral to do it.

You would need to make a regular function and wrap it with the anonymous function.
i.e.
function r = ternary(a, b, c)
if (a)
r = b;
else
r = c;
end
end
h = #(x)ternary(isnan(f(x)), g(x), f(x));
Note that this will evaluate your function twice. A less generalized solution for your particular case that won't evaluate the function twice.
function r = avoidNAN(a, b)
if (isnan(a))
r = b;
else
r = a;
end
end

There is a solution without any additional functions:
f = #(x)x.*1./x;
g = #(x)100+x;
h= #(x)getfield(struct('a',f(x),'b',g(x)),char(isnan(f(x))+'a'))

Related

MATLAB - create anonymous function recursively

For use within the least square fitting routine lsqcurvefit, I need a function in terms of a series representation like :
F = #(D, t) F0 - D(1)*(1-exp(-t))...
- D(2)*(1-exp(-t))...
- D(3)*(1-exp(-t))...
...
- D(n)*(1-exp(-t));
However, the amount of terms in the series is to be determined by the user; so the anonymous function F needs to be created within a loop, like
F = #(D, t) F0;
for i=1:n
F = F - D(i)*(1-exp(-t));
end
Unfortunately, the above method is not working within MATLAB; is there a possibility to get it work?
Unless I'm misunderstanding something, your function is not actually recursive. You can just do:
F = #(D,t) F0 - sum(D*(1-exp(-t));
or, if you want to specify n explicitly:
F = #(D,n,t) F0 - sum(D(1:n)*(1-exp(-t));
or, if t is a vector the same size as D:
F = #(D,n,t) F0 - D(1:n)*(1-exp(-t(1:n)).';
The best way to do this is with a combination of anonymous and normal functions.
recursionDepth = 5
CoefficientList = ones(numel(recursionDepth) + 1);
functionResults = #(t) myFunction(t, CoefficientList, recursionDepth);
function F = myFunction(t, CoefficientList, Depth)
F = CoefficientList(1);
for idx = 1:Depth
F = CoefficientList(idx) * (1 - exp(-1));
end
end
What I've done here is defined the full function that contains your model with all of its parameters, and then wrapped that into an anonymous function that sets the user selectable, unchanging parameters within the anonymous function, and leaves the single adjustable parameter as the input. You'll have to adjust for your particular model, but that is your basic template.

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.

How to define an inline function according to another inline function in Matlab?

Suppose that I have a vector of variables that I have created in this way:
A = sym('A%d',[1 , 3]);
And also an inline function which is a function of A:
f = inline(A(1)^2 + A(2)^3 - 10*A(3) , 'A');
Now, the question is how to define another function like g that has the following form:
g = f*10 or any other types of functions that depends on f.
thanks in advance
As suggested by #Daniel, you should use anonymous functions. In the documentation to inline, Mathworks warns that this will be removed in a future release, and tells you to use anonymous functions.
The syntax of anonymous functions is very easy:
f = #(A) A(1)^2 + A(2)^3 - 10*A(3)
with #(A), you define that you want one input variable, and name it A. If you have two inputs, A and B, then write #(A,B). But caution: these names A and B are only internal names inside your anonymous function. The following two functions are 100% identical:
f1 = #(x) 10*x
f2 = #(A) 10*A
You can call these anonymous functions like normal functions, e.g.
f([1, 2, 3])
f(x)
If you want to create a function g = 10*f, then you define this function as
g = #(A) 10*f(A)
Here's a small demonstration:
A = sym('A%d',[1 , 3]);
f = #(x) x(1)^2 + x(2)^3 - 10*x(3)
g = #(x) 10*f(x)
g(A)
ans =
10*A1^2 + 10*A2^3 - 100*A3

How to pass constants to a function which is used in fminbnd(#myfun,x1,x2) in a loop

I'm implementing a ML receiver for a communication channel.
For this I need to find the minimum value of the function below with respect to x in the range x = 0 to 15 (16QAM)
f = abs( rx(n) - (h'*h)*x )^2 ;
I have to iterate this in a loop (n=1:100). I found that I can do this by matlab function x = fminbnd(fun,x1,x2) where I can put the function in a separate .m-file as:
function f = myfun(x)
f = abs( rx(n) - (h'*h)*x )^2
and find the minimum for x from
x = fminbnd(#myfun,x1,x2);
My question is since constants to the function rx(n) is changing thorough the loop, how to sent it to the function myfun(x) within the loop.
You can do it by using an anonymous function to call your function in a separate file:
function mainfcnmin
h = [1;1];
rx = 1:3;
for n = 1:length(rx)
x = fminbnd(#(x)myfun(x,rx(n),h),0,15)
end
end
function f = myfun(x,rx,h)
f = abs(rx-(h'*h)*x)^2 ;
end
Or alternatively in one file by defining the function directly in the anonymous function like this:
h = [1;1];
rx = 1:3;
for n = 1:length(rx)
x = fminbnd(#(x)(abs(rx(n)-(h'*h)*x)^2),0,15)
end
You will need to make a function with rx(n) as a second parameter and then turn it into a single parameter anonymous function inside the loop.
Here is an example from the MATLAB documentation (for 'fminsearch' function):
If fun is parameterized, you can use anonymous functions to capture
the problem-dependent parameters. For example, suppose you want to
minimize the objective function myfun defined by the following
function file:
function f = myfun(x,a)
f = x(1)^2 + a*x(2)^2;`
Note that myfun has an extra parameter a, so you cannot pass it directly to > fminsearch. To optimize for a specific value of a, such as a = 1.5.
Assign the value to a
a = 1.5; % define parameter first
Call
fminsearch with a one-argument anonymous function that captures that
value of a and calls myfun with two arguments:
x = fminsearch(#(x) myfun(x,a),[0,1])
Hope that helped (sorry for bad text formatting).

Optimization with Matlab

A common way to write the objective function in matlab (including the gradient vector) is the following:
[L,G] = objfun(x)
where L is the value of objective function, G is the gradient vector and x is a vector of coefficients which I want to optimize.
However, when I include another input (i.e [L,G]=objfun(x,M), where M is a matrix) or when I call another function in the function objfun, the code is not running.
How can I include any inputs and call any functions in the objfun by keeping this format of optimization?
Note that I call the optimization as follows:
[x ,fval] = fminunc(#objfun,x,options)
where
options = optimoptions(#fminunc,'Algorithm','quasinewton',...
'Display','iter','Gradobj','on','TolFun',10^-8)
There's an mathworks help article on passing extra parameters to the objective function:
You can use the #(...) operator to generate an anonymous function handle to your function that will only depend on a single parameter.
a = 4; b = 2.1; c = 4;
f = #(x)objfun(x,a,b,c)
From the original page (where your objfun is parameterfun):
Note: The parameters passed in the anonymous function are those that exist at the time the anonymous function is created. Consider the
example
a = 4; b = 2.1; c = 4;
f = #(x)parameterfun(x,a,b,c)
Suppose you subsequently change, a to 3 and run
[x,fval] = fminunc(f,x0)
You get the same answer as before, since parameterfun uses a = 4, the
value when f was created.
To change the parameters that are passed to the function, renew the
anonymous function by reentering it:
a = 3;
f = #(x)parameterfun(x,a,b,c)