solver-HQP-qpmad.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2022 Inria, University of Oxford
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"
21 
22 #include <limits>
23 
24 using namespace tsid::math;
25 using namespace tsid::solvers;
26 using namespace Eigen;
27 
28 namespace tsid {
29 namespace solvers {
30 
31 SolverHQpmad::SolverHQpmad(const std::string& name)
33  m_hessian_regularization(DEFAULT_HESSIAN_REGULARIZATION) {
34  m_n = 0;
35  m_nc = 0;
36 }
37 
38 void SolverHQpmad::sendMsg(const std::string& s) {
39  std::cout << "[SolverHQpmad." << m_name << "] " << s << std::endl;
40 }
41 
42 void SolverHQpmad::resize(unsigned int n, unsigned int neq, unsigned int nin) {
43  unsigned int nc = neq + nin;
44 
45  const bool resizeVar = n != m_n;
46  const bool resizeEqIn = (resizeVar || nc != m_nc);
47 
48  if (resizeEqIn) {
49 #ifndef NDEBUG
50  sendMsg("Resizing equality-inequality constraints from " + toString(m_nc) +
51  " to " + toString(nc));
52 #endif
53  m_C.resize(nc, n);
54  m_cl.resize(nc);
55  m_cu.resize(nc);
56  }
57  if (resizeVar) {
58 #ifndef NDEBUG
59  sendMsg("Resizing Hessian from " + toString(m_n) + " to " + toString(n));
60 #endif
61  m_H.resize(n, n);
62  m_g.resize(n);
63  m_output.x.resize(n);
64 
65  if (m_has_bounds) {
66  m_lb.resize(n);
67  m_ub.resize(n);
68  }
69  }
70 
71  m_n = n;
72  m_nc = nc;
73 }
74 
75 void SolverHQpmad::retrieveQPData(const HQPData& problemData,
76  const bool /*hessianRegularization*/) {
77  if (problemData.size() > 2) {
79  false, "Solver not implemented for more than 2 hierarchical levels.");
80  }
81 
82  // Compute the constraint matrix sizes
83  m_has_bounds = false;
84  unsigned int nin = 0, neq = 0;
85  const ConstraintLevel& cl0 = problemData[0];
86  if (cl0.size() > 0) {
87  const unsigned int n = cl0[0].second->cols();
88  for (ConstraintLevel::const_iterator it = cl0.begin(); it != cl0.end();
89  it++) {
90  auto constr = it->second;
91  assert(n == constr->cols());
92  if (constr->isEquality())
93  neq += constr->rows();
94  else if (constr->isInequality())
95  nin += constr->rows();
96  else if (constr->isBound())
97  m_has_bounds = true;
98  }
99  // If necessary, resize the constraint matrices
100  resize(n, neq, nin);
101 
102  if (m_has_bounds) {
103  m_lb.setConstant(std::numeric_limits<double>::min());
104  m_ub.setConstant(std::numeric_limits<double>::max());
105  }
106 
107  int i_eq_in = 0;
108  for (ConstraintLevel::const_iterator it = cl0.begin(); it != cl0.end();
109  it++) {
110  auto constr = it->second;
111  if (constr->isEquality()) {
112  m_C.middleRows(i_eq_in, constr->rows()) = constr->matrix();
113  m_cl.segment(i_eq_in, constr->rows()) = constr->vector();
114  m_cu.segment(i_eq_in, constr->rows()) = constr->vector();
115  i_eq_in += constr->rows();
116  } else if (constr->isInequality()) {
117  m_C.middleRows(i_eq_in, constr->rows()) = constr->matrix();
118  m_cl.segment(i_eq_in, constr->rows()) = constr->lowerBound();
119  m_cu.segment(i_eq_in, constr->rows()) = constr->upperBound();
120  i_eq_in += constr->rows();
121  } else if (constr->isBound()) {
122  // not considering masks
123  m_lb = m_lb.cwiseMax(constr->lowerBound());
124  m_ub = m_ub.cwiseMin(constr->upperBound());
125  }
126  }
127  } else
128  resize(m_n, neq, nin);
129 
130  if (problemData.size() > 1) {
131  const ConstraintLevel& cl1 = problemData[1];
132  m_H.setZero();
133  m_g.setZero();
134  for (ConstraintLevel::const_iterator it = cl1.begin(); it != cl1.end();
135  it++) {
136  const double& w = it->first;
137  auto constr = it->second;
138  if (!constr->isEquality())
140  false, "Inequalities in the cost function are not implemented yet");
141 
142  m_H.noalias() += w * constr->matrix().transpose() * constr->matrix();
143  m_g.noalias() -= w * (constr->matrix().transpose() * constr->vector());
144  }
145  m_H.diagonal().array() += m_hessian_regularization;
146  }
147 }
148 
149 const HQPOutput& SolverHQpmad::solve(const HQPData& problemData) {
150  SolverHQpmad::retrieveQPData(problemData);
151 
152  // min 0.5 * x H x + g x
153  // s.t.
154  // cl <= C^T x <= cu
155  // lb <= x <= ub
156 
157  qpmad::Solver::ReturnStatus solve_status;
158 
159  if (m_has_bounds)
160  solve_status = m_solver.solve(m_output.x, m_H, m_g, m_lb, m_ub, m_C, m_cl,
161  m_cu, m_settings);
162  else
163  solve_status =
164  m_solver.solve(m_output.x, m_H, m_g, Eigen::VectorXd(),
165  Eigen::VectorXd(), m_C, m_cl, m_cu, m_settings);
166 
167  if (solve_status != qpmad::Solver::OK)
169  else {
171 
172 #ifndef NDEBUG
173  const Vector& x = m_output.x;
174 
175  const ConstraintLevel& cl0 = problemData[0];
176  if (cl0.size() > 0) {
177  for (ConstraintLevel::const_iterator it = cl0.begin(); it != cl0.end();
178  it++) {
179  auto constr = it->second;
180  if (constr->checkConstraint(x) == false) {
181  if (constr->isEquality()) {
182  sendMsg("Equality " + constr->name() + " violated: " +
183  toString((constr->matrix() * x - constr->vector()).norm()));
184  } else if (constr->isInequality()) {
185  sendMsg(
186  "Inequality " + constr->name() + " violated: " +
187  toString(
188  (constr->matrix() * x - constr->lowerBound()).minCoeff()) +
189  "\n" +
190  toString(
191  (constr->upperBound() - constr->matrix() * x).minCoeff()));
192  } else if (constr->isBound()) {
193  sendMsg("Bound " + constr->name() + " violated: " +
194  toString((x - constr->lowerBound()).minCoeff()) + "\n" +
195  toString((constr->upperBound() - x).minCoeff()));
196  }
197  }
198  }
199  }
200 #endif
201  }
202 
203  return m_output;
204 }
205 
207  // objective values is not stored by qpmad
208  return std::numeric_limits<double>::infinity();
209 }
210 
211 } // namespace solvers
212 } // namespace tsid
DEFAULT_HESSIAN_REGULARIZATION
#define DEFAULT_HESSIAN_REGULARIZATION
Definition: solvers/fwd.hpp:28
tsid::solvers::SolverHQpmad::sendMsg
void sendMsg(const std::string &s)
Definition: solver-HQP-qpmad.cpp:38
Eigen
tsid::solvers::SolverHQpmad::solve
const HQPOutput & solve(const HQPData &problemData) override
Definition: solver-HQP-qpmad.cpp:149
tsid::solvers::SolverHQPBase::m_output
HQPOutput m_output
Definition: solver-HQP-base.hpp:84
tsid::solvers::SolverHQpmad::m_cu
Vector m_cu
Definition: solver-HQP-qpmad.hpp:73
PINOCCHIO_CHECK_INPUT_ARGUMENT
#define PINOCCHIO_CHECK_INPUT_ARGUMENT(...)
tsid::solvers::SolverHQpmad::getObjectiveValue
double getObjectiveValue() override
Definition: solver-HQP-qpmad.cpp:206
test_Solvers.neq
int neq
Definition: test_Solvers.py:13
tsid::solvers::SolverHQpmad::m_hessian_regularization
double m_hessian_regularization
Definition: solver-HQP-qpmad.hpp:75
tsid::solvers::SolverHQpmad::m_has_bounds
bool m_has_bounds
Definition: solver-HQP-qpmad.hpp:65
tsid::solvers::SolverHQpmad::m_C
Matrix m_C
Definition: solver-HQP-qpmad.hpp:71
tsid::solvers::SolverHQpmad::m_ub
Vector m_ub
Definition: solver-HQP-qpmad.hpp:70
tsid::solvers::SolverHQpmad::m_H
Matrix m_H
Definition: solver-HQP-qpmad.hpp:67
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::SolverHQpmad::m_settings
Settings m_settings
Definition: solver-HQP-qpmad.hpp:63
tsid::solvers::SolverHQPBase::m_name
std::string m_name
Definition: solver-HQP-base.hpp:80
tsid::solvers::SolverHQpmad::resize
void resize(unsigned int n, unsigned int neq, unsigned int nin) override
Definition: solver-HQP-qpmad.cpp:42
tsid::solvers::SolverHQpmad::m_cl
Vector m_cl
Definition: solver-HQP-qpmad.hpp:72
tsid::math
Definition: constraint-base.hpp:26
tsid::solvers::SolverHQpmad::m_g
Vector m_g
Definition: solver-HQP-qpmad.hpp:68
tsid::solvers::HQPOutput
Definition: solver-HQP-output.hpp:29
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
tsid::solvers::SolverHQpmad::m_lb
Vector m_lb
Definition: solver-HQP-qpmad.hpp:69
tsid::solvers::SolverHQpmad::m_nc
unsigned int m_nc
Definition: solver-HQP-qpmad.hpp:77
setup.name
name
Definition: setup.in.py:179
w
w
stop-watch.hpp
HQP_STATUS_OPTIMAL
HQP_STATUS_OPTIMAL
Definition: solvers/fwd.hpp:63
it
int it
tsid::solvers::SolverHQpmad::m_n
unsigned int m_n
number of equality-inequality constraints
Definition: solver-HQP-qpmad.hpp:78
tsid
Definition: bindings/python/constraint/constraint-bound.cpp:21
tsid::solvers
Definition: solvers/fwd.hpp:31
HQP_STATUS_INFEASIBLE
HQP_STATUS_INFEASIBLE
Definition: solvers/fwd.hpp:64
tsid::solvers::HQPOutput::x
Vector x
solver status
Definition: solver-HQP-output.hpp:37
test_Formulation.s
s
Definition: test_Formulation.py:115
tsid::solvers::SolverHQpmad::retrieveQPData
void retrieveQPData(const HQPData &problemData, const bool hessianRegularization=true) override
Definition: solver-HQP-qpmad.cpp:75
tsid::solvers::SolverHQpmad::m_solver
qpmad::Solver m_solver
Definition: solver-HQP-qpmad.hpp:62
test_Solvers.x
x
Definition: test_Solvers.py:67
solver-HQP-qpmad.hpp
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::SolverHQpmad::Vector
math::Vector Vector
Definition: solver-HQP-qpmad.hpp:35
n
Vec3f n
tsid::solvers::HQPOutput::status
HQPStatus status
Definition: solver-HQP-output.hpp:36


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