| 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 |
4/8✓ Branch 1 taken 15426 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15426 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 15426 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 15426 times.
✗ Branch 11 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 |