Function handle as a property of a class - Matlab - matlab

I define a class CellArrayHandle whose only property is a cell array of function handles:
classdef CellArrayHandle < handle
properties
cel % cell array of function handles
end
end
Suppose myHandle is an object of CellArrayHandle, so myHandle.cel is a n-by-1 cell array of function handles, i.e myHandle.cel{i} is a function handle for i = 1 to n.
I want to do some update (for e.g. i=1), but the following does not work:
myHandle.cel{1} = #(x) myHandle.cel{1}(x) + 0.5;
Matlab says "Maximum recursion limit of 500 reached", so it seems to be understood as an infinite recursion. However the fowllowing works:
f = #(x) f(x) + 0.5;
for a function handle f.
It seems when I encapsulate a function handle into a class as a property, the above update method will not work.
I do not understand the difference between the former and the latter. Could any people help me on this point? Thank you very much.
Best regards,
Frank

The difference stems from the semantics of a handle class:
You can assign the handle object to multiple variables or pass it to functions without causing MATLAB to make a copy of the original object.
Or, to borrow the original idea of Highlander, when you instantiate a handle class, "there can be only one" (glob of the instance in memory which all variables you assign it to only creating references and not new copies).
Consider the example script:
f = #(x) x;
f = #(x) f(x) + 0.25;
f = #(x) f(x) + 0.50;
b = CellArrayHandle();
b.cel{1} = #(x) x;
b.cel{1} = #(x) b.cel{1}(x) + 0.25;
b.cel{1} = #(x) b.cel{1}(x) + 0.5;
fval = f(1);
bval = b.cel{1}(1);
If I debug this script and look at the stack right before fval evaluates, I see:
K>> dbstack
> In #(x)x
In #(x)f(x)+0.25
In #(x)f(x)+0.5
So Matlab was able to create a copy of the current f function handles during the creation of subsequent f handles and could form a stack.
When I do the same thing to b, I get this:
K>> dbstack
> In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
In #(x)b.cel{1}(x)+0.5
...
This happens because each assignment to a property of b makes the property of b that value without creating a new instance of the class. So the assignment is inherently infinitely recursive.
You can fix this by not having the class inherit from handle but from value (the default). By removing the < handle from the classdef, and repeating the dbstack of the handle call, we have
K>> dbstack
> In #(x)x
In #(x)b.cel{1}(x)+0.25
In #(x)b.cel{1}(x)+0.5
And this happens because each assignment to a property of b now makes a copy of the current b, instantiates a new b, and stores the old definition of b within the function handle to form the proper stack.

Related

Summation of N function handles in MATLAB

I have N functions in MATLAB and I can define them using strcat, num2str and eval in a for loop. So without defining by hand I am able to define N functions. Let N=4 and let them be given as follows:
f1=#(x) a1*x+1;
f2=#(x) a2*x+1;
f3=#(x) a3*x+1;
f4=#(x) a4*x+1;
Now I add these four functions and I can do this by hand as follows:
f=#(x)(f1(x)+f2(x)+f3(x)+f4(x));
Here I can do it by hand because I know that N=4. However, in general I never know how many functions I will have. For all cases I cannot write a new function.
Is there any way to do this automatically? I mean if I give N=6 I am expecting to see MATLAB giving me this:
f=#(x)(f1(x)+f2(x)+f3(x)+f4(x)+f5(x)+f6(x));
Whenever I give N=2 then I must have the function f, defined as follows:
f=#(x)(f1(x)+f2(x));
How can we do this?
First of all, you should read this answer that gives a series of reasons to avoid the use of eval. There are very few occasions where eval is necessary, in all other cases it just complicates things. In this case, you use to dynamically generate variable names, which is considered a very bad practice. As detailed in the linked answer and in further writings linked in that answer, dynamic variable names make the code harder to read, harder to maintain, and slower to execute in MATLAB.
So, instead of defining functions f1, f2, f3, ... fN, what you do is define functions f{1}, f{2}, f{3}, ... f{N}. That is, f is a cell array where each element is an anonymous function (or any other function handle).
For example, instead of
f1=#(x) a1*x+1;
f2=#(x) a2*x+1;
f3=#(x) a3*x+1;
f4=#(x) a4*x+1;
you do
N = 4;
a = [4.5, 3.4, 7.1, 2.1];
f = cell(N,1);
for ii=1:N
f{ii} = #(x) a(ii) * x + 1;
end
With these changes, we can easily answer the question. We can now write a function that outputs the sum of the functions in f:
function y = sum_of_functions(f,x)
y = 0;
for ii=1:numel(f)
y = y + f{ii}(x);
end
end
You can put this in a file called sum_of_functions.m, or you can put it at the end of your function file or script file, it doesn't matter. Now, in your code, when you want to evaluate y = f1(x) + f2(x) + f3(x)..., what you write is y = sum_of_functions(f,x).

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.

