I experienced a strange behaviour in Matlab with the function subs and the built-in besselj:
syms x
f = besselj(1,x)
subs(f,1)
returns
besselj(1, 1)
even though the documentation states
"subs(s,new) returns a copy of s replacing all occurrences of the default variable in s with new, and then evaluating s.
The default variable is defined by symvar.
So I would expect the output of subs(f,1) to be 0.4401. eval(subs(f,1)) produces the correct output of 0.4401. Does anyone know why this is the case?
I feel like you're trying to define an anonymous function, you don't need subs or eval here, simply use f as an actual function...
% No need to use symbolic math toolbox for x or f
f = #(x) besselj(1,x); % Define f as an anonymous function of x
f(1) % Evaulate f at a given point, say x = 1
>> ans = 0.4401
Side note: If for some reason you're really set on using symbolic variables (they seem overkill here) then you may just want to use the eval function and a symbolic function handle instead of subs.
syms f(x) % Defines f as a symfun and x as a sym variable
f(x) = besselj(1,x); % Define the function
eval(f(1)) % Evaluate at x=1
>> ans = 0.4401
In answer to your question about why subs doesn't "evaluate" the answer when using subs(f, 1)... It's probably because the nature of the besselj function. Because you're using symvars, you are using the symbolic math package's besselj function (as opposed to the core-package function by the same name).
This means that a symbolic expression is displayed to the command window when subs is used, in the same way that any other symbolic expression is displayed without needing to be evaluated - i.e. they can be simplified but don't run other functions.
This is why you then need to run eval, to evaluate the simplified symbolic expression.
Related
I have this signal:
x(t) = t*sin(m*pi*t)*heaviside(-m*pi-t)+t*cos(k*pi*t)*heaviside(t-k*pi)+sin(k*pi*t)*cos(m*pi*t)*(heaviside(t+m*pi)-heaviside(t-k*pi));
and I want to calculate the values only from -5pi to 5pi with a step of pi/100 using Matlab. How could I do it?
Provided you have defined m and k somewhere, and you have the matlab symbolic toolbox which provides the heaviside function, this is how it is done:
% First we define the function
x = #(t) t*sin(m*pi*t)*heaviside(-m*pi-t)+t*cos(k*pi*t)*heaviside(t-k*pi)+sin(k*pi*t)*cos(m*pi*t)*(heaviside(t+m*pi)-heaviside(t-k*pi));
% Then we define the values for which we want to compute the function
t_values = -5*pi:pi/100:5*pi;
% Finally we evaluate the function
x_values = x(t_values)
Details
First line we define your function as an anonymous function which is a handy tool in matlab.
Then we create a vector of values from -5pi to 5*pi with steps of pi/100. For this we use the matlab colon syntax. It makes it short and efficient.
Finally we evaluate the function on each of the t_values by passing the vector to the anonymous function.
Note: If you don't have the symbolic toolbox, you could easily implement heaviside yourself.
gr = 9.81; %gravity
syms phi(t) m l
theta=1/3*m*l^2;
phidot=diff(phi,t);
U=m*gr*l/2*cos(phi);
T=1/2*theta*phidot^2+(1/2*phidot*l)^2*m;
L=T-U;
frst=diff(L,phidot);
The code is shown above. As you can see that phi(t) is symbolic time dependent function and phidot is derivation of it(also time dependent). L is obtained using these symbolic functions.
So, The problem is I can't derive L in terms of phidot in Matlab. The error occurs as following:
Error using sym/diff (line 26)
All arguments, except for the first one, must not be **symbolic** functions.
Error in pndlm (line 11)
frst=diff(L,phidot)
Is there any way to derive symbolic function in terms of another symbolic function? If not, Can you suggest me another alternative for avoiding this kind of error?
Possible duplicate of this
If you want to differentiate L with respect to q, q must be a
variable. You can use subs to replace it with a function and calculate
d/dt(dL/dq') later.
Remember those derivatives are partial. Hence just include explicitly the variable and obtain the expression.
% Variables
syms q qt m l g
theta=1/3*m*l^2;
% Lagrangian
U=m*g*l/2*cos(q);
T=1/2*theta*qt^2+(1/2*qt*l)^2*m;
L=T-U;
% Partial Derivatives
dLdq=diff(L,q)
dLdqt=diff(L,qt)
syms qf(t)
% Time Derivatives
qtf(t)=diff(qf,t)
dLdqf=subs(dLdqt,qt,qtf)
% Solution
m=1;l=1;g=9.81;
dsolve(diff(dLdqf,t)-dLdqf==0)
x=1;
f=#(x) x^3 - (5/x^2)-4*sin(x)-2;
fzero(f,x)
ans =
1.9227
I am supposed to find the root of the equation, x^3 - (5/x^2)-4*sin(x)-2, and the above code is the solution for it.
I don't understand the general mechanism of this code.
(1) What does # operator do?
I know its something like function handle, but I don't understand what function handle is.
(2) How does it work when it includes x in the parenthesis?
(3) How can there be a function fzero(), when I haven't made a script for fzero()?
(4) why are there two variables inside fzero()?
I don't understand that the variable 'f' does there
(5) Why did it declare x=1 in the beginning?
Please consider that I am pretty much new to MATLAB, and don't know much.
f = #(x) ... is the way to declare an anonymous function in MATLAB, actually not very different than creating a function normally in MATLAB such as function output = f(input) .... It is just the pratical way especially when you are working with mathematical functions.
#(x) defines that x is the variable of which is the same as f(x) in mathematics. fzero() is MATLAB's existing function to calculate the x value for f(x) = 0 which means calculating roots of defined funtion. Giving your x a real value at the beginning does mean the starting point to find the root. It will find the roots greater than 1 in your case. It will be very clear for you when you read existing documentation of MATLAB.
Edit:
If you give an interval such as x = [0 1] instead of x = 1, fzero(f,x) would try to calculate roots of f function in given interval, if there is no roots exist in that interval it woud return a NaN value.
I have been working on solving some equation in a more complicated context. However, I want to illustrate my question through the following simple example.
Consider the following two functions:
function y=f1(x)
y=1-x;
end
function y=f2(x)
if x<0
y=0;
else
y=x;
end
end
I want to solve the following equation: f1(x)=f2(x). The code I used is:
syms x;
x=solve(f1(x)-f2(x));
And I got the following error:
??? Error using ==> sym.sym>notimplemented at 2621
Function 'lt' is not implemented for MuPAD symbolic objects.
Error in ==> sym.sym>sym.lt at 812
notimplemented('lt');
Error in ==> f2 at 3
if x<0
I know the error is because x is a symbolic variable and therefore I could not compare x with 0 in the piecewise function f2(x).
Is there a way to fix this and solve the equation?
First, make sure symbolic math is even the appropriate solution method for your problem. In many cases it isn't. Look at fzero and fsolve amongst many others. A symbolic method is only needed if, for example, you want a formula or if you need to ensure precision.
In such an old version of Matlab, you may want to break up your piecewise function into separate continuous functions and solve them separately:
syms x;
s1 = solve(1-x^2,x) % For x >= 0
s2 = solve(1-x,x) % For x < 0
Then you can either manually examine or numerically compare the outputs to determine if any or all of the solutions are valid for the chosen regime – something like this:
s = [s1(double(s1) >= 0);s2(double(s2) < 0)]
You can also take advantage of the heaviside function, which is available in much older versions.
syms x;
f1 = 1-x;
f2 = x*heaviside(x);
s = solve(f1-f2,x)
Yes, the Heaviside function is 0.5 at zero – this gives it the appropriate mathematical properties. You can shift it to compare values other than zero. This is a standard technique.
In Matlab R2012a+, you can take advantage of assumptions in addition to the normal relational operators. To add to #AlexB's comment, you should convert the output of any logical comparison to symbolic before using isAlways:
isAlways(sym(x<0))
In your case, x is obviously not "always" on one side or the other of zero, but you may still find this useful in other cases.
If you want to get deep into Matlab's symbolic math, you can create piecewise functions using MuPAD, which are accessible from Matlab – e.g., see my example here.
I have made a function in func.m which is defined as follows:
function f = func(b)
f = b^2+1;
end
now i wish to differentiate with respect to that function i.e.
find 2*b+1 with a given value for b (lets say 1)
I tried diff(func(1)) but it returned an empty matrix.
Any ideas?
thanks
Your input argument func(1) is a vector of size 1x1. The function diff caled on vectors is this one: here. If you want to use the symbolic one, which allows to differentiate a function but requires the symbolic toolbox, you have to use a symbolic input. Explained here
Example:
% create a symbolic variable x
syms x
%differentiate f(x) and name it f1(x)
f1(x)=diff(f(x))
%get the value at point 1
f1(1)
If you don't have the symbolic toolbox, there is also a numeric solution.