quadprog.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include "quadprog.h"
  2. #include "min_quad_with_fixed.h"
  3. #include <igl/matlab_format.h>
  4. #include <iostream>
  5. template <typename Scalar, int n, int m>
  6. IGL_INLINE Eigen::Matrix<Scalar,n,1> igl::quadprog(
  7. const Eigen::Matrix<Scalar,n,n> & H,
  8. const Eigen::Matrix<Scalar,n,1> & f,
  9. const Eigen::Matrix<Scalar,m,n> & A,
  10. const Eigen::Matrix<Scalar,m,1> & b,
  11. const Eigen::Matrix<Scalar,n,1> & lb,
  12. const Eigen::Matrix<Scalar,n,1> & ub)
  13. {
  14. typedef Eigen::Matrix<Scalar,n,1> VectorSn;
  15. typedef Eigen::Array<bool,n,1> Arraybn;
  16. assert( (lb.array() < ub.array() ).all() );
  17. const int dyn_n = n == Eigen::Dynamic ? H.rows() : n;
  18. VectorSn x(dyn_n);
  19. VectorSn bc = VectorSn::Constant(dyn_n,1,-1e26);
  20. Arraybn k = Arraybn::Constant(dyn_n,1,false);
  21. Eigen::Index iter;
  22. // n³ is probably way too conservative.
  23. for(iter = 0;iter<dyn_n*dyn_n*dyn_n;iter++)
  24. {
  25. // For dual contouring 99% of the time the active set is empty.
  26. // Optimize for this common case.
  27. x = min_quad_with_fixed(H,f,k,bc,A,b);
  28. //std::cout<<igl::matlab_format(x,"x")<<std::endl;
  29. // constraint violations
  30. VectorSn vl = lb-x;
  31. VectorSn vu = x-ub;
  32. // try to add/remove constraints
  33. Eigen::Index best_add = -1; Scalar worst_offense = 0;
  34. bool add_lower;
  35. Eigen::Index best_remove = -1; Scalar worst_lambda = 0;
  36. for(Eigen::Index i = 0;i<dyn_n;i++)
  37. {
  38. if(vl(i)>worst_offense)
  39. {
  40. best_add = i;
  41. add_lower = true;
  42. worst_offense = vl(i);
  43. }
  44. if(vu(i)>worst_offense)
  45. {
  46. best_add = i;
  47. add_lower = false;
  48. worst_offense = vu(i);
  49. }
  50. // bias toward adding constraints
  51. if(best_add<0 && k(i))
  52. {
  53. const Scalar sign = bc(i)==ub(i)?1:-1;
  54. const Scalar lambda_i = sign * (H.row(i)*x+f(i));
  55. //printf(" considering k(%d) (λ = %g)\n",i,lambda_i);
  56. if(lambda_i > worst_lambda)
  57. {
  58. //printf(" removing k(%d) (λ = %g)\n",i,lambda_i);
  59. best_remove = i;
  60. worst_lambda = lambda_i;
  61. }
  62. }
  63. }
  64. // bias toward adding constraints
  65. if(best_add >= 0)
  66. {
  67. const auto i = best_add;
  68. assert(!k(i));
  69. //add_lower ? printf(" adding lb(%d)\n",i) : printf(" adding lb(%d)\n",i);
  70. bc(i) = add_lower ? lb(i) : ub(i);
  71. k(i) = true;
  72. }else if(best_remove >= 0)
  73. {
  74. const auto i = best_remove;
  75. assert(k(i));
  76. //printf(" removing k(%d) (λ = %g)\n",i,worst_lambda);
  77. k(i) = false;
  78. }else /*if(best_add < 0 && best_remove < 0)*/
  79. {
  80. std::cout<<igl::matlab_format(x,"x")<<std::endl;
  81. return x;
  82. }
  83. }
  84. // Should never happen.
  85. assert(false && "quadprog failed after too many iterations");
  86. //std::cout<<igl::eigen_format(H,"H")<<std::endl;
  87. //std::cout<<igl::eigen_format(f,"f")<<std::endl;
  88. //std::cout<<igl::eigen_format(lb,"lb")<<std::endl;
  89. //std::cout<<igl::eigen_format(ub,"ub")<<std::endl;
  90. return VectorSn::Zero(dyn_n);
  91. }
  92. template <typename Scalar, int n>
  93. IGL_INLINE Eigen::Matrix<Scalar,n,1> igl::quadprog(
  94. const Eigen::Matrix<Scalar,n,n> & H,
  95. const Eigen::Matrix<Scalar,n,1> & f,
  96. const Eigen::Matrix<Scalar,n,1> & lb,
  97. const Eigen::Matrix<Scalar,n,1> & ub)
  98. {
  99. const int m = n == Eigen::Dynamic ? Eigen::Dynamic : 0;
  100. return quadprog(
  101. H,f,
  102. Eigen::Matrix<Scalar,m,n>(0,H.cols()),
  103. Eigen::Matrix<Scalar,m,1>(0,1),
  104. lb,ub);
  105. }
  106. #ifdef IGL_STATIC_LIBRARY
  107. // Explicit template instantiation
  108. template Eigen::Matrix<double, 2, 1, ((Eigen::StorageOptions)0) | ((((2) == (1)) && ((1) != (1))) ? ((Eigen::StorageOptions)1) : ((((1) == (1)) && ((2) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 2, 1> igl::quadprog<double, 2>(Eigen::Matrix<double, 2, 2, ((Eigen::StorageOptions)0) | ((((2) == (1)) && ((2) != (1))) ? ((Eigen::StorageOptions)1) : ((((2) == (1)) && ((2) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 2, 2> const&, Eigen::Matrix<double, 2, 1, ((Eigen::StorageOptions)0) | ((((2) == (1)) && ((1) != (1))) ? ((Eigen::StorageOptions)1) : ((((1) == (1)) && ((2) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 2, 1> const&, Eigen::Matrix<double, 2, 1, ((Eigen::StorageOptions)0) | ((((2) == (1)) && ((1) != (1))) ? ((Eigen::StorageOptions)1) : ((((1) == (1)) && ((2) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 2, 1> const&, Eigen::Matrix<double, 2, 1, ((Eigen::StorageOptions)0) | ((((2) == (1)) && ((1) != (1))) ? ((Eigen::StorageOptions)1) : ((((1) == (1)) && ((2) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 2, 1> const&);
  109. template Eigen::Matrix<double, 3, 1, ((Eigen::StorageOptions)0) | ((((3) == (1)) && ((1) != (1))) ? ((Eigen::StorageOptions)1) : ((((1) == (1)) && ((3) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 3, 1> igl::quadprog<double, 3>(Eigen::Matrix<double, 3, 3, ((Eigen::StorageOptions)0) | ((((3) == (1)) && ((3) != (1))) ? ((Eigen::StorageOptions)1) : ((((3) == (1)) && ((3) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 3, 3> const&, Eigen::Matrix<double, 3, 1, ((Eigen::StorageOptions)0) | ((((3) == (1)) && ((1) != (1))) ? ((Eigen::StorageOptions)1) : ((((1) == (1)) && ((3) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 3, 1> const&, Eigen::Matrix<double, 3, 1, ((Eigen::StorageOptions)0) | ((((3) == (1)) && ((1) != (1))) ? ((Eigen::StorageOptions)1) : ((((1) == (1)) && ((3) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 3, 1> const&, Eigen::Matrix<double, 3, 1, ((Eigen::StorageOptions)0) | ((((3) == (1)) && ((1) != (1))) ? ((Eigen::StorageOptions)1) : ((((1) == (1)) && ((3) != (1))) ? ((Eigen::StorageOptions)0) : ((Eigen::StorageOptions)0))), 3, 1> const&);
  110. #endif