Force evaluation of variables in MATLAB anonymous function - matlab

MATLAB stores variables along with anonymous functions. Here is an example of how this works from the documentation.
Variables in the Expression:
Function handles can store not only an expression, but also variables
that the expression requires for evaluation.
For example, create a function handle to an anonymous function that
requires coefficients a, b, and c.
a = 1.3;
b = .2;
c = 30;
parabola = #(x) a*x.^2 + b*x + c;
Because a, b, and c are available at the time you create parabola, the
function handle includes those values. The values persist within the
function handle even if you clear the variables:
clear a b c
x = 1;
y = parabola(x)
y =
31.5000
Supposedly, the values of a b and c are stored with the function even when it's saved and reloaded from a mat file. In practice, I've found that these values do not persist, especially if the code that originally created the function is edited.
Is there a way to define the function handle in terms of the numeric values of the variables? I would like something of the form
>> a = 1.3;
>> b = .2;
>> c = 30;
>> parabola = #(x) a*x.^2 + b*x + c
parabola = #(x) a*x.^2+b*x+c
>> parabola2 = forceEval(parabola)
parabola2 = #(x) 1.3*x.^2+.2x+30
EDIT: Perhaps my problem is with the file association, but when I edit the file that I originally defined the anonymous function in, I get an error that looks like:
Unable to find function #(ydata)nr/(na*dt)*normpdf(ydata,mu(j),s(j))./normpdf(ydata,mu_a(j),s_a(j)) within
C:...\mfilename.m. (where I've changed the name of my mfile to mfilename)
My usual solution to this kind of stuff has been to use func2str() to remove the file dependency, but this also strips out the workspace information including the parameter values. So I would like to force all the parameters to take on their numerical values in the function definition.

The values are stored in the function. As I've demonstrated in different answers before, you can check this with the functions command:
>> a = 1.3; b = .2; c = 30;
>> parabola = #(x) a*x.^2 + b*x + c;
>> x = 1;
>> y = parabola(x)
y =
31.5
>> clear a b c
>> y = parabola(x)
y =
31.5
>> fi = functions(parabola)
fi =
function: '#(x)a*x.^2+b*x+c'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
>> fi.workspace{1}
ans =
a: 1.3
b: 0.2
c: 30
Even when you save the handle to disk:
>> save parabolaFun.mat parabola
>> clear parabola a b c
>> load parabolaFun.mat parabola
>> y = parabola(x)
y =
31.5
>> fi = functions(parabola)
fi =
function: '#(x)a*x.^2+b*x+c'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
>> fi.workspace{1}
ans =
a: 1.3
b: 0.2
c: 30
And you can simplify the creation of a parabola handle like this:
function p = makeParabola(a,b,c)
p = #(x) a*x.^2 + b*x + c;
end
There are certain caveats:
You can save and load function handles in a MAT-file using the MATLABĀ® save and load functions. If you load a function handle that you saved in an earlier MATLAB session, the following conditions could cause unexpected behavior:
Any of the files that define the function have been moved, and thus no longer exist on the path stored in the handle.
You load the function handle into an environment different from that in which it was saved. For example, the source for the function either does not exist or is located in a different folder than on the system on which the handle was saved.
In both of these cases, the function handle is now invalid because it is no longer associated with any existing function code. Although the handle is invalid, MATLAB still performs the load successfully and without displaying a warning. Attempting to invoke the handle, however, results in an error.
Hence, if you create the handle from a file-backed function (not a script, that's OK), and then modify or delete the file, the handle will become invalid.

Anonymous functions capture the values of all variables involved in the expression. If you want to see the environment workspace captured, use functions as #chappjc showed in his answer.
Now you gotta be careful about the type of variables used in the anonymous function (think value-type vs. handle-type).
All native types (numerics, logicals, structs, cells, etc..) are captured by-value not by-reference. Example:
x = magic(4);
f = #() x; % captures matrix x
x(1) = 1 % modify x
xx = f() % change not reflected here
Compare that to using handle-class types (e.g containers.Map):
x = containers.Map('KeyType','char', 'ValueType','double');
f = #() x; % captures handle-class object x
x('1') = 1; % modify map
keys(x) % changed
keys(f()) % also changed!
f() == x % compare handle equality, evaluates to true

a = 1.3, b = 0.2, c = 30;
parabola = eval(['#(x) ', num2str(a), '*x^2 + ', num2str(b), '*x + ', num2str(c)]);

Related

MATLAB anonymous function detailed workings [duplicate]

MATLAB stores variables along with anonymous functions. Here is an example of how this works from the documentation.
Variables in the Expression:
Function handles can store not only an expression, but also variables
that the expression requires for evaluation.
For example, create a function handle to an anonymous function that
requires coefficients a, b, and c.
a = 1.3;
b = .2;
c = 30;
parabola = #(x) a*x.^2 + b*x + c;
Because a, b, and c are available at the time you create parabola, the
function handle includes those values. The values persist within the
function handle even if you clear the variables:
clear a b c
x = 1;
y = parabola(x)
y =
31.5000
Supposedly, the values of a b and c are stored with the function even when it's saved and reloaded from a mat file. In practice, I've found that these values do not persist, especially if the code that originally created the function is edited.
Is there a way to define the function handle in terms of the numeric values of the variables? I would like something of the form
>> a = 1.3;
>> b = .2;
>> c = 30;
>> parabola = #(x) a*x.^2 + b*x + c
parabola = #(x) a*x.^2+b*x+c
>> parabola2 = forceEval(parabola)
parabola2 = #(x) 1.3*x.^2+.2x+30
EDIT: Perhaps my problem is with the file association, but when I edit the file that I originally defined the anonymous function in, I get an error that looks like:
Unable to find function #(ydata)nr/(na*dt)*normpdf(ydata,mu(j),s(j))./normpdf(ydata,mu_a(j),s_a(j)) within
C:...\mfilename.m. (where I've changed the name of my mfile to mfilename)
My usual solution to this kind of stuff has been to use func2str() to remove the file dependency, but this also strips out the workspace information including the parameter values. So I would like to force all the parameters to take on their numerical values in the function definition.
The values are stored in the function. As I've demonstrated in different answers before, you can check this with the functions command:
>> a = 1.3; b = .2; c = 30;
>> parabola = #(x) a*x.^2 + b*x + c;
>> x = 1;
>> y = parabola(x)
y =
31.5
>> clear a b c
>> y = parabola(x)
y =
31.5
>> fi = functions(parabola)
fi =
function: '#(x)a*x.^2+b*x+c'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
>> fi.workspace{1}
ans =
a: 1.3
b: 0.2
c: 30
Even when you save the handle to disk:
>> save parabolaFun.mat parabola
>> clear parabola a b c
>> load parabolaFun.mat parabola
>> y = parabola(x)
y =
31.5
>> fi = functions(parabola)
fi =
function: '#(x)a*x.^2+b*x+c'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
>> fi.workspace{1}
ans =
a: 1.3
b: 0.2
c: 30
And you can simplify the creation of a parabola handle like this:
function p = makeParabola(a,b,c)
p = #(x) a*x.^2 + b*x + c;
end
There are certain caveats:
You can save and load function handles in a MAT-file using the MATLABĀ® save and load functions. If you load a function handle that you saved in an earlier MATLAB session, the following conditions could cause unexpected behavior:
Any of the files that define the function have been moved, and thus no longer exist on the path stored in the handle.
You load the function handle into an environment different from that in which it was saved. For example, the source for the function either does not exist or is located in a different folder than on the system on which the handle was saved.
In both of these cases, the function handle is now invalid because it is no longer associated with any existing function code. Although the handle is invalid, MATLAB still performs the load successfully and without displaying a warning. Attempting to invoke the handle, however, results in an error.
Hence, if you create the handle from a file-backed function (not a script, that's OK), and then modify or delete the file, the handle will become invalid.
Anonymous functions capture the values of all variables involved in the expression. If you want to see the environment workspace captured, use functions as #chappjc showed in his answer.
Now you gotta be careful about the type of variables used in the anonymous function (think value-type vs. handle-type).
All native types (numerics, logicals, structs, cells, etc..) are captured by-value not by-reference. Example:
x = magic(4);
f = #() x; % captures matrix x
x(1) = 1 % modify x
xx = f() % change not reflected here
Compare that to using handle-class types (e.g containers.Map):
x = containers.Map('KeyType','char', 'ValueType','double');
f = #() x; % captures handle-class object x
x('1') = 1; % modify map
keys(x) % changed
keys(f()) % also changed!
f() == x % compare handle equality, evaluates to true
a = 1.3, b = 0.2, c = 30;
parabola = eval(['#(x) ', num2str(a), '*x^2 + ', num2str(b), '*x + ', num2str(c)]);

Retrieve saved variable values from anonymous function

For example, taken from Matlab:
a = 1.3;
b = .2;
c = 30;
parabola = #(x) a*x.^2 + b*x + c;
parabola can be called even if a, b, c are removed from the workspace. The explanation is:
Because a, b, and c are available at the time you create parabola, the function handle includes those values. The values persist within the function handle even if you clear the variables:
After an anonymous function like parabola is created, how do I later retrieve or see the variables stored inside it?
You can use the functions function to get information about an anonymous function including the internal workspace in which those variables are defined.
a = 1.3;
b = .2;
c = 30;
parabola = #(x) a*x.^2 + b*x + c;
clear a b c
F = functions(parabola);
variables = F.workspace{1};
%// variables =
%//
%// a: 1.3
%// b: 0.2
%// c: 30
The workspace contains a struct with a field for each variable that is contained within the function handle's workspace.

Undefined function or variable

I have a simple function as below:
function dz = statespace(t,z)
dz = A*z + B*k*z
end
My main script is :
clear all;close all;format short;clc;
% step 1 -- input system parameters
% structure data
M1 = 1; M2= 1; M3= 1; %Lumped Mass(Tons)
M= diag([M1,M2,M3]);
k(1)= 980; k(2)= 980; k(3)= 980; %Stiffness Coefficient(KN/M)
K = zeros(3,3);
for i=1:2
K(i,i)=k(i)+k(i+1);
end
K(3,3)=k(3);
for i=1:2
K(i,i+1)=-k(i+1);
end
for i=2:3
K(i,i-1)=-k(i);
end %Stiffness Matrix(KN/M)
c(1)= 1.407; c(2)= 1.407; c(3)= 1.407; %Damping Coefficient(KN.sec/M)
C = zeros(3,3);
for i=1:2
C(i,i)=c(i)+c(i+1);
end
C(3,3)=c(3);
for i=1:2
C(i,i+1)=-c(i+1);
end
for i=2:3
C(i,i-1)=-c(i);
end %Damping Matrix(KN.sec/M)
A = [zeros(3) eye(3);-inv(M)*K -inv(M)*C]
H = [1;0;0]
B = [0;0;0;inv(M)*H]
k = [-1 -1 -1 -1 -1 -1]
t = 0:0.004:10;
[t,z] = ode45(statespace,t);
When I run my main script it comes with following error:
Undefined function or variable 'A'.
Error in statespace (line 2)
dz = A*z + B*k*z
As you can see I defined A in main script. Why this problem happening?
There multiple things wrong with your code. First, you need to supply the values of A and B to your function but as you are invoking it (incorrectly without the # and additional parameter y0 as I commented below) in the toolbox ode45, you have to keep just two parameters so you cannot supply A and B as additional parameters. If you define A and B within your function or share them via global variables you will get further. However, as noted below the definitions don't seem to be correct as A * z and B * k * z don't have the same dimensions. z is a scalar so B * k needs to be same size and shape as A which currently it is not.
Edit from:
As Jubobs suggested change your function's parameters to include A, B and k. Also you don't need t as it is never used in the function. So:
function dz = statespace(A, B, k, z)
dz = A*z + B*k*z
end
As others have pointed out, A, B and k are not defined in the function workspace, so you either need to define them again (ugly, not recommended), declare them as global variables (slightly better, but still not good practice), or pass them as arguments to your function (the better solution). However, because you then want to use the function with ode45, you need to be a bit careful with how you do it:
function dz = statespace(t,z,A,B,k)
dz = A*z + B*k*z
end
and then the call to ode45 would like this:
[t,z] = ode45(#(t,z)statespace(t,z,A,B,k),[0 Tf],z0); % where Tf is your final time and z0 your initial conditions
See Error using ode45 and deval for a similar problem.

Using inline function with constant arguments in MATLAB

This is a part of my code.
clear all;
clc;
p = 50;
t = [-6 : 0.01 : 6];
f = inline('(t+2).*sin(t)', 't')
v = inline('3*f(p*t+2)','t','f','p')
plot(t,f(t));
v(t,f,p);
figure;
plot(t,v(t,f,p));
Here I have two questions.
Why I have to pass p into the function v even though p is a constant which has already declared ?
How I can get an expression for v completely in terms of t as 3*[(50*t+2)*sin(50*t+2)] or in its simplified form ?
Update
This is an update for the second question
Let
f(x) = 1 + x - x^2
g(x) = sin(x)
If I give f(g(x)), I wanna get the output in words, like this
f(g(x)) = (cos(X))^2 + sin(x)
not in numerical value. Is there any function capable to do that?
1) Why do I have to pass p to v even though p is a constant which has already been declared?
Well, a MATLAB's inline function object has an eval wrapper, so the only variables in its scope are those which were automatically captured from the expression or explicitly specified.
In other words, if you want v to recognize p, you have no other option but declaring it when creating the inline object and passing it to v explicitly. The same goes for f as well!
2) How I can get an expression for v completely in terms of t as 3*[(50*t+2)*sin(50*t+2)] or in its simplified form?
Use anonymous functions, like Shai suggested. They are more powerful, more elegant and much faster. For instance:
v = #(t)(3*(50*t+2)*sin(50*t+2))
Note that if you use a name, which is already in use by a variable, as an argument, the anonymous function will treat it as an argument first. It does see other variables in the scope, so doing something like g = #(x)(x + p) is also possible.
EDIT #1:
Here's another example, this time a function of a function:
x = 1:5;
f = #(x)(x .^ 3); %// Here x is a local variable, not as defined above
g = #(x)(x + 2); %// Here x is also a local variable
result = f(g(x));
or alternatively define yet another function that implements that:
h = #(x)f(g(x)); %// Same result as h = #(x)((x + 2) .^ 3)
result = h(x);
The output should be the same.
EDIT #2:
If you want to make an anonymous function out of the expression string, concatenate the '#(x)' (or the correct anonymous header, as you see fit) to the beginning and apply eval, for example:
expr = '(x + 2) .^ 3';
f = eval(['#(x)', expr]) %// Same result as f = #(x)((x + 2) .^ 3)
Note that you can also do char(f) to convert it back into a string, but you'll have to manually get rid of the '#(...)' part.
EDIT #3:
If you're looking for a different solution, you can explore the Symbolic Toolbox. For example, try:
syms x
f(x) = x + 2
g(x) = x ^ 3
or can also use sym, like so:
f(x) = sym('x + 2');
g(x) = sym('x ^ 3');
Use subs to substitute values and evaluate the symbolic expression.
How about using anonymous functions:
p = 50;
t = -6:0.01:6;
f = #(x) (x+2).*sin(x);
v = #(x) 3*f(p*x+2);
figure;
subplot(1,2,1); plot( t, f(t) ); title('f(t)');
subplot(1,2,2); plot( t, v(t) ); title('v(t)');
Is this what you wanted?
Adding a constant into an inline can be done during its definition.
Instead of
p = 50;
v = inline('3*f(p*t+2)','t','f','p')
You can write
p = 50;
v = inline( sprintf('3*f(%f*t+2)', p), 't','f')

Anonymous Functions calling themselves in MATLAB

As an experiment (and because I'm generating anonymous functions off of user data) I ran the following MATLAB code:
h = #(x) x * x
h = #(x) x * x
h(3)
ans = 9
h = #(x) h(x) + 1
h = #(x)h(x)+1
h(3)
ans = 10
Basically, I made an anonymous function call itself. Instead of acting recursively, MATLAB remembered the old function definition. However, the workspace doesn't show it as one of the variables, and the handle doesn't seem to know it either.
Will the old function be stored behind the scenes as long as I keep the new one? Are there any "gotchas" with this kind of construction?
An anonymous function remembers the relevant part of the workspace at the time of definition, and makes a copy of it. Thus, if you include a variable in the definition of the anonymous function, and change that variable later, it will keep the old value inside the anonymous function.
>> a=1;
>> h=#(x)x+a %# define an anonymous function
h =
#(x)x+a
>> h(1)
ans =
2
>> a=2 %# change the variable
a =
2
>> h(1)
ans =
2 %# the anonymous function does not change
>> g = #()length(whos)
g =
#()length(whos)
>> g()
ans =
0 %# the workspace copy of the anonymous function is empty
>> g = #()length(whos)+a
g =
#()length(whos)+a
>> g()
ans =
3 %# now, there is something in the workspace (a is 2)
>> g = #()length(whos)+a*0
g =
#()length(whos)+a*0
>> g()
ans =
1 %# matlab doesn't care whether it is necessary to remember the variable
>>