Matlab simplify - why does it remove fractions? - matlab

I am recently working with Matlab's Symbolic Toolbox, but encountered a big problem. I have some example code:
syms s w;
G = 0.1253/(s^4 + 0.5816*s^3 + 1.1691*s^2 + 0.4048*s + 0.177)
L1=diff(G)
L2=subs(L1,s,-s)
M2=subs(G,s,-s)
Ts=(-1/2)*((L1/G)+(L2/M2))
T=subs(Ts,s,1i*w)
Ts = simplify(T)
Everything is working well, except for the part with T=subs(Ts,s,1i*w) and T=subs(Ts,s,1i*w). In order to calculate i as i^2 = -1, I have to use simplify, but then all of the fractions disappear.
Is there any other function to do what I need? Or am I doing something wrong?

Related

Definite integration using int command

Firstly, I'm quite new to Matlab.
I am currently trying to do a definite integral with respect to y of a particular function. The function that I want to integrate is
(note that the big parenthesis is multiplying with the first factor - I can't get the latex to not make it look like power)
I have tried plugging the above integral into Desmos and it worked as intended. My plan was to vary the value of x and y and will be using for loop via matlab.
However, after trying to use the int function to calculate the definite integral with the code as follow:
h = 5;
a = 2;
syms y
x = 3.8;
p = 2.*x.^2+2.*a.*y;
q = x.^2+y.^2;
r = x.^2+a.^2;
f = (-1./sqrt(1-(p.^2./(4.*q.*r)))).*(2.*sqrt(q).*sqrt(r).*2.*a-p.*2.*y.*sqrt(r)./sqrt(q))./(4.*q.*r);
theta = int(f,y,a+0.01,h) %the integral is undefined at y=2, hence the +0.01
the result is not quite as expected
theta =
int(-((8*461^(1/2)*(y^2 + 361/25)^(1/2))/5 - (461^(1/2)*y*(8*y + 1444/25))/(5*(y^2 + 361/25)^(1/2)))/((1 - (4*y + 722/25)^2/((1844*y^2)/25 + 665684/625))^(1/2)*((1844*y^2)/25 + 665684/625)), y, 21/10, 5)
After browsing through various posts, the common mistake is the undefined interval but the +0.01 should have fixed it. Any guidance on what went wrong is much appreciated.
The Definite Integrals example in the docs shows exactly this type of output when a closed form cannot be computed. You can approximate it numerically using vpa, i.e.
F = int(f,y,a,h);
theta = vpa(F);
Or you can do a numerical computation directly
theta = vpaintegral(f,y,a,h);
From the docs:
The vpaintegral function is faster and provides control over integration tolerances.

A double symbolic integral in Matlab

I am trying to calculate some integrals, for example:
a = 1/sqrt(2);
b = -5;
c = 62;
d = 1;
f = exp(-x^2-y^2)*(erfc((sym(a) + 1/(x^2+y^2)*(sym(b)*x+sym(d)*y))*sqrt((x^2+y^2)*sym(10.^(c/10))))...
+ erfc((sym(a) - 1/(x^2+y^2)*(sym(b)*x+sym(d)*y))*sqrt((x^2+y^2)*sym(10.^(c/10)))));
h = int(int(f,x,-Inf,Inf),y,-Inf,Inf);
It will occur error like this:
Warning: Explicit integral could not be found.
Then, I try to use vpato calculate that integral,and get the result like this
vpa(int(int(f,x,-Inf,Inf),y,-Inf,Inf),5)
numeric::int(numeric::int(exp(- x^2 - y^2)*(erfc(((6807064429273519*x^2)/4294967296 + (6807064429273519*y^2)/4294967296)^(1/2)*(2^(1/2)/2 + (5*x - y)/(x^2 + y^2))) + erfc(((6807064429273519*x^2)/4294967296 + (6807064429273519*y^2)/4294967296)^(1/2)*(2^(1/2)/2 - (5*x - y)/(x^2 + y^2)))), x == -Inf..Inf), y == -Inf..Inf)
I already tried to change the interval [-Inf,Inf] to [-100,100], and get the same above result:
numeric::int(numeric::int(exp(- x^2 - y^2)*(erfc(((6807064429273519*x^2)/4294967296 + (6807064429273519*y^2)/4294967296)^(1/2)*(2^(1/2)/2 + (5*x - y)/(x^2 + y^2))) + erfc(((6807064429273519*x^2)/4294967296 + (6807064429273519*y^2)/4294967296)^(1/2)*(2^(1/2)/2 - (5*x - y)/(x^2 + y^2)))), x == -100..100), y == -100..100)
My question is why vpa in this case could not return to a real value?
There are something wrong in above Matlab code? (I, myself, could not find the bug so far)
Thank you in advance for your help.
It is unlikely that there is an analytic solution to this integral so using int may not be a good choice. In some cases vpa can be used to for a numeric solution. When this fails (by returning a call to itself) it may be for several reason: the integral may not exist, the integral may converge too slowly, singularities may cause issues, the integrand may be highly oscillatory or non-smooth, etc. Mathematica also struggles with this integral.
You can try calculating the integral numerically using integral2:
a = 1/sqrt(2);
b = -5;
c = 62;
d = 1;
f = #(x,y)exp(-x.^2-y.^2).*(erfc((a + 1./(x.^2+y.^2).*(b*x+d*y)).*sqrt((x.^2+y.^2)*10^(c/10)))...
+erfc((a - 1./(x.^2+y.^2).*(b*x+d*y)).*sqrt((x.^2+y.^2)*10^(c/10))));
h = integral2(f,-Inf,Inf,-Inf,Inf)
which returns 5.790631184403967. This compares well with Mathematica's numerical integration using NIntegrate. You can try specifying smaller absolute and relative tolerances for integral2 to get more accurate values, but this will result in much slower compute times.

