Using inline function with constant arguments in MATLAB - 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')

Related

How to describe the derivative of matlab symbolic variable?

For example, I named the variables x(t), xdot(t) about time: syms t x(t) xdot(t);, and the derivative of x about time is xdot, xdot=diff(x,t).
But when I calculate diff (x, t), the result is not xdot. How can I set the display of diff (x, t) in the calculation result to xdot?
In addition, the time variable in the calculation result is displayed in the form of variable(t). How to set the result to display only variable?
syms t x(t) xdot(t);
xdot=diff(x,t);
y=diff(x,t);
y
the result of y is displayed as , however, I want it to be xdot
Consider the following code:
a = 3;
b = 3;
b
It appears to me, you would like this to display b = a, instead of b = 3. This is not how MATLAB works. Both a and b are equal to 3, but that doesn't mean a is b.
The same is true for the code:
a = 3;
b = a;
b
This gives b = 3, not b = a. I won't go into details about why this is the case (and why it has to be the case in MATLAB). It's enough to know that this is how it works.
You have assigned diff(x,t) to two different variables, xdot and y. This means that, while xdot and y have the same value, xdot is not y.
If you do xdot = 3 after your code, then y would still be dx/dt.
Side note: Why do you want this behaviour? Are you sure it's necessary? You can always print the result however you like:
fprintf('xdot = %s', y(t))
xdot = diff(x(t), t)
Ugly workaround to do something I don't understand why you would do:
Create a function:
function res = xdot(t)
syms x(t) res;
res = diff(x,t);
end
And then define y as a function handle:
y = #xdot
y = function_handle with value:
#xdot
Now y(t) will still give dx/dt, but y will give xdot
I strongly recommend you don't do this.

Problems attaching a function handle on Matlab to integral expression

I have an integral expression which I defined on Matlab using
x = 0:1/1000:1;
g = #(x) (exp(-1./x.^2).*heaviside(x)).*(exp(-1./(1-x).^2).*heaviside(1-x));
t = 0:1/1000:1;
f = zeros(size(t));
for i = 1:length(t)
f(i) = integral(g,0,t(i));
end
I can plot it, for example, using plot(t,f), but for other purposes I would like to attach a function handle to f, i.e. something like f = #(t) zeros(size(t)). I have not been able to figure it out thus far. f = #(t) integral(#(x)g(x),0,t) is also not sufficient.
Sorry, I can't comment yet. But does this work?
funcHand= #(t) integral(g,0,t);
You don't have to define x in your code above, since the input to integral is a function handle.
Then to check it's the same:
f2 = zeros(size(t));
for i = 1:length(t)
f2(i) = funcHand(t(i));
end
Whoops, the other answer said all the above (just replaced the for loop with arrayfun. I didn't see it while writing the answer.
Edit
If you want to build-in the for loop, try:
funcHand= #(t) arrayfun(#(u) integral(g, 0, u),t);
And test:
plot(funcHand(t))
Try
f = #(u) integral(g, 0, u)
The additional level of indirection in g seems superfluous. Note that I have called the input u. Keep in mind that f will not accept vectors as its inputs. So doing something like f(t) in your current workspace will not create the same array as your for loop is doing. You will have to iterate through the array. The convenience function arrayfun will do this for you:
o = arrayfun(f, t)
It is roughly equivalent to the loop you have now:
o = zeros(size(t));
for i = 1:length(o)
o(i) = f(t(i));
end
arrayfun can actually be incorporated into your function handle to allow it to process vector arguments:
h = #(t) arrayfun(f, t)
To avoid the proliferation of unnecessary function handles, you can do
f = #(t) arrayfun(#(u) integral(g, 0, u), t)

Use value of variable instead of its name lambdas matlab

How to use value of variable instead of its name during the description of a lambda expression? This is part of my code:
eq1 = k*x1+b==y1;
eq2 = k*x2+b==y2;
sol=solve([eq1,eq2],[k,b]);
linEq1 = #(x) sol.k*x+sol.b;
if (defY<linEq1(defX))
ineq = #(x,y) y<=sol.k*x+sol.b;
else
ineq = #(x,y) y>=sol.k*x+sol.b;
end
I need to use value of sol.b and sol.k in lambda expression instead of their names. When I use function which contains this code I can see in workspace:
y<=sol.k*x+sol.b
instead of
y<=5x+3
for example.
I tried to condense your code a bit. Please provide a minimal working example next time.
a = 5
b = 3
y = #(x) a*x + b % note that a and b are evaluated at definition
a = 4
y(1) % this is 8 (even though we changed the value of a)
% but if you really really want to do what you are asking, this is how:
eval(['y = #(x) ' num2str(a) '*x + ' num2str(b)]) % yields y = #(x)4*x+3

Replicating Simpson's rule, error with eval

I'm trying to replicate the Simpson's rule by writing a function for it. However, I'm still not clear how I could possibly use eval to transform a string to a actual function in MatLab.
The function is:
function result = simpson(fun, x0, xn, n)
f = eval(fun);
h = (xn-x0)/2;
xstart = f(x0) + f(xn);
x1 = 0;
x2 = 0;
for i = 1:n-1
x = x0 + h*i;
if (mod(i,2) == 0)
x2 = x2 + f(x);
else
x1 = x1 + f(x);
end
end
result = h*(xstart + 2*x2 + 4*x1)/3;
The error reported is
Error using eval
Undefined function or variable 'x'
How could I pass x to a string form of a function?
The clean way to do that: Use a function handle, avoid eval.
Function handles are documented here: http://www.mathworks.de/de/help/matlab/ref/function_handle.html
Define them like this:
sqr = #(x) x.^2;
and then call your function:
simpson(sqr, 1, 2, 3);
within your function, you should e able to call fun(3) and get 9 as a result.
If you have to use eval, I could see two solutions:
The Sneaky way: simpson('#(x) x.^2') (eval creates a proper function handle)
The dirty way:
function result = simpson(fun)
x = 4;
f = eval(fun);
result = f;
return;
end
Call it like this: simpson('x.^2')
The problem here is the way eval is being used. The documentation indicates that in your example the output f would not be a function handle (as is expected by the way the code uses it), but rather the output of the fun function.
So, in order to make the eval function work you need to provide it with it's input.
For example:
fun = 'x.^2';
x = 4;
f = eval(fun);
Results in f == 16
In short, any time you wish to call fun you would have to set x to the appropriate value, call eval and store the result.
For example, in your code:
f = eval(fun);
h = (xn-x0)/2;
xstart = f(x0) + f(xn);
Would become:
h = (xn-x0)/2;
x = x0;
fx0 = eval(fun);
x = xn;
fxn = eval(fun);
xstart = fx0 + fxn;
I would suggest function handles as a safer and easier way of implementing this, but as mentioned in the comments this is not allowed in your case.

Shortening long expressions

I want to create a function handle to the function:
f = #(x) (x-1)*(x-2)*...*(x-50);
How can I do this in MATLAB without typing all 50 terms?
Here is a vectorized solution:
y = prod((x-[1:50]))
Or if you want an anonymous function:
f = #(x) ( prod((x-[1:50])) )
By the way, it might not be faster than #Chris solution (which is good, and I upvoted it), because of Matlab JIT-Accelerator.
You could wrap it in a function. For example,
function y = myfunc(x, n)
y = 1.;
for i = 1:n
y = y*(x-i);
end
end
The function you defined is basically the product of a sequence, which are trivially written as for loops.
In your case you want to compute this result for 50 terms, so you could just use y = myfunc(x, 50) or, if you want this to be a function handle, you could define
f = #(x) myfunc(x, 50);