31  const Eigen::SparseMatrix<T>& A2,
 
   32  const Eigen::MatrixBase<Derivedknown> & known,
 
   33  const Eigen::SparseMatrix<T>& Aeq,
 
   39  using namespace Eigen;
 
   41  const Eigen::SparseMatrix<T> A = 0.5*A2;
 
   42#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
   54    assert(n == Aeq.cols() && 
"#Aeq.cols() should match A.rows()");
 
   57  assert(known.cols() == 1 && 
"known should be a vector");
 
   58  assert(A.rows() == n && 
"A should be square");
 
   59  assert(A.cols() == n && 
"A should be square");
 
   62  int kr = known.size();
 
   64  assert((kr == 0 || known.minCoeff() >= 0)&& 
"known indices should be in [0,n)");
 
   65  assert((kr == 0 || known.maxCoeff() < n) && 
"known indices should be in [0,n)");
 
   66  assert(neq <= n && 
"Number of equality constraints should be less than DOFs");
 
   71  data.
known = known.template cast<int>();
 
   75  std::vector<bool> unknown_mask;
 
   76  unknown_mask.resize(n,
true);
 
   77  for(
int i = 0;i<kr;i++)
 
   79    unknown_mask[known(i, 0)] = 
false;
 
   82  for(
int i = 0;i<n;i++)
 
   92  for(
int i = 0;i<neq;i++)
 
  113  assert(Auu.size() != 0 && Auu.rows() > 0 && 
"There should be at least one unknown.");
 
  125      "Auu should be symmetric if positive definite");
 
  130    Matrix<T,Eigen::Dynamic,Eigen::Dynamic> AuuV;
 
  131    find(Auu,AuuI,AuuJ,AuuV);
 
  139#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  144    assert(data.
Aequ.rows() == neq &&
 
  145      "#Rows in Aequ should match #constraints");
 
  147      "#cols in Aequ should match #unknowns");
 
  148    data.
AeqTQR.compute(data.
Aequ.transpose().eval());
 
  149#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  152    switch(data.
AeqTQR.info())
 
  156      case Eigen::NumericalIssue:
 
  157        cerr<<
"Error: Numerical issue."<<endl;
 
  159      case Eigen::InvalidInput:
 
  160        cerr<<
"Error: Invalid input."<<endl;
 
  163        cerr<<
"Error: Other."<<endl;
 
  168      "Rank of reduced constraints should be <= #original constraints");
 
  178#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  179    cout<<
"    Aeq_li=true"<<endl;
 
  182    SparseMatrix<T> new_A;
 
  183    SparseMatrix<T> AeqT = Aeq.transpose();
 
  184    SparseMatrix<T> Z(neq,neq);
 
  186    new_A = 
cat(1, 
cat(2,   A, AeqT ),
 
  192      SparseMatrix<T> Aulk,Akul;
 
  204        SparseMatrix<T> AkulT = Akul.transpose();
 
  205        data.
preY = Aulk + AkulT;
 
  214#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  215    cout<<
"    factorize"<<endl;
 
  217    if(data.
Auu_pd && neq == 0)
 
  219#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  222      data.
llt.compute(Auu);
 
  223      switch(data.
llt.info())
 
  227        case Eigen::NumericalIssue:
 
  228          cerr<<
"Error: Numerical issue."<<endl;
 
  231          cerr<<
"Error: Other."<<endl;
 
  237#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  238        cout<<
"    ldlt/lu"<<endl;
 
  246#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  249        data.
ldlt.compute(NA);
 
  250        switch(data.
ldlt.info())
 
  254          case Eigen::NumericalIssue:
 
  255            cerr<<
"Error: Numerical issue."<<endl;
 
  258            cerr<<
"Error: Other."<<endl;
 
  264#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  271        switch(data.
lu.info())
 
  275          case Eigen::NumericalIssue:
 
  276            cerr<<
"Error: Numerical issue."<<endl;
 
  278          case Eigen::InvalidInput:
 
  279            cerr<<
"Error: Invalid Input."<<endl;
 
  282            cerr<<