Make sure MATLAB does not recalculate symbolic expression

I am building (my first...) MatLab program, it needs to differentiate an equations symbolically and then use this solution many many times (with different numeric inputs).
I do not want it to recalculate the symbolic differentiation every time it needs to put in a new set of numeric values. This would probably greatly add to the time taken to run this program (which - given its nature, a numeric optimiser, will probably already be hours).
My question is how can I structure my program such that it will not recalculate the symbolic differentiation?
The class in question is:
function [ result ] = GradOmega(numX, numY, numZ, numMu)
syms x y z mu
omega = 0.5*(x^2+y^2+z^2) + (1-mu)/((x+mu)^2+y^2+z^2)^0.5 + mu/((x+mu-1)^2+y^2+z^2)^0.5;
symGradient = gradient(omega);
%//Substitute the given numeric values back into the funtion
result = subs(symGradient, {x,y,z,mu}, {numX, numY, numZ, numMu});
end
I know that I could just symbolically calculate the derivative and then copy-paste it into the code e.g.
gradX = x + ((2*mu + 2*x)*(mu - 1))/(2*((mu + x)^2 + y^2 + z^2)^(3/2)) - (mu*(2*mu + 2*x - 2))/(2*((mu + x - 1)^2 + y^2 + z^2)^(3/2));
gradY = y - (mu*y)/((mu + x - 1)^2 + y^2 + z^2)^(3/2) + (y*(mu - 1))/((mu + x)^2 + y^2 + z^2)^(3/2);
gradZ = z - (mu*z)/((mu + x - 1)^2 + y^2 + z^2)^(3/2) + (z*(mu - 1))/((mu + x)^2 + y^2 + z^2)^(3/2);
But then my code is a bit cryptic, which is a problem in a shared project.
There is a related query here: http://uk.mathworks.com/matlabcentral/answers/53542-oop-how-to-avoid-recalculation-on-dependent-properties-i-hope-a-mathwork-developer-could-give-me-a
But I'm afraid I couldn't follow the code.
Also I am much more familiar with Java and Python, if that helps explain anything.
You could wrap your function into some kind of Function-Factory, which does not return numerical results, but a function that can be evaluated:
(I had to replace the call syms with sym('mu'), because for some reason it kept calling a mutools function in line omega = .... I did also change the call to gradient to make sure the arguments are in correct order, and mu will be treated as constant.)
function GradOmega = GradOmegaFactory()
x = sym('x');
y = sym('y');
z = sym('z');
mu = sym('mu');
omega = 0.5*(x^2+y^2+z^2) + (1-mu)/((x+mu)^2+y^2+z^2)^0.5 + mu/((x+mu-1)^2+y^2+z^2)^0.5;
symGradient = gradient(omega,{'x','y','z'});
GradOmega = matlabFunction(symGradient, 'vars', {'x','y','z','mu'});
end
Then you would call it via:
GradOmega = GradOmegaFactory();
result1 = GradOmega(numX1, numY1, numZ1, numMu1);
result2 = GradOmega(numX2, numY2, numZ2, numMu2);
result3 = GradOmega(numX3, numY3, numZ3, numMu3);
...
Even better:
You could go even more fancy and use a wrapper function GradOmega which builds such a function inside and makes it persistent, to get the same interface you had with your initial approach. The first time you call the function GradOmega the symbolic expression is evaluated, but on each consecutive call you will only have to evaluate the generated function handle, which means it should be nearly as fast as if you hard-coded it.
function result = GradOmega(numX, numY, numZ, numMu)
persistent numericalGradOmega;
if isempty(numericalGradOmega)
numericalGradOmega = GradOmegaFactory();
end
result = numericalGradOmega(numX, numY, numZ, numMu);
end
Use this like you would use your original version
result = GradOmega(numX, numY, numZ, numMu);
Just copy and paste both functions into a single GradOmega.m file. (GradOmega should be the first function in the file.)
Another tip: You can even evaluate this function using vectors. Instead of calling GradOmega(1,2,3,4) and GradOmega(5,6,7,8) afterwards, you can save the time overhead via the call GradOmega([1,5], [2,6], [3,7], [4,8]) using row vectors.
Yet another tip: To clean up your code even more, you could also put the first lines into a separate symOmega.m file.
function omega = symOmega()
x = sym('x');
y = sym('y');
z = sym('z');
mu = sym('mu');
omega = 0.5*(x^2+y^2+z^2) + (1-mu)/((x+mu)^2+y^2+z^2)^0.5 + mu/((x+mu-1)^2+y^2+z^2)^0.5;
This way you don't have to have a copy of this symbolic expression in every file you use it. This can be beneficial if you also want to evaluate Omega itself, as you then can make use of the same Factory-approach listed in this answer. You would end up with the following files: symOmega.m, Omega.m and GradOmega.m, where only the file symOmega.m has the actual mathematical formula and the other two files make use of symOmega.m.

