Home | History | Annotate | Download | only in test
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1 (at) gmail.com>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 #include "main.h"
     11 #include <Eigen/LU>
     12 using namespace std;
     13 
     14 template<typename MatrixType> void lu_non_invertible()
     15 {
     16   typedef typename MatrixType::Index Index;
     17   typedef typename MatrixType::RealScalar RealScalar;
     18   /* this test covers the following files:
     19      LU.h
     20   */
     21   Index rows, cols, cols2;
     22   if(MatrixType::RowsAtCompileTime==Dynamic)
     23   {
     24     rows = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
     25   }
     26   else
     27   {
     28     rows = MatrixType::RowsAtCompileTime;
     29   }
     30   if(MatrixType::ColsAtCompileTime==Dynamic)
     31   {
     32     cols = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
     33     cols2 = internal::random<int>(2,EIGEN_TEST_MAX_SIZE);
     34   }
     35   else
     36   {
     37     cols2 = cols = MatrixType::ColsAtCompileTime;
     38   }
     39 
     40   enum {
     41     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
     42     ColsAtCompileTime = MatrixType::ColsAtCompileTime
     43   };
     44   typedef typename internal::kernel_retval_base<FullPivLU<MatrixType> >::ReturnType KernelMatrixType;
     45   typedef typename internal::image_retval_base<FullPivLU<MatrixType> >::ReturnType ImageMatrixType;
     46   typedef Matrix<typename MatrixType::Scalar, ColsAtCompileTime, ColsAtCompileTime>
     47           CMatrixType;
     48   typedef Matrix<typename MatrixType::Scalar, RowsAtCompileTime, RowsAtCompileTime>
     49           RMatrixType;
     50 
     51   Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
     52 
     53   // The image of the zero matrix should consist of a single (zero) column vector
     54   VERIFY((MatrixType::Zero(rows,cols).fullPivLu().image(MatrixType::Zero(rows,cols)).cols() == 1));
     55 
     56   MatrixType m1(rows, cols), m3(rows, cols2);
     57   CMatrixType m2(cols, cols2);
     58   createRandomPIMatrixOfRank(rank, rows, cols, m1);
     59 
     60   FullPivLU<MatrixType> lu;
     61 
     62   // The special value 0.01 below works well in tests. Keep in mind that we're only computing the rank
     63   // of singular values are either 0 or 1.
     64   // So it's not clear at all that the epsilon should play any role there.
     65   lu.setThreshold(RealScalar(0.01));
     66   lu.compute(m1);
     67 
     68   MatrixType u(rows,cols);
     69   u = lu.matrixLU().template triangularView<Upper>();
     70   RMatrixType l = RMatrixType::Identity(rows,rows);
     71   l.block(0,0,rows,(std::min)(rows,cols)).template triangularView<StrictlyLower>()
     72     = lu.matrixLU().block(0,0,rows,(std::min)(rows,cols));
     73 
     74   VERIFY_IS_APPROX(lu.permutationP() * m1 * lu.permutationQ(), l*u);
     75 
     76   KernelMatrixType m1kernel = lu.kernel();
     77   ImageMatrixType m1image = lu.image(m1);
     78 
     79   VERIFY_IS_APPROX(m1, lu.reconstructedMatrix());
     80   VERIFY(rank == lu.rank());
     81   VERIFY(cols - lu.rank() == lu.dimensionOfKernel());
     82   VERIFY(!lu.isInjective());
     83   VERIFY(!lu.isInvertible());
     84   VERIFY(!lu.isSurjective());
     85   VERIFY((m1 * m1kernel).isMuchSmallerThan(m1));
     86   VERIFY(m1image.fullPivLu().rank() == rank);
     87   VERIFY_IS_APPROX(m1 * m1.adjoint() * m1image, m1image);
     88 
     89   m2 = CMatrixType::Random(cols,cols2);
     90   m3 = m1*m2;
     91   m2 = CMatrixType::Random(cols,cols2);
     92   // test that the code, which does resize(), may be applied to an xpr
     93   m2.block(0,0,m2.rows(),m2.cols()) = lu.solve(m3);
     94   VERIFY_IS_APPROX(m3, m1*m2);
     95 }
     96 
     97 template<typename MatrixType> void lu_invertible()
     98 {
     99   /* this test covers the following files:
    100      LU.h
    101   */
    102   typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
    103   int size = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
    104 
    105   MatrixType m1(size, size), m2(size, size), m3(size, size);
    106   FullPivLU<MatrixType> lu;
    107   lu.setThreshold(RealScalar(0.01));
    108   do {
    109     m1 = MatrixType::Random(size,size);
    110     lu.compute(m1);
    111   } while(!lu.isInvertible());
    112 
    113   VERIFY_IS_APPROX(m1, lu.reconstructedMatrix());
    114   VERIFY(0 == lu.dimensionOfKernel());
    115   VERIFY(lu.kernel().cols() == 1); // the kernel() should consist of a single (zero) column vector
    116   VERIFY(size == lu.rank());
    117   VERIFY(lu.isInjective());
    118   VERIFY(lu.isSurjective());
    119   VERIFY(lu.isInvertible());
    120   VERIFY(lu.image(m1).fullPivLu().isInvertible());
    121   m3 = MatrixType::Random(size,size);
    122   m2 = lu.solve(m3);
    123   VERIFY_IS_APPROX(m3, m1*m2);
    124   VERIFY_IS_APPROX(m2, lu.inverse()*m3);
    125 }
    126 
    127 template<typename MatrixType> void lu_partial_piv()
    128 {
    129   /* this test covers the following files:
    130      PartialPivLU.h
    131   */
    132   typedef typename MatrixType::Index Index;
    133   Index rows = internal::random<Index>(1,4);
    134   Index cols = rows;
    135 
    136   MatrixType m1(cols, rows);
    137   m1.setRandom();
    138   PartialPivLU<MatrixType> plu(m1);
    139 
    140   VERIFY_IS_APPROX(m1, plu.reconstructedMatrix());
    141 }
    142 
    143 template<typename MatrixType> void lu_verify_assert()
    144 {
    145   MatrixType tmp;
    146 
    147   FullPivLU<MatrixType> lu;
    148   VERIFY_RAISES_ASSERT(lu.matrixLU())
    149   VERIFY_RAISES_ASSERT(lu.permutationP())
    150   VERIFY_RAISES_ASSERT(lu.permutationQ())
    151   VERIFY_RAISES_ASSERT(lu.kernel())
    152   VERIFY_RAISES_ASSERT(lu.image(tmp))
    153   VERIFY_RAISES_ASSERT(lu.solve(tmp))
    154   VERIFY_RAISES_ASSERT(lu.determinant())
    155   VERIFY_RAISES_ASSERT(lu.rank())
    156   VERIFY_RAISES_ASSERT(lu.dimensionOfKernel())
    157   VERIFY_RAISES_ASSERT(lu.isInjective())
    158   VERIFY_RAISES_ASSERT(lu.isSurjective())
    159   VERIFY_RAISES_ASSERT(lu.isInvertible())
    160   VERIFY_RAISES_ASSERT(lu.inverse())
    161 
    162   PartialPivLU<MatrixType> plu;
    163   VERIFY_RAISES_ASSERT(plu.matrixLU())
    164   VERIFY_RAISES_ASSERT(plu.permutationP())
    165   VERIFY_RAISES_ASSERT(plu.solve(tmp))
    166   VERIFY_RAISES_ASSERT(plu.determinant())
    167   VERIFY_RAISES_ASSERT(plu.inverse())
    168 }
    169 
    170 void test_lu()
    171 {
    172   for(int i = 0; i < g_repeat; i++) {
    173     CALL_SUBTEST_1( lu_non_invertible<Matrix3f>() );
    174     CALL_SUBTEST_1( lu_verify_assert<Matrix3f>() );
    175 
    176     CALL_SUBTEST_2( (lu_non_invertible<Matrix<double, 4, 6> >()) );
    177     CALL_SUBTEST_2( (lu_verify_assert<Matrix<double, 4, 6> >()) );
    178 
    179     CALL_SUBTEST_3( lu_non_invertible<MatrixXf>() );
    180     CALL_SUBTEST_3( lu_invertible<MatrixXf>() );
    181     CALL_SUBTEST_3( lu_verify_assert<MatrixXf>() );
    182 
    183     CALL_SUBTEST_4( lu_non_invertible<MatrixXd>() );
    184     CALL_SUBTEST_4( lu_invertible<MatrixXd>() );
    185     CALL_SUBTEST_4( lu_partial_piv<MatrixXd>() );
    186     CALL_SUBTEST_4( lu_verify_assert<MatrixXd>() );
    187 
    188     CALL_SUBTEST_5( lu_non_invertible<MatrixXcf>() );
    189     CALL_SUBTEST_5( lu_invertible<MatrixXcf>() );
    190     CALL_SUBTEST_5( lu_verify_assert<MatrixXcf>() );
    191 
    192     CALL_SUBTEST_6( lu_non_invertible<MatrixXcd>() );
    193     CALL_SUBTEST_6( lu_invertible<MatrixXcd>() );
    194     CALL_SUBTEST_6( lu_partial_piv<MatrixXcd>() );
    195     CALL_SUBTEST_6( lu_verify_assert<MatrixXcd>() );
    196 
    197     CALL_SUBTEST_7(( lu_non_invertible<Matrix<float,Dynamic,16> >() ));
    198 
    199     // Test problem size constructors
    200     CALL_SUBTEST_9( PartialPivLU<MatrixXf>(10) );
    201     CALL_SUBTEST_9( FullPivLU<MatrixXf>(10, 20); );
    202   }
    203 }
    204