001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.math.linear; 019 020 import static org.junit.Assert.assertEquals; 021 import static org.junit.Assert.assertTrue; 022 023 import org.apache.commons.math.MathException; 024 import org.apache.commons.math.linear.CholeskyDecomposition; 025 import org.apache.commons.math.linear.CholeskyDecompositionImpl; 026 import org.apache.commons.math.linear.MatrixUtils; 027 import org.apache.commons.math.linear.NonSquareMatrixException; 028 import org.apache.commons.math.linear.NotPositiveDefiniteMatrixException; 029 import org.apache.commons.math.linear.NotSymmetricMatrixException; 030 import org.apache.commons.math.linear.RealMatrix; 031 import org.junit.Test; 032 033 public class CholeskyDecompositionImplTest { 034 035 private double[][] testData = new double[][] { 036 { 1, 2, 4, 7, 11 }, 037 { 2, 13, 23, 38, 58 }, 038 { 4, 23, 77, 122, 182 }, 039 { 7, 38, 122, 294, 430 }, 040 { 11, 58, 182, 430, 855 } 041 }; 042 043 /** test dimensions */ 044 @Test 045 public void testDimensions() throws MathException { 046 CholeskyDecomposition llt = 047 new CholeskyDecompositionImpl(MatrixUtils.createRealMatrix(testData)); 048 assertEquals(testData.length, llt.getL().getRowDimension()); 049 assertEquals(testData.length, llt.getL().getColumnDimension()); 050 assertEquals(testData.length, llt.getLT().getRowDimension()); 051 assertEquals(testData.length, llt.getLT().getColumnDimension()); 052 } 053 054 /** test non-square matrix */ 055 @Test(expected = NonSquareMatrixException.class) 056 public void testNonSquare() throws MathException { 057 new CholeskyDecompositionImpl(MatrixUtils.createRealMatrix(new double[3][2])); 058 } 059 060 /** test non-symmetric matrix */ 061 @Test(expected = NotSymmetricMatrixException.class) 062 public void testNotSymmetricMatrixException() throws MathException { 063 double[][] changed = testData.clone(); 064 changed[0][changed[0].length - 1] += 1.0e-5; 065 new CholeskyDecompositionImpl(MatrixUtils.createRealMatrix(changed)); 066 } 067 068 /** test non positive definite matrix */ 069 @Test(expected = NotPositiveDefiniteMatrixException.class) 070 public void testNotPositiveDefinite() throws MathException { 071 new CholeskyDecompositionImpl(MatrixUtils.createRealMatrix(new double[][] { 072 { 14, 11, 13, 15, 24 }, 073 { 11, 34, 13, 8, 25 }, 074 { 13, 13, 14, 15, 21 }, 075 { 15, 8, 15, 18, 23 }, 076 { 24, 25, 21, 23, 45 } 077 })); 078 } 079 080 @Test(expected = NotPositiveDefiniteMatrixException.class) 081 public void testMath274() throws MathException { 082 new CholeskyDecompositionImpl(MatrixUtils.createRealMatrix(new double[][] { 083 { 0.40434286, -0.09376327, 0.30328980, 0.04909388 }, 084 {-0.09376327, 0.10400408, 0.07137959, 0.04762857 }, 085 { 0.30328980, 0.07137959, 0.30458776, 0.04882449 }, 086 { 0.04909388, 0.04762857, 0.04882449, 0.07543265 } 087 088 })); 089 } 090 091 /** test A = LLT */ 092 @Test 093 public void testAEqualLLT() throws MathException { 094 RealMatrix matrix = MatrixUtils.createRealMatrix(testData); 095 CholeskyDecomposition llt = new CholeskyDecompositionImpl(matrix); 096 RealMatrix l = llt.getL(); 097 RealMatrix lt = llt.getLT(); 098 double norm = l.multiply(lt).subtract(matrix).getNorm(); 099 assertEquals(0, norm, 1.0e-15); 100 } 101 102 /** test that L is lower triangular */ 103 @Test 104 public void testLLowerTriangular() throws MathException { 105 RealMatrix matrix = MatrixUtils.createRealMatrix(testData); 106 RealMatrix l = new CholeskyDecompositionImpl(matrix).getL(); 107 for (int i = 0; i < l.getRowDimension(); i++) { 108 for (int j = i + 1; j < l.getColumnDimension(); j++) { 109 assertEquals(0.0, l.getEntry(i, j), 0.0); 110 } 111 } 112 } 113 114 /** test that LT is transpose of L */ 115 @Test 116 public void testLTTransposed() throws MathException { 117 RealMatrix matrix = MatrixUtils.createRealMatrix(testData); 118 CholeskyDecomposition llt = new CholeskyDecompositionImpl(matrix); 119 RealMatrix l = llt.getL(); 120 RealMatrix lt = llt.getLT(); 121 double norm = l.subtract(lt.transpose()).getNorm(); 122 assertEquals(0, norm, 1.0e-15); 123 } 124 125 /** test matrices values */ 126 @Test 127 public void testMatricesValues() throws MathException { 128 RealMatrix lRef = MatrixUtils.createRealMatrix(new double[][] { 129 { 1, 0, 0, 0, 0 }, 130 { 2, 3, 0, 0, 0 }, 131 { 4, 5, 6, 0, 0 }, 132 { 7, 8, 9, 10, 0 }, 133 { 11, 12, 13, 14, 15 } 134 }); 135 CholeskyDecomposition llt = 136 new CholeskyDecompositionImpl(MatrixUtils.createRealMatrix(testData)); 137 138 // check values against known references 139 RealMatrix l = llt.getL(); 140 assertEquals(0, l.subtract(lRef).getNorm(), 1.0e-13); 141 RealMatrix lt = llt.getLT(); 142 assertEquals(0, lt.subtract(lRef.transpose()).getNorm(), 1.0e-13); 143 144 // check the same cached instance is returned the second time 145 assertTrue(l == llt.getL()); 146 assertTrue(lt == llt.getLT()); 147 148 } 149 150 }