Symmetry of the output of fft2 command in matlab - matlab

When I run in matlab
fft2([9.36,-3.42,-2.12;-3.42 0.8 3.68 ;-0.6 -3.88 -4.96 ; 2.82 0.52 2.82])
I obtain
1.6000 + 0.0000i 11.4400 + 4.6765i 11.4400 - 4.6765i
13.2600 + 5.1000i 8.8123 + 8.8711i 7.8077 + 4.7489i
-12.8400 + 0.0000i 20.4600 - 4.2955i 20.4600 + 4.2955i
13.2600 - 5.1000i 7.8077 - 4.7489i 8.8123 - 8.8711i
What is the symmetry of this last matrix? I know that in the fft there exists some symmetry used to do not store all the information of the matrix, and I need to know what is the symmetry of the matrices output of the command fft2.
Some of context (I do not if is useful for the question/answer):
I need understand this because the output of the Fast Fourier Transform using fttw3 library I obtain the vector
1.6
13.26 + 5.1i
-12.84
11.44 + 4.6765i
8.8123 + 8.871i
20.46 - 4.2955i
11.44 - 4.6765i
7.8077 + 4.7488i
20.46 + 4.2955i
***
***
***
As you see, are almost all the elements of the initial matrix, but I do not have the last row, and I think that this values could be calculated using some symmetry.
Thanks in advance.

Related

Eigen Library - EigenSolver get different eigen value comparing with matlab eig function [duplicate]

