// This function is called every time a keyboard button is pressed bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier) { using namespace std; using namespace Eigen; if (key >= '1' && key <= '9') { double t = double((key - '1')+1) / 9.0; VectorXd v = B.col(2).array() - B.col(2).minCoeff(); v /= v.col(0).maxCoeff(); vector<int> s; for (unsigned i=0; i<v.size();++i) if (v(i) < t) s.push_back(i); MatrixXd V_temp(s.size()*4,3); MatrixXi F_temp(s.size()*4,3); for (unsigned i=0; i<s.size();++i) { V_temp.row(i*4+0) = TV.row(TT(s[i],0)); V_temp.row(i*4+1) = TV.row(TT(s[i],1)); V_temp.row(i*4+2) = TV.row(TT(s[i],2)); V_temp.row(i*4+3) = TV.row(TT(s[i],3)); F_temp.row(i*4+0) << (i*4)+0, (i*4)+1, (i*4)+3; F_temp.row(i*4+1) << (i*4)+0, (i*4)+2, (i*4)+1; F_temp.row(i*4+2) << (i*4)+3, (i*4)+2, (i*4)+0; F_temp.row(i*4+3) << (i*4)+1, (i*4)+2, (i*4)+3; } viewer.data.clear(); viewer.data.set_mesh(V_temp,F_temp); viewer.data.set_face_based(true); } return false; }
void ConsistencyTest::printOBJ(int numberOfPrints, string printToHere, MatrixXd& cB, Simulation& cSim, MatrixXi& cTT){ double refinement = 9; double t = ((refinement - 1)+1) / 9.0; VectorXd v = cB.col(2).array() - cB.col(2).minCoeff(); v /= v.col(0).maxCoeff(); vector<int> s; for (unsigned i=0; i<v.size();++i){ if (v(i) < t){ s.push_back(i); } } MatrixXd V_temp(s.size()*4,3); MatrixXi F_temp(s.size()*4,3); for (unsigned i=0; i<s.size();++i) { V_temp.row(i*4+0) = cSim.integrator->TV.row(cSim.integrator->TT(s[i],0)); V_temp.row(i*4+1) = cSim.integrator->TV.row(cSim.integrator->TT(s[i],1)); V_temp.row(i*4+2) = cSim.integrator->TV.row(cSim.integrator->TT(s[i],2)); V_temp.row(i*4+3) = cSim.integrator->TV.row(cSim.integrator->TT(s[i],3)); F_temp.row(i*4+0) << (i*4)+0, (i*4)+1, (i*4)+3; F_temp.row(i*4+1) << (i*4)+0, (i*4)+2, (i*4)+1; F_temp.row(i*4+2) << (i*4)+3, (i*4)+2, (i*4)+0; F_temp.row(i*4+3) << (i*4)+1, (i*4)+2, (i*4)+3; } cout<<printToHere + to_string(numberOfPrints)<<endl; system(("mkdir -p "+printToHere).c_str()); igl::writeOBJ(printToHere + to_string(numberOfPrints)+".obj", V_temp, F_temp); return; }
// [[Rcpp::export]] List wasserstein_auto_(NumericVector p_, NumericVector q_, NumericMatrix cost_matrix_, double epsilon, double desired_alpha){ // compute distance between p and q // p corresponds to the weights of a N-sample // each q corresponds to the weights of a M-sample // Thus cost_matrix must be a N x M cost matrix // epsilon is a regularization parameter, equal to 1/lambda in some references int N = p_.size(); int M = q_.size(); Map<VectorXd> p(as<Map<VectorXd> >(p_)); Map<VectorXd> q(as<Map<VectorXd> >(q_)); Map<MatrixXd> cost_matrix(as<Map<MatrixXd> >(cost_matrix_)); // avoid to take exp(k) when k is less than -500, // as K then contains zeros, and then the upcoming computations divide by zero MatrixXd K = (cost_matrix.array() * (-1./epsilon)); // K = exp(- M / epsilon) for (int i = 0; i < N; i++){ for (int j = 0; j < M; j++){ if (K(i,j) < -500){ K(i,j) = exp(-500); } else { K(i,j) = exp(K(i,j)); } } } MatrixXd K_transpose = K.transpose(); MatrixXd K_tilde = p.array().inverse().matrix().asDiagonal() * K; // diag(1/p) %*% K VectorXd u = VectorXd::Constant(N, 1./N); // VectorXd marginal1, marginal2; MatrixXd transportmatrix; VectorXd v; double alpha = 0; double beta = 0; int niterations_max = 1000; int iteration = 0; // for (int iteration = 0; iteration < niterations; iteration ++){ while ((iteration < niterations_max) and (alpha < desired_alpha)){ iteration ++; u = 1. / (K_tilde * (q.array() / (K_transpose * u).array()).matrix()).array(); if (iteration % 10 == 1){ // check if criterion is satisfied v = q.array() / (K_transpose * u).array(); transportmatrix = u.col(0).asDiagonal() * K * v.col(0).asDiagonal(); marginal1 = transportmatrix.rowwise().sum(); marginal2 = transportmatrix.colwise().sum(); alpha = 10; for (int i = 0; i < N; i++){ beta = std::min(p(i) / marginal1(i), q(i) / marginal2(i)); alpha = std::min(alpha, beta); } // cerr << "alpha = " << alpha << endl; } } v = q.array() / (K_transpose * u).array(); // compute the optimal transport matrix between p and the first q transportmatrix = u.col(0).asDiagonal() * K * v.col(0).asDiagonal(); // MatrixXd uXIv = u.array() * ((K.array() * cost_matrix.array()).matrix() * v).array(); // NumericVector d = wrap(uXIv.colwise().sum()); return List::create(Named("transportmatrix") = wrap(transportmatrix), Named("u") = wrap(u), Named("v") = wrap(v), Named("iteration") = iteration); }