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    *      http://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  package org.apache.commons.math.linear;
19  
20  import junit.framework.Test;
21  import junit.framework.TestCase;
22  import junit.framework.TestSuite;
23  
24  import org.apache.commons.math.MathException;
25  import org.apache.commons.math.linear.CholeskyDecompositionImpl;
26  import org.apache.commons.math.linear.DecompositionSolver;
27  import org.apache.commons.math.linear.MatrixUtils;
28  import org.apache.commons.math.linear.RealMatrix;
29  import org.apache.commons.math.linear.ArrayRealVector;
30  
31  public class CholeskySolverTest extends TestCase {
32  
33      private double[][] testData = new double[][] {
34              {  1,  2,   4,   7,  11 },
35              {  2, 13,  23,  38,  58 },
36              {  4, 23,  77, 122, 182 },
37              {  7, 38, 122, 294, 430 },
38              { 11, 58, 182, 430, 855 }
39      };
40  
41      public CholeskySolverTest(String name) {
42          super(name);
43      }
44  
45      public static Test suite() {
46          TestSuite suite = new TestSuite(CholeskySolverTest.class);
47          suite.setName("LUSolver Tests");
48          return suite;
49      }
50  
51      /** test solve dimension errors */
52      public void testSolveDimensionErrors() throws MathException {
53          DecompositionSolver solver =
54              new CholeskyDecompositionImpl(MatrixUtils.createRealMatrix(testData)).getSolver();
55          RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]);
56          try {
57              solver.solve(b);
58              fail("an exception should have been thrown");
59          } catch (IllegalArgumentException iae) {
60              // expected behavior
61          } catch (Exception e) {
62              fail("wrong exception caught");
63          }
64          try {
65              solver.solve(b.getColumn(0));
66              fail("an exception should have been thrown");
67          } catch (IllegalArgumentException iae) {
68              // expected behavior
69          } catch (Exception e) {
70              fail("wrong exception caught");
71          }
72          try {
73              solver.solve(new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(0)));
74              fail("an exception should have been thrown");
75          } catch (IllegalArgumentException iae) {
76              // expected behavior
77          } catch (Exception e) {
78              fail("wrong exception caught");
79          }
80      }
81  
82      /** test solve */
83      public void testSolve() throws MathException {
84          DecompositionSolver solver =
85              new CholeskyDecompositionImpl(MatrixUtils.createRealMatrix(testData)).getSolver();
86          RealMatrix b = MatrixUtils.createRealMatrix(new double[][] {
87                  {   78,  -13,    1 },
88                  {  414,  -62,   -1 },
89                  { 1312, -202,  -37 },
90                  { 2989, -542,  145 },
91                  { 5510, -1465, 201 }
92          });
93          RealMatrix xRef = MatrixUtils.createRealMatrix(new double[][] {
94                  { 1,  0,  1 },
95                  { 0,  1,  1 },
96                  { 2,  1, -4 },
97                  { 2,  2,  2 },
98                  { 5, -3,  0 }
99          });
100 
101         // using RealMatrix
102         assertEquals(0, solver.solve(b).subtract(xRef).getNorm(), 1.0e-13);
103 
104         // using double[]
105         for (int i = 0; i < b.getColumnDimension(); ++i) {
106             assertEquals(0,
107                          new ArrayRealVector(solver.solve(b.getColumn(i))).subtract(xRef.getColumnVector(i)).getNorm(),
108                          1.0e-13);
109         }
110 
111         // using ArrayRealVector
112         for (int i = 0; i < b.getColumnDimension(); ++i) {
113             assertEquals(0,
114                          solver.solve(b.getColumnVector(i)).subtract(xRef.getColumnVector(i)).getNorm(),
115                          1.0e-13);
116         }
117 
118         // using RealVector with an alternate implementation
119         for (int i = 0; i < b.getColumnDimension(); ++i) {
120             ArrayRealVectorTest.RealVectorTestImpl v =
121                 new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(i));
122             assertEquals(0,
123                          solver.solve(v).subtract(xRef.getColumnVector(i)).getNorm(),
124                          1.0e-13);
125         }
126 
127     }
128 
129     /** test determinant */
130     public void testDeterminant() throws MathException {
131         assertEquals(7290000.0, getDeterminant(MatrixUtils.createRealMatrix(testData)), 1.0e-15);
132     }
133 
134     private double getDeterminant(RealMatrix m) throws MathException {
135         return new CholeskyDecompositionImpl(m).getDeterminant();
136     }
137 
138 }