LUDecomposition.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /**
  2. * @file LUDecomposition.cpp
  3. * @brief: LU-Decomposition of a matrix
  4. * @author: Alexander Freytag, Wolfgang Ortmann
  5. * @date: 22-10-2012
  6. */
  7. // Note: for further matrix operations, you might use the ICE library available at http://www.inf-cv.uni-jena.de/ice.html
  8. #include "LUDecomposition.h"
  9. using namespace std;
  10. using namespace NICE;
  11. LUDecomposition::LUDecomposition()
  12. {
  13. }
  14. LUDecomposition::~LUDecomposition()
  15. {
  16. }
  17. void LUDecomposition::decompose( const NICE::Matrix & m, NICE::Matrix & L, NICE::Matrix &U )
  18. {
  19. NICE::Matrix LU;
  20. this->decomposePacked( m, LU );
  21. int i,j;
  22. L = LU;
  23. U = LU;
  24. // get the actual matrices
  25. // U is an upper triangular matrix
  26. for (i = 0; i < (int)U.cols(); i++)
  27. {
  28. for (j = i + 1; j < (int)U.rows(); j++)
  29. U(j,i) = 0;
  30. }
  31. // L is a lower triangular matrix
  32. for (i = 0; i < (int)L.cols(); i++)
  33. {
  34. for (j = 0; j < i; j++)
  35. L(j,i) = 0;
  36. L(i,i) = 1.0;
  37. }
  38. }
  39. Vector LUSolve(const NICE::Matrix & LU, const NICE::VectorT<int> & indx, const NICE::Vector & b)
  40. {
  41. NICE::Vector res(b);
  42. double sum;
  43. int dim = LU.cols();
  44. //is the given matrix square?
  45. if (dim!=(int)LU.rows())
  46. {
  47. fthrow(Exception, "Matrix is not square");
  48. return res;
  49. }
  50. //do the matrix LU and the given index vector have same sizes?
  51. if ((int)indx.size()!=dim)
  52. {
  53. fthrow(Exception, "Wrong dimensions of matrix and index-vector");
  54. return res;
  55. }
  56. //do the matrix LU and the given b-vector have same sizes?
  57. if ((int)b.size()!=dim)
  58. {
  59. fthrow(Exception, "Wrong dimensions of matrix and b-vector");
  60. return res;
  61. }
  62. int i, ii, ip, j;
  63. ii = -1;
  64. for (i = 0; i < dim; i++)
  65. {
  66. ip = indx[i];
  67. sum = res[ip];
  68. res[ip] = res[i];
  69. if (ii >= 0)
  70. {
  71. for (j = ii; j < i; j++)
  72. sum -= LU(i, j) * res[j];
  73. }
  74. else
  75. {
  76. if (sum)
  77. ii = i;
  78. }
  79. res[i] = sum;
  80. }
  81. for (i = dim - 1; i >= 0; i--)
  82. {
  83. sum = res[i];
  84. for (j = i + 1; j < dim; j++)
  85. sum -= LU(i, j) * res[j];
  86. res[i] = sum / LU(i, i);
  87. }
  88. return res;
  89. }
  90. void LUDecomposition::decomposePacked(const NICE::Matrix & m, NICE::Matrix & LU, NICE::VectorT<int> &indx, bool pivot)
  91. {
  92. int dim = m.cols();
  93. // check, whether the matrix is square
  94. if (dim != (int)m.rows())
  95. {
  96. fthrow(Exception, "Matrix is not square");
  97. }
  98. LU = m;
  99. NICE::Vector vv(dim);
  100. indx.resize(dim);
  101. int i, j, k, imax;
  102. double sum, big, dum;
  103. int dsign = 1;
  104. for (i = 0; i < dim; i++)
  105. {
  106. big = 0.0;
  107. for (j = 0; j < dim; j++)
  108. {
  109. double temp = fabs(LU(i, j));
  110. if (temp > big)
  111. big = temp;
  112. }
  113. //check for singularity, i.e., the largest absolute singular value is zero
  114. if (big == 0)
  115. {
  116. fthrow(Exception, "Matrix is singular");
  117. }
  118. vv[i] = 1.0 / big;
  119. }
  120. // loop over all columns
  121. for (j = 0; j < dim; j++)
  122. {
  123. //and over all rows
  124. for (i = 0; i < j; i++)
  125. {
  126. sum = LU(i,j);
  127. for (k = 0; k < i; k++)
  128. sum -= LU(i, k) * LU(k, j);
  129. LU(i,j)=sum;
  130. }
  131. big = 0.0;
  132. imax = 0; // avoid warning
  133. for (i = j; i < dim; i++)
  134. {
  135. sum = LU(i, j);
  136. for (k = 0; k < j; k++)
  137. sum -= LU(i, k) * LU(k, j);
  138. LU(i, j) = sum;
  139. dum = vv[i] * fabs(sum);
  140. if (dum >= big)
  141. {
  142. big = dum;
  143. imax = i;
  144. }
  145. }
  146. //pivotization?
  147. if (pivot)
  148. {
  149. if (j != imax)
  150. {
  151. LU.exchangeRows(j, imax);
  152. dsign = -dsign;
  153. vv[imax] = vv[j];
  154. }
  155. indx[j] = imax;
  156. }
  157. else indx[j] = j;
  158. if (LU(j, j) == 0)
  159. {
  160. fthrow(Exception, "Matrix is singular");
  161. }
  162. if (j < dim - 1)
  163. {
  164. dum = 1.0 / LU(j, j);
  165. for (i = j + 1; i < dim; i++)
  166. LU(i, j) *= dum;
  167. }
  168. } // all columns
  169. }
  170. void LUDecomposition::decomposePacked(const NICE::Matrix & m, NICE::Matrix & LU)
  171. {
  172. NICE::VectorT<int> ndx; // dummy, not used (without pivotization)
  173. this->decomposePacked(m, LU, ndx, false);
  174. }