void SkelSmoothTerm::buildA() { Solver::DeformPetal& deform_petal = Solver::deform_petals_[petal_id_]; Solver::HandleMatrix& handle_matrix = deform_petal._handle_matrix; Solver::BranchList& branch_list = deform_petal._branch_list; int handle_number = handle_matrix.rows(); A_.resize(3); // biharmonic weights for handles themselves Eigen::MatrixXd weight_matrix(handle_number, handle_number); weight_matrix.setIdentity(); // handle coordinates Eigen::MatrixXd handles(handle_number, 4); handles.setOnes(); handles.block(0, 0, handle_number, 3) = handle_matrix; // M(convert affine) for handles Eigen::MatrixXd M(handle_number, 4*handle_number); for (size_t j = 0, j_end = handle_number; j < j_end; ++ j) { M.block(0, 4*j, handle_number, 4) = weight_matrix.col(j).asDiagonal() * handles; } // A for relationship between neighbor handles int a_cols = handle_number; int a_rows = 0; for (size_t i = 0; i < branch_list.size(); ++ i) { a_rows += (branch_list[i].size() - 2); } Eigen::MatrixXd A(a_rows, a_cols); A.setZero(); int row_count = 0; for (size_t i = 0, i_end = branch_list.size(); i < i_end; ++ i) { std::vector<int> branch = branch_list[i]; for (size_t j = 1, j_end = branch.size()-1; j < j_end; ++ j) { A(row_count, branch[j]) = -2; A(row_count, branch[j-1]) = 1; A(row_count, branch[j+1]) = 1; row_count++; } } // lambda_skel_smooth matrix Eigen::MatrixXd lambda_ss(a_rows, a_rows); lambda_ss.setIdentity(); lambda_ss = Solver::lambda_skel_smooth_ * lambda_ss; A_[0] = 2 * M.transpose() * A.transpose() * lambda_ss * A * M; A_[1] = 2 * M.transpose() * A.transpose() * lambda_ss * A * M; A_[2] = 2 * M.transpose() * A.transpose() * lambda_ss * A * M; }
Laplacian compute_laplacian(RandomAccessIterator begin, RandomAccessIterator end,const Neighbors& neighbors, DistanceCallback callback, ScalarType width) { SparseTriplets sparse_triplets; timed_context context("Laplacian computation"); const IndexType k = neighbors[0].size(); sparse_triplets.reserve((k+1)*(end-begin)); DenseVector D = DenseVector::Zero(end-begin); for (RandomAccessIterator iter=begin; iter!=end; ++iter) { const LocalNeighbors& current_neighbors = neighbors[iter-begin]; for (IndexType i=0; i<k; ++i) { ScalarType distance = callback(*iter,begin[current_neighbors[i]]); ScalarType heat = exp(-distance*distance/width); D(iter-begin) += heat; D(current_neighbors[i]) += heat; sparse_triplets.push_back(SparseTriplet(current_neighbors[i],(iter-begin),-heat)); sparse_triplets.push_back(SparseTriplet((iter-begin),current_neighbors[i],-heat)); } } for (IndexType i=0; i<(end-begin); ++i) sparse_triplets.push_back(SparseTriplet(i,i,D(i))); #ifdef EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET Eigen::DynamicSparseMatrix<ScalarType> dynamic_weight_matrix(end-begin,end-begin); dynamic_weight_matrix.reserve(sparse_triplets.size()); for (SparseTriplets::const_iterator it=sparse_triplets.begin(); it!=sparse_triplets.end(); ++it) dynamic_weight_matrix.coeffRef(it->col(),it->row()) += it->value(); SparseWeightMatrix weight_matrix(dynamic_weight_matrix); #else SparseWeightMatrix weight_matrix(end-begin,end-begin); weight_matrix.setFromTriplets(sparse_triplets.begin(),sparse_triplets.end()); #endif return Laplacian(weight_matrix,DenseDiagonalMatrix(D)); }
SparseWeightMatrix klle_weight_matrix(RandomAccessIterator begin, RandomAccessIterator end, const Neighbors& neighbors, PairwiseCallback callback, DefaultScalarType shift) { timed_context context("KLLE weight computation"); const unsigned int k = neighbors[0].size(); SparseTriplets sparse_triplets; sparse_triplets.reserve((k*k+2*k+1)*(end-begin)); RandomAccessIterator iter; RandomAccessIterator iter_begin = begin, iter_end = end; DenseMatrix gram_matrix = DenseMatrix::Zero(k,k); DenseVector dots(k); DenseVector rhs = DenseVector::Ones(k); DenseVector weights; for (RandomAccessIterator iter=iter_begin; iter!=iter_end; ++iter) { DefaultScalarType kernel_value = callback(*iter,*iter); const LocalNeighbors& current_neighbors = neighbors[iter-begin]; for (unsigned int i=0; i<k; ++i) dots[i] = callback(*iter, begin[current_neighbors[i]]); for (unsigned int i=0; i<k; ++i) { for (unsigned int j=i; j<k; ++j) gram_matrix(i,j) = kernel_value - dots(i) - dots(j) + callback(begin[current_neighbors[i]],begin[current_neighbors[j]]); } DefaultScalarType trace = gram_matrix.trace(); gram_matrix.diagonal().array() += 1e-3*trace; weights = gram_matrix.selfadjointView<Eigen::Upper>().ldlt().solve(rhs); weights /= weights.sum(); sparse_triplets.push_back(SparseTriplet(iter-begin,iter-begin,1.0+shift)); for (unsigned int i=0; i<k; ++i) { sparse_triplets.push_back(SparseTriplet(current_neighbors[i],iter-begin, -weights[i])); sparse_triplets.push_back(SparseTriplet(iter-begin,current_neighbors[i], -weights[i])); for (unsigned int j=0; j<k; ++j) sparse_triplets.push_back(SparseTriplet(current_neighbors[i],current_neighbors[j], +weights(i)*weights(j))); } } SparseWeightMatrix weight_matrix(end-begin,end-begin); weight_matrix.setFromTriplets(sparse_triplets.begin(),sparse_triplets.end()); return weight_matrix; }
SparseWeightMatrix kltsa_weight_matrix(RandomAccessIterator begin, RandomAccessIterator end, const Neighbors& neighbors, PairwiseCallback callback, unsigned int target_dimension, DefaultScalarType shift, bool partial_eigendecomposer=false) { timed_context context("KLTSA weight matrix computation"); const unsigned int k = neighbors[0].size(); SparseTriplets sparse_triplets; sparse_triplets.reserve((k*k+k+1)*(end-begin)); RandomAccessIterator iter; RandomAccessIterator iter_begin = begin, iter_end = end; DenseMatrix gram_matrix = DenseMatrix::Zero(k,k); DenseVector col_means(k), row_means(k); DenseVector rhs = DenseVector::Ones(k); DenseMatrix G = DenseMatrix::Zero(k,target_dimension+1); G.col(0).setConstant(1/sqrt(DefaultScalarType(k))); DefaultDenseSelfAdjointEigenSolver solver; RESTRICT_ALLOC; //#pragma omp parallel for private(iter,gram_matrix,G) for (iter=iter_begin; iter<iter_end; ++iter) { const LocalNeighbors& current_neighbors = neighbors[iter-begin]; for (unsigned int i=0; i<k; ++i) { for (unsigned int j=i; j<k; ++j) { DefaultScalarType kij = callback(begin[current_neighbors[i]],begin[current_neighbors[j]]); gram_matrix(i,j) = kij; gram_matrix(j,i) = kij; } } col_means = gram_matrix.colwise().mean(); DefaultScalarType grand_mean = gram_matrix.mean(); gram_matrix.array() += grand_mean; gram_matrix.rowwise() -= col_means.transpose(); gram_matrix.colwise() -= col_means; UNRESTRICT_ALLOC; if (partial_eigendecomposer) { G.rightCols(target_dimension).noalias() = eigen_embedding<DenseMatrix,DenseMatrixOperation>(ARPACK,gram_matrix,target_dimension,0).first; } else { solver.compute(gram_matrix); G.rightCols(target_dimension).noalias() = solver.eigenvectors().rightCols(target_dimension); } RESTRICT_ALLOC; gram_matrix.noalias() = G * G.transpose(); sparse_triplets.push_back(SparseTriplet(iter-begin,iter-begin,shift)); for (unsigned int i=0; i<k; ++i) { sparse_triplets.push_back(SparseTriplet(current_neighbors[i],current_neighbors[i],1.0)); for (unsigned int j=0; j<k; ++j) sparse_triplets.push_back(SparseTriplet(current_neighbors[i],current_neighbors[j], -gram_matrix(i,j))); } } UNRESTRICT_ALLOC; SparseWeightMatrix weight_matrix(end-begin,end-begin); weight_matrix.setFromTriplets(sparse_triplets.begin(),sparse_triplets.end()); return weight_matrix; }
SparseWeightMatrix hlle_weight_matrix(RandomAccessIterator begin, RandomAccessIterator end, const Neighbors& neighbors, PairwiseCallback callback, unsigned int target_dimension) { timed_context context("KLTSA weight matrix computation"); const unsigned int k = neighbors[0].size(); SparseTriplets sparse_triplets; sparse_triplets.reserve(k*k*(end-begin)); RandomAccessIterator iter_begin = begin, iter_end = end; DenseMatrix gram_matrix = DenseMatrix::Zero(k,k); DenseVector col_means(k), row_means(k); DenseVector rhs = DenseVector::Ones(k); DenseMatrix G = DenseMatrix::Zero(k,target_dimension+1); RandomAccessIterator iter; for (iter=iter_begin; iter!=iter_end; ++iter) { const LocalNeighbors& current_neighbors = neighbors[iter-begin]; for (unsigned int i=0; i<k; ++i) { for (unsigned int j=i; j<k; ++j) { DefaultScalarType kij = callback(begin[current_neighbors[i]],begin[current_neighbors[j]]); gram_matrix(i,j) = kij; gram_matrix(j,i) = kij; } } for (unsigned int i=0; i<k; ++i) { col_means[i] = gram_matrix.col(i).mean(); row_means[i] = gram_matrix.row(i).mean(); } DefaultScalarType grand_mean = gram_matrix.mean(); gram_matrix.array() += grand_mean; gram_matrix.rowwise() -= col_means.transpose(); gram_matrix.colwise() -= row_means; DefaultDenseSelfAdjointEigenSolver sae_solver; sae_solver.compute(gram_matrix); G.col(0).setConstant(1/sqrt(DefaultScalarType(k))); G.rightCols(target_dimension).noalias() = sae_solver.eigenvectors().rightCols(target_dimension); gram_matrix = G * G.transpose(); sparse_triplets.push_back(SparseTriplet(iter-begin,iter-begin,1e-8)); for (unsigned int i=0; i<k; ++i) { sparse_triplets.push_back(SparseTriplet(current_neighbors[i],current_neighbors[i],1.0)); for (unsigned int j=0; j<k; ++j) sparse_triplets.push_back(SparseTriplet(current_neighbors[i],current_neighbors[j], -gram_matrix(i,j))); } } SparseWeightMatrix weight_matrix(end-begin,end-begin); weight_matrix.setFromTriplets(sparse_triplets.begin(),sparse_triplets.end()); return weight_matrix; };