Use of (ilaplace) give different result through sym variable and directly - matlab

I have a symbolic variable, which contain, for example:
p =
(9311.0*s + 6.12e9)/(s^2 + 8500.0*s + 3.61e11)
where s - also symbolic.
Then, if I use inverse laplace through variable p, then result is
>>result=vpa(ilaplace(p,s,n),3)
result =
exp(n*(- 4255.0 + 6.01e5*i))*(4666.0 - 5066.0*i) + exp(n*(- 4255.0 - 6.01e5*i))*(4666.0 + 5066.0*i)
But if I put expression directly, I will get what I expect (by formula in Korn's book or by definition):
vpa(ilaplace((9311.0*s + 6.12e9)/(s^2 + 8500.0*s + 3.61e11),s,n),3)
ans =
9311.0*exp(-4255.0*n)*(cos(6.01e5*n) + 1.09*sin(6.01e5*n))
Why? And what should I do to get right answer through variable?
P.S. vpa - is not influenced on main goal. It only left 3 digits in this case after point.
P.S.S. Added more code:
t = tf(linsys1) %linsys1 - from simulink circuit
%get coefficients from transfer function t
[num,den] = tfdata(t);
syms s n real
% convert transfer function to symbolic
t_sym = poly2sym(cell2mat(num),s)/poly2sym(cell2mat(den),s);
functionInMuPad=['partfrac(',char(t_sym),',s,Domain = R_)']; %collect expression in string format
simpleFraction=evalin(symengine,functionInMuPad); % sum of simple fractions (only MuPad allows get denominator of 2nd order)
functionInMuPad2=['op(',char(simpleFraction),')']; %collect expression in string format
vectorOfOperand=evalin(symengine,functionInMuPad2); % vector of simple fractions
for k=1:length(vectorOfOperand)-1
z(k,1)=ilaplace(vectorOfOperand(k),s,n);
end
So, something wrong with vectorOfOperand.
ilaplace(vectorOfOperand(1)) gives complex result, but if copy (ctrl+c) value of vectorOfOperand(1) and make newVariable=Ctrl+V, then ilaplace(newVariable) - it's ok either in command window or in m-file:
bbb =(9313.8202564498255348020392071286*s + 6122529964.4040716985063406588769)/(8500.4056471180697831891961467533*s + s^2 + 360665607284.96754103451618653904);
ilaplace(bbb,s,n)
ans=9311.0*exp(-4255.0*n)*(cos(6.01e5*n) + 1.09*sin(6.01e5*n)) %after vpa
Kind of magic anyway. vectorOfOperand - is sym. I even made this:
vectorOfOperand=char(vectorOfOperand);
vectorOfOperand=sym(vectorOfOperand); it doesn't help..

Related

Getting real and imaginary parts of complex function in matlab

I've got a following question. I've got function f(t) = C3*exp(t*x*1i) + C4*exp(-t*x*1i) as a solution of a differential equation (as syms). But I need this solution as a real function (C3*cos + C4*sin). How can I do it? And how can I get real and imaginary parts of this function? Is there a function in matlab allowing me to do it?
You can use rewrite to rewrite the expression in terms of cosines and sines, then collect to collect coefficients in terms of i, giving you your real and imaginary terms:
f = C3*exp(t*x*1i) + C4*exp(-t*x*1i);
g = collect(rewrite(f, 'sincos'), i)
g =
(C3*sin(t*x) - C4*sin(t*x))*1i + C3*cos(t*x) + C4*cos(t*x)
You can see from the above that the imaginary term is zero if C3 is equal to C4.
You can rewrite the expression/function in terms of sine and cosine using rewrite. Still you cannot apply the real and imag functions to get the respective parts in as nicer form as you get in case of non-symbolic computations. The trick to get the real and imaginary parts in a complex expression is to substitute i with 0 to get the real part and then subtract the real part from the original expression to get the imaginary part. Use simplify for the surety.
An example:
syms C3 C4 t x
f(t) = C3*exp(t*x*1i) + C4*exp(-t*x*1i);
fsincos = rewrite(f, 'sincos');
realf = simplify(subs(fsincos, i,0));
imagf = simplify(fsincos-realf);
%or you can use the collect function to avoid simplify
>> fsincos
fsincos(t) =
C3*(cos(t*x) + sin(t*x)*1i) + C4*(cos(t*x) - sin(t*x)*1i)
>> realf
realf(t) =
cos(t*x)*(C3 + C4)
>> imagf
imagf(t) =
sin(t*x)*(C3*1i - C4*1i)

Solving the system of non-linear equations in MATLAB by fsolve

I have a code that produces a vector in MATLAB, for example the following is a three component vector (n=3):
a1_1 - sin((17*a1_1)/60 + a2_1/8 + a3_1/40 - 0.153233)
(15*a1_1)/16 + a2_1/4 + a3_1/32 - sin((17*a1_1)/60 + a2_1/8 + a3_1/40 - 0.0282326)
(3*a1_1)/4 + a2_1/2 + a3_1/8 - sin((17*a1_1)/60 + a2_1/8 + a3_1/40 + 0.846767)
as you can see each component is a non-linear equation. The three component of the vector forms a system of three non-linear equations having it's variables named as a1_1, a1_2and a1_3. I want to solve this system by fsolve.
How do I do that for arbitrary n?
To use fsolve, your function must accept a vector input and return a vector of the same size. In your case you can accomplish this with an anonymous function:
f = #(a)[a(1) - sin(17*a(1)/60 + a(2)/8 + a(3)/40 - 0.153233);...
15*a(1)/16 + a(2)/4 + a(3)/32 - sin(17*a(1)/60 + a(2)/8 + a(3)/40 - 0.0282326);...
3*a(1)/4 + a(2)/2 + a(3)/8 - sin(17*a(1)/60 + a(2)/8 + a(3)/40 + 0.846767)];
n = 3;
a0 = zeros(n,1); % Initial guess
opts = optimoptions('fsolve','Display','iter','TolFun',1e-8);
[a_sol,a_val,exitflag] = fsolve(f,a0,opts)
This returns
a_sol =
-0.002818738864459
-0.687953796565011
9.488284986072076
Of course there may be more than one solution, especially for larger n. You can choose your initial guess to find the others. See the documentation for fsolve and optimoptions for further details on on specifying options.
Did you try using the solve command ?
[y1,...,yN] = solve(eqns,vars) solves the system of equations eqns for the variables vars. The solutions are assigned to the variables y1,...,yN. If you do not specify the variables, solve uses symvar to find the variables to solve for. In this case, the number of variables that symvar finds is equal to the number of output arguments N.

