Directory: | ./ |
---|---|
File: | src/solver-abstract.cpp |
Date: | 2025-03-18 04:20:50 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 46 | 59 | 78.0% |
Branches: | 43 | 110 | 39.1% |
Line | Branch | Exec | Source |
---|---|---|---|
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 | |||
18 | #include "hpp/bezier-com-traj/solver/solver-abstract.hpp" | ||
19 | #ifdef USE_GLPK_SOLVER | ||
20 | #include <glpk.h> | ||
21 | |||
22 | #include <hpp/bezier-com-traj/solver/glpk-wrapper.hpp> | ||
23 | #endif | ||
24 | #include <Eigen/Sparse> | ||
25 | #include <hpp/bezier-com-traj/solver/eiquadprog-fast.hpp> | ||
26 | #include <stdexcept> | ||
27 | |||
28 | namespace solvers { | ||
29 | |||
30 | template <typename Derived> | ||
31 | 30852 | inline bool is_nan(const Eigen::MatrixBase<Derived>& x) { | |
32 |
3/6✓ Branch 2 taken 15426 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15426 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 15426 times.
✗ Branch 9 not taken.
|
30852 | bool isnan = !((x.array() == x.array()).all()); |
33 | 30852 | return isnan; | |
34 | } | ||
35 | |||
36 | typedef Eigen::SparseMatrix<double> SpMat; | ||
37 | typedef Eigen::SparseVector<double> SpVec; | ||
38 | typedef Eigen::SparseVector<int> SpVeci; | ||
39 | |||
40 | namespace { | ||
41 | 2571 | void addConstraintMinBoundQuadProg(solvers::Cref_vectorX minBounds, | |
42 | std::pair<MatrixXd, VectorXd>& data) { | ||
43 |
2/2✓ Branch 1 taken 2553 times.
✓ Branch 2 taken 18 times.
|
2571 | if (minBounds.size() == 0) return; |
44 | 18 | MatrixXd& res = data.first; | |
45 | 18 | VectorXd& resv = data.second; | |
46 |
1/2✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
18 | MatrixXd D(res.rows() + res.cols(), res.cols()); |
47 |
1/2✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
|
18 | VectorXd d(resv.rows() + res.cols()); |
48 |
2/4✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
|
18 | D.block(0, 0, res.rows(), res.cols()) = res; |
49 |
1/2✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
18 | D.block(res.rows(), 0, res.cols(), res.cols()) = |
50 |
3/6✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
|
36 | (-1.) * MatrixXd::Identity(res.cols(), res.cols()); |
51 |
2/4✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
|
18 | d.head(resv.size()) = resv; |
52 |
3/6✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 18 times.
✗ Branch 9 not taken.
|
18 | d.tail(res.cols()) = -minBounds; |
53 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | data.first = D; |
54 |
1/2✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
|
18 | data.second = d; |
55 | 18 | } | |
56 | |||
57 | 2571 | void addConstraintMaxBoundQuadProg(solvers::Cref_vectorX maxBounds, | |
58 | std::pair<MatrixXd, VectorXd>& data) { | ||
59 |
1/2✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
|
2571 | if (maxBounds.size() == 0) return; |
60 | ✗ | MatrixXd& res = data.first; | |
61 | ✗ | VectorXd& resv = data.second; | |
62 | ✗ | MatrixXd D(res.rows() + res.cols() - 3, res.cols()); | |
63 | ✗ | VectorXd d(resv.rows() + res.cols()); | |
64 | ✗ | D.block(0, 0, res.rows(), res.cols()) = res; | |
65 | ✗ | D.block(res.rows(), 0, res.cols(), res.cols()) = | |
66 | ✗ | MatrixXd::Identity(res.cols(), res.cols()); | |
67 | ✗ | d.head(resv.size()) = resv; | |
68 | ✗ | d.tail(res.cols()) = maxBounds; | |
69 | ✗ | data.first = D; | |
70 | ✗ | data.second = d; | |
71 | } | ||
72 | |||
73 | 2571 | std::pair<MatrixXd, VectorXd> addBoundaryConstraintsQuadProg( | |
74 | solvers::Cref_vectorX minBounds, solvers::Cref_vectorX maxBounds, | ||
75 | const MatrixXd& CI, const VectorXd& ci0) { | ||
76 | 2571 | std::pair<MatrixXd, VectorXd> data; | |
77 |
1/2✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
|
2571 | data.first = CI; |
78 |
1/2✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
|
2571 | data.second = ci0; |
79 |
1/2✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
|
2571 | addConstraintMinBoundQuadProg(minBounds, data); |
80 |
1/2✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
|
2571 | addConstraintMaxBoundQuadProg(maxBounds, data); |
81 | 2571 | return data; | |
82 | } | ||
83 | } // namespace | ||
84 | |||
85 | 2571 | ResultData solve(const MatrixXd& A, const VectorXd& b, const MatrixXd& D, | |
86 | const VectorXd& d, const MatrixXd& Hess, const VectorXd& g, | ||
87 | const VectorXd& initGuess, solvers::Cref_vectorX minBounds, | ||
88 | solvers::Cref_vectorX maxBounds, const SolverType solver) { | ||
89 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2571 times.
|
2571 | assert(!(is_nan(A))); |
90 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2571 times.
|
2571 | assert(!(is_nan(b))); |
91 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2571 times.
|
2571 | assert(!(is_nan(D))); |
92 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2571 times.
|
2571 | assert(!(is_nan(d))); |
93 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2571 times.
|
2571 | assert(!(is_nan(initGuess))); |
94 | 2571 | ResultData res; | |
95 |
1/2✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
|
2571 | res.x = initGuess; |
96 |
1/2✓ Branch 0 taken 2571 times.
✗ Branch 1 not taken.
|
2571 | switch (solver) { |
97 | /* | ||
98 | * solves the problem | ||
99 | * min. x' Hess x + 2 g0' x | ||
100 | * s.t. CE x + ce0 = 0 | ||
101 | * CI x + ci0 >= 0 | ||
102 | * Thus CI = -A; ci0 = b | ||
103 | * CI = D; ce0 = -d | ||
104 | */ | ||
105 | 2571 | case SOLVER_QUADPROG: | |
106 | // case SOLVER_QUADPROG_SPARSE: | ||
107 | { | ||
108 |
2/4✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2571 times.
|
2571 | assert(!(is_nan(Hess))); |
109 | std::pair<MatrixXd, VectorXd> CIp = | ||
110 |
1/2✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
|
2571 | addBoundaryConstraintsQuadProg(minBounds, maxBounds, A, b); |
111 |
2/4✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2571 times.
✗ Branch 5 not taken.
|
2571 | VectorXd ce0 = -d; |
112 | tsid::solvers::EiquadprogFast QPsolver = | ||
113 |
1/2✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
|
2571 | tsid::solvers::EiquadprogFast(); |
114 | tsid::solvers::EiquadprogFast_status status; | ||
115 | // if(solver == SOLVER_QUADPROG) | ||
116 |
2/4✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2571 times.
✗ Branch 5 not taken.
|
2571 | status = QPsolver.solve_quadprog(Hess, g, D, ce0, -CIp.first, |
117 |
1/2✓ Branch 1 taken 2571 times.
✗ Branch 2 not taken.
|
2571 | CIp.second, res.x); |
118 | /* else | ||
119 | { | ||
120 | SpMat Hsp = Hess.sparseView(); | ||
121 | status = QPsolver.solve_quadprog_sparse(Hsp,g,D,ce0,CI,b,res.x); | ||
122 | }*/ | ||
123 | 2571 | res.success_ = (status == tsid::solvers::EIQUADPROG_FAST_OPTIMAL); | |
124 |
2/2✓ Branch 0 taken 557 times.
✓ Branch 1 taken 2014 times.
|
2571 | if (res.success_) res.cost_ = QPsolver.getObjValue(); |
125 | 5142 | return res; | |
126 | 2571 | } | |
127 | #ifdef USE_GLPK_SOLVER | ||
128 | case SOLVER_GLPK: { | ||
129 | res.success_ = (solvers::solveglpk(g, D, d, A, b, minBounds, maxBounds, | ||
130 | res.x, res.cost_) == GLP_OPT); | ||
131 | return res; | ||
132 | } | ||
133 | #endif | ||
134 | ✗ | default: | |
135 | ✗ | throw std::runtime_error("Unknown solver type in solver-asbtract"); | |
136 | } | ||
137 | } | ||
138 | |||
139 | } /* namespace solvers */ | ||
140 |