Do anyone have any idea how can I rewrite eig(A,B) from Matlab used to calculate generalized eigenvector/eigenvalues? I've been struggling with this problem lately. So far:
Matlab definition of eig function I need:
[V,D] = eig(A,B) produces a diagonal matrix D of generalized
eigenvalues and a full matrix V whose columns are the corresponding
eigenvectors so that A*V = B*V*D.
So far I tried the Eigen library (http://eigen.tuxfamily.org/dox/classEigen_1_1GeneralizedSelfAdjointEigenSolver.html)
My implementation looks like this:
std::pair<Matrix4cd, Vector4d> eig(const Matrix4cd& A, const Matrix4cd& B)
{
Eigen::GeneralizedSelfAdjointEigenSolver<Matrix4cd> solver(A, B);
Matrix4cd V = solver.eigenvectors();
Vector4d D = solver.eigenvalues();
return std::make_pair(V, D);
}
But first thing that comes to my mind is, that I can't use Vector4cd as .eigenvalues() doesn't return complex values where Matlab does. Furthermore results of .eigenvectors() and .eigenvalues() for the same matrices are not the same at all:
C++:
Matrix4cd x;
Matrix4cd y;
pair<Matrix4cd, Vector4d> result;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
x.real()(i,j) = (double)(i+j+1+i*3);
y.real()(i,j) = (double)(17 - (i+j+1+i*3));
x.imag()(i,j) = (double)(i+j+1+i*3);
y.imag()(i,j) = (double)(17 - (i+j+1+i*3));
}
}
result = eig(x,y);
cout << result.first << endl << endl;
cout << result.second << endl << endl;
Matlab:
for i=1:1:4
for j=1:1:4
x(i,j) = complex((i-1)+(j-1)+1+((i-1)*3), (i-1)+(j-1)+1+((i-1)*3));
y(i,j) = complex(17 - ((i-1)+(j-1)+1+((i-1)*3)), 17 - ((i-1)+(j-1)+1+((i-1)*3)));
end
end
[A,B] = eig(x,y)
So I give eig the same 4x4 matrices holding values 1-16 ascending (x) and descending (y). But I receive different results, furthermore Eigen method returns double from eigenvalues while Matlab returns complex dobule. I also find out that there is other Eigen solver named GeneralizedEigenSolver. That one in the documentation (http://eigen.tuxfamily.org/dox/classEigen_1_1GeneralizedEigenSolver.html) has written that it solves A*V = B*V*D but to be honest I tried it and results (matrix sizes) are not the same size as Matlab so I got quite lost how it works (examplary results are on the website I've linked). It also has only .eigenvector method.
C++ results:
(-0.222268,-0.0108754) (0.0803437,-0.0254809) (0.0383264,-0.0233819) (0.0995482,0.00682079)
(-0.009275,-0.0182668) (-0.0395551,-0.0582127) (0.0550395,0.03434) (-0.034419,-0.0287563)
(-0.112716,-0.0621061) (-0.010788,0.10297) (-0.0820552,0.0294896) (-0.114596,-0.146384)
(0.28873,0.257988) (0.0166259,-0.0529934) (0.0351645,-0.0322988) (0.405394,0.424698)
-1.66983
-0.0733194
0.0386832
3.97933
Matlab results:
[A,B] = eig(x,y)
A =
Columns 1 through 3
-0.9100 + 0.0900i -0.5506 + 0.4494i 0.3614 + 0.3531i
0.7123 + 0.0734i 0.4928 - 0.2586i -0.5663 - 0.4337i
0.0899 - 0.4170i -0.1210 - 0.3087i 0.0484 - 0.1918i
0.1077 + 0.2535i 0.1787 + 0.1179i 0.1565 + 0.2724i
Column 4
-0.3237 - 0.3868i
0.2338 + 0.7662i
0.5036 - 0.3720i
-0.4136 - 0.0074i
B =
Columns 1 through 3
-1.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i
0.0000 + 0.0000i -1.0000 - 0.0000i 0.0000 + 0.0000i
0.0000 + 0.0000i 0.0000 + 0.0000i -4.5745 - 1.8929i
0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i
Column 4
0.0000 + 0.0000i
0.0000 + 0.0000i
0.0000 + 0.0000i
-0.3317 + 1.1948i
Second try was with Intel IPP but it seems that it solves only A*V = V*D and support told me that it's not supported anymore.
https://software.intel.com/en-us/node/505270 (list of constructors for Intel IPP)
I got suggestion to move from Intel IPP to MKL. I did it and hit the wall again. I tried to check all algorithms for Eigen but it seems that there are only A*V = V*D problems solved. I was checking lapack95.lib. The list of algorithms used by this library is available there:
https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/index.htm#dsyev.htm
Somewhere on the web I could find topic on Mathworks when someone said that managed to solve my problem partially with usage of MKL:
http://jp.mathworks.com/matlabcentral/answers/40050-generalized-eigenvalue-and-eigenvectors-differences-between-matlab-eig-a-b-and-mkl-lapack-dsygv
Person said that he/she used dsygv algorithm but I can't locate anything like that on the web. Maybe it's a typo.
Anyone has any other proposition/idea how can I implement it? Or maybe point my mistake. I'd appreciate that.
EDIT:
In comments I've received a hint that I was using Eigen solver wrong. My A matrix wasn't self-adjoint and my B matrix wasn't positive-definite. I took matrices from program I want to rewrite to C++ (from random iteration) and checked if they meet the requirements. They did:
Rj =
1.0e+02 *
Columns 1 through 3
0.1302 + 0.0000i -0.0153 + 0.0724i 0.0011 - 0.0042i
-0.0153 - 0.0724i 1.2041 + 0.0000i -0.0524 + 0.0377i
0.0011 + 0.0042i -0.0524 - 0.0377i 0.0477 + 0.0000i
-0.0080 - 0.0108i 0.0929 - 0.0115i -0.0055 + 0.0021i
Column 4
-0.0080 + 0.0108i
0.0929 + 0.0115i
-0.0055 - 0.0021i
0.0317 + 0.0000i
Rt =
Columns 1 through 3
4.8156 + 0.0000i -0.3397 + 1.3502i -0.2143 - 0.3593i
-0.3397 - 1.3502i 7.3635 + 0.0000i -0.5539 - 0.5176i
-0.2143 + 0.3593i -0.5539 + 0.5176i 1.7801 + 0.0000i
0.5241 + 0.9105i 0.9514 + 0.6572i -0.7302 + 0.3161i
Column 4
0.5241 - 0.9105i
0.9514 - 0.6572i
-0.7302 - 0.3161i
9.6022 + 0.0000i
As for Rj which is now my A - it is self-adjoint because Rj = Rj' and Rj = ctranspose(Rj). (http://mathworld.wolfram.com/Self-AdjointMatrix.html)
As for Rt which is now my B - it is Positive-Definite what is checked with method linked to me. (http://www.mathworks.com/matlabcentral/answers/101132-how-do-i-determine-if-a-matrix-is-positive-definite-using-matlab). So
>> [~,p] = chol(Rt)
p =
0
I've rewritten matrices manually to C++ and performed eig(A,B) again with matrices meeting requirements:
Matrix4cd x;
Matrix4cd y;
pair<Matrix4cd, Vector4d> result;
x.real()(0,0) = 13.0163601949795;
x.real()(0,1) = -1.53172561296005;
x.real()(0,2) = 0.109594869350436;
x.real()(0,3) = -0.804231869422614;
x.real()(1,0) = -1.53172561296005;
x.real()(1,1) = 120.406645675346;
x.real()(1,2) = -5.23758765476463;
x.real()(1,3) = 9.28686785230169;
x.real()(2,0) = 0.109594869350436;
x.real()(2,1) = -5.23758765476463;
x.real()(2,2) = 4.76648319080400;
x.real()(2,3) = -0.552823839520508;
x.real()(3,0) = -0.804231869422614;
x.real()(3,1) = 9.28686785230169;
x.real()(3,2) = -0.552823839520508;
x.real()(3,3) = 3.16510496622613;
x.imag()(0,0) = -0.00000000000000;
x.imag()(0,1) = 7.23946944213164;
x.imag()(0,2) = 0.419181335323979;
x.imag()(0,3) = 1.08441894337449;
x.imag()(1,0) = -7.23946944213164;
x.imag()(1,1) = -0.00000000000000;
x.imag()(1,2) = 3.76849276970080;
x.imag()(1,3) = 1.14635625342266;
x.imag()(2,0) = 0.419181335323979;
x.imag()(2,1) = -3.76849276970080;
x.imag()(2,2) = -0.00000000000000;
x.imag()(2,3) = 0.205129702522089;
x.imag()(3,0) = -1.08441894337449;
x.imag()(3,1) = -1.14635625342266;
x.imag()(3,2) = 0.205129702522089;
x.imag()(3,3) = -0.00000000000000;
y.real()(0,0) = 4.81562784930907;
y.real()(0,1) = -0.339731222392148;
y.real()(0,2) = -0.214319720979258;
y.real()(0,3) = 0.524107127885349;
y.real()(1,0) = -0.339731222392148;
y.real()(1,1) = 7.36354235698375;
y.real()(1,2) = -0.553927983436786;
y.real()(1,3) = 0.951404408649307;
y.real()(2,0) = -0.214319720979258;
y.real()(2,1) = -0.553927983436786;
y.real()(2,2) = 1.78008768533745;
y.real()(2,3) = -0.730246631850385;
y.real()(3,0) = 0.524107127885349;
y.real()(3,1) = 0.951404408649307;
y.real()(3,2) = -0.730246631850385;
y.real()(3,3) = 9.60215057284395;
y.imag()(0,0) = -0.00000000000000;
y.imag()(0,1) = 1.35016928394966;
y.imag()(0,2) = -0.359262708214312;
y.imag()(0,3) = -0.910512495060186;
y.imag()(1,0) = -1.35016928394966;
y.imag()(1,1) = -0.00000000000000;
y.imag()(1,2) = -0.517616473138836;
y.imag()(1,3) = -0.657235460367660;
y.imag()(2,0) = 0.359262708214312;
y.imag()(2,1) = 0.517616473138836;
y.imag()(2,2) = -0.00000000000000;
y.imag()(2,3) = -0.316090662865005;
y.imag()(3,0) = 0.910512495060186;
y.imag()(3,1) = 0.657235460367660;
y.imag()(3,2) = 0.316090662865005;
y.imag()(3,3) = -0.00000000000000;
result = eig(x,y);
cout << result.first << endl << endl;
cout << result.second << endl << endl;
And the results of C++:
(0.0295948,0.00562174) (-0.253532,0.0138373) (-0.395087,-0.0139696) (-0.0918132,-0.0788735)
(-0.00994614,-0.0213973) (-0.0118322,-0.0445976) (0.00993512,0.0127006) (0.0590018,-0.387949)
(0.0139485,-0.00832193) (0.363694,-0.446652) (-0.319168,0.376483) (-0.234447,-0.0859585)
(0.173697,0.268015) (0.0279387,-0.0103741) (0.0273701,0.0937148) (-0.055169,0.0295393)
0.244233
2.24309
3.24152
18.664
Results of MATLAB:
>> [A,B] = eig(Rj,Rt)
A =
Columns 1 through 3
0.0208 - 0.0218i 0.2425 + 0.0753i -0.1242 + 0.3753i
-0.0234 - 0.0033i -0.0044 + 0.0459i 0.0150 - 0.0060i
0.0006 - 0.0162i -0.4964 + 0.2921i 0.2719 + 0.4119i
0.3194 + 0.0000i -0.0298 + 0.0000i 0.0976 + 0.0000i
Column 4
-0.0437 - 0.1129i
0.2351 - 0.3142i
-0.1661 - 0.1864i
-0.0626 + 0.0000i
B =
0.2442 0 0 0
0 2.2431 0 0
0 0 3.2415 0
0 0 0 18.6640
Eigenvalues are the same! Nice, but why Eigenvectors are not similar at all?
There is no problem here with Eigen.
In fact for the second example run, Matlab and Eigen produced the very same result. Please remember from basic linear algebra that eigenvector are determined up to an arbitrary scaling factor. (I.e. if v is an eigenvector the same holds for alpha*v, where alpha is a non zero complex scalar.)
It is quite common that different linear algebra libraries compute different eigenvectors, but this does not mean that one of the two codes is wrong: it simply means that they choose a different scaling of the eigenvectors.
EDIT
The main problem with exactly replicating the scaling chosen by matlab is that eig(A,B) is a driver routine, which depending from the different properties of A and B may call different libraries/routines, and apply extra steps like balancing the matrices and so on. By quickly inspecting your example, I would say that in this case matlab is enforcing following condition:
all(imag(V(end,:))==0) (the last component of each eigenvector is real)
but not imposing other constraints. This unfortunately means that the scaling is not unique, and probably depends on intermediate results of the generalised eigenvector algorithm used. In this case I'm not able to give you advice on how to exactly replicate matlab: knowledge of the internal working of matlab is required.
As a general remark, in linear algebra usually one does not care too much about eigenvector scaling, since this is usually completely irrelevant for the problem solved, when the eigenvectors are just used as intermediate results.
The only case in which the scaling has to be defined exactly, is when you are going to give a graphic representation of the eigenvalues.
The eigenvector scaling in Matlab seems to be based on normalizing them to 1.0 (ie. the absolute value of the biggest term in each vector is 1.0). In the application I was using it also returns the left eigenvector rather than the more commonly used right eigenvector. This could explain the differences between Matlab and the eigensolvers in Lapack MKL.

Calculate roots of characteristic equation of symbolic matrix

I have 3 data matrices A,B,C (all 3x3), with which I use the following code to calculate roots of D(p)X = 0
syms p
D = A + B*p + C*(p^2)
solP = double(solve(det(D)))
From this, I get 6 values for solP. But when I try substituting it back into the symbolic matrix D, as follows, I get non-zero values of det(D) sometimes
for i = 1:6
p = solP(i)
det(double(subs(D)) % Should be zero always as we are substituting roots
end
Please help me understand this behaviour.
EDIT ::
Example :
A =
1.0e+11 *
4.8976 7.0936 6.7970
4.4559 7.5469 6.5510
6.4631 2.7603 1.6261
B =
1.0e+11 *
3.9223 7.0605 0.4617
6.5548 0.3183 0.9713
1.7119 2.7692 8.2346
C =
1.0e+11 *
6.9483 0.3445 7.6552
3.1710 4.3874 7.9520
9.5022 3.8156 1.8687
solP =
0.1061 + 0.0000i
1.5311 + 0.0000i
-0.3432 + 0.9356i
-0.3432 - 0.9356i
0.4228 - 0.5465i
0.4228 + 0.5465i
det(D) =
2.2143e+19
-5.4911e+20
-8.6415e+19 + 4.5024e+19i
-8.6415e+19 - 4.5024e+19i
-1.4547e+19 + 9.1135e+19i
-1.4547e+19 - 9.1135e+19i
The problem is related to the relative accuracy of floating point values, typically 1e-16.
The input matrices are of the order 1e+11 - 1e+12, the solution is of the order 1e+0, so the elements of D are also of the order 1e+11 - 1e+12. To calculate a determinant of a 3x3 matrix, one should take products of three matrix elements and add/subtract them. So, each term is of the order of 1e+33 - 1e+36. If you subtract such a values to obtain the determinant, the expected accuracy is in the order of 1e+17 - 1e+20. Indeed, this corresponds with the values you get. Given the relative accuracy, you are not able to reach further to zero.
Note that if you scale your input matrices, i.e. divide it by 1e+11, the solutions are indeed the same, but the determinants are probably more what you would expect.

Unstable Closed Loop System

You are given a transfer function G(s)=1.81K(s+20)/(0.03338(s^3+10s^2+32s+32)). This system is connected with unity negative feedback . Determine the smallest positive value of K which makes the closed-loop system unstable. Give the answer to 3 d.p.
Correct Answer:
0.531 ± 0.02
This question is set by my lecturer and I have no idea how to do it.
The closed loop system will become unstable as soon as the rlocus function is no longer in the LHP. Either of the two lines when they intersect with 0 on the x-axis. Assume K=1 at first as we are multiplying by the gain.
>> G=tf([1.81 36.2],[0.03338 0.3338 1.0682 1.0682])
G =
1.81 s + 36.2
------------------------------------------
0.03338 s^3 + 0.3338 s^2 + 1.068 s + 1.068
Continuous-time transfer function.
>> rlocus(G)
you should see that when the real axis is 0 the gain is at 0.531.
if we want greater accuracy we can simply use the rlocfind(G,(point that it is 0)
A smart friend of mine showed me that "Routh Array" is the key for this equation.
Expand the polynomial as you have it, therefore you will have this:
VARS TERM VALUE
A s^3 0.03338
B s^2 0.3338
C s 1.06816 + 1.81Κ
D 1.06816 + 36.2Κ
Equate them as A*D=B*C and you will have the term "s^3" on both sides and then you can cancel it out and solve for K.
(0.03338)(1.06816 + 36.2K) s^3 = (0.3338)(1.06816 + 1.81K) s^3
0.0357 + 1.2084K = 0.3566 + 0.6042K
(1.2084 - 0.6042) K = 0.3566-0.0357
K = 0.5311155247
Otherwise use the rlocus function in MATLAB.

PID Compensation in Matlab

Im trying to design a PID compensator with Matlab.
I'm doing the following:
My plant has this transfer function:
plant
( 0.0195 s - 6.5 )/ (1.74e-06 s^2 - 0.003 s - 1)
So, using the PID tune function, specifying the desired crossover frequency:
>> [info,pid_c] = pidtune(plant,'PID',(2E6/6)*2*pi)
info =
Kp + Ki * 1/s
with Kp = 162, Ki = 1.96e+08
Continuous-time PI controller in parallel form.
pid_c =
Stable: 1
CrossoverFrequency: 2.0944e+06
PhaseMargin: 60.0000
But, when I close the loop and analyse the poles of the system I see that there's a pole in the right semi-plane:
>> pid_c = 162 + 1.96E8/s
pid_c =
( 162 s + 1.96e08 ) / s
Continuous-time transfer function.
>> sys=feedback(plant*pid_c,1)
sys =
(3.159 s^2 + 3.821e06 s - 1.274e09 )/ ( 1.74e-06 s^3 + 3.156 s^2 + 3.821e06 s - 1.274e09)
Continuous-time transfer function.
>> pole(sys)
ans =
1.0e+06 *
-0.9071 + 1.1721i
-0.9071 - 1.1721i
0.0003 <==== RSP pole
My intuition says I should get away with this pole by adding a (s+0.0003) to the numerator of the PID:
>> pid_c=pid_c*(s+0.0003)
pid_c =
( 162 s^2 + 1.96e08 s + 5.88e04 )/ s
But it doesnt work at all, and the tranfer function of my closed-loop goes like that:
sys =
(3.159 s^3 + 3.821e06 s^2 - 1.274e09 s - 3.822e05) / (3.159 s^3 + 3.821e06 s^2 - 1.274e09 s - 3.822e05)
and off course thats wrong.
I really appreciate your help.
The problem is because you are not calling pidtune correctly. The first variable returned is the controller, the second the information about closed-loop stability, not the other way round. From the documentation:
[C,info] = pidtune(...) returns the data structure info, which
contains information about closed-loop stability, the selected
open-loop gain crossover frequency, and the actual phase margin.
So I would change the code to:
[pid_c,info] = pidtune(plant,'PID',(2E6/6)*2*pi);
sys=minreal(feedback(pid_c*plant,1));
pole(sys)
The second error you make is that the pole isn't at 0.0003, but at 0.0003 * 1e6. If you are going to rely on what is displayed on the screen, you should at least use format long g to have more significant digits.
Also, note that I have used minreal to compute a minimum realisation of the closed-loop transfer function, as you seem to be having a mix of very large and very small number, not a good combination.

Plotting Surfaces With 3 Symbolic Variables

First, I need to state that I'm not exactly a math lover or an avid Matlab user. This is college homework that I have been trying to solve for the last 3 hours with no luck. I have googled like crazy, even asked for help via Facebook (where I got replies, but nothing that solved my questions).
This is my first time using this software and I need to graph some things really quick. But no matter how much I read I keep getting syntax errors and the like.
Basically, I have this equation:
4*x^2 + y^2 + z^2 - 8*x + 2*y + 3 = 0
And I'm trying to plot it/graph it. I thought it would be very straightforward but I'm having problems doing it.
Google searches have shown me the functions ezplot() and ezsurf(), but:
When I do ezplot('4*x^2 + y^2 + z^2 - 8*x + 2*y + 3'), I get the following error:
??? Error using ==> char
Cell elements must be character arrays.
Error in ==> ezplot at 158
fmsg = char(f);
And when I do ezsurf('4*x^2 + y^2 + z^2 - 8*x + 2*y + 3')
The expression 4*x^2 + y^2 + z^2 - 8*x + 2*y + 3 must only have 2 symbolic variables
Error in ==> ezgraph3>surfplot at 526
[F,var] = ezfixfun(F,fargs,flabel);
Error in ==> ezgraph3 at 49
[dummy,h] = surfplot(f,domain,surfstyle,cax,Npts,fixdomain,flabel,fargs);
Error in ==> ezsurf at 65
h = ezgraph3('surf',args{:});
Again, this is really my first time using this software. The teacher didn't give us any explanation so I have no idea of what these errors are supposed to mean, let alone solving them. I have no idea of what I'm doing or what I am supposed to do.
I have tried using solve() to solve for 'z' first and then plot the two results I get.
s = solve('4*x^2 + y^2 + z^2 - 8*x + 2*y + 3', 'z')
s =
-(- 4*x^2 + 8*x - y^2 - 2*y - 3)^(1/2)
(- 4*x^2 + 8*x - y^2 - 2*y - 3)^(1/2)
But that's not working either. When I use ezplot() it tells me to use ezsurf, and when I use ezsurf() it tells me about a variable "h" that I have never even declared:
>> ezsurf('-(- 4*x^2 + 8*x - y^2 - 2*y - 3)^(1/2)', '(- 4*x^2 + 8*x - y^2 - 2*y - 3)^(1/2)')
??? Undefined function or variable "h".
Error in ==> ezgraph3 at 66
hh = h;
Error in ==> ezsurf at 65
h = ezgraph3('surf',args{:});
Any help plotting that will be really appreciated. My head is going to explode because people have been telling me this is supposed to be really straightforward.
Thank you!
The following works for me:
ezsurf('(8*x - 4*x^2 - y^2 - 2*y -3)^(1/2)');
Note that ezsurf accepts a function of 2 dimensions (that maps into a 3rd dimension). So you must express the function in the form f(x, y) = blah, where blah is what you want as your input to ezsurf. All I did was re-arrange your function into the form z = blah, and then input blah to ezsurf.
Oh, and two other things, 1) The resulting graph only tells half the story, since the square root of z^2 can be z or minus z (by default, matlab takes the positive square root). 2) The function as above can only be analyzed without complex numbers (such as I've done here) for a very restricted domain of x and y.