00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00064
00065
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
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 {
00093
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
00143
00144
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 {
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
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 }
00366