View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  
23  package org.hipparchus.linear;
24  
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.hipparchus.fraction.Fraction;
27  import org.hipparchus.fraction.FractionField;
28  import org.junit.Assert;
29  import org.junit.Test;
30  
31  public class FieldLUSolverTest {
32      private int[][] testData = {
33              { 1, 2, 3},
34              { 2, 5, 3},
35              { 1, 0, 8}
36      };
37      private int[][] luData = {
38              { 2, 3, 3 },
39              { 0, 5, 7 },
40              { 6, 9, 8 }
41      };
42  
43      // singular matrices
44      private int[][] singular = {
45              { 2, 3 },
46              { 2, 3 }
47      };
48      private int[][] bigSingular = {
49              { 1, 2,   3,    4 },
50              { 2, 5,   3,    4 },
51              { 7, 3, 256, 1930 },
52              { 3, 7,   6,    8 }
53      }; // 4th row = 1st + 2nd
54  
55      public static FieldMatrix<Fraction> createFractionMatrix(final int[][] data) {
56          final int numRows = data.length;
57          final int numCols = data[0].length;
58          final Array2DRowFieldMatrix<Fraction> m;
59          m = new Array2DRowFieldMatrix<Fraction>(FractionField.getInstance(),
60                                                  numRows, numCols);
61          for (int i = 0; i < numRows; i++) {
62              for (int j = 0; j < numCols; j++) {
63                  m.setEntry(i, j, new Fraction(data[i][j], 1));
64              }
65          }
66          return m;
67      }
68  
69      /** test singular */
70      @Test
71      public void testSingular() {
72          FieldDecompositionSolver<Fraction> solver;
73          solver = new FieldLUDecomposition<Fraction>(createFractionMatrix(testData))
74              .getSolver();
75          Assert.assertTrue(solver.isNonSingular());
76          solver = new FieldLUDecomposition<Fraction>(createFractionMatrix(singular))
77              .getSolver();
78          Assert.assertFalse(solver.isNonSingular());
79          solver = new FieldLUDecomposition<Fraction>(createFractionMatrix(bigSingular))
80              .getSolver();
81          Assert.assertFalse(solver.isNonSingular());
82      }
83  
84      /** test solve dimension errors */
85      @Test
86      public void testSolveDimensionErrors() {
87          FieldDecompositionSolver<Fraction> solver;
88          solver = new FieldLUDecomposition<Fraction>(createFractionMatrix(testData))
89              .getSolver();
90          FieldMatrix<Fraction> b = createFractionMatrix(new int[2][2]);
91          try {
92              solver.solve(b);
93              Assert.fail("an exception should have been thrown");
94          } catch (MathIllegalArgumentException iae) {
95              // expected behavior
96          }
97          try {
98              solver.solve(b.getColumnVector(0));
99              Assert.fail("an exception should have been thrown");
100         } catch (MathIllegalArgumentException iae) {
101             // expected behavior
102         }
103     }
104 
105     /** test solve singularity errors */
106     @Test
107     public void testSolveSingularityErrors() {
108         FieldDecompositionSolver<Fraction> solver;
109         solver = new FieldLUDecomposition<Fraction>(createFractionMatrix(singular))
110             .getSolver();
111         FieldMatrix<Fraction> b = createFractionMatrix(new int[2][2]);
112         try {
113             solver.solve(b);
114             Assert.fail("an exception should have been thrown");
115         } catch (MathIllegalArgumentException ime) {
116             // expected behavior
117         }
118         try {
119             solver.solve(b.getColumnVector(0));
120             Assert.fail("an exception should have been thrown");
121         } catch (MathIllegalArgumentException ime) {
122             // expected behavior
123         }
124     }
125 
126     /** test solve */
127     @Test
128     public void testSolve() {
129         FieldDecompositionSolver<Fraction> solver;
130         solver = new FieldLUDecomposition<Fraction>(createFractionMatrix(testData))
131             .getSolver();
132         FieldMatrix<Fraction> b = createFractionMatrix(new int[][] {
133                 { 1, 0 }, { 2, -5 }, { 3, 1 }
134         });
135         FieldMatrix<Fraction> xRef = createFractionMatrix(new int[][] {
136                 { 19, -71 }, { -6, 22 }, { -2, 9 }
137         });
138 
139         // using FieldMatrix
140         FieldMatrix<Fraction> x = solver.solve(b);
141         for (int i = 0; i < x.getRowDimension(); i++){
142             for (int j = 0; j < x.getColumnDimension(); j++){
143                 Assert.assertEquals("(" + i + ", " + j + ")",
144                                     xRef.getEntry(i, j), x.getEntry(i, j));
145             }
146         }
147 
148         // using ArrayFieldVector
149         for (int j = 0; j < b.getColumnDimension(); j++) {
150             final FieldVector<Fraction> xj = solver.solve(b.getColumnVector(j));
151             for (int i = 0; i < xj.getDimension(); i++){
152                 Assert.assertEquals("(" + i + ", " + j + ")",
153                                     xRef.getEntry(i, j), xj.getEntry(i));
154             }
155         }
156 
157         // using SparseFieldVector
158         for (int j = 0; j < b.getColumnDimension(); j++) {
159             final SparseFieldVector<Fraction> bj;
160             bj = new SparseFieldVector<Fraction>(FractionField.getInstance(),
161                                                  b.getColumn(j));
162             final FieldVector<Fraction> xj = solver.solve(bj);
163             for (int i = 0; i < xj.getDimension(); i++) {
164                 Assert.assertEquals("(" + i + ", " + j + ")",
165                                     xRef.getEntry(i, j), xj.getEntry(i));
166             }
167         }
168     }
169 
170     /** test determinant */
171     @Test
172     public void testDeterminant() {
173         Assert.assertEquals( -1, getDeterminant(createFractionMatrix(testData)), 1E-15);
174         Assert.assertEquals(-10, getDeterminant(createFractionMatrix(luData)), 1E-14);
175         Assert.assertEquals(  0, getDeterminant(createFractionMatrix(singular)), 1E-15);
176         Assert.assertEquals(  0, getDeterminant(createFractionMatrix(bigSingular)), 1E-15);
177     }
178 
179     private double getDeterminant(final FieldMatrix<Fraction> m) {
180         return new FieldLUDecomposition<Fraction>(m).getDeterminant().doubleValue();
181     }
182 }