Why are predefined variables not shown with their value in function handles? - matlab

In MATLAB R2020b I have the following code:
f=#(x) x.^2;
y=2;
g=#(x) f(x).*y
and the output is
g = function_handle with value: #(x)f(x).*y
But y = 2, so I would expect the output to be #(x)f.*2. Is this how its supposed to work or a bug? And can I display it as f.*2 rather than f.*y?

When you create the function handle g = #(x) f(x).*y, the current values of the variables f and y get "frozen" into g's definition, as discussed in the documentation.
To inspect the actual values of f and y that g uses, you can call functions as follows:
>> info = functions(g); disp(info)
function: '#(x)f(x).*y'
type: 'anonymous'
file: ''
workspace: {[1×1 struct]}
within_file_path: '__base_function'
Specifically, see the workspace field:
>> disp(info.workspace{1})
f: #(x)x.^2
y: 2

Related

Symbolic function based on existing function ignores conditions inside this existing function

I am trying to create a symbolic function based on an existing function zz.
Here is mu zz.m file:
function p = zz(b)
b(b==0) = 1;
p = b;
end
Here is the script to create a symbolic function yy:
syms a
yy = symfun(zz(a), a);
Then I have the expected result with zz(the condition is respected) when I do in the console:
>> zz(0)
ans =
1
But when I used the created symbolic function yy, I don't have the expected result:
>> yy(0)
ans =
0
I suspect there might be explicated somewhere that formulas for symbolic functions cannot have conditions, but I cannot find a reference.
I've been looking at symbolic, sym, syms documentations and tried to look some references online, but I didn't find any references (maybe I had the wrong keywords...).

MATLAB: Why is the anoynomous function missing `(t,y)` here?

function yprime=example1(t , y)
yprime=cos(t)./(2*y-2);
Then type
>> [t,y] =ode45(#example1, [0, 4*pi],3);
>> plot(t , y)
On the line ode45(#example...). Why isn't it ode(#45(t,y)example...)?. How can [0, 4*pi] and 3 be passed into the derivative (i.e. example1) if the input is missing?
The # operator can create two (maybe more) different types of handles: simple and anonymous. A simple function handle is one that directly references a function file and has no other levels of in-direction. An anonymous function is a handle that is itself a (very simple) function and possesses its own workspace for constant storage, closures, and other purposes. The difference can be seen using the functions function:
>> f1 = #example1
f1 =
#example1
>> f2 = #(t,x) example1(t,x)
f2 =
#(t,x)example1(t,x)
>> functions(f1)
ans =
function: 'example1'
type: 'simple'
file: 'C:\Development\example1.m'
>> functions(f2)
ans =
function: '#(t,x)example1(t,x)'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
within_file_path: '__base_function'
Anonymous functions add a bit of overhead due to them being more than just pointers to functions and are therefore only really needed if you're parameterizing functions.
Regardless of the creation, ode45 and its kin will always attempt to pass the t and y argument pair to the handle you pass it via feval, and the argument list is only required if you are using anonymous functions versus direct file handle references.
That is just how the ode45 function in MATLAB works.
ode45(#function, [start, end] for t, initial value of y).
So in the example above, function is example1, t0 will be 0, tn (last point) will be 4*pi, and the initial value of y is 3.
The most important part of using ode45 is properly setting up the function. Notice how the function is set for the dy/dt. Because of this, given an initial point, it can generate the rest of the points for y at time t because it can calculate the change in y as t increases.

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

Creating a function handle out of the input of the parent function?

forgive me if the answer is this is terribly obvious or if there's a much better way to do this.
I'm trying to make a function that accepts a function of x (e.g. x^2 + 5x + 2), and use that input to create a function handle. That way I can use that function for whatever else I need it to do.
I think the problem is just that I don't know what all the different function types are, and I don't understand how to "concatenate" the "#(x)" and the input function correctly to make the function handle.
Here's what I tried:
function test(input1)
function_1 = #(x) + input1
end
It says that input1 is of type double, even if it's just a letter.
And if I try to enter the input as a string and convert it to symbolic data, I just get an array of numbers for the concatentaion.
Any help would be greatly appreciated, thanks.
Passing a string probably won't get you what you want, or it will get ugly.
This might be off topic, but it's important to understand that anonymous functions store the value of non-input variables at the time of creation. Any values that you want to change on each call to the function need to be input arguments.
>> a = pi;
>> fun = #(x) x * a;
>> fun(2)
ans =
6.2832
You can see the stored values as follows,
>> fi = functions(fun)
fi =
function: '#(x)x*a'
type: 'anonymous'
file: ''
workspace: {[1x1 struct]}
>> fi.workspace{1}
ans =
a: 3.1416
If your intention is to have another input argument, just have two input arguments:
>> fun = #(x,y) x * y;
>> fun(2,pi)
ans =
6.2832
However, you can pass a function handle to a function, and then call it. Perhaps this is what you're after:
function myfun = funTester(fh,x)
% presumably do something useful here
myfun = fh(x);
end
For example,
>> fun = #(x) x.^2 + 5*x + 2
fun =
#(x)x.^2+5*x+2
>> funTester(fun,-2)
ans =
-4
Final thought: Construct a handle with eval:
>> expression = 'x^2 + 5*x + 2';
>> eval(['h = #(x) ' expression]) % put this in your function
h =
#(x)x^2+5*x+2
Or str2func, (thanks Luis Mendo)
h = str2func(['#(x)' expression])
Either way it's not too pretty, hence my suggestion to just pass a handle.

How to implement this function in mupad (MATLAB)

I want to implement the following function. But I dont know how to define a function over a set of variables such as mu(1), mu(2), mu(3),..., mu(c). c is a numeric symbol (i.e. it is a parameter of the function, but not an input value):
f := (mu(i), i=1..c) -> sum(mu(i)^2,i=1..c)
In other words, I want the symbolic form of f(MU)=norm(MU)^2, where MU is a vector of 1xc variables.
Thanks
EDIT:
In fact, I want to trace the following computation in mupad from Modeling Uncertainty with Fuzzy Logic: With Recent Theory and ....
I have also attached the picture of computation steps (of fuzzy c-means).
I'm not sure that I understand the question (how c can be a parameter, but not an input value?)
>> f = #(mu) sum(mu .^ 2); % applied on all elements
>> g = #(mu, c) sum(mu(1 : c) .^ 2); % applied on mu(1:c)
>> f(1:3)
ans =
14
>> g(1:10, 3)
ans =
14
f := mu -> _plus(mu[i]^2 $ i=1..nops(mu));
Call with a list:
f([1,2,3,4])
Or, to be able to invoke f(1,2,3,4):
f := () -> _plus(args(i)^2 $ i=1..args(0));