solver
RtQPSolverInterface.hpp
Go to the documentation of this file.
1 
10 #pragma once
11 
12 #include <vector>
13 #include <iostream>
15 
16 namespace rt_solver {
17 
18  template <int max_dim_qp, int max_num_eq, int max_num_ineq>
20  {
21  protected:
22  typename RtVector<max_dim_qp>::d g_;
23  typename RtVector<max_dim_qp>::d sol_;
24  typename RtVector<max_num_eq>::d eq_vec_;
25  typename RtVector<max_num_ineq>::d ineq_vec_;
27  typename RtMatrix<max_num_eq, max_dim_qp>::d Eq_mat_;
28  typename RtMatrix<max_num_ineq, max_dim_qp>::d Ineq_mat_;
29 
30  public:
31  enum QPProperties {
32  //ePP_ObjectivePD = 1 << 3,
33  //ePP_ObjectivePD = 1 << 1,
34  //ePP_MightZeroIneqs = 1 << 2
35  ePP_MightZeroIneqs = 1 << 0
36  };
37 
38  int qp_properties_;
39 
40  // getter and setter methods
41  typename RtVector<max_dim_qp>::d& solution() { return sol_; }
42  const typename RtVector<max_dim_qp>::d& solution() const { return sol_; }
43 
44  typename RtMatrix<max_dim_qp, max_dim_qp>::d& objectiveQuadPart() { return H_; }
45  const typename RtMatrix<max_dim_qp, max_dim_qp>::d& objectiveQuadPart() const { return H_; }
46 
47  typename RtVector<max_dim_qp>::d& objectiveLinPart() { return g_; }
48  const typename RtVector<max_dim_qp>::d& objectiveLinPart() const { return g_; }
49 
50  typename RtMatrix<max_num_eq, max_dim_qp>::d& eqConstraintsMat() { return Eq_mat_; }
51  const typename RtMatrix<max_num_eq, max_dim_qp>::d& eqConstraintsMat() const { return Eq_mat_; }
52 
53  typename RtVector<max_num_eq>::d& eqConstraintsVec() { return eq_vec_; }
54  const typename RtVector<max_num_eq>::d& eqConstraintsVec() const { return eq_vec_; }
55 
56  typename RtMatrix<max_num_ineq, max_dim_qp>::d& ineqConstraintsMat() { return Ineq_mat_; }
57  const typename RtMatrix<max_num_ineq, max_dim_qp>::d& ineqConstraintsMat() const { return Ineq_mat_; }
58 
59  typename RtVector<max_num_ineq>::d& ineqConstraintsVec() { return ineq_vec_; }
60  const typename RtVector<max_num_ineq>::d& ineqConstraintsVec() const { return ineq_vec_; }
61 
62  int numVariables() const { return H_.rows(); }
63  int numEqConstr() const { return Eq_mat_.rows(); }
64  int numIneqConstr() const { return Ineq_mat_.rows(); }
65 
66  // constructor and destructor
67  RtQPSolverInterface() { this->reset(); }
68  virtual ~RtQPSolverInterface(){}
69 
70  // functions to be implemented to use the interface
71  bool virtual optimize() =0;
72  bool virtual isOptimized() const =0;
73 
74  // Append equality constraints mat*x + vec = 0
75  template <typename Derived, typename OtherDerived>
76  inline void appendEqualities(const Eigen::MatrixBase<Derived>& mat, const Eigen::MatrixBase<OtherDerived>& vec)
77  {
78  RtAffineUtils::append(Eq_mat_, eq_vec_, mat, vec);
79  }
80 
81  template <typename Derived>
82  inline void appendEqualities(const Eigen::MatrixBase<Derived>& mat)
83  {
84  RtAffineUtils::append(Eq_mat_, eq_vec_, mat);
85  }
86 
87  // Append inequality constraints mat*x + vec <= 0
88  template <typename Derived, typename OtherDerived>
89  inline void appendInequalities(const Eigen::MatrixBase<Derived>& mat, const Eigen::MatrixBase<OtherDerived>& vec)
90  {
91  RtAffineUtils::append(Ineq_mat_, ineq_vec_, mat, vec);
92  }
93 
94  template <typename Derived>
95  inline void appendInequalities(const Eigen::MatrixBase<Derived>& mat)
96  {
97  RtAffineUtils::append(Ineq_mat_, ineq_vec_, mat);
98  }
99 
100  /*
101  * Helper functions for the interface
102  */
103 
104  // reset solver
105  inline virtual void reset()
106  {
107  qp_properties_ = 0;
108  g_ = Eigen::Matrix<double, max_dim_qp, 1>::Zero();
109  sol_ = Eigen::Matrix<double, max_dim_qp, 1>::Zero();
110  H_ = Eigen::Matrix<double, max_dim_qp, max_dim_qp>::Zero();
111 
112  RtVectorUtils::setZero(eq_vec_, 0);
113  RtVectorUtils::setZero(ineq_vec_, 0);
114  RtMatrixUtils::setZero(Eq_mat_, 0, max_dim_qp);
115  RtMatrixUtils::setZero(Ineq_mat_, 0, max_dim_qp);
116  }
117 
118  inline virtual void reset(int dim_qp, int num_eq, int num_ineq)
119  {
120  qp_properties_ = 0;
121  RtVectorUtils::setZero(g_, dim_qp);
122  RtVectorUtils::setZero(eq_vec_, 0);
123  RtVectorUtils::setZero(ineq_vec_, 0);
124  RtVectorUtils::setZero(sol_, dim_qp);
125  RtMatrixUtils::setZero(H_, dim_qp, dim_qp);
126  RtMatrixUtils::setZero(Eq_mat_, 0, dim_qp);
127  RtMatrixUtils::setZero(Ineq_mat_, 0, dim_qp);
128  }
129 
130  // compute optimality condition
131  double computeOptimalityCondition() const
132  {
133  typename RtMatrix<max_dim_qp, max_num_eq+max_num_ineq>::d constr_jac_transp;
134  constr_jac_transp.resize(numVariables(), numEqConstr()+numIneqConstr());
135  constr_jac_transp.leftCols(numEqConstr()) = eqConstraintsMat().transpose();
136 
137  double eq_vio_sqr = 0;
138  if (numEqConstr() != 0) { eq_vio_sqr = (eqConstraintsMat()*solution() + eqConstraintsVec()).squaredNorm(); }
139 
140  int to_col=numEqConstr();
141  double ineq_vio_sqr = 0;
142  for (int r=0; r<numIneqConstr(); r++) {
143  const double ineq_val = ineqConstraintsMat().row(r).dot(solution()) + ineqConstraintsVec()[r];
144  const double vio = std::max(0., ineq_val);
145  ineq_vio_sqr += vio*vio;
146  if (ineq_val > -1e-8) {
147  constr_jac_transp.col(to_col) = ineqConstraintsMat().row(r).transpose();
148  ++to_col;
149  }
150  }
151 
152  constr_jac_transp.conservativeResize(constr_jac_transp.rows(), to_col);
153  typename RtVector<max_dim_qp>::d obj_grad;
154  obj_grad.resize(numVariables());
155  obj_grad = objectiveQuadPart()*solution() + objectiveLinPart();
156  double grad_sqr_norm;
157  if (constr_jac_transp.cols() != 0) {
158  typename RtVector<max_num_eq+max_num_ineq>::d lagr;
159  lagr.resize(constr_jac_transp.cols());
160  lagr = constr_jac_transp.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(obj_grad);
161  grad_sqr_norm = (constr_jac_transp*lagr-obj_grad).squaredNorm();
162  } else {
163  grad_sqr_norm = obj_grad.squaredNorm();
164  }
165  return std::sqrt(grad_sqr_norm + ineq_vio_sqr + eq_vio_sqr);
166  }
167 
168  // check solution
169  virtual bool checkSolution(bool print = true, double eq_threashold = 0.001, double ineq_threashold = 0.001)
170  {
171  const double eq_norm = (eqConstraintsMat() * solution() + eqConstraintsVec()).norm();
172  typename RtVector<max_num_ineq>::d ineq_dist = ineqConstraintsMat() * solution() + ineqConstraintsVec();
173  for (int i=0; i<numIneqConstr(); ++i)
174  ineq_dist[i] *= ineq_dist[i] <= 0.0 ? 0.0 : 1.0;
175  const double ineq_norm = (ineq_dist).norm();
176  const double lagr_grad_norm = -1;//compute_optimality_condition();
177  bool is_sol_valid = eq_norm <= eq_threashold && ineq_norm <= ineq_threashold;
178 
179  if (print || (!is_sol_valid && isOptimized()))
180  {
181  std::cout << "qp check (num vars, num equalities, num inequalities, objective value): " <<
182  numVariables() << " " << numEqConstr() << " " << numIneqConstr() << " " <<
183  solution().transpose() * objectiveQuadPart() * solution() + 2*objectiveLinPart().transpose()*solution()<< std::endl;
184  std::cout << " lagrangian gradient norm: " << lagr_grad_norm << std::endl;
185  std::cout << " equality squared dist: " << eq_norm << std::endl;
186  std::cout << " inequality squared dist: " << ineq_norm << std::endl;
187  std::cout << " isOptimized(): " << ( isOptimized()? "yes" : "no" ) << std::endl;
188  }
189  return is_sol_valid;
190  }
191 
192  // evaluate the problem condition number
193  void printProblemCondition(std::ostream& stream)
194  {
195  stream << "QP:" << std::endl;
196  stream << " num Variables: " << numVariables() << std::endl;
197  stream << " num Equalities: " << numEqConstr() << std::endl;
198  stream << " num Inequalities: " << numIneqConstr() << std::endl;
199 
200  Eigen::JacobiSVD<typename RtMatrix<max_dim_qp, max_dim_qp>::d > Hess_svd;
201  if (objectiveQuadPart().rows() > 0)
202  {
203  Hess_svd.compute(objectiveQuadPart());
204  stream << " Hessian condition: " << Hess_svd.singularValues().maxCoeff()/
205  Hess_svd.singularValues().minCoeff() << " = " << Hess_svd.
206  singularValues().maxCoeff() << " / " << Hess_svd.singularValues().minCoeff() << std::endl;
207  }
208  Eigen::JacobiSVD<typename RtMatrix<max_num_eq, max_dim_qp>::d > EqConstr_svd;
209  if (eqConstraintsMat().rows() > 0)
210  {
211  EqConstr_svd.compute(eqConstraintsMat());
212  stream << " Equality Matrix condition: " << EqConstr_svd.singularValues().maxCoeff()/
213  EqConstr_svd.singularValues().minCoeff() << " = " << EqConstr_svd.
214  singularValues().maxCoeff() << " / " << EqConstr_svd.singularValues().minCoeff() << std::endl;
215  }
216  Eigen::JacobiSVD<typename RtMatrix<max_num_ineq, max_dim_qp>::d > IneqConstr_svd;
217  if (ineqConstraintsMat().rows() > 0)
218  {
219  IneqConstr_svd.compute(ineqConstraintsMat());
220  stream << " Inequality Matrix condition: " << IneqConstr_svd.singularValues().maxCoeff()/
221  IneqConstr_svd.singularValues().minCoeff() << " = " << IneqConstr_svd.
222  singularValues().maxCoeff() << " / " << IneqConstr_svd.singularValues().minCoeff() << std::endl;
223  }
224 
225  if(numVariables() < 10)
226  {
227  stream << " Hessian: " << objectiveQuadPart() << std::endl;
228  stream << " linear part: " << objectiveLinPart().transpose() << std::endl;
229  stream << " Equality Matrix: " << eqConstraintsMat() << std::endl;
230  stream << " Equality Vector: " << eqConstraintsVec().transpose() << std::endl;
231  stream << " Inequality Matrix: " << ineqConstraintsMat() << std::endl;
232  stream << " Inequality Vector: " << ineqConstraintsVec().transpose() << std::endl;
233  }
234  }
235  };
236 
237 }
Definition: RtQPSolverInterface.hpp:19
Definition: RtMatrix.hpp:18
Definition: Var.hpp:14
Definition: RtMatrix.hpp:44