GCC Code Coverage Report


Directory: ./
File: include/hpp/constraints/solver/impl/hierarchical-iterative.hh
Date: 2025-05-05 12:19:30
Exec Total Coverage
Lines: 72 73 98.6%
Branches: 41 74 55.4%

Line Branch Exec Source
1 // Copyright (c) 2017, Joseph Mirabel
2 // Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
3 //
4
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // 1. Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27 // DAMAGE.
28
29 #ifndef HPP_CONSTRAINTS_SOLVER_IMPL_HIERARCHICAL_ITERATIVE_HH
30 #define HPP_CONSTRAINTS_SOLVER_IMPL_HIERARCHICAL_ITERATIVE_HH
31
32 #include <hpp/constraints/config.hh>
33 #include <hpp/constraints/svd.hh>
34 #include <hpp/util/debug.hh>
35
36 namespace hpp {
37 namespace constraints {
38 namespace solver {
39 namespace lineSearch {
40 template <typename SolverType>
41 34 inline bool Constant::operator()(const SolverType& solver, vectorOut_t arg,
42 vectorOut_t darg) {
43
3/6
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 34 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 34 times.
✗ Branch 9 not taken.
34 solver.integrate(arg, darg, arg);
44 34 return true;
45 }
46
47 template <typename SolverType>
48 224 inline bool Backtracking::operator()(const SolverType& solver, vectorOut_t arg,
49 vectorOut_t u) {
50 224 arg_darg.resize(arg.size());
51
52 224 const value_type slope = computeLocalSlope(solver);
53 224 const value_type t = 2 * c * slope;
54 224 const value_type f_arg_norm2 = solver.residualError();
55
56
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 if (t > 0) {
57 hppDout(error, "The descent direction is not valid: " << t / c);
58 } else {
59 224 value_type alpha = 1;
60 /* TODO add a threshold to avoid too large steps.
61 const value_type u2 = u.squaredNorm();
62 if (u2 > 1.) alpha = 1. / std::sqrt(u2);
63 */
64
65
2/2
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 6 times.
254 while (alpha > smallAlpha) {
66
2/4
✓ Branch 1 taken 248 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 248 times.
✗ Branch 5 not taken.
248 darg = alpha * u;
67
4/8
✓ Branch 1 taken 248 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 248 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 248 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 248 times.
✗ Branch 11 not taken.
248 solver.integrate(arg, darg, arg_darg);
68
2/4
✓ Branch 1 taken 248 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 248 times.
✗ Branch 5 not taken.
248 solver.template computeValue<false>(arg_darg);
69
1/2
✓ Branch 1 taken 248 times.
✗ Branch 2 not taken.
248 solver.computeError();
70 // Check if we are doing better than the linear approximation with coef
71 // multiplied by c < 1
72 // t < 0 must hold
73 248 const value_type f_arg_darg_norm2 = solver.residualError();
74
2/2
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 30 times.
248 if (f_arg_norm2 - f_arg_darg_norm2 >= -alpha * t) {
75
1/2
✓ Branch 1 taken 218 times.
✗ Branch 2 not taken.
218 arg = arg_darg;
76
1/2
✓ Branch 1 taken 218 times.
✗ Branch 2 not taken.
218 u = darg;
77 218 return true;
78 }
79 // Prepare next step
80 30 alpha *= tau;
81 }
82 hppDout(error, "Could find alpha such that ||f(q)||**2 + "
83 << c
84 << " * 2*(f(q)^T * J * dq) is doing worse than "
85 "||f(q + alpha * dq)||**2");
86 }
87
88 6 u *= smallAlpha;
89
3/6
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
6 solver.integrate(arg, u, arg);
90 6 return false;
91 }
92
93 template <typename SolverType>
94 224 inline value_type Backtracking::computeLocalSlope(
95 const SolverType& solver) const {
96 224 value_type slope = 0;
97
2/2
✓ Branch 1 taken 341 times.
✓ Branch 2 taken 224 times.
565 for (std::size_t i = 0; i < solver.stacks_.size(); ++i) {
98 341 typename SolverType::Data& d = solver.datas_[i];
99 341 const size_type nrows = d.reducedJ.rows();
100
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 326 times.
341 if (df.size() < nrows) df.resize(nrows);
101
3/6
✓ Branch 2 taken 341 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 341 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 341 times.
✗ Branch 9 not taken.
341 df.head(nrows).noalias() = d.reducedJ * solver.dqSmall_;
102 341 slope +=
103
4/8
✓ Branch 2 taken 341 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 341 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 341 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 341 times.
✗ Branch 12 not taken.
341 df.head(nrows).dot(d.activeRowsOfJ.keepRows().rview(d.error).eval());
104 }
105 224 return slope;
106 }
107
108 template <typename SolverType>
109 21589 inline bool FixedSequence::operator()(const SolverType& solver, vectorOut_t arg,
110 vectorOut_t darg) {
111 21589 darg *= alpha;
112 21589 alpha = alphaMax - K * (alphaMax - alpha);
113
3/6
✓ Branch 2 taken 21589 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 21589 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 21589 times.
✗ Branch 9 not taken.
21589 solver.integrate(arg, darg, arg);
114 21589 return true;
115 }
116
117 template <typename SolverType>
118 48 inline bool ErrorNormBased::operator()(const SolverType& solver,
119 vectorOut_t arg, vectorOut_t darg) {
120 48 const value_type r = solver.residualError() / solver.squaredErrorThreshold();
121 48 const value_type alpha = C - K * std::tanh(a * r + b);
122
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 darg *= alpha;
123
4/8
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 48 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 48 times.
✗ Branch 11 not taken.
48 solver.integrate(arg, darg, arg);
124 48 return true;
125 }
126 } // namespace lineSearch
127
128 template <typename LineSearchType>
129 inline solver::HierarchicalIterative::Status
130 440 solver::HierarchicalIterative::solve(vectorOut_t arg,
131 LineSearchType lineSearch) const {
132 hppDout(info, "before projection: " << arg.transpose());
133 440 assert(!arg.hasNaN());
134
135 440 size_type errorDecreased = 3, iter = 0;
136 440 value_type previousSquaredNorm = std::numeric_limits<value_type>::infinity();
137 static const value_type dqMinSquaredNorm =
138 Eigen::NumTraits<value_type>::dummy_precision();
139
140 // Fill value and Jacobian
141 440 computeValue<true>(arg);
142 440 computeError();
143
144 440 if (squaredNorm_ > squaredErrorThreshold_ && reducedDimension_ == 0)
145 return INFEASIBLE;
146
147 Status status;
148 8945 while (squaredNorm_ > squaredErrorThreshold_ && errorDecreased &&
149 8892 iter < maxIterations_) {
150 8748 computeSaturation(arg);
151 8748 computeDescentDirection();
152 8748 if (dq_.squaredNorm() < dqMinSquaredNorm) {
153 // TODO INFEASIBLE means that we have reached a local minima.
154 // The problem may still be feasible from a different starting point.
155 243 status = INFEASIBLE;
156 243 break;
157 }
158 8505 lineSearch(*this, arg, dq_);
159
160 8505 computeValue<true>(arg);
161 8505 computeError();
162
163 hppDout(info, "squareNorm = " << squaredNorm_);
164 8505 --errorDecreased;
165 8505 if (squaredNorm_ < previousSquaredNorm)
166 6050 errorDecreased = 3;
167 else
168 2455 status = ERROR_INCREASED;
169 8505 previousSquaredNorm = squaredNorm_;
170 8505 ++iter;
171 }
172
173 hppDout(info, "number of iterations: " << iter);
174 440 if (squaredNorm_ > squaredErrorThreshold_) {
175 hppDout(info, "Projection failed.");
176 396 return (iter >= maxIterations_) ? MAX_ITERATION_REACHED : status;
177 }
178 hppDout(info, "After projection: " << arg.transpose());
179 44 assert(!arg.hasNaN());
180 44 return SUCCESS;
181 }
182 } // namespace solver
183 } // namespace constraints
184 } // namespace hpp
185
186 #endif // HPP_CONSTRAINTS_SOLVER_IMPL_HIERARCHICAL_ITERATIVE_HH
187