1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.linear;
18
19 import org.hipparchus.complex.Complex;
20 import org.hipparchus.complex.ComplexField;
21 import org.hipparchus.exception.LocalizedCoreFormats;
22 import org.hipparchus.exception.MathIllegalArgumentException;
23 import org.hipparchus.util.FastMath;
24 import org.junit.Assert;
25 import org.junit.Test;
26
27 public class ComplexEigenDecompositionTest {
28
29 @Test
30 public void testNonSquare() {
31 try {
32 new ComplexEigenDecomposition(MatrixUtils.createRealMatrix(2, 3), 1.0e-5, 1.0e-12, 1.0e-6);
33 Assert.fail("an axception should have been thrown");
34 } catch (MathIllegalArgumentException miae) {
35 Assert.assertEquals(LocalizedCoreFormats.NON_SQUARE_MATRIX, miae.getSpecifier());
36 }
37 }
38
39 @Test
40 public void testRealEigenValues() {
41 final RealMatrix m = MatrixUtils.createRealMatrix(new double[][] { { 2, 0 }, { 0, 3 } });
42 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(m);
43 Assert.assertFalse(eigenDecomp.hasComplexEigenvalues());
44 }
45
46 @Test
47 public void testGetEigenValues() {
48 final RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { 3, -2 }, { 4, -1 } });
49 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(A);
50 Complex ev1 = eigenDecomp.getEigenvalues()[0];
51 Complex ev2 = eigenDecomp.getEigenvalues()[1];
52 Assert.assertEquals(new Complex(1, +2), ev1);
53 Assert.assertEquals(new Complex(1, -2), ev2);
54 }
55
56 @Test
57 public void testHasComplexEigenValues() {
58 final RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { 3, -2 }, { 4, -1 } });
59 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(A);
60 Assert.assertTrue(eigenDecomp.hasComplexEigenvalues());
61 }
62
63 @Test
64 public void testGetDeterminant() {
65 final RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { 3, -2 }, { 4, -1 } });
66 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(A);
67 Assert.assertEquals(5, eigenDecomp.getDeterminant(), 1.0e-12);
68 }
69
70 @Test
71 public void testGetEigenVectors() {
72 final RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { 3, -2 }, { 4, -1 } });
73 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(A);
74 checkScaledVector(eigenDecomp.getEigenvector(0), buildVector(new Complex(1), new Complex(1, -1)), 1.0e-15);
75 checkScaledVector(eigenDecomp.getEigenvector(1), buildVector(new Complex(1), new Complex(1, +1)), 1.0e-15);
76 }
77
78 @Test
79 public void testEigenValuesAndVectors() {
80 final RealMatrix aR = MatrixUtils.createRealMatrix(new double[][] { { 3, -2 }, { 4, -1 } });
81 final ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(aR);
82 final FieldMatrix<Complex> aC = toComplex(aR);
83 for (int i = 0; i < aR.getRowDimension(); ++i) {
84 final Complex lambda = eigenDecomp.getEigenvalues()[i];
85 final FieldVector<Complex> u = eigenDecomp.getEigenvector(i);
86 final FieldVector<Complex> v = aC.operate(u);
87 checkScaledVector(v, u.mapMultiplyToSelf(lambda), 1.0e-12);
88 }
89 }
90
91 @Test
92 public void testGetV() {
93 final RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { 3, -2 }, { 4, -1 } });
94 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(A);
95 FieldMatrix<Complex> V = eigenDecomp.getV();
96 Assert.assertEquals(0.0, new Complex(.5, .5).subtract(V.getEntry(0, 0)).norm(), 1.0e-15);
97 Assert.assertEquals(0.0, new Complex(.5, -.5).subtract(V.getEntry(0, 1)).norm(), 1.0e-15);
98 Assert.assertEquals(0.0, new Complex(1).subtract(V.getEntry(1, 0)).norm(), 1.0e-15);
99 Assert.assertEquals(0.0, new Complex(1).subtract(V.getEntry(1, 1)).norm(), 1.0e-15);
100 }
101
102 @Test
103 public void testGetVT() {
104 final RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { 3, -2 }, { 4, -1 } });
105 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(A);
106 FieldMatrix<Complex> V = eigenDecomp.getVT();
107 Assert.assertEquals(0.0, new Complex(.5, .5).subtract(V.getEntry(0, 0)).norm(), 1.0e-15);
108 Assert.assertEquals(0.0, new Complex(.5, -.5).subtract(V.getEntry(1, 0)).norm(), 1.0e-15);
109 Assert.assertEquals(0.0, new Complex(1).subtract(V.getEntry(0, 1)).norm(), 1.0e-15);
110 Assert.assertEquals(0.0, new Complex(1).subtract(V.getEntry(1, 1)).norm(), 1.0e-15);
111 }
112
113 @Test
114 public void testGetD() {
115 final RealMatrix A = MatrixUtils.createRealMatrix(new double[][] { { 3, -2 }, { 4, -1 } });
116 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(A);
117 FieldMatrix<Complex> D = eigenDecomp.getD();
118 Assert.assertEquals(0.0, new Complex(1, +2).subtract(D.getEntry(0, 0)).norm(), 1.0e-15);
119 Assert.assertEquals(0.0, new Complex(0).subtract(D.getEntry(0, 1)).norm(), 1.0e-15);
120 Assert.assertEquals(0.0, new Complex(0).subtract(D.getEntry(0, 1)).norm(), 1.0e-15);
121 Assert.assertEquals(0.0, new Complex(1, -2).subtract(D.getEntry(1, 1)).norm(), 1.0e-15);
122 }
123
124 @Test
125 public void testEqualEigenvalues() {
126
127 final RealMatrix A = MatrixUtils.createRealMatrix(new double[][] {
128 { 1.0, 0.0, 0.0 },
129 { 0.0, 1.0, 0.0 },
130 { 0.0, 0.0, 1.0 }
131 });
132 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(A);
133
134 Assert.assertEquals(3, eigenDecomp.getEigenvalues().length);
135 for (Complex z : eigenDecomp.getEigenvalues()) {
136 Assert.assertEquals(Complex.ONE, z);
137 }
138
139 checkScaledVector(buildVector(Complex.ONE, Complex.ZERO, Complex.ZERO), eigenDecomp.getEigenvector(0), 1.0e-12);
140 checkScaledVector(buildVector(Complex.ZERO, Complex.ONE, Complex.ZERO), eigenDecomp.getEigenvector(1), 1.0e-12);
141 checkScaledVector(buildVector(Complex.ZERO, Complex.ZERO, Complex.ONE), eigenDecomp.getEigenvector(2), 1.0e-12);
142
143 }
144
145 @Test
146 public void testDefinition() {
147
148 final RealMatrix aR = MatrixUtils.createRealMatrix(new double[][] { { 3, -2 }, { 4, -1 } });
149 ComplexEigenDecomposition eigenDecomp = new ComplexEigenDecomposition(aR);
150 FieldMatrix<Complex> aC = toComplex(aR);
151
152
153 checkScaledVector(aC.operate(eigenDecomp.getEigenvector(0)),
154 eigenDecomp.getEigenvector(0).mapMultiply(eigenDecomp.getEigenvalues()[0]),
155 1.0e-12);
156
157
158 checkScaledVector(aC.operate(eigenDecomp.getEigenvector(1)),
159 eigenDecomp.getEigenvector(1).mapMultiply(eigenDecomp.getEigenvalues()[1]),
160 1.0e-12);
161
162
163 checkMatrix(aC.multiply(eigenDecomp.getV()),
164 eigenDecomp.getV().multiply(eigenDecomp.getD()),
165 1.0e-12);
166 }
167
168 @Test
169 public void testIssue249() {
170
171
172
173
174
175 final RealMatrix matrix = new Array2DRowRealMatrix(new double[][] {
176 { 1.0, 0.0, 0.0 },
177 { -2.0, 1.0, 0.0 },
178 { 0.0, 0.0, 1.0 }
179 });
180
181 final ComplexEigenDecomposition ced = new OrderedComplexEigenDecomposition(matrix,
182 ComplexEigenDecomposition.DEFAULT_EIGENVECTORS_EQUALITY,
183 ComplexEigenDecomposition.DEFAULT_EPSILON,
184 ComplexEigenDecomposition.DEFAULT_EPSILON_AV_VD_CHECK,
185 (c1, c2) -> Double.compare(c2.norm(), c1.norm()));
186
187 Assert.assertEquals(3, ced.getEigenvalues().length);
188 Assert.assertEquals(1.0, ced.getEigenvector(0).dotProduct(ced.getEigenvector(0)).norm(), 1.0e-15);
189 Assert.assertEquals(1.0, ced.getEigenvector(1).dotProduct(ced.getEigenvector(1)).norm(), 1.0e-15);
190 Assert.assertEquals(0.0, ced.getEigenvector(2).dotProduct(ced.getEigenvector(2)).norm(), 1.0e-15);
191
192 }
193
194 private FieldMatrix<Complex> toComplex(final RealMatrix m) {
195 FieldMatrix<Complex> c = MatrixUtils.createFieldMatrix(ComplexField.getInstance(),
196 m.getRowDimension(),
197 m.getColumnDimension());
198 for (int i = 0; i < m.getRowDimension(); ++i) {
199 for (int j = 0; j < m.getColumnDimension(); ++j) {
200 c.setEntry(i, j, new Complex(m.getEntry(i, j)));
201 }
202 }
203
204 return c;
205
206 }
207
208 private FieldVector<Complex> buildVector(final Complex... vi) {
209 return new ArrayFieldVector<>(vi);
210 }
211
212 private void checkScaledVector(final FieldVector<Complex> v, final FieldVector<Complex> reference, final double tol) {
213
214 Assert.assertEquals(reference.getDimension(), v.getDimension());
215
216
217 Complex scale = Complex.NaN;
218 double norm = Double.NEGATIVE_INFINITY;
219 for (int i = 0; i < reference.getDimension(); i++) {
220 final Complex ri = reference.getEntry(i);
221 final double ni = FastMath.hypot(ri.getReal(), ri.getImaginary());
222 if (ni > norm) {
223 scale = ri.divide(v.getEntry(i));
224 norm = ni;
225 }
226 }
227
228
229 for (int i = 0; i < reference.getDimension(); ++i) {
230 final Complex ri = reference.getEntry(i);
231 final Complex vi = v.getEntry(i);
232 final Complex si = vi.multiply(scale);
233 Assert.assertEquals("" + (ri.getReal() - si.getReal()), ri.getReal(), si.getReal(), tol);
234 Assert.assertEquals("" + (ri.getImaginary() - si.getImaginary()), ri.getImaginary(), si.getImaginary(), tol);
235 }
236
237 }
238
239 private void checkMatrix(final FieldMatrix<Complex> m, final FieldMatrix<Complex> reference, final double tol) {
240 Assert.assertEquals(reference.getRowDimension(), m.getRowDimension());
241 Assert.assertEquals(reference.getColumnDimension(), m.getColumnDimension());
242 for (int i = 0; i < reference.getRowDimension(); ++i) {
243 for (int j = 0; j < reference.getColumnDimension(); ++j) {
244 Assert.assertEquals("" + (reference.getEntry(i, j).getReal() - m.getEntry(i, j).getReal()),
245 reference.getEntry(i, j).getReal(), m.getEntry(i, j).getReal(), tol);
246 Assert.assertEquals("" + (reference.getEntry(i, j).getImaginary() - m.getEntry(i, j).getImaginary()),
247 reference.getEntry(i, j).getImaginary(), m.getEntry(i, j).getImaginary(), tol);
248 }
249 }
250 }
251
252 }