void UnknownVars::Solve(const AAndBVars& aAndBVars) { // solve Ax = b using UmfPack: Eigen::SparseMatrix<double> A = aAndBVars.GetA(); A.transpose(); Eigen::SparseLU<Eigen::SparseMatrix<double>,Eigen::UmfPack> lu_of_A(A); wxASSERT(lu_of_A.succeeded()); bool success = lu_of_A.solve(aAndBVars.GetBVarsConst(),&m_u); wxASSERT(success); }
int main() { int n = 10; Eigen::SparseMatrix<double> S = Eigen::MatrixXd::Random(n,n).sparseView(0.5,1); S = S.transpose()*S; MatrixReplacement A; A.attachMyMatrix(S); Eigen::VectorXd b(n), x; b.setRandom(); // Solve Ax = b using various iterative solver with matrix-free version: { Eigen::ConjugateGradient<MatrixReplacement, Eigen::Lower|Eigen::Upper, Eigen::IdentityPreconditioner> cg; cg.compute(A); x = cg.solve(b); std::cout << "CG: #iterations: " << cg.iterations() << ", estimated error: " << cg.error() << std::endl; } { Eigen::BiCGSTAB<MatrixReplacement, Eigen::IdentityPreconditioner> bicg; bicg.compute(A); x = bicg.solve(b); std::cout << "BiCGSTAB: #iterations: " << bicg.iterations() << ", estimated error: " << bicg.error() << std::endl; } { Eigen::GMRES<MatrixReplacement, Eigen::IdentityPreconditioner> gmres; gmres.compute(A); x = gmres.solve(b); std::cout << "GMRES: #iterations: " << gmres.iterations() << ", estimated error: " << gmres.error() << std::endl; } { Eigen::DGMRES<MatrixReplacement, Eigen::IdentityPreconditioner> gmres; gmres.compute(A); x = gmres.solve(b); std::cout << "DGMRES: #iterations: " << gmres.iterations() << ", estimated error: " << gmres.error() << std::endl; } { Eigen::MINRES<MatrixReplacement, Eigen::Lower|Eigen::Upper, Eigen::IdentityPreconditioner> minres; minres.compute(A); x = minres.solve(b); std::cout << "MINRES: #iterations: " << minres.iterations() << ", estimated error: " << minres.error() << std::endl; } }
IGL_INLINE double igl::polyvector_field_poisson_reconstruction( const Eigen::PlainObjectBase<DerivedV> &Vcut, const Eigen::PlainObjectBase<DerivedF> &Fcut, const Eigen::PlainObjectBase<DerivedS> &sol3D_combed, Eigen::PlainObjectBase<DerivedSF> &scalars, Eigen::PlainObjectBase<DerivedS> &sol3D_recon, Eigen::PlainObjectBase<DerivedE> &max_error ) { Eigen::SparseMatrix<typename DerivedV::Scalar> gradMatrix; igl::grad(Vcut, Fcut, gradMatrix); Eigen::VectorXd FAreas; igl::doublearea(Vcut, Fcut, FAreas); FAreas = FAreas.array() * .5; int nf = FAreas.rows(); Eigen::SparseMatrix<typename DerivedV::Scalar> M,M1; Eigen::VectorXi II = igl::colon<int>(0, nf-1); igl::sparse(II, II, FAreas, M1); igl::repdiag(M1, 3, M) ; int half_degree = sol3D_combed.cols()/3; sol3D_recon.setZero(sol3D_combed.rows(),sol3D_combed.cols()); int numF = Fcut.rows(); scalars.setZero(Vcut.rows(),half_degree); Eigen::SparseMatrix<typename DerivedV::Scalar> Q = gradMatrix.transpose()* M *gradMatrix; //fix one point at Ik=fix, value at fixed xk=0 int fix = 0; Eigen::VectorXi Ik(1);Ik<<fix; Eigen::VectorXd xk(1);xk<<0; //unknown indices Eigen::VectorXi Iu(Vcut.rows()-1,1); Iu<<igl::colon<int>(0, fix-1), igl::colon<int>(fix+1,Vcut.rows()-1); Eigen::SparseMatrix<typename DerivedV::Scalar> Quu, Quk; igl::slice(Q, Iu, Iu, Quu); igl::slice(Q, Iu, Ik, Quk); Eigen::SimplicialLDLT<Eigen::SparseMatrix<typename DerivedV::Scalar> > solver; solver.compute(Quu); Eigen::VectorXd vec; vec.setZero(3*numF,1); for (int i =0; i<half_degree; ++i) { vec<<sol3D_combed.col(i*3+0),sol3D_combed.col(i*3+1),sol3D_combed.col(i*3+2); Eigen::VectorXd b = gradMatrix.transpose()* M * vec; Eigen::VectorXd bu = igl::slice(b, Iu); Eigen::VectorXd rhs = bu-Quk*xk; Eigen::MatrixXd yu = solver.solve(rhs); Eigen::VectorXi index = i*Eigen::VectorXi::Ones(Iu.rows(),1); igl::slice_into(yu, Iu, index, scalars);scalars(Ik[0],i)=xk[0]; } // evaluate gradient of found scalar function for (int i =0; i<half_degree; ++i) { Eigen::VectorXd vec_poisson = gradMatrix*scalars.col(i); sol3D_recon.col(i*3+0) = vec_poisson.segment(0*numF, numF); sol3D_recon.col(i*3+1) = vec_poisson.segment(1*numF, numF); sol3D_recon.col(i*3+2) = vec_poisson.segment(2*numF, numF); } max_error.setZero(numF,1); for (int i =0; i<half_degree; ++i) { Eigen::VectorXd diff = (sol3D_recon.block(0, i*3, numF, 3)-sol3D_combed.block(0, i*3, numF, 3)).rowwise().norm(); diff = diff.array() / sol3D_combed.block(0, i*3, numF, 3).rowwise().norm().array(); max_error = max_error.cwiseMax(diff.cast<typename DerivedE::Scalar>()); } return max_error.mean(); }
IGL_INLINE bool igl::lu_lagrange( const Eigen::SparseMatrix<T> & ATA, const Eigen::SparseMatrix<T> & C, Eigen::SparseMatrix<T> & L, Eigen::SparseMatrix<T> & U) { #if EIGEN_VERSION_AT_LEAST(3,0,92) #if defined(_WIN32) #pragma message("lu_lagrange has not yet been implemented for your Eigen Version") #else #warning lu_lagrange has not yet been implemented for your Eigen Version #endif return false; #else // number of unknowns int n = ATA.rows(); // number of lagrange multipliers int m = C.cols(); assert(ATA.cols() == n); if(m != 0) { assert(C.rows() == n); if(C.nonZeros() == 0) { // See note above about empty columns in C fprintf(stderr,"Error: lu_lagrange() C has columns but no entries\n"); return false; } } // Check that each column of C has at least one entry std::vector<bool> has_entry; has_entry.resize(C.cols(),false); // Iterate over outside for(int k=0; k<C.outerSize(); ++k) { // Iterate over inside for(typename Eigen::SparseMatrix<T>::InnerIterator it (C,k); it; ++it) { has_entry[it.col()] = true; } } for(int i=0;i<(int)has_entry.size();i++) { if(!has_entry[i]) { // See note above about empty columns in C fprintf(stderr,"Error: lu_lagrange() C(:,%d) has no entries\n",i); return false; } } // Cholesky factorization of ATA //// Eigen fails if you give a full view of the matrix like this: //Eigen::SparseLLT<SparseMatrix<T> > ATA_LLT(ATA); Eigen::SparseMatrix<T> ATA_LT = ATA.template triangularView<Eigen::Lower>(); Eigen::SparseLLT<Eigen::SparseMatrix<T> > ATA_LLT(ATA_LT); Eigen::SparseMatrix<T> J = ATA_LLT.matrixL(); //if(!ATA_LLT.succeeded()) if(!((J*0).eval().nonZeros() == 0)) { fprintf(stderr,"Error: lu_lagrange() failed to factor ATA\n"); return false; } if(m == 0) { // If there are no constraints (C is empty) then LU decomposition is just L // and L' from cholesky decomposition L = J; U = J.transpose(); }else { // Construct helper matrix M Eigen::SparseMatrix<T> M = C; J.template triangularView<Eigen::Lower>().solveInPlace(M); // Compute cholesky factorizaiton of M'*M Eigen::SparseMatrix<T> MTM = M.transpose() * M; Eigen::SparseLLT<Eigen::SparseMatrix<T> > MTM_LLT(MTM.template triangularView<Eigen::Lower>()); Eigen::SparseMatrix<T> K = MTM_LLT.matrixL(); //if(!MTM_LLT.succeeded()) if(!((K*0).eval().nonZeros() == 0)) { fprintf(stderr,"Error: lu_lagrange() failed to factor MTM\n"); return false; } // assemble LU decomposition of Q Eigen::Matrix<int,Eigen::Dynamic,1> MI; Eigen::Matrix<int,Eigen::Dynamic,1> MJ; Eigen::Matrix<T,Eigen::Dynamic,1> MV; igl::find(M,MI,MJ,MV); Eigen::Matrix<int,Eigen::Dynamic,1> KI; Eigen::Matrix<int,Eigen::Dynamic,1> KJ; Eigen::Matrix<T,Eigen::Dynamic,1> KV; igl::find(K,KI,KJ,KV); Eigen::Matrix<int,Eigen::Dynamic,1> JI; Eigen::Matrix<int,Eigen::Dynamic,1> JJ; Eigen::Matrix<T,Eigen::Dynamic,1> JV; igl::find(J,JI,JJ,JV); int nnz = JV.size() + MV.size() + KV.size(); Eigen::Matrix<int,Eigen::Dynamic,1> UI(nnz); Eigen::Matrix<int,Eigen::Dynamic,1> UJ(nnz); Eigen::Matrix<T,Eigen::Dynamic,1> UV(nnz); UI << JJ, MI, (KJ.array() + n).matrix(); UJ << JI, (MJ.array() + n).matrix(), (KI.array() + n).matrix(); UV << JV, MV, KV*-1; igl::sparse(UI,UJ,UV,U); Eigen::Matrix<int,Eigen::Dynamic,1> LI(nnz); Eigen::Matrix<int,Eigen::Dynamic,1> LJ(nnz); Eigen::Matrix<T,Eigen::Dynamic,1> LV(nnz); LI << JI, (MJ.array() + n).matrix(), (KI.array() + n).matrix(); LJ << JJ, MI, (KJ.array() + n).matrix(); LV << JV, MV, KV; igl::sparse(LI,LJ,LV,L); } return true; #endif }
// [[Rcpp::export]] List predictLong_cpp(Rcpp::List in_list) { //********************************** // basic parameter //********************************** int nSim = Rcpp::as< int > (in_list["nSim"]); int nBurnin = Rcpp::as< int > (in_list["nBurnin"] ); int silent = Rcpp::as< int > (in_list["silent"]); //********************************** // setting up the main data //********************************** //if(silent == 0){ // Rcpp::Rcout << " Setup data\n"; //} Rcpp::List obs_list = Rcpp::as<Rcpp::List> (in_list["obs_list"]); int nindv = obs_list.length(); //count number of patients std::vector< Eigen::SparseMatrix<double,0,int> > As( nindv); std::vector< Eigen::SparseMatrix<double,0,int> > As_pred( nindv); std::vector< Eigen::VectorXd > Ys( nindv); std::vector< Eigen::MatrixXd > pred_ind(nindv); std::vector< Eigen::MatrixXd > obs_ind(nindv); std::vector< Eigen::MatrixXd > Bfixed_pred(nindv); std::vector< Eigen::MatrixXd > Brandom_pred(nindv); int count; count = 0; for( List::iterator it = obs_list.begin(); it != obs_list.end(); ++it ) { List obs_tmp = Rcpp::as<Rcpp::List>(*it); As[count] = Rcpp::as<Eigen::SparseMatrix<double,0,int> >(obs_tmp["A"]); As_pred[count] = Rcpp::as<Eigen::SparseMatrix<double,0,int> >(obs_tmp["Apred"]); pred_ind[count] = Rcpp::as<Eigen::MatrixXd>(obs_tmp["pred_ind"]); obs_ind[count] = Rcpp::as<Eigen::MatrixXd>(obs_tmp["obs_ind"]); Ys[count] = Rcpp::as<Eigen::VectorXd>(obs_tmp["Y"]); Brandom_pred[count] = Rcpp::as<Eigen::MatrixXd>(obs_tmp["Brandom_pred"]); Bfixed_pred[count] = Rcpp::as<Eigen::MatrixXd>(obs_tmp["Bfixed_pred"]); count++; } //********************************** //operator setup //*********************************** //if(silent == 0){ // Rcpp::Rcout << " Setup operator\n"; //} Rcpp::List operator_list = Rcpp::as<Rcpp::List> (in_list["operator_list"]); std::string type_operator = Rcpp::as<std::string>(operator_list["type"]); operator_list["nIter"] = 1; operatorMatrix* Kobj; //Kobj = new MaternMatrixOperator; operator_select(type_operator, &Kobj); Kobj->initFromList(operator_list, List::create(Rcpp::Named("use.chol") = 1)); Eigen::VectorXd h = Rcpp::as<Eigen::VectorXd>( operator_list["h"]); //Prior solver cholesky_solver Qsolver; Qsolver.init( Kobj->d, 0, 0, 0); Qsolver.analyze( Kobj->Q); Qsolver.compute( Kobj->Q); //Create solvers for each patient std::vector< cholesky_solver > Solver( nindv); Eigen::SparseMatrix<double, 0, int> Q; count = 0; for( List::iterator it = obs_list.begin(); it != obs_list.end(); ++it ) { List obs_tmp = Rcpp::as<Rcpp::List>( *it); Solver[count].init(Kobj->d, 0, 0, 0); Q = Eigen::SparseMatrix<double,0,int>(Kobj->Q.transpose()); Q = Q * Kobj->Q; Q = Q + As[count].transpose()*As[count]; Solver[count].analyze(Q); Solver[count].compute(Q); count++; } //********************************** // mixed effect setup //*********************************** //if(silent == 0){ // Rcpp::Rcout << " Setup mixed effect\n"; //} Rcpp::List mixedEffect_list = Rcpp::as<Rcpp::List> (in_list["mixedEffect_list"]); std::string type_mixedEffect = Rcpp::as<std::string> (mixedEffect_list["noise"]); MixedEffect *mixobj; if(type_mixedEffect == "Normal") mixobj = new NormalMixedEffect; else mixobj = new NIGMixedEffect; mixobj->initFromList(mixedEffect_list); //********************************** // measurement setup //*********************************** //if(silent == 0){ // Rcpp::Rcout << " Setup noise\n"; //} MeasurementError *errObj; Rcpp::List measurementError_list = Rcpp::as<Rcpp::List> (in_list["measurementError_list"]); std::string type_MeasurementError= Rcpp::as <std::string> (measurementError_list["noise"]); if(type_MeasurementError == "Normal") errObj = new GaussianMeasurementError; else errObj = new NIGMeasurementError; errObj->initFromList(measurementError_list); //********************************** // stochastic processes setup //*********************************** //if(silent == 0){ // Rcpp::Rcout << " Setup process\n"; //} Rcpp::List processes_list = Rcpp::as<Rcpp::List> (in_list["processes_list"]); Rcpp::List V_list = Rcpp::as<Rcpp::List> (processes_list["V"]); std::string type_processes = Rcpp::as<std::string> (processes_list["noise"]); Process *process; if (type_processes != "Normal"){ process = new GHProcess; }else{ process = new GaussianProcess;} process->initFromList(processes_list, h); /* Simulation objects */ std::mt19937 random_engine; std::normal_distribution<double> normal; std::default_random_engine gammagenerator; random_engine.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count()); gig rgig; rgig.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count()); Eigen::VectorXd z; z.setZero(Kobj->d); Eigen::VectorXd b, Ysim; b.setZero(Kobj->d); std::vector<int> longInd; for (int i=0; i< nindv; i++) longInd.push_back(i); Eigen::SparseMatrix<double,0,int> K = Eigen::SparseMatrix<double,0,int>(Kobj->Q); K *= sqrt(Kobj->tau); std::vector< Eigen::MatrixXd > WVec(nindv); std::vector< Eigen::MatrixXd > XVec(nindv); for(int i = 0; i < nindv; i++ ) { if(silent == 0){ Rcpp::Rcout << " Compute prediction for patient " << i << "\n"; } XVec[i].resize(As_pred[i].rows(), nSim); WVec[i].resize(As_pred[i].rows(), nSim); Eigen::MatrixXd random_effect = mixobj->Br[i]; Eigen::MatrixXd fixed_effect = mixobj->Bf[i]; for(int ipred = 0; ipred < pred_ind[i].rows(); ipred++){ //if(silent == 0){ // Rcpp::Rcout << " location = " << ipred << ": "<< obs_ind[i](ipred,0)<< " " << obs_ind[i](ipred,1) << "\n"; // Rcpp::Rcout << " A size = " << As[i].rows() << " " << As[i].cols() << "\n"; // Rcpp::Rcout << " Y size = " << Ys[i].size() << ", re = " << random_effect.rows() << ", fe = "<< fixed_effect.size() << "\n"; //} //extract data to use for prediction: Eigen::SparseMatrix<double,0,int> A = As[i].middleRows(obs_ind[i](ipred,0),obs_ind[i](ipred,1)); Eigen::VectorXd Y = Ys[i].segment(obs_ind[i](ipred,0),obs_ind[i](ipred,1)); mixobj->Br[i] = random_effect.middleRows(obs_ind[i](ipred,0),obs_ind[i](ipred,1)); mixobj->Bf[i] = fixed_effect.middleRows(obs_ind[i](ipred,0),obs_ind[i](ipred,1)); //Rcpp::Rcout << "here1111\n"; for(int ii = 0; ii < nSim + nBurnin; ii ++){ //Rcpp::Rcout << "iter = " << ii << "\n"; Eigen::VectorXd res = Y; //*************************************** //*************************************** // building the residuals and sampling //*************************************** //*************************************** // removing fixed effect from Y mixobj->remove_cov(i, res); res -= A * process->Xs[i]; //*********************************** // mixobj sampling //*********************************** //Rcpp::Rcout << "here2\n"; if(type_MeasurementError == "Normal") mixobj->sampleU( i, res, 2 * log(errObj->sigma)); else //errObj->Vs[i] = errObj->Vs[i].head(ipred+1); mixobj->sampleU2( i, res, errObj->Vs[i].segment(obs_ind[i](ipred,0),obs_ind[i](ipred,1)).cwiseInverse(), 2 * log(errObj->sigma)); mixobj->remove_inter(i, res); //*********************************** // sampling processes //*********************************** //Rcpp::Rcout << "here3\n"; Eigen::SparseMatrix<double,0,int> Q = Eigen::SparseMatrix<double,0,int>(K.transpose()); Eigen::VectorXd iV(process->Vs[i].size()); iV.array() = process->Vs[i].array().inverse(); Q = Q * iV.asDiagonal(); Q = Q * K; for(int j =0; j < Kobj->d; j++) z[j] = normal(random_engine); res += A * process->Xs[i]; //Sample X|Y, V, sigma if(type_MeasurementError == "Normal") process->sample_X(i, z, res, Q, K, A, errObj->sigma, Solver[i]); else process->sample_Xv2( i, z, res, Q, K, A, errObj->sigma, Solver[i], errObj->Vs[i].segment(obs_ind[i](ipred,0),obs_ind[i](ipred,1)).cwiseInverse()); res -= A * process->Xs[i]; //if(res.cwiseAbs().sum() > 1e16){ // throw("res outof bound\n"); //} // sample V| X process->sample_V(i, rgig, K); //*********************************** // random variance noise sampling //*********************************** //Rcpp::Rcout << "here4\n"; if(type_MeasurementError != "Normal"){ errObj->sampleV(i, res,obs_ind[i](ipred,0)+obs_ind[i](ipred,1)); } // save samples if(ii >= nBurnin){ //if(silent == 0){ // Rcpp::Rcout << " save samples << " << i << ", " << ipred << ", " << ii << "\n"; //} //Rcpp::Rcout << "here 1\n"; Eigen::SparseMatrix<double,0,int> Ai = As_pred[i]; Ai = Ai.middleRows(pred_ind[i](ipred,0),pred_ind[i](ipred,1)); //Rcpp::Rcout << "here 2\n"; Eigen::VectorXd random_effect = Bfixed_pred[i]*mixobj->beta_fixed; //Rcpp::Rcout << "here 3\n"; random_effect += Brandom_pred[i]*(mixobj->U.col(i)+mixobj->beta_random); //Rcpp::Rcout << "here 4\n"; Eigen::VectorXd random_effect_c = random_effect.segment(pred_ind[i](ipred,0),pred_ind[i](ipred,1)); Eigen::VectorXd AX = Ai * process->Xs[i]; //Rcpp::Rcout << "here 5\n"; WVec[i].block(pred_ind[i](ipred,0), ii - nBurnin, pred_ind[i](ipred,1), 1) = AX; XVec[i].block(pred_ind[i](ipred,0), ii - nBurnin, pred_ind[i](ipred,1), 1) = random_effect_c + AX; //Rcpp::Rcout << "here 6\n"; } } } } Rcpp::Rcout << "store results\n"; // storing the results Rcpp::List out_list; out_list["XVec"] = XVec; out_list["WVec"] = WVec; return(out_list); }