"Error: Other."<<endl;
 
  290#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  291    cout<<
"    Aeq_li=false"<<endl;
 
  294    const int nu = data.
unknown.size();
 
  299    SparseMatrix<T> AeqTR,AeqTQ;
 
  300    AeqTR = data.
AeqTQR.matrixR();
 
  302    AeqTR.prune(
static_cast<T
>(0.0));
 
  303#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  304    cout<<
"    matrixQ"<<endl;
 
  308    AeqTQ = data.
AeqTQR.matrixQ();
 
  309#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  310    cout<<
"    prune"<<endl;
 
  311    cout<<
"      nnz: "<<AeqTQ.nonZeros()<<endl;
 
  314    AeqTQ.prune(
static_cast<T
>(0.0));
 
  318#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  319    cout<<
"      nnz: "<<AeqTQ.nonZeros()<<endl;
 
  322    SparseMatrix<T> I(neq,neq);
 
  325    data.
AeqTET = data.
AeqTQR.colsPermutation().transpose() * I;
 
  326    assert(AeqTR.rows() == nu   && 
"#rows in AeqTR should match #unknowns");
 
  327    assert(AeqTR.cols() == neq  && 
"#cols in AeqTR should match #constraints");
 
  328    assert(AeqTQ.rows() == nu && 
"#rows in AeqTQ should match #unknowns");
 
  329    assert(AeqTQ.cols() == nu && 
"#cols in AeqTQ should match #unknowns");
 
  331#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  332    cout<<
"    slice"<<endl;
 
  334    data.
AeqTQ1 = AeqTQ.topLeftCorner(nu,nc);
 
  337    data.
AeqTR1 = AeqTR.topLeftCorner(nc,nc);
 
  341    data.
AeqTQ2 = AeqTQ.bottomRightCorner(nu,nu-nc);
 
  343#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  349#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  350      cout<<
"    factorize"<<endl;
 
  353      data.
llt.compute(QRAuu);
 
  354      switch(data.
llt.info())
 
  358        case Eigen::NumericalIssue:
 
  359          cerr<<
"Error: Numerical issue."<<endl;
 
  362          cerr<<
"Error: Other."<<endl;
 
  367#ifdef MIN_QUAD_WITH_FIXED_CPP_DEBUG 
  368    cout<<
"    smash"<<endl;
 
  375    SparseMatrix<T> AkuT = Aku.transpose();
 
  376    data.
preY = Auk + AkuT;
 
  380    assert(data.
Aeqk.rows() == neq);
 
  381    assert(data.
Aeqk.cols() == data.
known.size());
 
 
  396  const Eigen::MatrixBase<DerivedB> & B,
 
  397  const Eigen::MatrixBase<DerivedY> & Y,
 
  398  const Eigen::MatrixBase<DerivedBeq> & Beq,
 
  399  Eigen::PlainObjectBase<DerivedZ> & Z,
 
  400  Eigen::PlainObjectBase<Derivedsol> & sol)
 
  403  using namespace Eigen;
 
  404  typedef Matrix<T,Dynamic,Dynamic> MatrixXT;
 
  406  int kr = data.
known.size();
 
  409    assert(kr == Y.rows());
 
  413  assert(B.cols() == 1 || B.cols() == cols);
 
  414  assert(Beq.size() == 0 || Beq.cols() == 1 || Beq.cols() == cols);
 
  417  Z.resize(data.
n,cols);
 
  419  for(
int i = 0;i < kr;i++)
 
  421    for(
int j = 0;j < cols;j++)
 
  423      Z(data.
known(i),j) = Y(i,j);
 
  432    MatrixXT BBeq(B.rows() + Beq.rows(),cols);
 
  435      BBeq.topLeftCorner(B.rows(),cols) = B.replicate(1,B.cols()==cols?1:cols);
 
  439      BBeq.bottomLeftCorner(Beq.rows(),cols) = -2.0*Beq.replicate(1,Beq.cols()==cols?1:cols);
 
  450      NB = data.