Solve trigonometrics equations in Matlab

I'm trying to solve for t trigonometric equations in Matlab, as i.e. 7*cos(t) + 5*sin(t) = 0. I would solve it as: sin(t)/cos(t) = -7/5 and I would find it as arctan(-7/5) = -0.9505.
I have tried to do it on matlab using solve function:
syms t
theta = solve(7*cos(t) + 5*sin(t)==0, t);
disp(theta);
But I get -(log(- 12/37 - (35*i)/37)*i)/2 instead of -0.9505. Could someone explain me why I get this answer from solve and how to get -0.9505?
The expression is the exact result, expressed symbolically (due to the use of syms).
To make Matlab display the result in the format your looking for use double(theta)
which should give you:
double(theta)
ans =
-0.9505

How can I solve 2 complex equations with 2 variables in MATLAB?

I have these two equations:
y1=a*(10/11- (3*i)/4) + b*(5/6+ (7*i)/5)
y2= -1+(j*2)
where: y1=y2 , And I want to find the exact value of "a" and "b" using only MATLAB.
Is there any MATLAB command I should use to solve these two equations??
p.s.: I tried to use solve command, but it doesn't give me any answer:
syms a b
y1=a*(10/11- (3*i)/4) + b*(5/6+ (7*i)/5);
y2= -1+(j*2);
s=solve('y1-y2=0',[a b])
It gives me this:
Warning: Explicit solution could not be found.
> In solve at 160
s =
[ empty sym ]
First, make sure you wrote your equations properly (operation precedence, parentheses):
in y1, the second and third terms are written weird:
if you simplify (according to what you wrote) it just becomes (45/124)*i + b*(67/30)
Also, why mix i and j in y2 ?
If you did all this well, and you still get the same answer, it really means there is no solution possible.
EDIT:
And looking at this again, you don't have a 2 equation / 2 variable system, you have 3 variables (y,a,b)... which means you can't solve.
EDIT 2:
From the last comment: well just do what you say you want to do, equalize the real and imaginary part of both equations:
syms a;
S = solve('a*(10/11)+b*(5/6)=-1','a*(3/4)+b*(7/5)=2');
S = [S.a S.b]
S =
[-4048/855, 226/57]
>> syms a b
>> solve( a*(10/11- (3*i)/4) + (3/4*i+ ((12)/(31*i))) + b*(5/6+ (7*i)/5i)==-1+(j*2))
a*(- 300/737 + (45*i)/134) - 30/67 + (3045*i)/4154
See official doc.