Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

bgmatrix.cpp

Go to the documentation of this file.
00001 //****************************************************
00002 //  April, 1993, University of Illinois
00003 // Copyright (C) 1993, 1994 Tianlin Wang
00004 /* Copyright (C) 1994-2003 Matvec Development Team. 
00005 
00006   This program is free software; you can redistribute it and/or
00007   modify it under the terms of the GNU Library General Public
00008   License as published by the Free Software Foundation; either
00009   version 2 of the License, or (at your option) any later version.
00010   
00011   This program is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   Library General Public License for more details.
00015     
00016   You should have received a copy of the GNU Library General Public
00017   License along with this library; if not, write to the Free
00018   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00019   MA 02111-1307, USA 
00020 */
00021 
00022 #include <iostream>
00023 #include "session.h"
00024 #include "util.h"
00025 #include "bgmatrix.h"
00026 
00027 namespace matvec {
00028 
00029 extern void ludcmp(BG **a,int n,int *indx,int& d, double tol);
00030 extern void lubksb(BG **a,int n,int *indx,BG *b);
00031 extern bool psdefinite(const BG **mat,const unsigned m,const unsigned n,const double tol);
00032 
00033 
00034 BGMatrix::BGMatrix(const doubleMatrix &a)
00035 {
00036    resize(a.num_rows(),a.num_cols());
00037    for (int j,i=0; i<a.num_rows(); ++i) {
00038      for (j=0; j<a.num_cols(); ++j) {
00039        Matrix<BG>::me[i][j] = a[i][j];
00040      }
00041    }
00042 }
00043 
00044 BGMatrix&  BGMatrix::operator = (const Matrix<bool> &a)
00045 {
00046    resize(a.num_rows(),a.num_cols());
00047    for (int j,i=0; i<a.num_rows(); ++i) for (j=0; j<a.num_cols(); ++j) Matrix<BG>::me[i][j] = (BG)a[i][j];
00048    return *this;
00049 }
00050 
00051 
00052 bool BGMatrix::psd(void) const
00053 {
00054    if (!this->symmetric()) return false;
00055    return psdefinite(begin(),Matrix<BG>::nrow,Matrix<BG>::ncol,SESSION.epsilon);
00056 }
00057 
00058 
00059 
00060 BGMatrix& BGMatrix::inv(void)
00061 {
00062    //////////////////////////////////////////////////////////
00063    // A itself turns into its inverse
00064    // returns non_singular indicator
00065    // REQUIREMENTS:  A must be nonsingular
00066    /////////////////////////////////////////////////////////
00067    int nrow =  Matrix<BG>::nrow;
00068    int ncol =  Matrix<BG>::ncol;
00069    BG** me =  Matrix<BG>::me;
00070 
00071    int i,j,d;
00072    if ( nrow != ncol ) throw exception("BGMatrix::inv(): matrix must be square");
00073    Vector<int>    indx;  indx.reserve(nrow);
00074    Vector<BG> tempcol; tempcol.reserve(nrow);
00075    Matrix<BG> temp; temp.reserve(nrow,nrow);
00076 
00077    ludcmp(me,nrow,indx.begin(),d, SESSION.epsilon);
00078    for (j=0; j<nrow; j++) {
00079       tempcol.assign(0.0);
00080       tempcol[j] = 1.0;
00081       lubksb(me,nrow,indx.begin(),tempcol.begin());
00082       for (i=0; i<nrow;i++) temp[i][j] = tempcol[i];
00083    }
00084    //for (i=0;i<nrow; i++) memcpy(me[i],temp[i],sizeof(BG)*nrow);
00085    for (j=0; j<nrow; j++) { 
00086      for (i=0; i<nrow;i++) me[i][j] = temp[i][j];
00087    }
00088    return *this;
00089 }
00090 
00091 BGMatrix& BGMatrix::ginv1(unsigned *irank)
00092 {         // it only works for symmetric-positive-semidefinite matrix
00093           //  Matrix itself becomes its inverse;
00094    if (!this->symmetric()) {
00095      throw exception("BGMatrix::ginv1(): matrix must be symmetric");
00096    }
00097    BG lgdet;
00098    unsigned myrank = ginverse1(begin(),num_rows(),lgdet,1,SESSION.epsilon);
00099    if (irank) *irank = myrank;
00100    return *this;
00101 }
00102 
00103 
00104 BGMatrix BGMatrix::lu_solve(const BGMatrix& rhs)
00105 {
00106    int nrow =  Matrix<BG>::nrow;
00107    int ncol =  Matrix<BG>::ncol;
00108    BG** me =  Matrix<BG>::me;
00109 
00110    if (nrow  != ncol) throw exception("BGMatrix::lu_solve(): matrix is not square ");
00111    int m = rhs.num_rows();
00112    int n = rhs.num_cols();
00113 
00114    if (ncol != m ) throw exception("BGMatrix::lu_solve(): bad arg");
00115    BGMatrix solmat(m,n);
00116    int i,j,d;
00117    Vector<BG> solvec; solvec.reserve(m);
00118    Vector<int> indx;  indx.reserve(m);
00119    ludcmp(me,nrow,indx.begin(),d,SESSION.epsilon);
00120    warning("A.solve(b), A destroyed");
00121    for (j=0; j<n; j++) {
00122       for (i=0; i<m; i++) solvec[i] = rhs[i][j];
00123       lubksb(me,m,indx.begin(),solvec.begin());
00124       for (i=0; i<m; i++) solmat[i][j] = solvec[i];
00125    }
00126    return solmat;
00127 }
00128 
00129 Vector<BG> BGMatrix::lu_solve(const Vector<BG>& rhs)
00130 {
00131    int n = rhs.size();
00132    BGMatrix bmat(n,1);
00133    for (int i=0; i<n; i++) bmat[i][0] = rhs[i];
00134    bmat = lu_solve(bmat);
00135    return bmat.vec();
00136 }
00137 
00138 
00139 void BGMatrix::gs_solve(const BGMatrix& rhs,BGMatrix& solmat,const double relax,
00140                      const double stopval,const int mxiter)
00141 {
00142   //   relax    relaxation coefficient, relax=1.2 seems good for some case
00143   //   stopval  the accuracy at which iteration stops.
00144   //   mxiter   maximum number of iterations allowed
00145 
00146    int nrow =  Matrix<BG>::nrow;
00147    int ncol =  Matrix<BG>::ncol;
00148    BG** me =  Matrix<BG>::me;
00149 
00150    int m = rhs.num_rows();
00151    int n = rhs.num_cols();
00152    if (nrow != ncol) throw exception("BGMatrix::gs_solve(): matrix must be square ");
00153    if (ncol != m ) throw exception("BGMatrix::gs_solve(): matrix and rhs are not conformable");
00154    if (solmat.num_rows() != m || solmat.num_cols() != n) {
00155       solmat.resize(m,n);
00156    }
00157    int i,j,k;
00158    BG diag;
00159    int niter = 0;
00160    BG a,cmax;
00161    BG tol = SESSION.epsilon;
00162 
00163    Vector<BG> oldsol(n);
00164    Vector<BG> newsol(n);
00165    Vector<BG> cval(n);
00166    Vector<BG> local(n);
00167    do {                             // now iteration begins
00168       cmax = 0.0;
00169       for (i=0; i<m; i++) {
00170          for (k=0; k<n; k++) {
00171             oldsol[k] = solmat[i][k];
00172             local[k] = 0.0;
00173          }
00174          for (j=0; j<m; j++) {
00175             a = me[i][j];
00176             if (j != i) for (k=0; k<n; k++) local[k] += a * solmat[j][k];
00177          }
00178          diag = me[i][i];
00179          if (diag > tol) {
00180             for (k=0; k<n; k++) {
00181                newsol[k] = (rhs[i][k] - local[k])/diag;
00182                cval[k] = (newsol[k] - oldsol[k])*relax;
00183                if (fabs(cval[k]) > cmax) cmax = fabs(cval[k]);
00184                newsol[k] = solmat[i][k] = oldsol[k] + cval[k];
00185             }
00186          }
00187          else if (diag > -tol) {
00188             throw exception("BGMatrix::gs_solve(): zero-diagonal found in Matrix::gs_solve()");
00189          }
00190          else {
00191             throw exception("BGMatrix::gs_solve(): matrix is not psd");
00192          }
00193       }
00194       niter += 1;
00195       if ( (niter % 10) ==0) {
00196          std::cout << " GS: # of iter = " << niter << ", max_change = "
00197               << cmax << std::endl;
00198       }
00199    } while (niter <= mxiter && cmax > stopval);
00200    if (cmax > stopval) {
00201       warning("BGMatrix::gs_solve(): not converge: %20.10f",cmax.f);
00202    }
00203 }
00204 
00205 void BGMatrix::gs_solve(const Vector<BG>& rhs, Vector<BG>& sol, const double relax,
00206                      const double stopval, const int mxiter)
00207 {
00208    int n = rhs.size();
00209    BGMatrix bmat(n,1),solmat(n,1);
00210    if (sol.size() != n) {
00211       sol.resize(n);
00212    }
00213    int i;
00214    for (i=0; i<n; i++) {
00215       bmat[i][0] = rhs[i];
00216       solmat[i][0] = sol[i];
00217    }
00218    gs_solve(bmat,solmat,relax,stopval,mxiter);
00219    for (i=0; i<n; i++) sol[i] = solmat[i][0];
00220 }
00221 
00222 
00223 BG BGMatrix::det(void) const
00224 {
00225    int nrow =  Matrix<BG>::nrow;
00226    int ncol =  Matrix<BG>::ncol;
00227 
00228    BG detval = 0.0;
00229    if ( nrow != ncol ) throw exception("BGMatrix::det(): matrix must be square");
00230    int i,d;
00231    Vector<int> indx(nrow);
00232    BGMatrix temp(*this);
00233    ludcmp(temp.begin(),nrow,indx.begin(),d, SESSION.epsilon);
00234    detval = (BG)d;
00235    for (i=0; i<nrow; i++) detval *= temp[i][i];
00236    return detval;
00237 }
00238 
00239 
00240 BG BGMatrix::norm(const std::string &s) const
00241 {
00242    BG retval = 0.0;
00243    BGMatrix A = this->transpose();
00244    if (s == "fro") {
00245       retval = sqrt((A*(*this)).diag(0).sum());
00246    }
00247    else {
00248       throw exception("BGMatrix::norm((): bad arg, it must be either \"inf\" or \"fro\" ");
00249    }
00250    return retval;
00251 }
00252 
00253 BG BGMatrix::logdet(void)
00254 {
00255    int nrow =  Matrix<BG>::nrow;
00256    int ncol =  Matrix<BG>::ncol;
00257    BG** me =  Matrix<BG>::me;
00258 
00259    BG retval = 0.0;
00260    if (!this->symmetric()) throw exception("BGMatrix::logdet(): matrix must be symmetric");
00261    Matrix<BG> temp(*this);
00262 
00263    ginverse1(temp.begin(),nrow,retval,3,SESSION.epsilon);
00264    return retval;
00265 }
00266 
00267 BG BGMatrix::quadratic(const Vector<BG> &x, const Vector<BG> &y) const
00268 {
00269    int nrow =  Matrix<BG>::nrow;
00270    int ncol =  Matrix<BG>::ncol;
00271    BG** me =  Matrix<BG>::me;
00272    int m = x.size();
00273    int n = y.size();
00274 
00275    BG s = 0.0;
00276    if (m != nrow  || n != ncol)  throw exception("BGMatrix::quadratic(): size not conformable");
00277    for (int j,i=0;i<m; i++) for (j=0; j<n; j++) s += x[i]*me[i][j]*y[j];
00278    return s;
00279 }
00280 Vector<BG> BGMatrix::variance(orientation orien) const
00281 {
00282    int nrow =  Matrix<BG>::nrow;
00283    int ncol =  Matrix<BG>::ncol;
00284    BG** me =  Matrix<BG>::me;
00285    int i,j;
00286    BG ss,s;
00287    Vector<BG> temp;
00288    if (orien == COLUMN) {
00289       assert(nrow > 1);
00290       temp.resize(ncol);
00291       for (j=0; j<ncol; j++) {
00292          for (ss=0.0,s=0.0,i=0; i<ncol; ++i) {
00293              ss += me[i][j]*me[i][j];
00294              s  += me[i][j];
00295          }
00296          temp[j] = (ss-s*s/nrow)/(nrow - 1);
00297       }
00298    } else if (orien == ROW) {
00299       assert(ncol > 1);
00300       temp.resize(nrow);
00301       for (i=0; i<nrow; i++) {
00302          for (ss=0.0,s=0.0,j=0; j<ncol; ++j) {
00303              ss += me[i][j]*me[i][j];
00304              s  += me[i][j];
00305          }
00306          temp[i] = (ss-s*s/ncol)/(ncol - 1);
00307       }
00308    } else {
00309       warning("unknown orientation");
00310    }
00311    return temp;
00312 }
00313 
00314 BGMatrix BGMatrix::covariance(const BGMatrix &B) const
00315 {
00316    int nrow =  Matrix<BG>::nrow;
00317    int ncol =  Matrix<BG>::ncol;
00318    BG** me =  Matrix<BG>::me;
00319 
00320    assert (nrow == B.num_rows() && ncol == B.num_cols());
00321    BGMatrix temp(ncol,ncol);
00322    int i,j,k;
00323    BG ss,sx,sy;
00324    for (i=0; i<ncol; ++i) {
00325       for (j=0; j<=i; ++j) {
00326          for (ss=0.0,sx=0.0,sy=0.0,k=0; k<nrow; ++k) {
00327             ss += me[k][i]*B[k][j];
00328             sx += me[k][i];
00329             sy += B[k][j];
00330          }
00331          temp[i][j] = temp[j][i] = (ss - sx*sy/ncol)/(ncol - 1);
00332       }
00333    }
00334    return temp;
00335 }
00336 
00337 BGMatrix& BGMatrix::sqrtm(void)
00338 {
00339    if (!this->symmetric()) throw exception("BGMatrix::sqrtm(): matrix must be symmetric");
00340    BG lgdet;
00341    ginverse1(begin(),num_rows(),lgdet,2,SESSION.epsilon);
00342    return *this;
00343 }
00344 
00345 BGMatrix& BGMatrix::identity(const int m,const int n)
00346 {
00347    resize(m,n);
00348    BG **me = begin();
00349    for (int i=0; i<m; ++i) if (i < n) me[i][i] = 1.0;
00350    return *this;
00351 }
00352 
00353 // BGMatrix& BGMatrix::sweep(const int i0,const int i1)
00354 // {
00355 //    int nrow =  Matrix<BG>::nrow;
00356 //    int ncol =  Matrix<BG>::ncol;
00357 
00358 //    int n = std::min(nrow,ncol);
00359 //    if (i0<0 || i0 >=n || i0 > i1) throw exception("BGMatrix::sweep(): range error");
00360 //    matvec::sweep(nrow,ncol,begin(),i0,i1,SESSION.epsilon);
00361 //    return *this;
00362 // }
00363 
00364 
00365 }  //////////// end of namespace
00366 

Generated on Thu Jun 16 17:13:38 2005 for Matvec by doxygen1.2.16