MatrixXd slice(const MatrixXd &A, const VectorXi &R, const VectorXi &C) { assert(R.minCoeff() >= 0); assert(C.minCoeff() >= 0); assert(R.maxCoeff() < A.rows()); assert(C.maxCoeff() < A.cols()); int rows = R.size(); int cols = C.size(); MatrixXd B(rows,cols); for ( int i = 0 ; i < rows ; i++ ) { for ( int j = 0 ; j < cols ; j++ ) { B(i,j) = A(R(i),C(j)); } } return (B); }
void init_patches() { using namespace Eigen; using namespace igl; using namespace std; { VectorXi VCC; components(F,VCC); cout<<"There are "<<VCC.maxCoeff()+1<<" connected components of vertices."<<endl; } bfs_orient(F,F,CC); VectorXi I; switch(orient_method) { case ORIENT_METHOD_AO: { cout<<"orient_outward_ao()"<<endl; igl::embree::reorient_facets_raycast(V,F,F,I); break; } case ORIENT_METHOD_OUTWARD: default: cout<<"orient_outward()"<<endl; orient_outward(V,F,CC,F,I); break; } double num_cc = (double)CC.maxCoeff()+1.0; cout<<"There are "<<num_cc<<" 'manifold/orientable' patches of faces."<<endl; }
VectorXd slice(const VectorXd &A, const VectorXi &I) { assert(I.minCoeff() >= 0); assert(I.maxCoeff() < A.size()); int size = I.size(); VectorXd B(size); for ( int i = 0 ; i < size ; i++ ) { B(i) = A(I(i)); } return (B); }
virtual float gain( const VectorXb& is_left ) const { const int N = lbl_.maxCoeff()+1; ArrayXf wl = 1e-20*ArrayXf::Ones(N), wr = 1e-20*ArrayXf::Ones(N); for( int i=0; i<(int)lbl_.size(); i++ ) if( is_left[i] ) wl[lbl_[i]] += weight_[i]; else wr[lbl_[i]] += weight_[i]; const float l = wl.sum(), r = wr.sum(); const float sl = score(wl/l), sr = score(wr/r); printf("%d %d\n", (int)l, (int)r ); return score( (wl+wr)/(l+r) ) - (sl*l/(l+r) + sr*r/(l+r)); }
virtual int repLabel() const { // Count the label occurence const int n_lbl = lbl_.maxCoeff()+1; VectorXi lbl_cnt = VectorXi::Zero( n_lbl ); for( int i=0; i<lbl_.size(); i++ ) lbl_cnt[lbl_[i]]++; // And return the maximum int rep_lbl = 0; for( int i=0; i<lbl_.size(); i++ ) if( lbl_cnt[lbl_[rep_lbl]] < lbl_cnt[lbl_[i]] ) rep_lbl = i; return rep_lbl; }
virtual float bestThreshold( const VectorXf & f, float * gain ) const { const int N = lbl_.maxCoeff()+1; const float EPS=1e-6; // Create the feature/label pairs std::vector< std::pair<float,int> > elements( f.size() ); for( int i=0; i<f.size(); i++ ) elements[i] = std::make_pair( f[i], i ); std::sort(elements.begin(), elements.end() ); // And compute the probabilities and cirterion ArrayXf wl = 1e-20*ArrayXf::Ones(N), wr = 1e-20*ArrayXf::Ones(N); for( int i=0; i<lbl_.size(); i++ ) wr[ lbl_[i] ] += weight_[i]; // Initialize the thresholds float best_gain = 0, tbest = (elements.front().first+elements.back().first)/2, last_t = elements.front().first; const float tot_s = score( wr/wr.sum() ); // Find the best threshold for( auto i: elements ) { const float t = i.first; const int j = i.second; // If there is a threshold if( t - last_t > EPS ) { // Compute the score const float l = wl.sum(), r = wr.sum(); const float sl = score(wl/l), sr = score(wr/r); const float g = tot_s - ( sl*l/(l+r) + sr*r/(l+r) ); if( g > best_gain ) { best_gain = g; tbest = (last_t+t)/2.; } } // Update the probabilities wl[ lbl_[j] ] += weight_[j]; wr[ lbl_[j] ] -= weight_[j]; last_t = t; } if( gain ) *gain = best_gain; return tbest; }
//#define IGL_LINPROG_VERBOSE IGL_INLINE bool igl::linprog( const Eigen::VectorXd & c, const Eigen::MatrixXd & _A, const Eigen::VectorXd & b, const int k, Eigen::VectorXd & x) { // This is a very literal translation of // http://www.mathworks.com/matlabcentral/fileexchange/2166-introduction-to-linear-algebra/content/strang/linprog.m using namespace Eigen; using namespace std; bool success = true; // number of constraints const int m = _A.rows(); // number of original variables const int n = _A.cols(); // number of iterations int it = 0; // maximum number of iterations //const int MAXIT = 10*m; const int MAXIT = 100*m; // residual tolerance const double tol = 1e-10; const auto & sign = [](const Eigen::VectorXd & B) -> Eigen::VectorXd { Eigen::VectorXd Bsign(B.size()); for(int i = 0;i<B.size();i++) { Bsign(i) = B(i)>0?1:(B(i)<0?-1:0); } return Bsign; }; // initial (inverse) basis matrix VectorXd Dv = sign(sign(b).array()+0.5); Dv.head(k).setConstant(1.); MatrixXd D = Dv.asDiagonal(); // Incorporate slack variables MatrixXd A(_A.rows(),_A.cols()+D.cols()); A<<_A,D; // Initial basis VectorXi B = igl::colon<int>(n,n+m-1); // non-basis, may turn out that vector<> would be better here VectorXi N = igl::colon<int>(0,n-1); int j; double bmin = b.minCoeff(&j); int phase; VectorXd xb; VectorXd s; VectorXi J; if(k>0 && bmin<0) { phase = 1; xb = VectorXd::Ones(m); // super cost s.resize(n+m+1); s<<VectorXd::Zero(n+k),VectorXd::Ones(m-k+1); N.resize(n+1); N<<igl::colon<int>(0,n-1),B(j); J.resize(B.size()-1); // [0 1 2 3 4] // ^ // [0 1] // [3 4] J.head(j) = B.head(j); J.tail(B.size()-j-1) = B.tail(B.size()-j-1); B(j) = n+m; MatrixXd AJ; igl::slice(A,J,2,AJ); const VectorXd a = b - AJ.rowwise().sum(); { MatrixXd old_A = A; A.resize(A.rows(),A.cols()+a.cols()); A<<old_A,a; } D.col(j) = -a/a(j); D(j,j) = 1./a(j); }else if(k==m) { phase = 2; xb = b; s.resize(c.size()+m); // cost function s<<c,VectorXd::Zero(m); }else //k = 0 or bmin >=0 { phase = 1; xb = b.array().abs(); s.resize(n+m); // super cost s<<VectorXd::Zero(n+k),VectorXd::Ones(m-k); } while(phase<3) { double df = -1; int t = std::numeric_limits<int>::max(); // Lagrange mutipliers fro Ax=b VectorXd yb = D.transpose() * igl::slice(s,B); while(true) { if(MAXIT>0 && it>=MAXIT) { #ifdef IGL_LINPROG_VERBOSE cerr<<"linprog: warning! maximum iterations without convergence."<<endl; #endif success = false; break; } // no freedom for minimization if(N.size() == 0) { break; } // reduced costs VectorXd sN = igl::slice(s,N); MatrixXd AN = igl::slice(A,N,2); VectorXd r = sN - AN.transpose() * yb; int q; // determine new basic variable double rmin = r.minCoeff(&q); // optimal! infinity norm if(rmin>=-tol*(sN.array().abs().maxCoeff()+1)) { break; } // increment iteration count it++; // apply Bland's rule to avoid cycling if(df>=0) { if(MAXIT == -1) { #ifdef IGL_LINPROG_VERBOSE cerr<<"linprog: warning! degenerate vertex"<<endl; #endif success = false; } igl::find((r.array()<0).eval(),J); double Nq = igl::slice(N,J).minCoeff(); // again seems like q is assumed to be a scalar though matlab code // could produce a vector for multiple matches (N.array()==Nq).cast<int>().maxCoeff(&q); } VectorXd d = D*A.col(N(q)); VectorXi I; igl::find((d.array()>tol).eval(),I); if(I.size() == 0) { #ifdef IGL_LINPROG_VERBOSE cerr<<"linprog: warning! solution is unbounded"<<endl; #endif // This seems dubious: it=-it; success = false; break; } VectorXd xbd = igl::slice(xb,I).array()/igl::slice(d,I).array(); // new use of r int p; { double r; r = xbd.minCoeff(&p); p = I(p); // apply Bland's rule to avoid cycling if(df>=0) { igl::find((xbd.array()==r).eval(),J); double Bp = igl::slice(B,igl::slice(I,J)).minCoeff(); // idiotic way of finding index in B of Bp // code down the line seems to assume p is a scalar though the matlab // code could find a vector of matches) (B.array()==Bp).cast<int>().maxCoeff(&p); } // update x xb -= r*d; xb(p) = r; // change in f df = r*rmin; } // row vector RowVectorXd v = D.row(p)/d(p); yb += v.transpose() * (s(N(q)) - d.transpose()*igl::slice(s,B)); d(p)-=1; // update inverse basis matrix D = D - d*v; t = B(p); B(p) = N(q); if(t>(n+k-1)) { // remove qth entry from N VectorXi old_N = N; N.resize(N.size()-1); N.head(q) = old_N.head(q); N.head(q) = old_N.head(q); N.tail(old_N.size()-q-1) = old_N.tail(old_N.size()-q-1); }else { N(q) = t; } } // iterative refinement xb = (xb+D*(b-igl::slice(A,B,2)*xb)).eval(); // must be due to rounding VectorXi I; igl::find((xb.array()<0).eval(),I); if(I.size()>0) { // so correct VectorXd Z = VectorXd::Zero(I.size(),1); igl::slice_into(Z,I,xb); } // B, xb,n,m,res=A(:,B)*xb-b if(phase == 2 || it<0) { break; } if(xb.transpose()*igl::slice(s,B) > tol) { it = -it; #ifdef IGL_LINPROG_VERBOSE cerr<<"linprog: warning, no feasible solution"<<endl; #endif success = false; break; } // re-initialize for Phase 2 phase = phase+1; s*=1e6*c.array().abs().maxCoeff(); s.head(n) = c; } x.resize(std::max(B.maxCoeff()+1,n)); igl::slice_into(xb,B,x); x = x.head(n).eval(); return success; }
bool CodeAtlas::ComponentLayouter::compute() { CHECK_ERRORS_RETURN_BOOL(m_status); SymbolNode::Ptr node = m_parent; // for a interior node, find attribute FuzzyDependAttr::Ptr fuzzyAttr = node->getAttr<FuzzyDependAttr>(); #ifndef ONLY_USE_WORD_SIMILARITY if (fuzzyAttr.isNull() || fuzzyAttr->edgeWeightVector().size() <= 0 || fuzzyAttr->vtxEdgeMatrix().cols() <= 0 || fuzzyAttr->vtxEdgeMatrix().rows() <= 0) { m_status |= WARNING_NO_EDGE; if (!ComponentLayouter::compute(NULL, NULL, m_childList, m_nodePos, m_nodeRadius, m_totalRadius)) trivalLayout(); } else { // fill data used to compute layout SparseMatrix& vtxEdgeMatrix = fuzzyAttr->vtxEdgeMatrix(); VectorXd& edgeWeight = fuzzyAttr->edgeWeightVector(); #ifdef CHOOSE_IMPORTANT_EDGES // filter edges VectorXi degreeVec; degreeVec.setZero(vtxEdgeMatrix.rows()); for (int ithEdge = 0; ithEdge < vtxEdgeMatrix.cols(); ++ithEdge) { int src, tar; GraphUtility::getVtxFromEdge(vtxEdgeMatrix, ithEdge, src, tar); degreeVec[src]++; degreeVec[tar]++; } float maxVal = degreeVec.maxCoeff(); float minVal = degreeVec.minCoeff(); const float ratio = 0.2f; float threshold = min(minVal + (maxVal - minVal) * ratio, 3.f); std::vector<Triplet> tripletArray; std::vector<double> filteredEdgeArray; for (int ithEdge = 0; ithEdge < edgeWeight.size(); ++ithEdge) { int src, tar; GraphUtility::getVtxFromEdge(vtxEdgeMatrix, ithEdge, src, tar); if (min(degreeVec[src], degreeVec[tar]) <= threshold) { tripletArray.push_back(Triplet(src, filteredEdgeArray.size() ,1.0)); tripletArray.push_back(Triplet(tar, filteredEdgeArray.size() ,-1.0)); filteredEdgeArray.push_back(edgeWeight[ithEdge]); } } SparseMatrix filteredVEMat(vtxEdgeMatrix.rows(), filteredEdgeArray.size()); filteredVEMat.setFromTriplets(tripletArray.begin(), tripletArray.end()); VectorXd filteredEdgeVec(filteredEdgeArray.size()); memcpy(filteredEdgeVec.data(), &filteredEdgeArray[0], sizeof(double)*filteredEdgeArray.size()); if (!ComponentLayouter::compute(&filteredVEMat, &filteredEdgeVec, m_childList, m_nodePos, m_nodeRadius, m_totalRadius)) trivalLayout(); #else if (!ComponentLayouter::compute(&vtxEdgeMatrix, &edgeWeight, m_childList, m_nodePos, m_nodeRadius, m_totalRadius)) trivalLayout(); #endif qDebug("compute edge routes"); DelaunayCore::DelaunayRouter router; router.setSmoothParam(0.5, 4); computeEdgeRoute(router); } #else if (!ComponentLayouter::compute(NULL, NULL, m_childList, m_nodePos, m_nodeRadius, m_totalRadius)) trivalLayout(); if (!fuzzyAttr.isNull()) { m_status &= ~WARNING_NO_EDGE; qDebug("compute edge routes"); DelaunayCore::DelaunayRouter router; router.setSmoothParam(0.5, 4); computeEdgeRoute(router); } #endif if ((m_status & WARNING_TRIVAL_LAYOUT) == 0) computeVisualHull(); return true; }