Passing default arguments along function handles in Matlab

Say that I have the following function
function y = f(x,a)
if nargin < 2
a = 2;
end
y = x.^2 - a;
end
I have another function which finds the root through Newton's method. Say that this is how I call upon the method :
newton(#f,#df,x0)
If I run the newton function with the supplied arguments, then it will only run for the default value of a = 2.
I was wondering if it is possible to some how specify a default parameter for a function when sending it through a function handle. Like this for instance
newton(#f(a),#df,x0)
If you mean this newton, then it expects a univariate function. You can still use your bivariate function f, but you have to be tricky: you need to define a new, anonymous function, and use your variable a as parameter to that:
a = 3; %or any other specific value, have to be set before calling newton
newton(#(x) f(x,a),#df,x0)
If you find that more transparent, you can also do it in a separate step:
f_uni = #(x) f(x,a); %defines f_uni(x), "a" is a parameter to it
newton(f_uni,#df,x0);
Note that in this case f_uni is already a function handle, so you don't have to (and mustn't) put a # before it.

Variable or function undefined

I am trying to implement following in MATLAB,
n1 = 6;
n2 = 1;
n3=0.1;
global ps
ps=zeros(3,15);
[R,t,d]=model(n1,n2,n3);
ps=R;
[x, fval] = fmincon(#Obj,[1/3,1/3, 1/3],[],[],[],[],[],[],#cons);
function f = Obj(x)
f = x(1)^2+x(2)^3+x(3)^4;
function [c, ceq] = cons(x)
c=[];
ceq(1) = sum(ps(1,:))*x(1)+sum(ps(2,:))*x(2)+sum(ps(3,:))*x(3) - (sum(d(1,:)));
ceq(2) = sum(x) - 4;
I'm getting following error, what is wrong here?
variable or function 'ps' undefined
You don't need to and definitelty should not use global variables for this. It is a very bad habit and inefficient to boot. Any time you think about using global you should ask yourself if there is another way and search for it. It is only in the very very rare case that globals are needed/helpful (usually in large codebases such as toolboxes).
In your case, you should pass your ps variable in as a parameter by creating an anonymous function. First define your cons function like this so that it takes in a parameter argument:
function [c, ceq] = cons(x,ps)
Then create the anonymous function with one input (x) and one captured parameter (the variable ps, which needs to be defined before this):
[x, fval] = fmincon(#Obj,[1/3,1/3, 1/3],[],[],[],[],[],[],#(x)cons(x,ps));
Alternatively you can save a handle to the anonymous function and pass that in:
cfun = #(x)cons(x,ps);
[x, fval] = fmincon(#Obj,[1/3,1/3, 1/3],[],[],[],[],[],[],cfun);
Here's a blog post from The MathWorks with other bad habits.
I cannot run your lines of code, but I think you have to put
global ps
in your function cons to inform Matlab that you are referring to the global ps. More information on global variables can be found here: http://www.mathworks.de/de/help/matlab/ref/global.html
EDIT: For a cleaner design, you should take into account horchler's advice: https://stackoverflow.com/a/20721808/3060323

Matlab, function handle auto use parameter

Hi I have a question about how to achieve the following behaviour in Matlab.
A.x=pi
A.sin=#()sin(A.x)
A.sin() % Returns 1.2246e-16, essentially 0 so all good so far.
% Now for the problem
A.x = pi/2
A.sin() % Returns 1.2246e-16, meaning the new A.x is not used. It should return 1.
Does anyone have any ideas how to achieve this. I know I could define A.sin as #(x) sin(x) then provide A.x but would rather find an alternative.
Thanks.
Create this class:
classdef mytrig
properties
x
end
methods
function out = sin(obj)
out = sin(obj.x);
end
end
end
Then at the command line:
>> A = mytrig;
>> A.x = pi;
>> A.sin
ans =
1.2246e-016
>> A.x = pi/2;
>> A.sin
ans =
1
The way you're doing it at the moment won't work, because when you create the function handle A.sin=#()sin(A.x), the function handle captures a copy of the current workspace, including x, which then remains fixed afterwards, even if you subsequently change x. If you want to be able to change x afterwards yourself, these best way would be to be implement a class as above.
Hope that helps!
Once you assign a value to a variable in Matlab, it is fixed.
If you want to have something that is updated automatically, please look into classes.
If you don't like classes, you could also define a function, for example
myAsin = #()sin(A.x)
Can't test it now, but as it is a function you should be getting the updated value when you call it after A.x is updated.