GCC Code Coverage Report


Directory: ./
File: include/hpp/constraints/solver/impl/by-substitution.hh
Date: 2025-05-05 12:19:30
Exec Total Coverage
Lines: 55 69 79.7%
Branches: 58 134 43.3%

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_BY_SUBSTITUTION_HH
30 #define HPP_CONSTRAINTS_SOLVER_IMPL_BY_SUBSTITUTION_HH
31
32 namespace hpp {
33 namespace constraints {
34 namespace solver {
35 typedef std::numeric_limits<value_type> numeric_limits;
36 typedef Eigen::NumTraits<value_type> NumTraits;
37
38 template <typename LineSearchType>
39 3294 inline HierarchicalIterative::Status BySubstitution::impl_solve(
40 vectorOut_t arg, bool _optimize, LineSearchType lineSearch) const {
41
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1647 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3294 bool optimize = _optimize && lastIsOptional_;
42
2/4
✓ Branch 1 taken 1647 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1647 times.
3294 assert(!arg.hasNaN());
43
44
2/4
✓ Branch 1 taken 1647 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1647 times.
✗ Branch 5 not taken.
3294 explicit_.solve(arg);
45
2/4
✓ Branch 1 taken 1647 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1647 times.
3294 assert(!arg.hasNaN());
46
47 3294 size_type errorDecreased = 3, iter = 0;
48 value_type previousSquaredNorm;
49 static const value_type dqMinSquaredNorm = NumTraits::dummy_precision();
50 3294 value_type initSquaredNorm = 0;
51
52 // Variables for optimization only
53 3294 value_type previousCost = 0;
54 3294 value_type scaling = 1.;
55 3294 bool onlyLineSearch = false;
56
1/2
✓ Branch 1 taken 1647 times.
✗ Branch 2 not taken.
3294 vector_t qopt;
57
58 // Fill value and Jacobian
59
2/4
✓ Branch 1 taken 1647 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1647 times.
✗ Branch 5 not taken.
3294 computeValue<true>(arg);
60
1/2
✓ Branch 1 taken 1647 times.
✗ Branch 2 not taken.
3294 computeError();
61
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1647 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3294 if (optimize) previousCost = datas_.back().error.squaredNorm();
62
63 3294 bool errorWasBelowThr = (squaredNorm_ < squaredErrorThreshold_);
64
1/2
✓ Branch 1 taken 1647 times.
✗ Branch 2 not taken.
3294 vector_t initArg;
65
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 1146 times.
3294 if (errorWasBelowThr) {
66
1/2
✓ Branch 1 taken 501 times.
✗ Branch 2 not taken.
1002 initArg = arg;
67
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
1002 if (!optimize) iter = std::max(maxIterations_, size_type(2)) - 2;
68 1002 initSquaredNorm = squaredNorm_;
69 }
70
71 3294 bool errorIsAboveThr = (squaredNorm_ > .25 * squaredErrorThreshold_);
72
3/4
✓ Branch 0 taken 1146 times.
✓ Branch 1 taken 501 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1146 times.
3294 if (errorIsAboveThr && reducedDimension_ == 0) return INFEASIBLE;
73
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1647 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
3294 if (optimize && !errorIsAboveThr) qopt = arg;
74
75 3294 Status status = SUCCESS;
76
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 15037 times.
✓ Branch 2 taken 13427 times.
✓ Branch 3 taken 1610 times.
✓ Branch 4 taken 13426 times.
✓ Branch 5 taken 1 times.
30074 while ((optimize || (errorIsAboveThr && errorDecreased))) {
77 // 1. Maximum iterations
78
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 13390 times.
26852 if (iter >= maxIterations_) {
79 72 status = MAX_ITERATION_REACHED;
80 72 break;
81 }
82 26780 status = SUCCESS;
83
84 // 2. Compute step
85 // onlyLineSearch is true when we only reduced the scaling.
86
1/2
✓ Branch 0 taken 13390 times.
✗ Branch 1 not taken.
26780 if (!onlyLineSearch) {
87 26780 previousSquaredNorm = squaredNorm_;
88 // Update the jacobian using the jacobian of the explicit system.
89
2/4
✓ Branch 1 taken 13390 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13390 times.
✗ Branch 5 not taken.
26780 updateJacobian(arg);
90
2/4
✓ Branch 1 taken 13390 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13390 times.
✗ Branch 5 not taken.
26780 computeSaturation(arg);
91
1/2
✓ Branch 1 taken 13390 times.
✗ Branch 2 not taken.
26780 computeDescentDirection();
92 }
93 // Apply scaling to avoid too large steps.
94
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 13390 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
26780 if (optimize) dq_ *= scaling;
95
2/4
✓ Branch 1 taken 13390 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 13390 times.
26780 if (dq_.squaredNorm() < dqMinSquaredNorm) {
96 // We assume that the algorithm reached a local minima.
97 status = INFEASIBLE;
98 break;
99 }
100 // 3. Apply line search algorithm for the computed step
101
3/6
✓ Branch 1 taken 13390 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13390 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13390 times.
✗ Branch 8 not taken.
26780 lineSearch(*this, arg, dq_);
102
2/4
✓ Branch 1 taken 13390 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13390 times.
✗ Branch 5 not taken.
26780 explicit_.solve(arg);
103
2/4
✓ Branch 1 taken 13390 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 13390 times.
26780 assert(!arg.hasNaN());
104
105 // 4. Evaluate the error at the new point.
106
2/4
✓ Branch 1 taken 13390 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13390 times.
✗ Branch 5 not taken.
26780 computeValue<true>(arg);
107
1/2
✓ Branch 1 taken 13390 times.
✗ Branch 2 not taken.
26780 computeError();
108
109 26780 --errorDecreased;
110
2/2
✓ Branch 0 taken 13377 times.
✓ Branch 1 taken 13 times.
26780 if (squaredNorm_ < previousSquaredNorm)
111 26754 errorDecreased = 3;
112 else
113 26 status = ERROR_INCREASED;
114
115 26780 errorIsAboveThr = (squaredNorm_ > .25 * squaredErrorThreshold_);
116 // 5. In case of optimization,
117 // - if the constraints is satisfied and the cost decreased, increase
118 // the scaling (amount of confidence in the linear approximation)
119 // - if the constraints is not satisfied, decrease the scaling and
120 // and cancel this step.
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13390 times.
26780 if (optimize) {
122 if (!errorIsAboveThr) {
123 value_type cost = datas_.back().error.squaredNorm();
124 if (cost < previousCost) {
125 qopt = arg;
126 previousCost = cost;
127 if (scaling < 0.5) scaling *= 2;
128 }
129 onlyLineSearch = false;
130 } else {
131 dq_ /= scaling;
132 scaling *= 0.5;
133 if (qopt.size() > 0) arg = qopt;
134 onlyLineSearch = true;
135 }
136 }
137
138 26780 ++iter;
139 }
140
141
3/4
✓ Branch 0 taken 1647 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 501 times.
✓ Branch 3 taken 1146 times.
3294 if (!optimize && errorWasBelowThr) {
142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
1002 if (squaredNorm_ > initSquaredNorm) {
143 arg = initArg;
144 }
145 1002 return SUCCESS;
146 }
147 // If optimizing, qopt is the visited configuration that satisfies the
148 // constraints and has lowest cost.
149
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1146 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1146 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
2292 if (optimize && qopt.size() > 0) arg = qopt;
150
151
2/4
✓ Branch 1 taken 1146 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1146 times.
2292 assert(!arg.hasNaN());
152 2292 return status;
153 3294 }
154 } // namespace solver
155 } // namespace constraints
156 } // namespace hpp
157
158 #endif // HPP_CONSTRAINTS_SOLVER_IMPL_BY_SUBSTITUTION_HH
159