preY * Y + BBequlcols;
 
  458        sol = data.
llt.solve(NB);
 
  461        sol = data.
ldlt.solve(NB);
 
  465        sol = data.
lu.solve(NB);
 
  468        cerr<<
"Error: invalid solver type"<<endl;
 
  476    for(
int i = 0;i<(sol.rows()-neq);i++)
 
  478      for(
int j = 0;j<sol.cols();j++)
 
  490      data.
AeqTET * (-data.
Aeqk * Y + Beq.replicate(1,Beq.cols()==cols?1:cols));
 
  492    MatrixXT Bu = B(data.
unknown,Eigen::all);
 
  494    NB = -0.5*(Bu.replicate(1,B.cols()==cols?1:cols) + data.
preY * Y);
 
  496    const int nc = data.
AeqTQR.rank();
 
  497    const int neq = Beq.rows();
 
  498    eff_Beq = eff_Beq.topLeftCorner(nc,cols).eval();
 
  499    data.
AeqTR1T.template triangularView<Lower>().solveInPlace(eff_Beq);
 
  502    lambda_0 = data.
AeqTQ1 * eff_Beq;
 
  507    lambda = data.
llt.solve(QRB);
 
  510    solu = data.
AeqTQ2 * lambda + lambda_0;
 
  512    Derivedsol solLambda;
 
  514      Derivedsol temp1,temp2;
 
  516      data.
AeqTR1.template triangularView<Upper>().solveInPlace(temp1);
 
  518      temp2 = Derivedsol::Zero(neq,cols);
 
  519      temp2.topLeftCorner(nc,cols) = temp1;
 
  521      solLambda = data.
