core/vnl/algo/vnl_sparse_lu.cxx
Go to the documentation of this file.
00001 // This is core/vnl/algo/vnl_sparse_lu.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 #include "vnl_sparse_lu.h"
00008 #include <vcl_cassert.h>
00009 #include <vcl_iostream.h>
00010 
00011 #include <sparse/spMatrix.h>
00012 
00013 // destructor - undo the spCreate() from the constructor(s)
00014 // (memory leak fix of 7 Feb. 2008 by Toon Huysmans)
00015 vnl_sparse_lu::~vnl_sparse_lu()
00016 {
00017   spDestroy( pmatrix_ );
00018 }
00019 
00020 //: constructor - controls if condition information is computed
00021 vnl_sparse_lu::vnl_sparse_lu(vnl_sparse_matrix<double> const & M, operation mode):
00022   A_(M), factored_(false),condition_computed_(false), mode_(mode),norm_(0), rcond_(0), largest_(0), pivot_thresh_(0),absolute_thresh_(0),diag_pivoting_(1),pmatrix_(0)
00023 {
00024   int n = (int)M.columns();
00025   assert(n == (int)(M.rows()));
00026   int error = 0;
00027   pmatrix_ = spCreate(n, 0, &error);
00028   if (error!=spOKAY)
00029   {
00030     vcl_cout << "In vnl_sparse_lu::vnl_sparse_lu - error in creating matrix\n";
00031     return;
00032   }
00033   // fill the internal sparse matrix from A_
00034   spElement* pelement = 0;
00035   for (A_.reset(); A_.next();)
00036   {
00037     int r = A_.getrow();
00038     int c = A_.getcolumn();
00039     double v = A_.value();
00040     pelement = spGetElement(pmatrix_, r+1, c+1);
00041     if (pelement == 0)
00042     {
00043       vcl_cout<< "In vnl_sparse_lu::vnl_sparse_lu - error in getting element\n";
00044       return;
00045     }
00046     *pelement = v;
00047   }
00048   if (mode==estimate_condition || mode_==estimate_condition_verbose)
00049   {
00050     largest_ = spLargestElement(pmatrix_);
00051     if (mode_==estimate_condition_verbose)
00052       vcl_cout << " Largest element in matrix = " << largest_ << '\n';
00053     norm_ = spNorm(pmatrix_);
00054   }
00055 }
00056 
00057 //: estimate the condition number.
00058 bool vnl_sparse_lu::est_condition()
00059 {
00060   int error = spOKAY;
00061   rcond_ = spCondition(pmatrix_, norm_, &error);
00062   if (error!=spOKAY)
00063   {
00064     vcl_cout << "In vnl_sparse_lu::est_condition(..) - error in condition number calculation\n";
00065     return false;
00066   }
00067   condition_computed_ = true;
00068   return true;
00069 }
00070 
00071 //: Solve least squares problem M x = b.
00072 void vnl_sparse_lu::solve(vnl_vector<double> const& b, vnl_vector<double>* x)
00073 {
00074   if (!pmatrix_)
00075   {
00076     vcl_cout << "In vnl_sparse_lu::solve(..) - matrix not defined\n";
00077     return;
00078   }
00079   unsigned n = b.size();
00080   assert(n == A_.columns());
00081   spREAL* rhs = new spREAL[n+1];
00082   for (unsigned i = 0; i<n; ++i)
00083     rhs[i+1]=b[i];
00084   if (mode_==verbose || mode_==estimate_condition_verbose)
00085   {
00086     vcl_cout << "Matrix before ordering\n";
00087     spPrint(pmatrix_,1,1,1);
00088   }
00089 
00090   int error = 0;
00091   //check if the matrix needs ordering
00092   //if not, run the decomposition
00093   if (!factored_)
00094   {
00095     error = spOrderAndFactor(pmatrix_, rhs, pivot_thresh_,
00096                              absolute_thresh_, diag_pivoting_);
00097     if (error != spOKAY)
00098     {
00099       vcl_cout << "In vnl_sparse_lu::solve(..) - error in factoring\n";
00100       return;
00101     }
00102     if (mode_==estimate_condition || mode_==estimate_condition_verbose)
00103       if (!est_condition())
00104         return;
00105     factored_ = true;
00106   }
00107 
00108   if (mode_==verbose || mode_==estimate_condition_verbose)
00109   {
00110     vcl_cout << "Matrix after ordering\n";
00111     spPrint(pmatrix_,1,1,1);
00112   }
00113 
00114   spSolve(pmatrix_, rhs, rhs);
00115 
00116   for (unsigned i = 0; i<n; ++i)
00117     (*x)[i]=rhs[i+1];
00118 
00119   delete [] rhs;
00120 }
00121 
00122 //: Solve least squares problem M x = b.
00123 vnl_vector<double> vnl_sparse_lu::solve(vnl_vector<double> const& b)
00124 {
00125   vnl_vector<double> ret(b.size());
00126   this->solve(b, &ret);
00127   return ret;
00128 }
00129 
00130 //: Solve problem M^t x = b
00131 void vnl_sparse_lu::solve_transpose(vnl_vector<double> const& b, vnl_vector<double>* x)
00132 {
00133   if (!pmatrix_)
00134   {
00135     vcl_cout << "In vnl_sparse_lu::solve(..) - matrix not defined\n";
00136     return;
00137   }
00138   unsigned n = b.size();
00139   assert(n == A_.columns());
00140   spREAL* rhs = new spREAL[n+1];
00141   for (unsigned i = 0; i<n; ++i)
00142     rhs[i+1]=b[i];
00143   int error = 0;
00144   if (mode_== verbose || mode_== estimate_condition_verbose)
00145   {
00146     vcl_cout << "Matrix before ordering\n";
00147     spPrint(pmatrix_,1,1,1);
00148   }
00149 
00150   //check if the matrix needs ordering
00151   //if not, run the decomposition
00152   if (!factored_)
00153   {
00154     error = spOrderAndFactor(pmatrix_, rhs, pivot_thresh_,
00155                              absolute_thresh_, diag_pivoting_);
00156     if (error != spOKAY)
00157     {
00158       vcl_cout << "In vnl_sparse_lu::solve(..) - error in factoring\n";
00159       return;
00160     }
00161     if (mode_==estimate_condition || mode_==estimate_condition_verbose)
00162       if (!est_condition())
00163         return;
00164     factored_ = true;
00165   }
00166 
00167   if (mode_==verbose || mode_== estimate_condition_verbose)
00168   {
00169     vcl_cout << "Matrix after ordering\n";
00170     spPrint(pmatrix_,1,1,1);
00171   }
00172 
00173   spSolveTransposed(pmatrix_, rhs, rhs);
00174 
00175   for (unsigned i = 0; i<n; ++i)
00176     (*x)[i]=rhs[i+1];
00177 
00178   delete [] rhs;
00179 }
00180 
00181 //: Solve problem M^t x = b
00182 vnl_vector<double> vnl_sparse_lu::solve_transpose(vnl_vector<double> const& b)
00183 {
00184   vnl_vector<double> ret(b.size());
00185   this->solve_transpose(b, &ret);
00186   return ret;
00187 }
00188 
00189 // This routine might be eventually useful if other operations are to be done
00190 // after the factoring. Note that the routine spRowColOrder was
00191 // added to the sparse library (in spoutput.c).
00192 #if 0
00193 //: copy the matrix into a vnl_sparse_matrix
00194 vnl_sparse_matrix<double> vnl_sparse_lu::lu_matrix()
00195 {
00196   unsigned n = A_.rows();
00197   vnl_sparse_matrix<double> temp(n, n);
00198   int error = 0;
00199   spElement* pelement = 0;
00200   if (!factored_)
00201   {
00202     error = spFactor(pmatrix_);
00203     if (error != spOKAY)
00204     {
00205       vcl_cout << "In vnl_sparse_lu::lu_matrix() - factoring failed\n";
00206       return temp;
00207     }
00208     factored_=true;
00209   }
00210   // get the row and column maps
00211   int* row_map = new int[n+1];
00212   int* col_map = new int[n+1];
00213   spRowColOrder(pmatrix_, row_map, col_map);
00214 
00215   // create inverse maps
00216   int* inv_row_map = new int[n+1];
00217   int* inv_col_map = new int[n+1];
00218   for (unsigned i = 1; i<=n; ++i)
00219   {
00220     inv_row_map[row_map[i]]=i;
00221     inv_col_map[col_map[i]]=i;
00222   }
00223 
00224   if (mode_==verbose || mode_==estimate_condition_verbose)
00225     for (unsigned i = 1; i<=n; ++i)
00226       vcl_cout << "inv_row_map[" << i << "]= " << inv_row_map[i]
00227                << "    inv_col_map[" << i << "]= " << inv_col_map[i] << '\n';
00228   for (unsigned r = 0; r<n; r++)
00229     for (unsigned c = 0; c<n; c++)
00230     {
00231       pelement = spGetElement(pmatrix_, inv_row_map[r+1], inv_col_map[c+1]);
00232       if (pelement)
00233       {
00234         double v = *pelement;
00235         temp(r,c)= v;
00236       }
00237     }
00238   delete [] row_map;
00239   delete [] col_map;
00240   return temp;
00241 }
00242 #endif
00243 
00244 //: Compute determinant.
00245 double vnl_sparse_lu::determinant()
00246 {
00247   int exponent;
00248   double determ;
00249   if (!factored_)
00250   {
00251     spFactor(pmatrix_);
00252     if (mode_==estimate_condition || mode_==estimate_condition_verbose)
00253       if (!est_condition())
00254         return 0;
00255     factored_ = true;
00256   }
00257   spDeterminant(pmatrix_, &exponent, &determ);
00258   if (exponent<0)
00259   {
00260     while (exponent<0)
00261     {
00262       determ *= 0.1;
00263       exponent++;
00264     }
00265     return determ;
00266   }
00267   else if (exponent>0)
00268     while (exponent>0)
00269     {
00270       determ *= 10.0;
00271       exponent--;
00272     }
00273 
00274   return determ;
00275 }
00276 
00277 //: the reciprocal of the condition number
00278 double vnl_sparse_lu::rcond()
00279 {
00280   if (!factored_)
00281   {
00282     spFactor(pmatrix_);
00283     if (mode_==estimate_condition || mode_==estimate_condition_verbose)
00284       if (!est_condition())
00285         return 0;
00286     factored_ = true;
00287   }
00288   return rcond_;
00289 }
00290 
00291 //:Estimated upper bound of error in solution
00292 double vnl_sparse_lu::max_error_bound()
00293 {
00294   if (mode_!=estimate_condition && mode_ != estimate_condition_verbose)
00295     return 0;
00296 
00297   if (!factored_)
00298   {
00299     spFactor(pmatrix_);
00300     if (!est_condition())
00301       return 0;
00302     factored_ = true;
00303   }
00304   double roundoff = spRoundoff(pmatrix_, largest_);
00305   if (rcond_>0)
00306     return roundoff/rcond_;
00307   return 0;
00308 }