Split Anonymous Function into Terms

I am wanting to take a matlab anonymous function of something like #(x) = x + x^2 and split it into a cell array so that
f{1} = #(x) x
f{2} = #(x) x^2
I want to be able to do this with some arbitrary function handle. The best that I have come up with so far is taking in #(x) = x + x^2 as a string and splitting it by the addition signs and appending #(x) to the beginning of this. However, I would like to be able to directly use a function handle as the function argument. It would also be nice as using other variables could lead to some difficulty in the string approach.
I am also considering just taking in a cell array of function handles as an argument, which would be more difficult for the user but easier in my code.
For some background, I'm wanting to do this for some least squares data fitting code that I am writing for a class. This code will be for taking in a model function as an argument and I need to evaluate each term separately for the least squares process. I'm not limiting these models to polynomials and even if a polynomial is the model, I want the option to leave out certain powers in the polynomial. If someone has a better suggestion for taking a model function, that would be great too.
UPDATE: Someone wanted to know what I meant by
I'm not limiting these models to polynomials and even if a polynomial
is the model, I want the option to leave out certain powers in the
polynomial.
For some clarification, I was saying that I didn't want to limit the models to
c0 + c1*x + ... + cn*x^n
in which case I could just take in n as a parameter and create terms from that similar to what happens in polyfit. For example, if I know that my input data fits an even or odd function, I may want one of the following models
c0 + c1*x^2 + c2*x^4 + ... + ck*x^(2k)
c1*x + c2*x^3 + ... + cm*x^(2m-1)
Where k is even and m is odd. Or possibly a model that isn't strictly a polynomial, but keeps the coefficients linear, such as
c0 + exp(x) * ( c1 + c2*x + ... cn*x^(n-1) )
This is an interesting problem. The string should not be split at + signs that are within a parenthesis group. For example, with
f = #(x) x + (x+1)*sqrt(x) + x^2 + exp(x+2);
the string should be split at the first, but not at the second + sign.
This can be accomplished as follows. To detect only + signs that are outside parentheses, add 1 for each opening parenthesis and subtract 1 for each closing parenthesis. Then the desired + signs are those with count 0.
I'm assuming the output should be a cell array of function handles. If it should be a cell array of strings just remove the last line.
F = functions(f);
str = F.function; %// get string from function handle
[pref, body] = regexp(str, '#\(.+?\)', 'match', 'split'); %// pref is the '#(...)' part
body = body{2}; %// body is the main part
ind = cumsum((body=='(')-(body==')'))==0 & body=='+'; %// indices for splitting
body(ind) = '?'; %// '?' will be used as split marker
ff = strcat(pref, strsplit(body, '?')); %// split, and then add prefix
ff = cellfun(#str2func, ff, 'uniformoutput', 0); %// convert strings to functions
Result in this example:
ff{1} =
#(x)x
ff{2} =
#(x)(x+1)*sqrt(x)
ff{3} =
#(x)x^2
ff{4} =
#(x)exp(x+2)

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.

Matlab numerical error and how to get the correct answer

I somehow obtain the following expression in Matlab (R2014a on W7, 64b)
1/1034591578977116160000*prod(1:19)*(29576428208904825-17729494921579950*k - 20479697577410832*k^2 + 13867226524449248*k^3 - 836937224095392*k^4 - 869194297188672*k^5 + 163710902234880*k^6 + 2589894827520*k^7 - 2476912838400*k^8 + 144848704000*k^9)
where k is initially a symbolic variable. Then I set k=10 and get the result 370371188237528 using LONGG output format. But if I put the same expression to Mathematica (substituting prod(1:19) with 19!), I get 370371188237525, which I believe is the correct answer. This seems to be a rounding error described many times on this site (is it correct?). How do I avoid it with or without Matlab symbolic toolbox?
There is the High Precision Float class. After adding it to the path you can simply write k = hpf(10); before evaluating your expression. The result will be
370371188237525.0106290979251578332118698122510380699168308638036
With the Symbolic Math Toolbox I would write
syms k
expr = 1/1034591578977116160000*prod(1:19)*(29576428208904825-17729494921579950*k - 20479697577410832*k^2 + 13867226524449248*k^3 - 836937224095392*k^4 - 869194297188672*k^5 + 163710902234880*k^6 + 2589894827520*k^7 - 2476912838400*k^8 + 144848704000*k^9);
subs(expr, k, 10);
which evaluates to 3150006955960150124/8505 = 370371188237525.