Computing mixed derivatives in MATLAB using syms and diff - matlab

I'm using MATLAB 2012b.
I want to get d²/dxdy of a simple function:
f(x,y) = (x-1)² + 2y²
The documentation states that I can use syms and diff as in the following example:
> syms x y
> diff(x*sin(x*y), x, y)
ans =
2*x*cos(x*y) - x^2*y*sin(x*y)
But doing the same I got the wrong answer:
> syms x y
> f = (x-1)^2 + 2*y^2;
> diff(f,x,y)
ans =
4*y
The answer is right if I use diff like this:
diff(diff(f,x),y)
Well, it's not a problem for me to use it this way, but nevertheless why is the first variant not working? Is it a version issue?

The actual documentation from R2010a:
diff(expr) differentiates a symbolic expression expr with respect to its free variable as determined by symvar.
diff(expr, v) and diff(expr, sym('v')) differentiate expr with respect to v.
diff(expr, n) differentiates expr n times. n is a positive integer.
diff(expr, v, n) and diff(expr, n, v) differentiate expr with respect to v n times.
So, the command diff(f,x,y) is the last case. It would be equal to differentiating f w.r.t. x, y times, or w.r.t y, x times.
For some reason I don't quite understand, you don't get a warning or error, but one of the syms variables gets interpreted as n = 1, and then the differentiation is carried out. In this case, what diff seems to do is basically diff(f, y, 1).
In any case, it seems that the behavior changed from version to version, because in the documentation you link to (R2016b), there is an additional case:
diff(F,var1,...,varN) differentiates F with respect to the variables var1,...,varN
So I suspect you're running into a version issue.
If you want to differentiate twice, both w.r.t x and y, your second attempt is indeed the correct and most portable way to do that:
diff( diff(f,x), y )
or equivalently
diff( diff(f,y), x )
NB
I checked the R2010a code for symbolic/symbolic/#sym/diff.m and indeed, n is defaulted to 1 and only changed if one of the input variables is a double, and the variable to differentiate over is set equal to the last syms variable in the argument list. The multiple syms variable call is not supported, nor detected and error-trapped.

Syms is only creating symbolic variables.
The first code you execute is only a single derivative. The second code you provided differentiates two times. So I think you forgot to differentiate a second time in the first piece of code you provided.
I am also wondering what answer you expect? If you want 4*y as answer, than you should use
diff(f,y)
and not
diff(f,x,y)
Performing the second derivative is giving me zero?
diff(diff(f,x),y)
If you want 4 as answer than you have to do following:
diff(diff(f,y),y)

Related

Gradient of implicit symbolic expression in Matlab

