Here is a transfer function:
S = [tf([10 2 4],[1 95 2000 3450])];
How can I get real(S) and Imag(S)?
It sounds like you want the Fourier form of your transfer function. As far as I know, there's no builtin function for this so you'll need to use symbolic math:
num = [10 2 4];
den = [1 95 2000 3450];
syms s;
syms omega real; % Define as real-valued
f1 = poly2sym(num,s)/poly2sym(den,s)
f2 = subs(f1,s,1i*omega)
f2_real = simplify(real(f2))
f2_imag = simplify(imag(f2))
which returns
f1 =
(10*s^2 + 2*s + 4)/(s^3 + 95*s^2 + 2000*s + 3450)
f2 =
(- 10*omega^2 + omega*2i + 4)/(- omega^3*1i - 95*omega^2 + omega*2000i + 3450)
f2_real =
(4*(237*omega^4 - 7720*omega^2 + 3450))/(omega^6 + 5025*omega^4 + 3344500*omega^2 + 11902500)
f2_imag =
-(2*omega*(5*omega^4 - 9907*omega^2 + 550))/(omega^6 + 5025*omega^4 + 3344500*omega^2 + 11902500)
You can then use subs and vpa/double to evaluate these for a particular value of omega.
Related
I am solving a fourth order equation in matlab using the solve function.My script looks like this:
syms m M I L Bp Bc g x
m = 0.127
M = 1.206
I = 0.001
L = 0.178
Bc = 5.4
Bp = 0.002
g = 9.8
eqn = ((m + M)*(I + m*L^2) - m^2*L^2)*x^4 + ((m + M)*Bp + (I + m*L^2)*Bc)*x^3 + ((m + M)*m*g*L + Bc*Bp)*x^2 + m*g*L*Bc*x == 0
S = solve(eqn, x)
In the answer, I should get 4 roots, but instead I get such strange expressions:
S =
0
root(z^3 + (34351166180215288*z^2)/7131724328013535 + (352922208800606144*z)/7131724328013535 + 1379250971773894912/7131724328013535, z, 1)
root(z^3 + (34351166180215288*z^2)/7131724328013535 + (352922208800606144*z)/7131724328013535 + 1379250971773894912/7131724328013535, z, 2)
root(z^3 + (34351166180215288*z^2)/7131724328013535 + (352922208800606144*z)/7131724328013535 + 1379250971773894912/7131724328013535, z, 3)
The first root, which is 0, is displayed clearly. Is it possible to make the other three roots appear as numbers as well? I looked for something about this in the documentation for the solve function, but did not find it.
How does one extract specific parts of an expression in Matlab/ Octave symbolic package? In XCAS, one can use indexing expressions, but I can't find anything similar in Octave/ Matlab.
For instance, with X = C*L*s**2 + C*R*s + 1, is there a way to get C*R*s by X(2) or the like?
It would be nice to do this with factors too. X = (alpha + s)*(beta**2 + s**2)*(C*R*s + 1), and have X(2) give (beta**2 + s**2).
Thanks!
children (MATLAB doc, Octave doc) does this but the order in which you write the expressions will not necessarily be the same. The order is also different in MATLAB and Octave.
Expanded Expression:
syms R L C s;
X1 = C*L*s^2 + C*R*s + 1;
partsX1 = children(X1);
In MATLAB:
>> X1
X1 =
C*L*s^2 + C*R*s + 1
>> partsX1
partsX1 =
[ C*R*s, C*L*s^2, 1]
In Octave:
octave:1> X1
X1 = (sym)
2
C⋅L⋅s + C⋅R⋅s + 1
octave:2> partsX1
partsX1 = (sym 1×3 matrix)
⎡ 2 ⎤
⎣1 C⋅L⋅s C⋅R⋅s⎦
Factorised Expression:
syms R C a beta s; %alpha is also a MATLAB function so don't shadow it with your variable
X2 = (a + s) * (beta^2 + s^2) * (C*R*s + 1);
partsX2 = children(X2);
In MATLAB:
>> X2
X2 =
(a + s)*(C*R*s + 1)*(beta^2 + s^2)
>> partsX2
partsX2 =
[ a + s, C*R*s + 1, beta^2 + s^2]
In Octave:
octave:3> X2
X2 = (sym)
⎛ 2 2⎞
(a + s)⋅⎝β + s ⎠⋅(C⋅R⋅s + 1)
octave:4> partsX2
partsX2 = (sym 1×3 matrix)
⎡ 2 2⎤
⎣C⋅R⋅s + 1 a + s β + s ⎦
I have the following script
clc; clear all; close all;
syms x n
f = x;
L = 1;
subplot(2,1,1)
h = ezplot(f,[-L,L])
set(h, 'Color','r','LineWidth',1)
a0 = (1/L) * int(f * cos(0* pi*x/L),-L,L)
an = (1/L) * int(f * cos(n* pi*x/L),-L,L)
bn = (1/L)* int(f* sin(n* pi*x/L),-L,L)
fx = a0/2 + symsum((an* cos(n*pi*x/L) + bn* sin(n*pi*x/L)),n,1,5)
% for n =5, the answer: fx = (2*sin(pi*x))/pi - sin(2*pi*x)/pi +
%(2*sin(3*pi*x))/(3*pi) - sin(4*pi*x)/(2*pi) + (2*sin(5*pi*x))/(5*pi)
hold on
h = ezplot(fx,[-L,L])
grid on
%Solution with complex Fourier
c0 = (1/(2*L))*int(f*exp(-j*0*pi*x/L),-L,L)
cn = (1/(2*L))*int(f*exp(-j*n*pi*x/L),-L,L)
subplot(2,1,2)
h = ezplot(f,[-L,L])
set(h, 'Color','r','LineWidth',1)
fx_c = c0 + symsum(cn*exp(j*n*pi*x/L),n,-5,-1) + ...
symsum(cn*exp(j*n*pi*x/L),n,1,5) % n for complex -5,5
hold on
h = ezplot(fx_c,[-L,L])
grid on
My question: Since the answer of fx should be equal to fx_c (complex fourier). We can see from the figures produced by these 2 functions. They are same. But
fx =
(2*sin(pi*x))/pi - sin(2*pi*x)/pi + (2*sin(3*pi*x))/(3*pi) - sin(4*pi*x)/(2*pi) + (2*sin(5*pi*x))/(5*pi)
and
fx_c =
exp(-pi*x*i)*((pi*i - 1)/(2*pi^2) + (pi*i + 1)/(2*pi^2)) - exp(pi*x*i)*((pi*i - 1)/(2*pi^2) + (pi*i + 1)/(2*pi^2)) - exp(-pi*x*2*i)*((pi*2*i - 1)/(8*pi^2) + (pi*2*i + 1)/(8*pi^2)) + exp(pi*x*2*i)*((pi*2*i - 1)/(8*pi^2) + (pi*2*i + 1)/(8*pi^2)) + exp(-pi*x*3*i)*((pi*3*i - 1)/(18*pi^2) + (pi*3*i + 1)/(18*pi^2)) - exp(pi*x*3*i)*((pi*3*i - 1)/(18*pi^2) + (pi*3*i + 1)/(18*pi^2)) - exp(-pi*x*4*i)*((pi*4*i - 1)/(32*pi^2) + (pi*4*i + 1)/(32*pi^2)) + exp(pi*x*4*i)*((pi*4*i - 1)/(32*pi^2) + (pi*4*i + 1)/(32*pi^2)) + exp(-pi*x*5*i)*((pi*5*i - 1)/(50*pi^2) + (pi*5*i + 1)/(50*pi^2)) - exp(pi*x*5*i)*((pi*5*i - 1)/(50*pi^2) + (pi*5*i + 1)/(50*pi^2))
How to convert fx_c to be fx?
They are related by Euler's formula. You can check it with rewrite command:
>> rewrite(exp(1i*x), 'cos')
ans =
cos(x) + sin(x)*1i
Applying it to your function and simplifying a bit, you can get to the same expression:
>> expand(rewrite(fx_c, 'cos'), 'ArithmeticOnly', true)
ans =
(2*sin(pi*x))/pi - sin(2*pi*x)/pi + (2*sin(3*pi*x))/(3*pi) - sin(4*pi*x)/(2*pi) + (2*sin(5*pi*x))/(5*pi)
>> fx
fx =
(2*sin(pi*x))/pi - sin(2*pi*x)/pi + (2*sin(3*pi*x))/(3*pi) - sin(4*pi*x)/(2*pi) + (2*sin(5*pi*x))/(5*pi)
This question is related to the post below:
Matlab: Nonlinear equation solver
With 8 variables x0-x8, I got great results. However, when I increase to solving 10 variables, the results aren't so good. Even if my "guess" is close to the actual value and change the max iteration to 100000, the results are still poor. Is there anything else I can do?
Here is the code:
function F = fcn(x)
F=[x(6) + x(7) + x(8) + x(9) + x(10)-2 ;
x(6)*x(1) + x(7)*x(2) + x(8)*x(3) + x(9)*x(4) + x(10)*x(5) ;
x(6)*x(1)^2 + x(7)*x(2)^2 + x(8)*x(3)^2 + x(9)*x(4)^2 + x(10)*x(5)-2/3 ;
x(6)*x(1)^3 + x(7)*x(2)^3 + x(8)*x(3)^3 + x(9)*x(4)^3 + x(10)*x(5) ;
x(6)*x(1)^4 + x(7)*x(2)^4 + x(8)*x(3)^4 + x(9)*x(4)^4 + x(10)*x(5)-2/5 ;
x(6)*x(1)^5 + x(7)*x(2)^5 + x(8)*x(3)^5 + x(9)*x(4)^5 + x(10)*x(5) ;
x(6)*x(1)^6 + x(7)*x(2)^6 + x(8)*x(3)^6 + x(9)*x(4)^6 + x(10)*x(5)-2/7 ;
x(6)*x(1)^7 + x(7)*x(2)^7 + x(8)*x(3)^7 + x(9)*x(4)^7 + x(10)*x(5) ;
x(6)*x(1)^8 + x(7)*x(2)^8 + x(8)*x(3)^8 + x(9)*x(4)^8 + x(10)*x(5)-2/9 ;
x(6)*x(1)^9 + x(7)*x(2)^9 + x(8)*x(3)^9 + x(9)*x(4)^9 + x(10)*x(5)
];
end
clc
clear all;
format long
x0 = [0.90; 0.53; 0; -0.53; -0.90; 0.23; 0.47; 0.56; 0.47; 0.23]; %Guess
F0 = fcn(x0);
[x,fval]=fsolve(#fcn, x0) %solve without optimization
options = optimset('MaxFunEvals',100000, 'MaxIter', 100000); %optimization criteria
[x,fval]=fsolve(#fcn, x0, options) %solve with optimization
Here are the actual values I'm trying to get:
x1 = 0.906179
x2 = 0.538469
x3 = 0.000000
x4 = -0.53846
x5 = -0.906179
x6 = 0.236926
x7 = 0.478628
x8 = 0.568888
x9 = 0.478628
x10 = 0.236926
The result of such optimization functions like fsolve depends on the initial point very much. A non-linear function like yours can have a lot of local minima and your option is to randomly dice the initial point and hope it will lead the optimization to a better minimum than before.
You can do like this:
clear;
options = optimset('MaxFunEvals',2000, 'MaxIter', 1000, 'Display', 'off');
n = 200; %how many times calculate f with different initial points
z_min = 10000; %the current minimum Euclidian distance between fval and zeros
for i=1:n
x0 = rand(10, 1);
[x,fval]=fsolve(#fcn, x0, options);
z = norm(fval);
if (z < z_min)
z_min = z;
x_best = x;
f_best = fval;
display(['i = ', num2str(i), '; z_min = ', num2str(z_min)]);
display(['x = ', num2str(x_best')]);
display(['f = ', num2str(f_best')]);
fprintf('\n')
end
end
Change the maximum number of the optimization loops and look at the z value. It shows how close your function is to a zero vector.
The best solution I've got so far:
x_best =
0.9062
-0.9062
-0.5385
0.5385
0.0000
0.2369
0.2369
0.4786
0.4786
0.5689
f_best =
1.0e-08 * %these are very small numbers :)
0
0.9722
0.9170
0.8740
0.8416
0.8183
0.8025
0.7929
0.7883
0.7878
For this solution z_min is 2.5382e-08.
I use function with multiple outputs farina4 that computes coefficients a, b, e, f and a vector out_p5tads_final (1 x n array) through a minimization of a system of equations using the data input set p5tads (1 x n array):
function [a b e f fval out_p5tads_final] = farina4(p5tads)
f = #(coeff)calculs_farina4(coeff,p5tads);
[ans,fval] = fminsearchcon(f,coeff0,[0 0 0 0],[1 1 1 1]);% fminsearch with constrains
a = ans(1);
b = ans(2);
e = ans(3);
f = ans(4);
out_p5tads_final = p5tads_farina4(a,b,e,f);
function out_coeff = calculs_farina4(coeff0,p5tads)
%bla-bla-bla
end
function out_p5tads = p5tads_farina4(a,b,e,f)
%bla-bla-bla
end
end
After calculating a, b, e, f and out_p5tads_final I need to calculate/minimize the RMS function with respect to out_p5tads_f4.
RMS = sqrt(mean((p5tads(:) - out_p5tads_f4(:)).^2))*100
and to repeat function farina4 in order to find the optimal set of the parameters a, b, e, f and out_p5tads_final.
I am trying to build up an algorithm of such optimization and do not see a way so far.
For instance, it seems to be not possible to introduce a function with multiple output inside the above RMS equation unless there is a way to index somehow the output of this function farina4.
If there can be an alternative optimization algorithm for RMS without fminsearch (or similar) ?
a b e and f are values between 0 and 1
out_p5tads_final is an (1 x 10) array
%
function out_coeff = calculs_farina4(coeff0,p5tads)
%
mmmm = p5tads(1);
mmmr = p5tads(2);
rmmr = p5tads(3);
mmrm = p5tads(4);
mmrr = p5tads(5);
rmrm = p5tads(6);
rmrr = p5tads(7);
mrrm = p5tads(8);
mrrr = p5tads(9);
rrrr = p5tads(10);
%
a = coeff0(1);
b = coeff0(2);
e = coeff0(3);
f = coeff0(4);
%
f_mmmm = mmmm - ((a^2*b^2*(a + b) + e^2*f^2*(e + f))/2);
f_mmmr = mmmr - (a^2*b^2*(e + f) + e^2*f^2*(a + b));
f_rmmr = rmmr - ((a^2*f^2*(b + e) + b^2*e^2*(a + f))/2);
f_mmrm = mmrm - 2*a*b*e*f;
f_mmrr = mmrr - b*f*(a^3 + e^3) + a*e*(a^3 + f^3);
f_rmrm = rmrm - 2*a*b*e*f;
f_rmrr = rmrr - 2*a*b*e*f;
f_mrrm = mrrm - ((a^2*b^2*(e + f) + e^2*f^2*(a + b))/2);
f_mrrr = mrrr - (a^2*f^2*(b + e) + b^2*e^2*(a + f));
f_rrrr = rrrr - ((a^2*f^2*(a + f) + b^2*e^2*(b + e))/2);
%
out_coeff = f_mmmm^2 + f_mmmr^2 + f_rmmr^2 + f_mmrm^2 + f_mmrr^2 + f_rmrm^2 + f_rmrr^2 + f_mrrm^2 + f_mrrr^2 + f_rrrr^2;
end
%
function out_p5tads = p5tads_farina4(a,b,e,f)
%
p_mmmm = ((a^2*b^2*(a + b) + e^2*f^2*(e + f))/2);
p_mmmr = (a^2*b^2*(e + f) + e^2*f^2*(a + b));
p_rmmr = ((a^2*f^2*(b + e) + b^2*e^2*(a + f))/2);
p_mmrm = 2*a*b*e*f;
p_mmrr = b*f*(a^3 + e^3) + a*e*(a^3 + f^3);
p_rmrm = 2*a*b*e*f;
p_rmrr = 2*a*b*e*f;
p_mrrm = ((a^2*b^2*(e + f) + e^2*f^2*(a + b))/2);
p_mrrr = (a^2*f^2*(b + e) + b^2*e^2*(a + f));
p_rrrr = ((a^2*f^2*(a + f) + b^2*e^2*(b + e))/2);
%
out_p5tads = [p_mmmm,p_mmmr,p_rmmr,p_mmrm,p_mmrr,p_rmrm,p_rmrr,p_mrrm,p_mrrr,p_rrrr];
end
end
Thanks much in advance !
19/08/2014 3:35 pm
I need to get an optimal set of coefficients a b e f that the RMS value , which is calculated from
RMS = sqrt(mean((p5tads(:) - out_p5tads_f4(:)).^2))*100
is minimal. Here, the vector p5tads is used to calculate/optimize the set of a b e f coefficients, which are in turn used to calculate the vector out_p5tads_f4. The code should run a desired number of optimizations cycles (e.g. by default 100) and then select the series of a b e f and out_p5tads_f4 afforded the minimal RMS error value (with respect to out_p5tads_f4).