#include "active_set.h" #include "min_quad_with_fixed.h" #include "slice.h" #include #include #include template < typename AT, typename DerivedB, typename Derivedknown, typename DerivedY, typename AeqT, typename DerivedBeq, typename AieqT, typename DerivedBieq, typename Derivedlx, typename Derivedux, typename DerivedZ > IGL_INLINE igl::SolverStatus igl::active_set( const Eigen::SparseMatrix& A, const Eigen::PlainObjectBase & B, const Eigen::PlainObjectBase & known, const Eigen::PlainObjectBase & Y, const Eigen::SparseMatrix& Aeq, const Eigen::PlainObjectBase & Beq, const Eigen::SparseMatrix& Aieq, const Eigen::PlainObjectBase & Bieq, const Eigen::PlainObjectBase & lx, const Eigen::PlainObjectBase & ux, const igl::active_set_params & params, Eigen::PlainObjectBase & Z ) { using namespace igl; using namespace Eigen; using namespace std; // Linear inequality constraints are not supported yet assert(Aieq.size() == 0); assert(Bieq.size() == 0); SolverStatus ret = SOLVER_STATUS_ERROR; const int n = A.rows(); assert(n == A.cols()); // Discard const qualifiers //if(B.size() == 0) //{ // B = Eigen::PlainObjectBase::Zero(n,1); //} assert(n == B.rows()); assert(B.cols() == 1); assert(Y.cols() == 1); assert((Aeq.size() == 0 && Beq.size() == 0) || Aeq.cols() == n); assert((Aeq.size() == 0 && Beq.size() == 0) || Aeq.rows() == Beq.rows()); assert((Aeq.size() == 0 && Beq.size() == 0) || Beq.cols() == 1); assert((Aieq.size() == 0 && Bieq.size() == 0) || Aieq.cols() == n); assert((Aieq.size() == 0 && Bieq.size() == 0) || Aieq.rows() == Bieq.rows()); assert((Aieq.size() == 0 && Bieq.size() == 0) || Bieq.cols() == 1); // Discard const qualifiers //if(lx.size() == 0) //{ // lx = Eigen::PlainObjectBase::Constant( // n,1,numeric_limits::min()); //} //if(ux.size() == 0) //{ // ux = Eigen::PlainObjectBase::Constant( // n,1,numeric_limits::max()); //} assert(lx.rows() == n); assert(ux.rows() == n); assert(ux.cols() == 1); assert(lx.cols() == 1); assert((ux.array()-lx.array()).minCoeff() > 0); if(Z.size() != 0) { // Initial guess should have correct size assert(Z.rows() == n); assert(Z.cols() == 1); } // Initialize active sets Matrix as_lx(n,1); Matrix as_ux(n,1); Matrix as_ieq(Aieq.rows(),1); int iter = 0; while(true) { // FIND BREACHES OF CONSTRAINTS if(Z.size() > 0) { for(int z = 0;z < n;z++) { if(Z(z) < lx(z)) { as_lx(z) = true; } if(Z(z) > ux(z)) { as_ux(z) = true; } } } const int as_lx_count = count(as_lx.data(),as_lx.data()+n,true); const int as_ux_count = count(as_ux.data(),as_ux.data()+n,true); // PREPARE FIXED VALUES Eigen::PlainObjectBase known_i; known_i.resize((int)known.size() + as_lx_count + as_ux_count,1); Eigen::PlainObjectBase Y_i; Y_i.resize((int)known.size() + as_lx_count + as_ux_count,1); { known_i.block(0,0,known.rows(),known.cols()) = known; Y_i.block(0,0,Y.rows(),Y.cols()) = Y; int k = known.size(); // Then all lx for(int z = 0;z < n;z++) { if(as_lx(z)) { known_i(k) = z; Y_i(k) = lx(z); k++; } } // Finally all ux for(int z = 0;z < n;z++) { if(as_ux(z)) { known_i(k) = z; Y_i(k) = ux(z); k++; } } assert(k==Y_i.size()); assert(k==known_i.size()); } min_quad_with_fixed_data data; if(!min_quad_with_fixed_precompute(A,known_i,Aeq,params.Auu_pd,data)) { cerr<<"Error: min_quad_with_fixed precomputation failed."< Ak; // Slow slice(A,known_i,1,Ak); Eigen::PlainObjectBase Bk; slice(B,known_i,Bk); MatrixXd Lambda_known_i = -(Ak*Z + 0.5*Bk); // reverse the lambda values for lx Lambda_known_i.block(known.size(),0,as_lx_count,1) = (-1*Lambda_known_i.block(known.size(),0,as_lx_count,1)).eval(); // Remove from active set for(int z = 0;z0 && iter>=params.max_iter) { ret = SOLVER_STATUS_MAX_ITER; break; } } finish: return ret; } #ifndef IGL_HEADER_ONLY // Explicit template specialization template igl::SolverStatus igl::active_set, Eigen::Matrix, Eigen::Matrix, double, Eigen::Matrix, double, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::SparseMatrix const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::SparseMatrix const&, Eigen::PlainObjectBase > const&, Eigen::SparseMatrix const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, igl::active_set_params const&, Eigen::PlainObjectBase >&); #endif