void Matrix::set_col(int col1, const Vector& v) { assert(col1>=0 && col1<nb_cols()); assert(nb_rows()==v.size()); for (int i=0; i<nb_rows(); i++) M[i][col1]=v[i]; }
Vector Matrix::col(int j) const { assert(j>=0 && j<nb_cols()); Vector res(nb_rows()); for (int i=0; i<nb_rows(); i++) res[i]=(*this)[i][j]; return res; }
Matrix& Matrix::operator=(const Matrix& x) { assert(nb_rows()==x.nb_rows() && nb_cols()==x.nb_cols()); // or implement "resize" //resize(x.nb_rows(), x.nb_cols()); for (int i=0; i<nb_rows(); i++) (*this)[i]=x[i]; return *this; }
Matrix IntervalMatrix::mag() const { assert(!is_empty()); Matrix res(nb_rows(), nb_cols()); for (int i=0; i<nb_rows(); i++) { res[i]=(*this)[i].mag(); } return res; }
Matrix IntervalMatrix::mid() const { assert(!is_empty()); Matrix mV(nb_rows(), nb_cols()); for (int i=0; i<nb_rows(); i++) { mV[i]=(*this)[i].mid(); } return mV; }
Matrix IntervalMatrix::ub() const { assert(!is_empty()); Matrix u(nb_rows(), nb_cols()); for (int i=0; i<nb_rows(); i++) { u[i]=(*this)[i].ub(); } return u; }
Matrix IntervalMatrix::lb() const { assert(!is_empty()); Matrix l(nb_rows(), nb_cols()); for (int i=0; i<nb_rows(); i++) { l[i]=(*this)[i].lb(); } return l; }
bool Matrix::operator==(const Matrix& m) const { if (m.nb_rows()!=nb_rows()) return false; if (m.nb_cols()!=nb_cols()) return false; for (int i=0; i<_nb_rows; i++) { if (row(i)!=m.row(i)) return false; } return true; }
IntervalMatrix& IntervalMatrix::inflate(double rad) { // see comment in IntervalVector::inflate if (is_empty()) return *this; Interval r(-rad,rad); for (int i=0; i<nb_rows(); i++) for (int j=0; j<nb_cols(); j++) (*this)[i][j]+=r; return *this; }
// Construit une matrix low rank SVD à nombre de matrice de rang 1 fixé LowRankMatrixSVD(const SubMatrix& A, const vectInt& ir0, const vectInt& ic0, int k){ nr = nb_rows(A); nc = nb_cols(A); ir=ir0; ic=ic0; Matrix M(A); PartialSVD(M,u,v,k); rank = u.size(); }
IntervalMatrix& IntervalMatrix::operator&=(const IntervalMatrix& m) { assert(nb_rows()==m.nb_rows()); assert(nb_cols()==m.nb_cols()); if (is_empty()) return *this; if (m.is_empty()) { set_empty(); return *this; } for (int i=0; i<_nb_rows; i++) { if ((row(i) &= m.row(i)).is_empty()) { set_empty(); return *this; } } return *this; }
void IntervalMatrix::init(const Interval& x) { for (int i=0; i<nb_rows(); i++) (*this)[i].init(x); }
bool IntervalMatrix::is_zero() const { for (int i=0; i<nb_rows(); i++) if (!(*this)[i].is_zero()) return false; return true; }
//=========================// // PARTIAL PIVOT ACA // //=========================// // If reqrank=-1 (default value), we use the precision given by epsilon for the stopping criterion; // otherwise, we use the required rank for the stopping criterion (!: at the end the rank could be lower) LowRankMatrix(const SubMatrix& A, const vectInt& ir0, const vectInt& ic0, const Cluster& t, const Cluster& s, int reqrank=-1){ nr = nb_rows(A); nc = nb_cols(A); ir=ir0; ic=ic0; vector<bool> visited_row(nr,false); vector<bool> visited_col(nc,false); Real frob = 0.; Real aux = 0.; Cplx frob_aux=0; //// Choice of the first row (see paragraph 3.4.3 page 151 Bebendorf) Real dist=1e30; int I=0; for (int i =0;i<int(nr/ndofperelt);i++){ Real aux_dist= norm(pts_(t)[tab_(t)[num_(t)[i*ndofperelt]]]-ctr_(t)); if (dist>aux_dist){ dist=aux_dist; I=i*ndofperelt; } } int J=0; int q = 0; if(reqrank == 0){ rank = 0; // approximate with a zero matrix } else if ( (nr+nc)>=(nr*nc) ){ // even rank 1 is not advantageous rank=-5; // just a flag for BuildBlockTree (the block won't be treated as a FarField block) } else{ vectCplx r(nc),c(nr); // Compute the first cross //==================// // Recherche colonne Real rmax = 0.; for(int k=0; k<nc; k++){ r[k] = A(I,k); for(int j=0; j<u.size(); j++){ r[k] += -u[j][I]*v[j][k];} if( abs(r[k])>rmax && !visited_col[k] ){ J=k; rmax=abs(r[k]);} } visited_row[I] = true; //==================// // Recherche ligne if( abs(r[J]) > 1e-15 ){ Cplx gamma = Cplx(1.)/r[J]; Real cmax = 0.; for(int j=0; j<nr; j++){ c[j] = A(j,J); for(int k=0; k<u.size(); k++){ c[j] += -u[k][j]*v[k][J];} c[j] = gamma*c[j]; if( abs(c[j])>cmax && !visited_row[j] ){ I=j; cmax=abs(c[j]);} } visited_col[J] = true; // We accept the cross q++; //====================// // Estimateur d'erreur frob_aux = 0.; aux = abs(dprod(c,c)*dprod(r,r)); // aux: terme quadratiques du developpement du carre' de la norme de Frobenius de la matrice low rank for(int j=0; j<u.size(); j++){ frob_aux += dprod(r,v[j])*dprod(c,u[j]);} // frob_aux: termes croises du developpement du carre' de la norme de Frobenius de la matrice low rank frob += aux + 2*frob_aux.real(); // frob: Frobenius norm of the low rank matrix //==================// // Nouvelle croix u.push_back(c); v.push_back(r); } else{cout << "There is a zero row in the starting submatrix and ACA didn't work" << endl;} // Stopping criterion of slide 26 of Stephanie Chaillat and Rjasanow-Steinbach // (if epsilon>=1, it always stops to rank 1 since frob=aux) while ( ((reqrank > 0) && (q < reqrank) ) || ( (reqrank < 0) && ( sqrt(aux/frob)>epsilon ) ) ) { if (q >= min(nr,nc) ) break; if ( (q+1)*(nr +nc) > (nr*nc) ){ // one rank more is not advantageous if (reqrank <0){ // If we didn't required a rank, i.e. we required a precision with epsilon rank=-5; // a flag for BuildBlockTree to say that the block won't be treated as a FarField block } break; // If we required a rank, we keep the computed ACA approximation (of lower rank) } // Compute another cross //==================// // Recherche colonne rmax = 0.; for(int k=0; k<nc; k++){ r[k] = A(I,k); for(int j=0; j<u.size(); j++){ r[k] += -u[j][I]*v[j][k];} if( abs(r[k])>rmax && !visited_col[k] ){ J=k; rmax=abs(r[k]);} } visited_row[I] = true; //==================// // Recherche ligne if( abs(r[J]) > 1e-15 ){ Cplx gamma = Cplx(1.)/r[J]; Real cmax = 0.; for(int j=0; j<nr; j++){ c[j] = A(j,J); for(int k=0; k<u.size(); k++){ c[j] += -u[k][j]*v[k][J];} c[j] = gamma*c[j]; if( abs(c[j])>cmax && !visited_row[j] ){ I=j; cmax=abs(c[j]);} } visited_col[J] = true; aux = abs(dprod(c,c)*dprod(r,r)); // aux: terme quadratiques du developpement du carre' de la norme de Frobenius de la matrice low rank } else{ cout << "ACA's loop terminated" << endl; break; } // terminate algorithm with exact rank q (not full-rank submatrix) // We accept the cross q++; //====================// // Estimateur d'erreur frob_aux = 0.; for(int j=0; j<u.size(); j++){ frob_aux += dprod(r,v[j])*dprod(c,u[j]);} // frob_aux: termes croises du developpement du carre' de la norme de Frobenius de la matrice low rank frob += aux + 2*frob_aux.real(); // frob: Frobenius norm of the low rank matrix //==================// // Nouvelle croix u.push_back(c); v.push_back(r); } rank = u.size(); } // Use this for Bebendorf stopping criterion (3.58) pag 141 (not very flexible): // if(reqrank == 0) // rank = 0; // approximate with a zero matrix // else if ( (nr+nc)>=(nr*nc) ){ // even rank 1 is not advantageous // rank=-5; // just a flag for BuildBlockTree (the block won't be treated as a FarField block) // } else{ // vectCplx r(nc),c(nr); // // // Compute the first cross // // (don't modify the code because we want to really use the Bebendorf stopping criterion (3.58), // // i.e. we don't want to accept the new cross if it is not satisfied because otherwise the approximation would be more precise than desired) // //==================// // // Recherche colonne // Real rmax = 0.; // for(int k=0; k<nc; k++){ // r[k] = A(I,k); // for(int j=0; j<u.size(); j++){ // r[k] += -u[j][I]*v[j][k];} // if( abs(r[k])>rmax && !visited_col[k] ){ // J=k; rmax=abs(r[k]);} // } // visited_row[I] = true; // //==================// // // Recherche ligne // if( abs(r[J]) > 1e-15 ){ // Cplx gamma = Cplx(1.)/r[J]; // Real cmax = 0.; // for(int j=0; j<nr; j++){ // c[j] = A(j,J); // for(int k=0; k<u.size(); k++){ // c[j] += -u[k][j]*v[k][J];} // c[j] = gamma*c[j]; // if( abs(c[j])>cmax && !visited_row[j] ){ // I=j; cmax=abs(c[j]);} // } // visited_col[J] = true; // // aux = abs(dprod(c,c)*dprod(r,r)); // } // else{cout << "There is a zero row in the starting submatrix and ACA didn't work" << endl;} // // // (see Bebendorf stopping criterion (3.58) pag 141) // while ( (q == 0) || // ( (reqrank > 0) && (q < reqrank) ) || // ( (reqrank < 0) && ( sqrt(aux/frob)>Parametres.epsilon * (1 - Parametres.eta)/(1 + Parametres.epsilon) ) ) ) { // // // We accept the cross // q++; // //====================// // // Estimateur d'erreur // frob_aux = 0.; // //aux = abs(dprod(c,c)*dprod(r,r)); // (already computed to evaluate the test) // // aux: terme quadratiques du developpement du carre' de la norme de Frobenius de la matrice low rank // for(int j=0; j<u.size(); j++){ // frob_aux += dprod(r,v[j])*dprod(c,u[j]);} // // frob_aux: termes croises du developpement du carre' de la norme de Frobenius de la matrice low rank // frob += aux + 2*frob_aux.real(); // frob: Frobenius norm of the low rank matrix // //==================// // // Nouvelle croix // u.push_back(c); // v.push_back(r); // // if (q >= min(nr,nc) ) // break; // if ( (q+1)*(nr +nc) > (nr*nc) ){ // one rank more is not advantageous // if (reqrank <0){ // If we didn't required a rank, i.e. we required a precision with epsilon // rank=-5; // a flag for BuildBlockTree to say that the block won't be treated as a FarField block // } // break; // If we required a rank, we keep the computed ACA approximation (of lower rank) // } // // Compute another cross // //==================// // // Recherche colonne // rmax = 0.; // for(int k=0; k<nc; k++){ // r[k] = A(I,k); // for(int j=0; j<u.size(); j++){ // r[k] += -u[j][I]*v[j][k];} // if( abs(r[k])>rmax && !visited_col[k] ){ // J=k; rmax=abs(r[k]);} // } // visited_row[I] = true; // //==================// // // Recherche ligne // if( abs(r[J]) > 1e-15 ){ // Cplx gamma = Cplx(1.)/r[J]; // Real cmax = 0.; // for(int j=0; j<nr; j++){ // c[j] = A(j,J); // for(int k=0; k<u.size(); k++){ // c[j] += -u[k][j]*v[k][J];} // c[j] = gamma*c[j]; // if( abs(c[j])>cmax && !visited_row[j] ){ // I=j; cmax=abs(c[j]);} // } // visited_col[J] = true; // // aux = abs(dprod(c,c)*dprod(r,r)); // } // else{ cout << "ACA's loop terminated" << endl; break; } // terminate algorithm with exact rank q (not full-rank submatrix) // } // // rank = u.size(); // } }