The situation I have is as follows:
I have a symbolic expression like:
syms X Y Z K
Ra=51.7;
P=[0 0 200];
Sa=sym('Ra^2==(Z-P(3))^2+(Y-P(2))^2')
Where Y and Z are defined as symbolic. Ra and P are vectors.
I need to get the gradient of Sa but I get an error:
G=gradient(Sa,[Y Z]);
Error using symengine (line 59)
The first argument must be of type 'Type::Arithmetical'.
Error in sym/gradient (line 39)
res = mupadmex('symobj::gradient',fsym.s,x.s);
But if I write the same expression as:
Sa(Y,Z)=((Z-P(3))^2+(Y-P(2))^2-Ra^2);
I get the expected result
G=gradient(Sa,[Y Z])
G(X, Y, Z) =
2*Y
2*Z - 400
Does anyone knows why this is so and if there's any way of using the implicit expression as this is a particular case but in general I have different implicit expressions and my code should be able to deal with them.
I've read the documentation on gradient and some sites, but if I found the answer I didn't notice.
I believe I could use the second form but still, I am curious about this subject.
Thanks for your time.
In the first one Sa is the entire equation, including the ==, while in the second one its a symbolic function depending on 2 variables.
Ultimately the way MATLAB seems to be handle this is that the first one is not derivable (also its dependent in another 2 sym variables, that doesn't know if they are related or not to the derived ones), while the second one gets identified as a function (symbolic) and can get derived.

Indefinite integration with Matlab's Symbolic Toolbox - complex solution

I'm using Matlab 2014b. I've tried:
clear all
syms x real
assumeAlso(x>=5)
This returned:
ans =
[ 5 <= x, in(x, 'real')]
Then I tried:
int(sqrt(x^2-25)/x,x)
But this still returned a complex answer:
(x^2 - 25)^(1/2) - log(((x^2 - 25)^(1/2) + 5*i)/x)*5*i
I tried the simplify command, but still a complex answer. Now, this might be fixed in the latest version of Matlab. If so, can people let me know or offer a suggestion for getting the real answer?
The hand-calculated answer is sqrt(x^2-25)-5*asec(x/5)+C.
This behavior is present in R2017b, though when converted to floating point the imaginary components are different.
Why does this occur?
This occurs because Matlab's int function returns the full general solution when you ask for the indefinite integral. This solution is valid over the entire domain of of real values, including your restricted domain of x>=5.
With a bit of math you can show that the solution is always real for x>=5 (see complex logarithm). Or you can use more symbolic math via the isAlways function to show this:
syms x real
assume(x>=5)
y = int(sqrt(x^2-25)/x, x)
isAlways(imag(y)==0)
This returns true (logical 1). Unfortunately, Matlab's simplification routines appear to not be able to reduce this expression when assumptions are included. You might also submit this case to The MathWorks as a service request in case they'd consider improving the simplification for this and similar equations.
How can this be "fixed"?
If you want to get rid of the zero-valued imaginary part of the solution you can use sym/real:
real(y)
which returns 5*atan2(5, (x^2-25)^(1/2)) + (x^2-25)^(1/2).
Also, as #SardarUsama points out, when the full solution is converted to floating point (or variable precision) there will sometimes numeric imprecision when converting from exact symbolic form. Using the symbolic real form above should avoid this.
The answer is not really complex.
Take a look at this:
clear all; %To clear the conditions of x as real and >=5 (simple clear doesn't clear that)
syms x;
y = int(sqrt(x^2-25)/x, x)
which, as we know, gives:
y =
(x^2 - 25)^(1/2) - log(((x^2 - 25)^(1/2) + 5i)/x)*5i
Now put some real values of x≥5 to check what result it gives:
n = 1004; %We'll be putting 1000 values of x in y from 5 to 1004
yk = zeros(1000,1); %Preallocation
for k=5:n
yk(k-4) = subs(y,x,k); %Putting the value of x
end
Now let's check the imaginary part of the result we have:
>> imag(yk)
ans =
1.0e-70 *
0
0
0
0
0.028298997121333
0.028298997121333
0.028298997121333
%and so on...
Notice the multiplier 1e-70.
Let's check the maximum value of imaginary part in yk.
>> max(imag(yk))
ans =
1.131959884853339e-71
This implies that the imaginary part is extremely small and it is not a considerable amount to be worried about. Ideally it may be zero and it's coming due to imprecise calculations. Hence, it is safe to call your result real.

Set complicated assumptions on symbolic function

I am trying to find the roots of a nonlinear function that depends on several symbolic variables and a symbolic function. To guarantee the existence of a solution I need to set some assumptions on the symbolic function b(x).
By using the Matlab function assume I can set simple assumptions like
syms b(x) d
assume(b(0)==0 & b(x)>=0);
Now I am looking for a way to include this assumption: (symbolic function b(x), symbolic variable d)
There is a value y such that b(x) < d*x for x < y and b(x) > d*x for x > y.
To make it easier we can fix for example d=0.1 and b(10)=1 such that y=10. However I would prefer leaving d and y symbolic.
I tried to write a function that checks the assumption but unsurprisingly Matlab does not seem to accept a symbolic function as an input variable.
Do you know a solution to this problem or have an idea?
Update 2017-01-03:
While having fixed d=0.1,b(10)=1 and y=10 I am trying to check the above assumption by using
syms b(x)
d=0.1;
assume(x, 'real');
assume(x>=0);
assume(b(0)==0 & b(x)>=0 & b(10)==1);
checkAssumption(x)= mySign(x)*(d*x-b(x));
assume(checkAssumption(x)>=0);
where
function sign=mySign(x)
if x<10
sign=-1;
else if x==10
sign=0;
else if x>10
sign=-1;
end
end
end
Then I get the error "Conversion to logical from sym is not possible." in mySign. Using double(x) as the input variable of mySign leads to the error "DOUBLE cannot convert the input expression into a double array".
Do you know a way to get mySign and checkAssumptions evaluated or have an other idea how to assume the above assumption?

Unable to code non linear equation in MATLAB R2013a - MATLAB giving warning message

I wanted to solve the following equation in MATLAB R2013a using the Symbolic Math Toolbox.
(y/x)-(((1+r)^n)-1)/r=0 where y,x and n>3 are given and r is the dependent variable
I tried myself & coded as follows:
f=solve('(y/x)-(((1+r)^n)-1)/r','r')
but as the solution for r is not exact i.e. it is converging on successive iterations hence MATLAB is giving a warning output with the message
Warning: Explicit solution could not be found.
f =
[ empty sym ]
How do I code this?
There are an infinite number of solutions to this for an unspecified value of n > 3 and unknown r. I hope that it's pretty clear why – it's effectively asking for a greater and greater number of roots of (1+r)^n. You can find solutions for fixed values of n, however. Note that as n becomes larger there are more and more solutions and of course some of them are complex. I'm going to assume that you're only interested in real values of r. You can use solve and symbolic math for n = 4, n = 5, and n = 6 (for n = 6, the solution may not be in a convenient form):
y = 441361;
x = 66990;
n = 5;
syms r;
rsol = solve(y/x-((1+r)^n-1)/r==0,r,'IgnoreAnalyticConstraints',true)
double(rsol)
However, the question is "do you need all the solutions or just a particular solution for a given value of n"? If you just need a particular solution, you shouldn't be using symbolic math at all as it's slower and has practical issues like the ones you're experiencing. You can instead just use a numerical approach to find a zero of the equation that is near a specified initial guess. fzero is the standard function for solving this sort of problem in a single variable:
y = 441361;
x = 66990;
n = 5;
f = #(r)y/x-((1+r).^n-1)./r;
r0 = 1;
rsol = fzero(f,r0)
You'll see that the value returned is the same as one of the solutions from the symbolic solution above. If you adjust the initial guess r0 (say r0 = -3), it will return the other solution. When using numeric approaches in cases when there are multiple solutions, if you want specific solutions you'll need to know about the behavior of your function and you'll need to add some clever extra code to choose initial guesses.
I think you forgot to define n as well.
f=solve('(y/x)-(((1+r)^n)-1)/r=0','n-3>0','r','n')
Should solve your problem :)

Can I change the formula of a symbolic function in MATLAB?

I have the following code:
syms t x;
e=symfun(x-t,[x,t]);
In the problem I want to solve x is a function of t but I only know its value at the given t,so I modeled it here as a variable.I want to differentiate e with respect to time without "losing" x,so that I can then substitute it with x'(t) which is known to me.
In another question of mine here,someone suggested that I write the following:
e=symfun(exp(t)-t,[t]);
and after the differentiation check if I can substitute exp(t) with the value of x'(t).
Is this possible?Is there any other neater way?
I'm really not sure I understand what you're asking (and I didn't understand your other question either), but here's an attempt.
Since, x is a function of time, let's make that explicit by making it what the help and documentation for symfun calls an "abstract" or "arbitrary" symbolic function, i.e., one without a definition. In Matlab R2014b:
syms t x(t);
e = symfun(x-t,t)
which returns
e(t) =
x(t) - t
Taking the derivative of the symfun function e with respect to time:
edot = diff(e,t)
returns
edot(t) =
D(x)(t) - 1
the expression for edot(t) is a function of the derivative of x with respect to time:
xdot = diff(x,t)
which is the abstract symfun:
xdot(t) =
D(x)(t)
Now, I think you want to be able to substitute a specific value for xdot (xdot_given) into e(t) for t at t_given. You should be able to do this just using subs, e.g., something like this:
sums t_given xdot_given;
edot_t_given = subs(edot,{t,xdot},{t_given, xdot_given});
You may not need to substitute t if the only parts of edot that are a function of time are the xdot parts.