solver-HQP-eiquadprog-fast.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2017 CNRS
3 //
4 // This file is part of tsid
5 // tsid is free software: you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation, either version
8 // 3 of the License, or (at your option) any later version.
9 // tsid is distributed in the hope that it will be
10 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
11 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Lesser Public License for more details. You should have
13 // received a copy of the GNU Lesser General Public License along with
14 // tsid If not, see
15 // <http://www.gnu.org/licenses/>.
16 //
17 
19 #include "tsid/math/utils.hpp"
22 
23 // #define PROFILE_EIQUADPROG_FAST
24 
25 using namespace eiquadprog::solvers;
26 
27 namespace tsid {
28 namespace solvers {
29 
30 using namespace math;
31 SolverHQuadProgFast::SolverHQuadProgFast(const std::string& name)
33  m_hessian_regularization(DEFAULT_HESSIAN_REGULARIZATION) {
34  m_n = 0;
35  m_neq = 0;
36  m_nin = 0;
37 }
38 
39 void SolverHQuadProgFast::sendMsg(const std::string& s) {
40  std::cout << "[SolverHQuadProgFast." << m_name << "] " << s << std::endl;
41 }
42 
43 void SolverHQuadProgFast::resize(unsigned int n, unsigned int neq,
44  unsigned int nin) {
45  const bool resizeVar = n != m_n;
46  const bool resizeEq = (resizeVar || neq != m_neq);
47  const bool resizeIn = (resizeVar || nin != m_nin);
48 
49  if (resizeEq) {
50 #ifndef NDEBUG
51  sendMsg("Resizing equality constraints from " + toString(m_neq) + " to " +
52  toString(neq));
53 #endif
54  m_qpData.CE.resize(neq, n);
55  m_qpData.ce0.resize(neq);
56  }
57  if (resizeIn) {
58 #ifndef NDEBUG
59  sendMsg("Resizing inequality constraints from " + toString(m_nin) + " to " +
60  toString(nin));
61 #endif
62  m_qpData.CI.resize(2 * nin, n);
63  m_qpData.ci0.resize(2 * nin);
64  }
65  if (resizeVar) {
66 #ifndef NDEBUG
67  sendMsg("Resizing Hessian from " + toString(m_n) + " to " + toString(n));
68 #endif
69  m_qpData.H.resize(n, n);
70  m_qpData.g.resize(n);
71  m_output.x.resize(n);
72  }
73 
74  if (resizeVar || resizeIn || resizeEq) {
75  m_solver.reset(n, neq, nin * 2);
76  m_output.resize(n, neq, 2 * nin);
77  }
78 
79  m_n = n;
80  m_neq = neq;
81  m_nin = nin;
82 }
83 
85  const bool hessianRegularization) {
86  if (problemData.size() > 2) {
88  false, "Solver not implemented for more than 2 hierarchical levels.");
89  }
90 
91  // Compute the constraint matrix sizes
92  unsigned int neq = 0, nin = 0;
93  const ConstraintLevel& cl0 = problemData[0];
94  if (cl0.size() > 0) {
95  const unsigned int n = cl0[0].second->cols();
96  for (ConstraintLevel::const_iterator it = cl0.begin(); it != cl0.end();
97  it++) {
98  auto constr = it->second;
99  assert(n == constr->cols());
100  if (constr->isEquality())
101  neq += constr->rows();
102  else
103  nin += constr->rows();
104  }
105  // If necessary, resize the constraint matrices
106  resize(n, neq, nin);
107 
108  unsigned int i_eq = 0, i_in = 0;
109  for (ConstraintLevel::const_iterator it = cl0.begin(); it != cl0.end();
110  it++) {
111  auto constr = it->second;
112  if (constr->isEquality()) {
113  m_qpData.CE.middleRows(i_eq, constr->rows()) = constr->matrix();
114  m_qpData.ce0.segment(i_eq, constr->rows()) = -constr->vector();
115  i_eq += constr->rows();
116 
117  } else if (constr->isInequality()) {
118  m_qpData.CI.middleRows(i_in, constr->rows()) = constr->matrix();
119  m_qpData.ci0.segment(i_in, constr->rows()) = -constr->lowerBound();
120  i_in += constr->rows();
121  m_qpData.CI.middleRows(i_in, constr->rows()) = -constr->matrix();
122  m_qpData.ci0.segment(i_in, constr->rows()) = constr->upperBound();
123  i_in += constr->rows();
124  } else if (constr->isBound()) {
125  m_qpData.CI.middleRows(i_in, constr->rows()).setIdentity();
126  m_qpData.ci0.segment(i_in, constr->rows()) = -constr->lowerBound();
127  i_in += constr->rows();
128  m_qpData.CI.middleRows(i_in, constr->rows()) =
129  -Matrix::Identity(m_n, m_n);
130  m_qpData.ci0.segment(i_in, constr->rows()) = constr->upperBound();
131  i_in += constr->rows();
132  }
133  }
134  } else
135  resize(m_n, neq, nin);
136 
138 
139  // Compute the cost
140  if (problemData.size() > 1) {
141  const ConstraintLevel& cl1 = problemData[1];
142  m_qpData.H.setZero();
143  m_qpData.g.setZero();
144 
145  for (ConstraintLevel::const_iterator it = cl1.begin(); it != cl1.end();
146  it++) {
147  const double& w = it->first;
148  auto constr = it->second;
149  if (!constr->isEquality())
151  false, "Inequalities in the cost function are not implemented yet");
152 
154  m_qpData.H.noalias() +=
155  w * constr->matrix().transpose() * constr->matrix();
157 
158  m_qpData.g.noalias() -=
159  w * constr->matrix().transpose() * constr->vector();
160  }
161 
162  if (hessianRegularization) {
164  m_qpData.H.diagonal().array() += m_hessian_regularization;
165  }
166  }
167 }
168 
169 const HQPOutput& SolverHQuadProgFast::solve(const HQPData& problemData) {
171 
172  START_PROFILER_EIQUADPROG_FAST(PROFILE_EIQUADPROG_SOLUTION);
173  // min 0.5 * x G x + g0 x
174  // s.t.
175  // CE x + ce0 = 0
176  // CI x + ci0 >= 0
181 
182  STOP_PROFILER_EIQUADPROG_FAST(PROFILE_EIQUADPROG_SOLUTION);
183 
184  if (status == EIQUADPROG_FAST_OPTIMAL) {
188  // m_output.activeSet =
189  // m_solver.getActiveSet().tail(2*m_nin).head(m_solver.getActiveSetSize()-m_neq);
192 #ifndef NDEBUG
193  const Vector& x = m_output.x;
194 
195  const ConstraintLevel& cl0 = problemData[0];
196  if (cl0.size() > 0) {
197  for (ConstraintLevel::const_iterator it = cl0.begin(); it != cl0.end();
198  it++) {
199  auto constr = it->second;
200  if (constr->checkConstraint(x) == false) {
201  // m_output.status = HQP_STATUS_ERROR;
202  if (constr->isEquality()) {
203  sendMsg("Equality " + constr->name() + " violated: " +
204  toString((constr->matrix() * x - constr->vector()).norm()));
205  } else if (constr->isInequality()) {
206  sendMsg(
207  "Inequality " + constr->name() + " violated: " +
208  toString(
209  (constr->matrix() * x - constr->lowerBound()).minCoeff()) +
210  "\n" +
211  toString(
212  (constr->upperBound() - constr->matrix() * x).minCoeff()));
213  } else if (constr->isBound()) {
214  sendMsg("Bound " + constr->name() + " violated: " +
215  toString((x - constr->lowerBound()).minCoeff()) + "\n" +
216  toString((constr->upperBound() - x).minCoeff()));
217  }
218  }
219  }
220  }
221 #endif
222  } else if (status == EIQUADPROG_FAST_UNBOUNDED)
224  else if (status == EIQUADPROG_FAST_MAX_ITER_REACHED)
226  else if (status == EIQUADPROG_FAST_REDUNDANT_EQUALITIES)
227  m_output.status = HQP_STATUS_ERROR;
228 
229  return m_output;
230 }
231 
233  return m_solver.getObjValue();
234 }
235 
236 bool SolverHQuadProgFast::setMaximumIterations(unsigned int maxIter) {
238  return m_solver.setMaxIter(maxIter);
239 }
240 } // namespace solvers
241 } // namespace tsid
tsid::solvers::QPDataQuadProgTpl::ci0
Vector ci0
Definition: solver-qpData.hpp:51
eiquadprog::solvers::EiquadprogFast::getLagrangeMultipliers
const VectorXd & getLagrangeMultipliers() const
DEFAULT_HESSIAN_REGULARIZATION
#define DEFAULT_HESSIAN_REGULARIZATION
Definition: solvers/fwd.hpp:28
eiquadprog::solvers::EiquadprogFast::setMaxIter
bool setMaxIter(int maxIter)
tsid::solvers::QPDataBaseTpl::g
Vector g
Definition: solver-qpData.hpp:30
solver-HQP-eiquadprog-fast.hpp
EIGEN_MALLOC_ALLOWED
#define EIGEN_MALLOC_ALLOWED
Definition: math/fwd.hpp:27
tsid::solvers::HQPOutput::activeSet
VectorXi activeSet
Lagrange multipliers.
Definition: solver-HQP-output.hpp:39
tsid::solvers::SolverHQuadProgFast::m_solver
eiquadprog::solvers::EiquadprogFast m_solver
Definition: solver-HQP-eiquadprog-fast.hpp:65
tsid::solvers::HQPOutput::resize
void resize(unsigned int nVars, unsigned int nEqCon, unsigned int nInCon)
Definition: solver-HQP-output.hpp:48
tsid::solvers::SolverHQPBase::m_output
HQPOutput m_output
Definition: solver-HQP-base.hpp:84
eiquadprog::solvers::EiquadprogFast::solve_quadprog
EiquadprogFast_status solve_quadprog(const MatrixXd &Hess, const VectorXd &g0, const MatrixXd &CE, const VectorXd &ce0, const MatrixXd &CI, const VectorXd &ci0, VectorXd &x)
tsid::solvers::QPDataBaseTpl::H
Matrix H
Definition: solver-qpData.hpp:29
PINOCCHIO_CHECK_INPUT_ARGUMENT
#define PINOCCHIO_CHECK_INPUT_ARGUMENT(...)
EIQUADPROG_FAST_REDUNDANT_EQUALITIES
EIQUADPROG_FAST_REDUNDANT_EQUALITIES
EIQUADPROG_FAST_UNBOUNDED
EIQUADPROG_FAST_UNBOUNDED
test_Solvers.neq
int neq
Definition: test_Solvers.py:13
tsid::solvers::SolverHQuadProgFast::m_qpData
QPDataQuadProgTpl< double > m_qpData
number of variables
Definition: solver-HQP-eiquadprog-fast.hpp:85
tsid::solvers::SolverHQuadProgFast::resize
void resize(unsigned int n, unsigned int neq, unsigned int nin) override
Definition: solver-HQP-eiquadprog-fast.cpp:43
tsid::solvers::ConstraintLevel
pinocchio::container::aligned_vector< aligned_pair< double, std::shared_ptr< math::ConstraintBase > > > ConstraintLevel
Definition: solvers/fwd.hpp:95
utils.hpp
tsid::solvers::SolverHQPBase::m_name
std::string m_name
Definition: solver-HQP-base.hpp:80
tsid::solvers::HQPOutput::lambda
Vector lambda
solution
Definition: solver-HQP-output.hpp:38
tsid::solvers::QPDataBaseTpl::CE
Matrix CE
Definition: solver-qpData.hpp:31
tsid::solvers::SolverHQuadProgFast::Vector
math::Vector Vector
Definition: solver-HQP-eiquadprog-fast.hpp:35
eiquadprog::solvers::EiquadprogFast::getActiveSet
const VectorXi & getActiveSet() const
tsid::solvers::SolverHQuadProgFast::getObjectiveValue
double getObjectiveValue() override
Definition: solver-HQP-eiquadprog-fast.cpp:232
tsid::solvers::HQPOutput
Definition: solver-HQP-output.hpp:29
STOP_PROFILER_EIQUADPROG_FAST
#define STOP_PROFILER_EIQUADPROG_FAST(x)
tsid::solvers::SolverHQuadProgFast::sendMsg
void sendMsg(const std::string &s)
Definition: solver-HQP-eiquadprog-fast.cpp:39
tsid::solvers::SolverHQPBase
Abstract interface for a Quadratic Program (HQP) solver.
Definition: solver-HQP-base.hpp:34
test_Solvers.nin
int nin
Definition: test_Solvers.py:14
eiquadprog-fast.hpp
tsid::solvers::SolverHQuadProgFast::m_neq
unsigned int m_neq
Definition: solver-HQP-eiquadprog-fast.hpp:81
tsid::solvers::QPDataBaseTpl::ce0
Vector ce0
Definition: solver-qpData.hpp:32
eiquadprog::solvers::EiquadprogFast::getObjValue
double getObjValue() const
setup.name
name
Definition: setup.in.py:179
w
w
EIQUADPROG_FAST_MAX_ITER_REACHED
EIQUADPROG_FAST_MAX_ITER_REACHED
stop-watch.hpp
HQP_STATUS_OPTIMAL
HQP_STATUS_OPTIMAL
Definition: solvers/fwd.hpp:63
it
int it
HQP_STATUS_MAX_ITER_REACHED
HQP_STATUS_MAX_ITER_REACHED
Definition: solvers/fwd.hpp:66
eiquadprog::solvers::EiquadprogFast_status
EiquadprogFast_status
eiquadprog::solvers::EiquadprogFast::getIteratios
int getIteratios() const
tsid::solvers::SolverHQPBase::setMaximumIterations
virtual bool setMaximumIterations(unsigned int maxIter)
Definition: solver-HQP-base.cpp:36
tsid
Definition: bindings/python/constraint/constraint-bound.cpp:21
tsid::solvers::SolverHQuadProgFast::m_n
unsigned int m_n
number of inequality constraints
Definition: solver-HQP-eiquadprog-fast.hpp:83
HQP_STATUS_INFEASIBLE
HQP_STATUS_INFEASIBLE
Definition: solvers/fwd.hpp:64
START_PROFILER_EIQUADPROG_FAST
#define START_PROFILER_EIQUADPROG_FAST(x)
tsid::solvers::HQPOutput::x
Vector x
solver status
Definition: solver-HQP-output.hpp:37
test_Formulation.s
s
Definition: test_Formulation.py:115
test_Solvers.x
x
Definition: test_Solvers.py:67
tsid::solvers::SolverHQuadProgFast::setMaximumIterations
bool setMaximumIterations(unsigned int maxIter) override
Definition: solver-HQP-eiquadprog-fast.cpp:236
tsid::solvers::SolverHQuadProgFast::solve
const HQPOutput & solve(const HQPData &problemData) override
Definition: solver-HQP-eiquadprog-fast.cpp:169
eiquadprog::solvers
eiquadprog::solvers::EiquadprogFast::reset
void reset(size_t dim_qp, size_t num_eq, size_t num_ineq)
tsid::solvers::SolverHQuadProgFast::retrieveQPData
void retrieveQPData(const HQPData &problemData, const bool hessianRegularization=true) override
Definition: solver-HQP-eiquadprog-fast.cpp:84
eiquadprog::solvers::EiquadprogFast::getActiveSetSize
size_t getActiveSetSize() const
tsid::solvers::QPDataQuadProgTpl::CI
Matrix CI
Definition: solver-qpData.hpp:50
tsid::solvers::SolverHQuadProgFast::m_nin
unsigned int m_nin
number of equality constraints
Definition: solver-HQP-eiquadprog-fast.hpp:82
tsid::solvers::HQPData
pinocchio::container::aligned_vector< ConstraintLevel > HQPData
Definition: solvers/fwd.hpp:99
tsid::toString
std::string toString(const T &v)
Definition: math/utils.hpp:39
tsid::solvers::SolverHQuadProgFast::m_hessian_regularization
double m_hessian_regularization
Definition: solver-HQP-eiquadprog-fast.hpp:75
EIQUADPROG_FAST_OPTIMAL
EIQUADPROG_FAST_OPTIMAL
tsid::solvers::HQPOutput::iterations
int iterations
indexes of active inequalities
Definition: solver-HQP-output.hpp:40
n
Vec3f n
tsid::solvers::HQPOutput::status
HQPStatus status
Definition: solver-HQP-output.hpp:36
EIGEN_MALLOC_NOT_ALLOWED
#define EIGEN_MALLOC_NOT_ALLOWED
Definition: math/fwd.hpp:28


tsid
Author(s): Andrea Del Prete, Justin Carpentier
autogenerated on Sat May 3 2025 02:48:16