AeqTE * temp2;
 
  524    assert(data.
unknown.size() == solu.rows());
 
  525    assert(cols == solu.cols());
 
  526    assert(data.
neq == neq);
 
  527    assert(data.
neq == solLambda.rows());
 
  528    assert(cols == solLambda.cols());
 
  529    sol.resize(data.
unknown.size()+data.
neq,cols);
 
  530    sol.block(0,0,solu.rows(),solu.cols()) = solu;
 
  531    sol.block(solu.rows(),0,solLambda.rows(),solLambda.cols()) = solLambda;
 
  532    for(
int u = 0;u<data.
unknown.size();u++)
 
  534      for(
int j = 0;j<Z.cols();j++)
 
  536        Z(data.
unknown(u),j) = solu(u,j);
 
 
  588  const Eigen::Matrix<Scalar,n,n> & H,
 
  589  const Eigen::Matrix<Scalar,n,1> & f,
 
  590  const Eigen::Array<bool,n,1> & k,
 
  591  const Eigen::Matrix<Scalar,n,1> & bc,
 
  592  const Eigen::Matrix<Scalar,m,n> & A,
 
  593  const Eigen::Matrix<Scalar,m,1> & b)
 
  595  const auto dyn_n = n == Eigen::Dynamic ? H.rows() : n;
 
  596  const auto dyn_m = m == Eigen::Dynamic ? A.rows() : m;
 
  597  constexpr const int nn = n == Eigen::Dynamic ? Eigen::Dynamic : n+m;
 
  598  const auto dyn_nn = nn == Eigen::Dynamic ? dyn_n+dyn_m : nn;
 
  601    return igl::min_quad_with_fixed<Scalar,n,Hpd>(H,f,k,bc);
 
  606  const auto make_HH = [&]()
 
  609    constexpr const int nn = n == Eigen::Dynamic ? Eigen::Dynamic : n+m;
 
  610    Eigen::Matrix<Scalar,nn,nn> HH =
 
  611      Eigen::Matrix<Scalar,nn,nn>::Zero(dyn_nn,dyn_nn);
 
  612    HH.topLeftCorner(dyn_n,dyn_n) = H;
 
  613    HH.bottomLeftCorner(dyn_m,dyn_n) = A;
 
  614    HH.topRightCorner(dyn_n,dyn_m) = A.transpose();
 
  617  const Eigen::Matrix<Scalar,nn,nn> HH = make_HH();
 
  618  const auto make_ff  = [&]()
 
  621    constexpr const int nn = n == Eigen::Dynamic ? Eigen::Dynamic : n+m;
 
  622    Eigen::Matrix<Scalar,nn,1> ff(dyn_nn);
 
  627  const Eigen::Matrix<Scalar,nn,1> ff = make_ff();
 
  628  const auto make_kk  = [&]()
 
  631    constexpr const int nn = n == Eigen::Dynamic ? Eigen::Dynamic : n+m;
 
  632    Eigen::Array<bool,nn,1> kk =
 
  633      Eigen::Array<bool,nn,1>::Constant(dyn_nn,1,
false);
 
  637  const Eigen::Array<bool,nn,1> kk = make_kk();
 
  638  const auto make_bcbc= [&]()
 
  641    constexpr const int nn = n == Eigen::Dynamic ? Eigen::Dynamic : n+m;
 
  642    Eigen::Matrix<Scalar,nn,1> bcbc(dyn_nn);
 
  643    bcbc.head(dyn_n) =  bc;
 
  646  const Eigen::Matrix<Scalar,nn,1> bcbc = make_bcbc();
 
  647  const Eigen::Matrix<Scalar,nn,1> xx =
 
  648    min_quad_with_fixed<Scalar,nn,false>(HH,ff,kk,bcbc);
 
  649  return xx.head(dyn_n);
 
 
  654  const Eigen::Matrix<Scalar,n,n> & H,
 
  655  const Eigen::Matrix<Scalar,n,1> & f,
 
  656  const Eigen::Array<bool,n,1> & k,
 
  657  const Eigen::Matrix<Scalar,n,1> & bc)
 
  659  assert(H.isApprox(H.transpose(),1e-7));
 
  660  assert(H.rows() == H.cols());
 
  661  assert(H.rows() == f.size());
 
  662  assert(H.rows() == k.size());
 
  663  assert(H.rows() == bc.size());
 
  664  const auto kcount = k.count();
 
  666  if(kcount == (Eigen::Dynamic?H.rows():n))
 
  674    typedef Eigen::Matrix<Scalar,n,n> MatrixSn;
 
  676      std::conditional<Hpd,Eigen::LLT<MatrixSn>,Eigen::CompleteOrthogonalDecomposition<MatrixSn>>::type
 
  678    return Solver(H).solve(-f);
 
  681  if( (Eigen::Dynamic?H.rows():n)-kcount == 1)
 
  685    for(
int i=0;i<k.size();i++){ 
if(!k(i)){ u=i; 
break; } }
 
  690    Eigen::Matrix<Scalar,n,1> x = bc;
 
  692    for(
int i=0;i<k.size();i++){ 
if(i!=u){ x(u)-=bc(i)*H(i,u); } }
 
  703    case 0: assert(
false && 
"Handled above."); 
return Eigen::Matrix<Scalar,n,1>();
 
  708     const bool D = (n-1<=0)||(1>=n)||(n>16);
 
  709     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:1,Hpd>(H,f,k,bc);
 
  713     const bool D = (n-2<=0)||(2>=n)||(n>16);
 
  714     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:2,Hpd>(H,f,k,bc);
 
  718     const bool D = (n-3<=0)||(3>=n)||(n>16);
 
  719     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:3,Hpd>(H,f,k,bc);
 
  723     const bool D = (n-4<=0)||(4>=n)||(n>16);
 
  724     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:4,Hpd>(H,f,k,bc);
 
  728     const bool D = (n-5<=0)||(5>=n)||(n>16);
 
  729     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:5,Hpd>(H,f,k,bc);
 
  733     const bool D = (n-6<=0)||(6>=n)||(n>16);
 
  734     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:6,Hpd>(H,f,k,bc);
 
  738     const bool D = (n-7<=0)||(7>=n)||(n>16);
 
  739     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:7,Hpd>(H,f,k,bc);
 
  743     const bool D = (n-8<=0)||(8>=n)||(n>16);
 
  744     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:8,Hpd>(H,f,k,bc);
 
  748     const bool D = (n-9<=0)||(9>=n)||(n>16);
 
  749     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:9,Hpd>(H,f,k,bc);
 
  753     const bool D = (n-10<=0)||(10>=n)||(n>16);
 
  754     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:10,Hpd>(H,f,k,bc);
 
  758     const bool D = (n-11<=0)||(11>=n)||(n>16);
 
  759     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:11,Hpd>(H,f,k,bc);
 
  763     const bool D = (n-12<=0)||(12>=n)||(n>16);
 
  764     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:12,Hpd>(H,f,k,bc);
 
  768     const bool D = (n-13<=0)||(13>=n)||(n>16);
 
  769     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:13,Hpd>(H,f,k,bc);
 
  773     const bool D = (n-14<=0)||(14>=n)||(n>16);
 
  774     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:14,Hpd>(H,f,k,bc);
 
  778     const bool D = (n-15<=0)||(15>=n)||(n>16);
 
  779     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:15,Hpd>(H,f,k,bc);
 
  783     const bool D = (n-16<=0)||(16>=n)||(n>16);
 
  784     return min_quad_with_fixed<Scalar,D?Eigen::Dynamic:n,D?Eigen::Dynamic:16,Hpd>(H,f,k,bc);
 
  787      return min_quad_with_fixed<Scalar,Eigen::Dynamic,Eigen::Dynamic,Hpd>(H,f,k,bc);
 
 
  793  const Eigen::Matrix<Scalar,n,n> & H,
 
  794  const Eigen::Matrix<Scalar,n,1> & f,
 
  795  const Eigen::Array<bool,n,1> & k,
 
  796  const Eigen::Matrix<Scalar,n,1> & bc)
 
  799  static_assert(kcount==Eigen::Dynamic || kcount>0                  ,
"");
 
  800  static_assert(kcount==Eigen::Dynamic || kcount<n                  ,
"");
 
  801  const int ucount = n==Eigen::Dynamic ? Eigen::Dynamic : n-kcount;
 
  802  static_assert(kcount==Eigen::Dynamic || ucount+kcount == n        ,
"");
 
  803  static_assert((n==Eigen::Dynamic) == (ucount==Eigen::Dynamic),
"");
 
  804  static_assert((kcount==Eigen::Dynamic) == (ucount==Eigen::Dynamic),
"");
 
  805  assert((n==Eigen::Dynamic) || n == H.rows());
 
  806  assert((kcount==Eigen::Dynamic) || kcount == k.count());
 
  807  typedef Eigen::Matrix<Scalar,ucount,ucount> MatrixSuu;
 
  808  typedef Eigen::Matrix<Scalar,ucount,kcount> MatrixSuk;
 
  809  typedef Eigen::Matrix<Scalar,n,1>      VectorSn;
 
  810  typedef Eigen::Matrix<Scalar,ucount,1> VectorSu;
 
  811  typedef Eigen::Matrix<Scalar,kcount,1> VectorSk;
 
  812  const auto dyn_n = n==Eigen::Dynamic ? H.rows() : n;
 
  813  const auto dyn_kcount = kcount==Eigen::Dynamic ? k.count() : kcount;
 
  814  const auto dyn_ucount = ucount==Eigen::Dynamic ? dyn_n- dyn_kcount : ucount;
 
  817  MatrixSuu Huu(dyn_ucount,dyn_ucount);
 
  818  MatrixSuk Huk(dyn_ucount,dyn_kcount);
 
  819  VectorSu mrhs(dyn_ucount);
 
  820  VectorSk  bck(dyn_kcount);
 
  824    for(
int i = 0;i<dyn_n;i++)
 
  835        for(
int j = 0;j<dyn_n;j++)
 
  853    std::conditional<Hpd,
 
  854      Eigen::LLT<MatrixSuu>,
 
  863      Eigen::CompleteOrthogonalDecomposition<MatrixSuu>>::type
 
  865  VectorSu xu = Solver(Huu).solve(-mrhs);
 
  870    for(
int i = 0;i<dyn_n;i++)