GCC Code Coverage Report


Directory: ./
File: src/solver/hierarchical-iterative.cc
Date: 2025-05-05 12:19:30
Exec Total Coverage
Lines: 539 578 93.3%
Branches: 451 870 51.8%

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 #include <boost/serialization/shared_ptr.hpp>
30 #include <boost/serialization/vector.hpp>
31 #include <hpp/constraints/implicit.hh>
32 #include <hpp/constraints/macros.hh>
33 #include <hpp/constraints/solver/hierarchical-iterative.hh>
34 #include <hpp/constraints/solver/impl/hierarchical-iterative.hh>
35 #include <hpp/constraints/svd.hh>
36 #include <hpp/pinocchio/device.hh>
37 #include <hpp/pinocchio/joint-collection.hh>
38 #include <hpp/pinocchio/liegroup-element.hh>
39 #include <hpp/pinocchio/serialization.hh>
40 #include <hpp/pinocchio/util.hh>
41 #include <hpp/util/debug.hh>
42 #include <hpp/util/serialization.hh>
43 #include <hpp/util/timer.hh>
44 #include <limits>
45 #include <pinocchio/multibody/model.hpp>
46 #include <pinocchio/serialization/eigen.hpp>
47
48 // #define SVD_THRESHOLD Eigen::NumTraits<value_type>::dummy_precision()
49 #define SVD_THRESHOLD 1e-8
50
51 namespace hpp {
52 namespace constraints {
53 namespace solver {
54 namespace {
55 template <bool Superior, bool ComputeJac, typename Derived>
56 2618 void compare(value_type& val, const Eigen::MatrixBase<Derived>& jac,
57 const value_type& thr) {
58
2/2
✓ Branch 0 taken 410 times.
✓ Branch 1 taken 899 times.
2618 if ((Superior && val < thr) || (!Superior && -thr < val)) {
59 if (Superior)
60 352 val -= thr;
61 else
62 468 val += thr;
63 } else {
64 1798 val = 0;
65 if (ComputeJac)
66 842 const_cast<Eigen::MatrixBase<Derived>&>(jac).derived().setZero();
67 }
68 2618 }
69
70 template <bool ComputeJac>
71 51854 void applyComparison(const ComparisonTypes_t comparison,
72 const std::vector<std::size_t>& indices, vector_t& value,
73 matrix_t& jacobian, const value_type& thr) {
74
2/2
✓ Branch 1 taken 1309 times.
✓ Branch 2 taken 25927 times.
54472 for (std::size_t i = 0; i < indices.size(); ++i) {
75 2618 const std::size_t j = indices[i];
76
2/2
✓ Branch 1 taken 523 times.
✓ Branch 2 taken 786 times.
2618 if (comparison[j] == Superior) {
77
2/4
✓ Branch 2 taken 523 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 523 times.
✗ Branch 6 not taken.
1046 compare<true, ComputeJac>(value[j], jacobian.row(j), thr);
78
1/2
✓ Branch 1 taken 786 times.
✗ Branch 2 not taken.
1572 } else if (comparison[j] == Inferior) {
79
2/4
✓ Branch 2 taken 786 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 786 times.
✗ Branch 6 not taken.
1572 compare<false, ComputeJac>(value[j], jacobian.row(j), thr);
80 }
81 }
82 51854 }
83 } // namespace
84
85 namespace lineSearch {
86 template bool Constant::operator()(const HierarchicalIterative& solver,
87 vectorOut_t arg, vectorOut_t darg);
88
89
2/4
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
13 Backtracking::Backtracking() : c(0.001), tau(0.7), smallAlpha(0.2) {}
90 template bool Backtracking::operator()(const HierarchicalIterative& solver,
91 vectorOut_t arg, vectorOut_t darg);
92
93 2041 FixedSequence::FixedSequence() : alpha(.2), alphaMax(.95), K(.8) {}
94 template bool FixedSequence::operator()(const HierarchicalIterative& solver,
95 vectorOut_t arg, vectorOut_t darg);
96
97 ErrorNormBased::ErrorNormBased(value_type alphaMin, value_type _a,
98 value_type _b)
99 : C(0.5 + alphaMin / 2), K((1 - alphaMin) / 2), a(_a), b(_b) {}
100
101 2 ErrorNormBased::ErrorNormBased(value_type alphaMin)
102 2 : C(0.5 + alphaMin / 2), K((1 - alphaMin) / 2) {
103 static const value_type delta = 0.02;
104 static const value_type r_half = 1e6;
105
106 2 a = atanh((delta - 1 + C) / K) / (1 - r_half);
107 2 b = -r_half * a;
108 2 }
109
110 template bool ErrorNormBased::operator()(const HierarchicalIterative& solver,
111 vectorOut_t arg, vectorOut_t darg);
112 } // namespace lineSearch
113
114 namespace saturation {
115 39730 bool Base::saturate(vectorIn_t q, vectorOut_t qSat,
116 Eigen::VectorXi& saturation) {
117 39730 qSat = q;
118 39730 saturation.setZero();
119 39730 return false;
120 }
121
122 138010 bool clamp(const value_type& lb, const value_type& ub, const value_type& v,
123 value_type& vsat, int& s) {
124
2/2
✓ Branch 0 taken 3527 times.
✓ Branch 1 taken 134483 times.
138010 if (v <= lb) {
125 3527 vsat = lb;
126 3527 s = -1;
127 3527 return true;
128
2/2
✓ Branch 0 taken 2790 times.
✓ Branch 1 taken 131693 times.
134483 } else if (v >= ub) {
129 2790 vsat = ub;
130 2790 s = 1;
131 2790 return true;
132 } else {
133 131693 vsat = v;
134 131693 s = 0;
135 131693 return false;
136 }
137 }
138
139 465 bool Bounds::saturate(vectorIn_t q, vectorOut_t qSat,
140 Eigen::VectorXi& saturation) {
141 465 bool sat = false;
142
2/2
✓ Branch 1 taken 2388 times.
✓ Branch 2 taken 465 times.
2853 for (size_type i = 0; i < q.size(); ++i)
143
5/8
✓ Branch 5 taken 2388 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2388 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2388 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 250 times.
✓ Branch 14 taken 2138 times.
2388 if (clamp(lb[i], ub[i], q[i], qSat[i], saturation[iq2iv_[i]])) sat = true;
144 465 return sat;
145 }
146
147 3604 bool Device::saturate(vectorIn_t q, vectorOut_t qSat, Eigen::VectorXi& sat) {
148 3604 bool ret = false;
149 3604 const pinocchio::Model& m = device->model();
150
151
2/2
✓ Branch 1 taken 113998 times.
✓ Branch 2 taken 3604 times.
117602 for (std::size_t i = 1; i < m.joints.size(); ++i) {
152
1/2
✓ Branch 2 taken 113998 times.
✗ Branch 3 not taken.
113998 const size_type nq = m.joints[i].nq();
153
1/2
✓ Branch 2 taken 113998 times.
✗ Branch 3 not taken.
113998 const size_type nv = m.joints[i].nv();
154
1/2
✓ Branch 2 taken 113998 times.
✗ Branch 3 not taken.
113998 const size_type idx_q = m.joints[i].idx_q();
155
1/2
✓ Branch 2 taken 113998 times.
✗ Branch 3 not taken.
113998 const size_type idx_v = m.joints[i].idx_v();
156
2/2
✓ Branch 0 taken 135622 times.
✓ Branch 1 taken 113998 times.
249620 for (size_type j = 0; j < nq; ++j) {
157 135622 const size_type iq = idx_q + j;
158 135622 const size_type iv = idx_v + std::min(j, nv - 1);
159
5/8
✓ Branch 1 taken 135622 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 135622 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 135622 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 6067 times.
✓ Branch 10 taken 129555 times.
135622 if (clamp(m.lowerPositionLimit[iq], m.upperPositionLimit[iq], q[iq],
160
3/6
✓ Branch 1 taken 135622 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 135622 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 135622 times.
✗ Branch 8 not taken.
135622 qSat[iq], sat[iv]))
161 6067 ret = true;
162 }
163 }
164
165 3604 const hpp::pinocchio::ExtraConfigSpace& ecs = device->extraConfigSpace();
166 3604 const size_type& d = ecs.dimension();
167
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3604 times.
3604 for (size_type k = 0; k < d; ++k) {
169 const size_type iq = m.nq + k;
170 const size_type iv = m.nv + k;
171 if (clamp(ecs.lower(k), ecs.upper(k), q[iq], qSat[iq], sat[iv])) ret = true;
172 }
173 3604 return ret;
174 }
175 } // namespace saturation
176
177 typedef std::pair<DifferentiableFunctionPtr_t, size_type> iqIt_t;
178 typedef std::pair<DifferentiableFunctionPtr_t, std::size_t> priorityIt_t;
179
180 1034 HierarchicalIterative::HierarchicalIterative(
181 1034 const LiegroupSpacePtr_t& configSpace)
182 1034 : squaredErrorThreshold_(0),
183 1034 inequalityThreshold_(0),
184 1034 maxIterations_(0),
185 1034 stacks_(),
186 1034 configSpace_(configSpace),
187 1034 dimension_(0),
188 1034 reducedDimension_(0),
189 1034 lastIsOptional_(false),
190 1034 solveLevelByLevel_(false),
191
1/2
✓ Branch 1 taken 1034 times.
✗ Branch 2 not taken.
1034 freeVariables_(),
192
2/4
✓ Branch 1 taken 1034 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1034 times.
✗ Branch 6 not taken.
1034 saturate_(new saturation::Base()),
193 1034 constraints_(),
194 1034 iq_(),
195 1034 iv_(),
196 1034 priority_(),
197 1034 sigma_(0),
198
1/2
✓ Branch 1 taken 1034 times.
✗ Branch 2 not taken.
1034 dq_(),
199
1/2
✓ Branch 1 taken 1034 times.
✗ Branch 2 not taken.
1034 dqSmall_(),
200
1/2
✓ Branch 1 taken 1034 times.
✗ Branch 2 not taken.
1034 reducedJ_(),
201
1/2
✓ Branch 3 taken 1034 times.
✗ Branch 4 not taken.
1034 saturation_(configSpace->nv()),
202
1/2
✓ Branch 1 taken 1034 times.
✗ Branch 2 not taken.
1034 reducedSaturation_(),
203
1/2
✓ Branch 3 taken 1034 times.
✗ Branch 4 not taken.
1034 qSat_(configSpace_->nq()),
204
1/2
✓ Branch 1 taken 1034 times.
✗ Branch 2 not taken.
1034 tmpSat_(),
205 1034 squaredNorm_(0),
206 1034 datas_(),
207
1/2
✓ Branch 1 taken 1034 times.
✗ Branch 2 not taken.
1034 svd_(),
208
1/2
✓ Branch 3 taken 1034 times.
✗ Branch 4 not taken.
1034 OM_(configSpace->nv()),
209
1/2
✓ Branch 4 taken 1034 times.
✗ Branch 5 not taken.
2068 OP_(configSpace->nv()) {
210 // Initialize freeVariables_ to all indices.
211
1/2
✓ Branch 3 taken 1034 times.
✗ Branch 4 not taken.
1034 freeVariables_.addRow(0, configSpace_->nv());
212 1034 }
213
214 4 HierarchicalIterative::HierarchicalIterative(const HierarchicalIterative& other)
215 4 : squaredErrorThreshold_(other.squaredErrorThreshold_),
216 4 inequalityThreshold_(other.inequalityThreshold_),
217 4 maxIterations_(other.maxIterations_),
218 4 stacks_(other.stacks_),
219 4 configSpace_(other.configSpace_),
220 4 dimension_(other.dimension_),
221 4 reducedDimension_(other.reducedDimension_),
222 4 lastIsOptional_(other.lastIsOptional_),
223
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 freeVariables_(other.freeVariables_),
224 4 saturate_(other.saturate_),
225
1/2
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
4 constraints_(other.constraints_.size()),
226
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 iq_(other.iq_),
227
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 iv_(other.iv_),
228
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 priority_(other.priority_),
229 4 sigma_(other.sigma_),
230
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 dq_(other.dq_),
231
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 dqSmall_(other.dqSmall_),
232
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 reducedJ_(other.reducedJ_),
233
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 saturation_(other.saturation_),
234
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 reducedSaturation_(other.reducedSaturation_),
235
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 qSat_(other.qSat_),
236
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 tmpSat_(other.tmpSat_),
237 4 squaredNorm_(other.squaredNorm_),
238
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 datas_(other.datas_),
239
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 svd_(other.svd_),
240
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 OM_(other.OM_),
241
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 OP_(other.OP_) {
242
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 4 times.
16 for (std::size_t i = 0; i < constraints_.size(); ++i)
243
1/2
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 constraints_[i] = other.constraints_[i]->copy();
244 4 }
245
246 2108 bool HierarchicalIterative::contains(
247 const ImplicitPtr_t& numericalConstraint) const {
248
1/2
✓ Branch 3 taken 2108 times.
✗ Branch 4 not taken.
2108 return find_if(constraints_.begin(), constraints_.end(),
249 1159 [&numericalConstraint](const ImplicitPtr_t& arg) {
250 1159 return *arg == *numericalConstraint;
251 4216 }) != constraints_.end();
252 }
253
254 1043 bool HierarchicalIterative::add(const ImplicitPtr_t& constraint,
255 const std::size_t& priority) {
256 1043 DifferentiableFunctionPtr_t f(constraint->functionPtr());
257
1/2
✓ Branch 3 taken 1043 times.
✗ Branch 4 not taken.
1043 if (find_if(priority_.begin(), priority_.end(),
258 1064 [&f](const priorityIt_t& arg) { return *arg.first == *f; }) !=
259
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1042 times.
2086 priority_.end()) {
260
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 std::ostringstream oss;
261
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 oss << "Contraint \"" << f->name() << "\" already in solver";
262
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 throw std::logic_error(oss.str().c_str());
263 1 }
264
1/2
✓ Branch 1 taken 1042 times.
✗ Branch 2 not taken.
1042 priority_[f] = priority;
265
2/4
✓ Branch 2 taken 1042 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1042 times.
✗ Branch 6 not taken.
1042 const ComparisonTypes_t comp(constraint->comparisonType());
266
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1042 times.
1042 assert((size_type)comp.size() == f->outputDerivativeSize());
267 1042 const std::size_t minSize = priority + 1;
268
2/2
✓ Branch 1 taken 1032 times.
✓ Branch 2 taken 10 times.
1042 if (stacks_.size() < minSize) {
269
2/4
✓ Branch 1 taken 1032 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1032 times.
✗ Branch 5 not taken.
1032 stacks_.resize(minSize, ImplicitConstraintSet());
270
2/4
✓ Branch 1 taken 1032 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1032 times.
✗ Branch 5 not taken.
1032 datas_.resize(minSize, Data());
271 }
272 1042 Data& d = datas_[priority];
273 // Store rank in output vector value
274
1/2
✓ Branch 5 taken 1042 times.
✗ Branch 6 not taken.
1042 iq_[f] = datas_[priority].output.space()->nq();
275 // Store rank in output vector derivative
276
1/2
✓ Branch 5 taken 1042 times.
✗ Branch 6 not taken.
1042 iv_[f] = datas_[priority].output.space()->nv();
277 // warning adding constraint to the stack modifies behind the stage
278 // the dimension of datas_ [priority].output.space (). It should
279 // therefore be done after the previous lines.
280
1/2
✓ Branch 2 taken 1042 times.
✗ Branch 3 not taken.
1042 stacks_[priority].add(constraint);
281
2/2
✓ Branch 1 taken 10103 times.
✓ Branch 2 taken 1042 times.
11145 for (std::size_t i = 0; i < comp.size(); ++i) {
282
6/6
✓ Branch 1 taken 10100 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 10095 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 10095 times.
10103 if ((comp[i] == Superior) || (comp[i] == Inferior)) {
283
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 d.inequalityIndices.push_back(d.comparison.size());
284
2/2
✓ Branch 1 taken 6058 times.
✓ Branch 2 taken 4037 times.
10095 } else if (comp[i] == Equality) {
285
1/2
✓ Branch 2 taken 6058 times.
✗ Branch 3 not taken.
6058 d.equalityIndices.addRow(d.comparison.size(), 1);
286 }
287
1/2
✓ Branch 2 taken 10103 times.
✗ Branch 3 not taken.
10103 d.comparison.push_back(comp[i]);
288 }
289
1/2
✓ Branch 1 taken 1042 times.
✗ Branch 2 not taken.
1042 d.equalityIndices.updateRows<true, true, true>();
290
1/2
✓ Branch 1 taken 1042 times.
✗ Branch 2 not taken.
1042 constraints_.push_back(constraint);
291
1/2
✓ Branch 1 taken 1042 times.
✗ Branch 2 not taken.
1042 update();
292
293 1042 return true;
294 1043 }
295
296 1 void HierarchicalIterative::merge(const HierarchicalIterative& other) {
297 std::size_t priority;
298 1 for (NumericalConstraints_t::const_iterator it(other.constraints_.begin());
299
2/2
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
3 it != other.constraints_.end(); ++it) {
300
3/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 if (!this->contains(*it)) {
301 1 const DifferentiableFunctionPtr_t& f = (*it)->functionPtr();
302 std::map<DifferentiableFunctionPtr_t, std::size_t>::const_iterator itp(
303
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 std::find_if(
304 other.priority_.begin(), other.priority_.end(),
305 1 [&f](const priorityIt_t& arg) { return *arg.first == *f; }));
306
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (itp == other.priority_.end()) {
307 // If priority is not set, constraint is explicit
308 1 priority = 0;
309 } else {
310 priority = itp->second;
311 }
312
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 this->add(*it, priority);
313 }
314 }
315 1 }
316
317 ArrayXb HierarchicalIterative::activeParameters() const {
318 ArrayXb ap(ArrayXb::Constant(configSpace_->nq(), false));
319 for (std::size_t i = 0; i < stacks_.size(); ++i) {
320 #ifndef NDEBUG
321 dynamic_cast<const DifferentiableFunctionSet&>(stacks_[i].function());
322 #endif
323 const DifferentiableFunctionSet& dfs(
324 dynamic_cast<const DifferentiableFunctionSet&>(stacks_[i].function()));
325 ap = ap || dfs.activeParameters();
326 }
327 return ap;
328 }
329
330 2 ArrayXb HierarchicalIterative::activeDerivativeParameters() const {
331
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 ArrayXb ap(ArrayXb::Constant(configSpace_->nv(), false));
332
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 for (std::size_t i = 0; i < stacks_.size(); ++i) {
333 #ifndef NDEBUG
334
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 dynamic_cast<const DifferentiableFunctionSet&>(stacks_[i].function());
335 #endif
336 const DifferentiableFunctionSet& dfs(
337
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 dynamic_cast<const DifferentiableFunctionSet&>(stacks_[i].function()));
338
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 ap = ap || dfs.activeDerivativeParameters();
339 }
340 2 return ap;
341 }
342
343 1071 void HierarchicalIterative::update() {
344 // Compute reduced size
345 1071 std::size_t reducedSize = freeVariables_.nbIndices();
346
347 1071 dimension_ = 0;
348 1071 reducedDimension_ = 0;
349
2/2
✓ Branch 1 taken 1073 times.
✓ Branch 2 taken 1071 times.
2144 for (std::size_t i = 0; i < stacks_.size(); ++i) {
350 1073 computeActiveRowsOfJ(i);
351
352 1073 const ImplicitConstraintSet& constraints(stacks_[i]);
353 #ifndef NDEBUG
354
1/2
✓ Branch 1 taken 1073 times.
✗ Branch 2 not taken.
1073 dynamic_cast<const DifferentiableFunctionSet&>(constraints.function());
355 #endif
356 const DifferentiableFunctionSet& f(
357 1073 static_cast<const DifferentiableFunctionSet&>(constraints.function()));
358 1073 dimension_ += f.outputDerivativeSize();
359 1073 reducedDimension_ += datas_[i].activeRowsOfJ.nbRows();
360
1/2
✓ Branch 2 taken 1073 times.
✗ Branch 3 not taken.
1073 datas_[i].output = LiegroupElement(f.outputSpace());
361
1/2
✓ Branch 2 taken 1073 times.
✗ Branch 3 not taken.
1073 datas_[i].rightHandSide = LiegroupElement(f.outputSpace());
362 1073 datas_[i].rightHandSide.setNeutral();
363
1/2
✓ Branch 5 taken 1073 times.
✗ Branch 6 not taken.
1073 datas_[i].error.resize(f.outputSpace()->nv());
364
365
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1073 times.
1073 assert(configSpace_->nv() == f.inputDerivativeSize());
366 1073 datas_[i].jacobian.resize(f.outputDerivativeSize(),
367 f.inputDerivativeSize());
368 1073 datas_[i].jacobian.setZero();
369 1073 datas_[i].reducedJ.resize(datas_[i].activeRowsOfJ.nbRows(), reducedSize);
370
371 2146 datas_[i].svd = SVD_t(
372 f.outputDerivativeSize(), reducedSize,
373
2/2
✓ Branch 1 taken 1068 times.
✓ Branch 2 taken 5 times.
1073 Eigen::ComputeThinU | (i == stacks_.size() - 1 ? Eigen::ComputeThinV
374 1073 : Eigen::ComputeFullV));
375
1/2
✓ Branch 2 taken 1073 times.
✗ Branch 3 not taken.
1073 datas_[i].svd.setThreshold(SVD_THRESHOLD);
376 1073 datas_[i].PK.resize(reducedSize, reducedSize);
377
378 1073 datas_[i].maxRank = 0;
379 }
380
381
1/2
✓ Branch 4 taken 1071 times.
✗ Branch 5 not taken.
1071 dq_ = vector_t::Zero(configSpace_->nv());
382 1071 dqSmall_.resize(reducedSize);
383 1071 reducedJ_.resize(reducedDimension_, reducedSize);
384 2142 svd_ = SVD_t(reducedDimension_, reducedSize,
385 1071 Eigen::ComputeThinU | Eigen::ComputeThinV);
386 1071 }
387
388 24 void HierarchicalIterative::computeActiveRowsOfJ(std::size_t iStack) {
389 24 Data& d = datas_[iStack];
390 const ImplicitConstraintSet::Implicits_t constraints(
391
1/2
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
24 stacks_[iStack].constraints());
392 24 std::size_t offset = 0;
393
394 typedef Eigen::MatrixBlocks<false, false> BlockIndices;
395 24 BlockIndices::segments_t rows;
396 // Loop over functions of the stack
397
2/2
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 24 times.
58 for (std::size_t i = 0; i < constraints.size(); ++i) {
398 34 ArrayXb adp = freeVariables_
399
1/2
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
68 .rview(constraints[i]
400 34 ->function()
401 34 .activeDerivativeParameters()
402
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 .matrix())
403
2/4
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
34 .eval();
404
2/4
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
✗ Branch 4 not taken.
34 if (adp.any()) // If at least one element of adp is true
405
2/2
✓ Branch 7 taken 35 times.
✓ Branch 8 taken 34 times.
69 for (const segment_t s : constraints[i]->activeRows()) {
406
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 rows.emplace_back(s.first + offset, s.second);
407 }
408 34 offset += constraints[i]->function().outputDerivativeSize();
409 34 }
410 d.activeRowsOfJ =
411
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
24 Eigen::MatrixBlocks<false, false>(rows, freeVariables_.m_rows);
412
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 d.activeRowsOfJ.updateRows<true, true, true>();
413 24 }
414
415 1909 vector_t HierarchicalIterative::rightHandSideFromConfig(
416 ConfigurationIn_t config) {
417
2/2
✓ Branch 1 taken 1505 times.
✓ Branch 2 taken 1909 times.
3414 for (std::size_t i = 0; i < stacks_.size(); ++i) {
418 1505 ImplicitConstraintSet& ics = stacks_[i];
419 1505 Data& d = datas_[i];
420
2/4
✓ Branch 2 taken 1505 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1505 times.
✗ Branch 6 not taken.
1505 ics.rightHandSideFromConfig(config, d.rightHandSide);
421 }
422 1909 return rightHandSide();
423 }
424
425 4103 bool HierarchicalIterative::rightHandSideFromConfig(
426 const ImplicitPtr_t& constraint, ConfigurationIn_t config) {
427 4103 const DifferentiableFunctionPtr_t& f(constraint->functionPtr());
428
429 std::map<DifferentiableFunctionPtr_t, size_type>::iterator iqi(
430
1/2
✓ Branch 3 taken 4103 times.
✗ Branch 4 not taken.
4103 find_if(iq_.begin(), iq_.end(),
431 4103 [&f](const iqIt_t& arg) { return *arg.first == *f; }));
432
2/2
✓ Branch 2 taken 2002 times.
✓ Branch 3 taken 2101 times.
4103 if (iqi == iq_.end()) return false;
433 2101 LiegroupSpacePtr_t space(f->outputSpace());
434 2101 size_type iq = iqi->second;
435
436 std::map<DifferentiableFunctionPtr_t, std::size_t>::iterator prioi(
437
1/2
✓ Branch 3 taken 2101 times.
✗ Branch 4 not taken.
2101 find_if(priority_.begin(), priority_.end(),
438 2101 [&f](const iqIt_t& arg) { return *arg.first == *f; }));
439
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2101 times.
2101 if (prioi == priority_.end()) return false;
440 2101 std::size_t i = prioi->second;
441
442 2101 size_type nq = space->nq();
443 2101 Data& d = datas_[i];
444 LiegroupElementRef rhs(
445
3/6
✓ Branch 3 taken 2101 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2101 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2101 times.
✗ Branch 10 not taken.
2101 space->elementRef(d.rightHandSide.vector().segment(iq, nq)));
446
3/6
✓ Branch 2 taken 2101 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2101 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2101 times.
✗ Branch 9 not taken.
2101 constraint->rightHandSideFromConfig(config, rhs);
447 2101 return true;
448 2101 }
449
450 3103 bool HierarchicalIterative::rightHandSide(const ImplicitPtr_t& constraint,
451 vectorIn_t rightHandSide) {
452 3103 const DifferentiableFunctionPtr_t& f(constraint->functionPtr());
453 3103 LiegroupSpacePtr_t space(f->outputSpace());
454
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 3103 times.
3103 assert(rightHandSide.size() == space->nq());
455
456 std::map<DifferentiableFunctionPtr_t, size_type>::iterator iqi(
457
1/2
✓ Branch 3 taken 3103 times.
✗ Branch 4 not taken.
3103 find_if(iq_.begin(), iq_.end(),
458 3106 [&f](const iqIt_t& arg) { return *arg.first == *f; }));
459
2/2
✓ Branch 2 taken 1002 times.
✓ Branch 3 taken 2101 times.
3103 if (iqi == iq_.end()) return false;
460 2101 size_type iq = iqi->second;
461 2101 size_type nq = space->nq();
462
463 std::map<DifferentiableFunctionPtr_t, std::size_t>::iterator prioi(
464
1/2
✓ Branch 3 taken 2101 times.
✗ Branch 4 not taken.
2101 find_if(priority_.begin(), priority_.end(),
465 2102 [&f](const iqIt_t& arg) { return *arg.first == *f; }));
466
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2101 times.
2101 if (prioi == priority_.end()) return false;
467 2101 std::size_t i = prioi->second;
468
469 2101 Data& d = datas_[i];
470 #ifndef NDEBUG
471 2101 size_type nv = space->nv();
472
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2101 times.
2101 assert(d.error.size() >= nv);
473 #endif
474 pinocchio::LiegroupElementConstRef inRhs(
475
2/4
✓ Branch 2 taken 2101 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2101 times.
✗ Branch 6 not taken.
2101 space->elementConstRef(rightHandSide));
476 LiegroupElementRef rhs(
477
3/6
✓ Branch 3 taken 2101 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2101 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2101 times.
✗ Branch 10 not taken.
2101 space->elementRef(d.rightHandSide.vector().segment(iq, nq)));
478
1/2
✓ Branch 1 taken 2101 times.
✗ Branch 2 not taken.
2101 rhs = inRhs;
479
3/6
✓ Branch 2 taken 2101 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2101 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2101 times.
2101 assert(constraint->checkRightHandSide(inRhs));
480 2101 return true;
481 3103 }
482
483 5103 bool HierarchicalIterative::getRightHandSide(const ImplicitPtr_t& constraint,
484 vectorOut_t rightHandSide) const {
485 5103 const DifferentiableFunctionPtr_t& f(constraint->functionPtr());
486 std::map<DifferentiableFunctionPtr_t, std::size_t>::const_iterator itp(
487
1/2
✓ Branch 3 taken 5103 times.
✗ Branch 4 not taken.
5103 find_if(priority_.begin(), priority_.end(),
488 5106 [&f](const priorityIt_t& arg) { return *arg.first == *f; }));
489
2/2
✓ Branch 2 taken 2002 times.
✓ Branch 3 taken 3101 times.
5103 if (itp == priority_.end()) {
490 2002 return false;
491 }
492 std::map<DifferentiableFunctionPtr_t, size_type>::const_iterator itIq(
493
1/2
✓ Branch 3 taken 3101 times.
✗ Branch 4 not taken.
3101 find_if(iq_.begin(), iq_.end(),
494 3102 [&f](const iqIt_t& arg) { return *arg.first == *f; }));
495
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3101 times.
3101 if (itIq == iq_.end()) {
496 return false;
497 }
498 3101 LiegroupSpacePtr_t space(f->outputSpace());
499 3101 std::size_t i = itp->second;
500 3101 size_type iq = itIq->second;
501 3101 Data& d = datas_[i];
502
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 3101 times.
3101 assert(rightHandSide.size() == space->nq());
503
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 3101 times.
3101 assert(d.rightHandSide.space()->nq() >= iq + space->nq());
504
2/4
✓ Branch 4 taken 3101 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3101 times.
✗ Branch 8 not taken.
3101 rightHandSide = d.rightHandSide.vector().segment(iq, space->nq());
505 3101 return true;
506 3101 }
507
508 8 bool HierarchicalIterative::isConstraintSatisfied(
509 const ImplicitPtr_t& constraint, vectorIn_t arg, vectorOut_t error,
510 bool& constraintFound) const {
511 8 const DifferentiableFunctionPtr_t& f(constraint->functionPtr());
512
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
8 assert(error.size() == f->outputSpace()->nv());
513 std::map<DifferentiableFunctionPtr_t, std::size_t>::const_iterator itp(
514
1/2
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
8 find_if(priority_.begin(), priority_.end(),
515 8 [&f](const priorityIt_t& arg) { return *arg.first == *f; }));
516
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
8 if (itp == priority_.end()) {
517 4 constraintFound = false;
518 4 return false;
519 }
520 4 constraintFound = true;
521 std::map<DifferentiableFunctionPtr_t, size_type>::const_iterator itIq(
522
1/2
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
4 find_if(iq_.begin(), iq_.end(),
523 4 [&f](const iqIt_t& arg) { return *arg.first == *f; }));
524
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 assert(itIq != iq_.end());
525 std::map<DifferentiableFunctionPtr_t, size_type>::const_iterator itIv(
526
1/2
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
4 find_if(iv_.begin(), iv_.end(),
527 4 [&f](const iqIt_t& arg) { return *arg.first == *f; }));
528
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 assert(itIv != iv_.end());
529 4 size_type priority(itp->second);
530 4 Data& d = datas_[priority];
531 // Evaluate constraint function
532 4 size_type iq = itIq->second, nq = f->outputSpace()->nq();
533
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 LiegroupElementRef output(d.output.vector().segment(iq, nq),
534
2/4
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
8 f->outputSpace());
535
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 LiegroupElementRef rhs(d.rightHandSide.vector().segment(iq, nq),
536
2/4
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
8 f->outputSpace());
537
3/6
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
4 f->value(output, arg);
538
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 error = output - rhs;
539
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 constraint->setInactiveRowsToZero(error);
540
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 return (error.squaredNorm() < squaredErrorThreshold_);
541 4 }
542
543 100 void HierarchicalIterative::rightHandSide(vectorIn_t rightHandSide) {
544 100 size_type iq = 0, iv = 0;
545
2/2
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 100 times.
200 for (std::size_t i = 0; i < stacks_.size(); ++i) {
546 100 Data& d = datas_[i];
547 100 LiegroupSpacePtr_t space(d.rightHandSide.space());
548 100 size_type nq = space->nq();
549 100 size_type nv = space->nv();
550 pinocchio::LiegroupElementConstRef output(
551
3/6
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
100 space->elementConstRef(rightHandSide.segment(iq, nq)));
552 LiegroupElementRef rhs(
553
3/6
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 100 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 100 times.
✗ Branch 10 not taken.
100 space->elementRef(d.rightHandSide.vector().segment(iq, nq)));
554
555 // d.error is used here as an intermediate storage. The value
556 // computed is not the error
557
2/4
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
100 d.error = output - space->neutral(); // log (rightHandSide)
558
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 100 times.
700 for (size_type k = 0; k < nv; ++k) {
559
1/6
✗ Branch 1 not taken.
✓ Branch 2 taken 600 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
600 if (d.comparison[iv + k] != Equality) assert(d.error[k] == 0);
560 }
561
4/8
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 100 times.
✗ Branch 12 not taken.
100 rhs = space->neutral() + d.error; // exp (d.error)
562 100 iq += nq;
563 100 iv += nv;
564 100 }
565
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
100 assert(iq == rightHandSide.size());
566 100 }
567
568 void HierarchicalIterative::rightHandSideAt(const value_type& s) {
569 for (std::size_t i = 0; i < constraints_.size(); ++i) {
570 ImplicitPtr_t implicit = constraints_[i];
571 // If constraint has no right hand side function set, do nothing
572 if ((implicit->parameterSize() != 0) &&
573 (implicit->rightHandSideFunction())) {
574 rightHandSide(implicit, implicit->rightHandSideAt(s));
575 }
576 }
577 }
578
579 2309 vector_t HierarchicalIterative::rightHandSide() const {
580
1/2
✓ Branch 2 taken 2309 times.
✗ Branch 3 not taken.
2309 vector_t rhs(rightHandSideSize());
581 2309 size_type iq = 0;
582
2/2
✓ Branch 1 taken 1905 times.
✓ Branch 2 taken 2309 times.
4214 for (std::size_t i = 0; i < stacks_.size(); ++i) {
583 1905 const Data& d = datas_[i];
584 1905 size_type nq = d.rightHandSide.space()->nq();
585 // this does not take the comparison type into account.
586 // It shouldn't matter as rhs should be zero when comparison type is
587 // not Equality
588
3/6
✓ Branch 1 taken 1905 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1905 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1905 times.
✗ Branch 8 not taken.
1905 rhs.segment(iq, nq) = d.rightHandSide.vector();
589 1905 iq += nq;
590 }
591
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2309 times.
2309 assert(iq == rhs.size());
592 2309 return rhs;
593 }
594
595 4314 size_type HierarchicalIterative::rightHandSideSize() const {
596 4314 size_type rhsSize = 0;
597
2/2
✓ Branch 1 taken 3506 times.
✓ Branch 2 taken 4314 times.
7820 for (std::size_t i = 0; i < stacks_.size(); ++i)
598 3506 rhsSize += stacks_[i].function().outputSize();
599 4314 return rhsSize;
600 }
601
602 template <bool ComputeJac>
603 52078 void HierarchicalIterative::computeValue(vectorIn_t config) const {
604
2/2
✓ Branch 1 taken 25927 times.
✓ Branch 2 taken 26039 times.
103932 for (std::size_t i = 0; i < stacks_.size(); ++i) {
605 51854 const ImplicitConstraintSet& constraints(stacks_[i]);
606 51854 const DifferentiableFunction& f = constraints.function();
607 51854 Data& d = datas_[i];
608
609
2/4
✓ Branch 2 taken 25927 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 25927 times.
✗ Branch 6 not taken.
51854 f.value(d.output, config);
610
2/4
✓ Branch 1 taken 25927 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 25927 times.
51854 assert(hpp::pinocchio::checkNormalized(d.output));
611
2/4
✓ Branch 1 taken 25927 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 25927 times.
51854 assert(hpp::pinocchio::checkNormalized(d.rightHandSide));
612 51854 d.error = d.output - d.rightHandSide;
613
1/2
✓ Branch 2 taken 25927 times.
✗ Branch 3 not taken.
51854 constraints.setInactiveRowsToZero(d.error);
614 if (ComputeJac) {
615
2/4
✓ Branch 2 taken 23739 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 23739 times.
✗ Branch 6 not taken.
47478 f.jacobian(d.jacobian, config);
616
3/6
✓ Branch 4 taken 23739 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 23739 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 23739 times.
✗ Branch 11 not taken.
142434 d.output.space()->dDifference_dq1<pinocchio::DerivativeTimesInput>(
617 94956 d.rightHandSide.vector(), d.output.vector(), d.jacobian);
618 }
619
1/2
✓ Branch 1 taken 25927 times.
✗ Branch 2 not taken.
51854 applyComparison<ComputeJac>(d.comparison, d.inequalityIndices, d.error,
620 51854 d.jacobian, inequalityThreshold_);
621
622 // Copy columns that are not reduced
623
1/2
✓ Branch 2 taken 23739 times.
✗ Branch 3 not taken.
47478 if (ComputeJac) d.reducedJ = d.activeRowsOfJ.rview(d.jacobian);
624 }
625 52078 }
626
627 template void HierarchicalIterative::computeValue<false>(
628 vectorIn_t config) const;
629 template void HierarchicalIterative::computeValue<true>(
630 vectorIn_t config) const;
631
632 22138 void HierarchicalIterative::computeSaturation(vectorIn_t config) const {
633
2/4
✓ Branch 3 taken 22138 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 22138 times.
✗ Branch 7 not taken.
22138 bool applySaturate = saturate_->saturate(config, qSat_, saturation_);
634
2/2
✓ Branch 0 taken 20657 times.
✓ Branch 1 taken 1481 times.
22138 if (!applySaturate) return;
635
636
1/2
✓ Branch 2 taken 1481 times.
✗ Branch 3 not taken.
1481 reducedSaturation_ = freeVariables_.rview(saturation_);
637
10/20
✓ Branch 1 taken 1481 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1481 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1481 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1481 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1481 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1481 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1481 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1481 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1481 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 1481 times.
1481 assert((reducedSaturation_.array() == -1 || reducedSaturation_.array() == 0 ||
638 reducedSaturation_.array() == 1)
639 .all());
640
641
2/2
✓ Branch 1 taken 1492 times.
✓ Branch 2 taken 1481 times.
2973 for (std::size_t i = 0; i < stacks_.size(); ++i) {
642 1492 Data& d = datas_[i];
643
644
3/6
✓ Branch 1 taken 1492 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1492 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1492 times.
✗ Branch 8 not taken.
1492 vector_t error = d.activeRowsOfJ.keepRows().rview(d.error);
645 tmpSat_ = (reducedSaturation_.cast<value_type>()
646
3/6
✓ Branch 1 taken 1492 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1492 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1492 times.
✗ Branch 8 not taken.
1492 .cwiseProduct(d.reducedJ.transpose() * error)
647
4/8
✓ Branch 1 taken 1492 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1492 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1492 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1492 times.
✗ Branch 11 not taken.
2984 .array() < 0);
648
2/2
✓ Branch 1 taken 49502 times.
✓ Branch 2 taken 1492 times.
50994 for (size_type j = 0; j < tmpSat_.size(); ++j)
649
5/8
✓ Branch 1 taken 49502 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2108 times.
✓ Branch 4 taken 47394 times.
✓ Branch 6 taken 2108 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2108 times.
✗ Branch 10 not taken.
49502 if (tmpSat_[j]) d.reducedJ.col(j).setZero();
650 1492 }
651 }
652
653 void HierarchicalIterative::getValue(vectorOut_t v) const {
654 size_type row = 0;
655 for (std::size_t i = 0; i < datas_.size(); ++i) {
656 const Data& d = datas_[i];
657 v.segment(row, d.output.vector().rows()) = d.output.vector();
658 row += d.output.vector().rows();
659 }
660 assert(v.rows() == row);
661 }
662
663 6 void HierarchicalIterative::getReducedJacobian(matrixOut_t J) const {
664 6 size_type row = 0;
665
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
12 for (std::size_t i = 0; i < datas_.size(); ++i) {
666 6 const Data& d = datas_[i];
667
1/2
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
6 J.middleRows(row, d.reducedJ.rows()) = d.reducedJ;
668 6 row += d.reducedJ.rows();
669 }
670
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 assert(J.rows() == row);
671 6 }
672
673 26033 void HierarchicalIterative::computeError() const {
674 const std::size_t end =
675
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 26026 times.
26033 (lastIsOptional_ ? stacks_.size() - 1 : stacks_.size());
676 26033 squaredNorm_ = 0;
677
2/2
✓ Branch 0 taken 25914 times.
✓ Branch 1 taken 26033 times.
51947 for (std::size_t i = 0; i < end; ++i) {
678 const ImplicitConstraintSet::Implicits_t constraints(
679
1/2
✓ Branch 3 taken 25914 times.
✗ Branch 4 not taken.
25914 stacks_[i].constraints());
680 25914 const Data& d = datas_[i];
681 25914 size_type iv = 0;
682
2/2
✓ Branch 1 taken 26877 times.
✓ Branch 2 taken 25914 times.
52791 for (std::size_t j = 0; j < constraints.size(); ++j) {
683 26877 size_type nv(constraints[j]->function().outputDerivativeSize());
684 26877 squaredNorm_ =
685
2/4
✓ Branch 1 taken 26877 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26877 times.
✗ Branch 5 not taken.
26877 std::max(squaredNorm_, d.error.segment(iv, nv).squaredNorm());
686 26877 iv += nv;
687 }
688 25914 }
689 26033 }
690
691 21925 bool HierarchicalIterative::integrate(vectorIn_t from, vectorIn_t velocity,
692 vectorOut_t result) const {
693 typedef pinocchio::LiegroupElementRef LgeRef_t;
694
1/2
✓ Branch 1 taken 21925 times.
✗ Branch 2 not taken.
21925 result = from;
695
1/2
✓ Branch 1 taken 21925 times.
✗ Branch 2 not taken.
21925 LgeRef_t M(result, configSpace_);
696
2/4
✓ Branch 1 taken 21925 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21925 times.
✗ Branch 5 not taken.
21925 M += velocity;
697
3/6
✓ Branch 2 taken 21925 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 21925 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 21925 times.
✗ Branch 9 not taken.
43850 return saturate_->saturate(result, result, saturation_);
698 21925 }
699
700 1392 void HierarchicalIterative::residualError(vectorOut_t error) const {
701 1392 size_type row = 0;
702
2/2
✓ Branch 1 taken 1388 times.
✓ Branch 2 taken 1392 times.
2780 for (std::size_t i = 0; i < datas_.size(); ++i) {
703 1388 const Data& d = datas_[i];
704
1/2
✓ Branch 3 taken 1388 times.
✗ Branch 4 not taken.
1388 error.segment(row, d.error.size()) = d.error;
705 1388 row += d.error.size();
706 }
707 1392 }
708
709 6 bool HierarchicalIterative::definesSubmanifoldOf(
710 const HierarchicalIterative& solver) const {
711 6 for (NumericalConstraints_t::const_iterator it(solver.constraints().begin());
712
2/2
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 6 times.
14 it != solver.constraints().end(); ++it) {
713 8 const DifferentiableFunctionPtr_t& f = (*it)->functionPtr();
714
1/2
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
8 if (find_if(constraints_.begin(), constraints_.end(),
715 10 [&f](const ImplicitPtr_t& arg) {
716 10 return arg->function() == *f;
717
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
16 }) == constraints_.end())
718 return false;
719 }
720 6 return true;
721 }
722
723 22138 void HierarchicalIterative::computeDescentDirection() const {
724 22138 sigma_ = std::numeric_limits<value_type>::max();
725
726
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22138 times.
22138 if (stacks_.empty()) {
727 dq_.setZero();
728 return;
729 }
730
1/2
✓ Branch 1 taken 22138 times.
✗ Branch 2 not taken.
22138 vector_t err;
731
2/2
✓ Branch 1 taken 21996 times.
✓ Branch 2 taken 142 times.
22138 if (stacks_.size() == 1) { // one level only
732 21996 Data& d = datas_[0];
733
1/2
✓ Branch 1 taken 21996 times.
✗ Branch 2 not taken.
21996 d.svd.compute(d.reducedJ);
734 HPP_DEBUG_SVDCHECK(d.svd);
735 // TODO Eigen::JacobiSVD does a dynamic allocation here.
736
4/8
✓ Branch 1 taken 21996 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21996 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 21996 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 21996 times.
✗ Branch 11 not taken.
21996 err = d.activeRowsOfJ.keepRows().rview(-d.error);
737
2/4
✓ Branch 1 taken 21996 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21996 times.
✗ Branch 5 not taken.
21996 dqSmall_ = d.svd.solve(err);
738
1/2
✓ Branch 1 taken 21996 times.
✗ Branch 2 not taken.
21996 d.maxRank = std::max(d.maxRank, d.svd.rank());
739
2/2
✓ Branch 0 taken 21995 times.
✓ Branch 1 taken 1 times.
21996 if (d.maxRank > 0)
740
2/4
✓ Branch 1 taken 21995 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21995 times.
✗ Branch 5 not taken.
21995 sigma_ = std::min(sigma_, d.svd.singularValues()[d.maxRank - 1]);
741 } else {
742 // dq = dQ_0 + P_0 * v_1
743 // f_1(q+dq) = f_1(q) + J_1 * dQ_0 + M_1 * v_1
744 // M_1 = J_1 * P_0
745 // v_1 = M+_1 * (-f_1(q) - J_1 * dQ_1) + K_1 * v_2
746 // dq = dQ_0 + P_0 * M+_1 * (-f_1(q) - J_1 * dQ_1) + P_0 * K_1 * v_2
747 // = dQ_1 + P_1 * b_2
748 //
749 // dQ_1 = dQ_0 + P_0 * M+_1 * (-f_1(q) - J_1 * dQ_1)
750 // P_1 = P_0 * K_1
751 142 matrix_t* projector = NULL;
752
1/2
✓ Branch 1 taken 284 times.
✗ Branch 2 not taken.
284 for (std::size_t i = 0; i < stacks_.size(); ++i) {
753 284 Data& d = datas_[i];
754
755 // TODO: handle case where this is the first element of the stack and it
756 // has no functions
757
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 284 times.
284 if (d.reducedJ.rows() == 0) continue;
758 /// projector is of size numberDof
759 284 bool first = (i == 0);
760 284 bool last = (i == stacks_.size() - 1);
761
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 142 times.
284 if (first) {
762
4/8
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 142 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 142 times.
✗ Branch 11 not taken.
142 err = d.activeRowsOfJ.keepRows().rview(-d.error);
763 // dq should be zero and projector should be identity
764
1/2
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
142 d.svd.compute(d.reducedJ);
765 HPP_DEBUG_SVDCHECK(d.svd);
766 // TODO Eigen::JacobiSVD does a dynamic allocation here.
767
2/4
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
142 dqSmall_ = d.svd.solve(err);
768 } else {
769
4/8
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 142 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 142 times.
✗ Branch 11 not taken.
142 err = d.activeRowsOfJ.keepRows().rview(-d.error);
770
3/6
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 142 times.
✗ Branch 8 not taken.
142 err.noalias() -= d.reducedJ * dqSmall_;
771
772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
142 if (projector == NULL) {
773 d.svd.compute(d.reducedJ);
774 // TODO Eigen::JacobiSVD does a dynamic allocation here.
775 dqSmall_ += d.svd.solve(err);
776 } else {
777
3/6
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 142 times.
✗ Branch 8 not taken.
142 d.svd.compute(d.reducedJ * *projector);
778 // TODO Eigen::JacobiSVD does a dynamic allocation here.
779
3/6
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 142 times.
✗ Branch 8 not taken.
142 dqSmall_ += *projector * d.svd.solve(err);
780 }
781 HPP_DEBUG_SVDCHECK(d.svd);
782 }
783 // Update sigma
784
1/2
✓ Branch 1 taken 284 times.
✗ Branch 2 not taken.
284 const size_type rank = d.svd.rank();
785 284 d.maxRank = std::max(d.maxRank, rank);
786
2/2
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 2 times.
284 if (d.maxRank > 0)
787
2/4
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 282 times.
✗ Branch 5 not taken.
282 sigma_ = std::min(sigma_, d.svd.singularValues()[d.maxRank - 1]);
788
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 284 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 284 times.
284 if (solveLevelByLevel_ && err.squaredNorm() > squaredErrorThreshold_)
789 142 break;
790
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 142 times.
284 if (last) break; // No need to compute projector for next step.
791
792
2/4
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 142 times.
142 if (d.svd.matrixV().cols() == rank) break; // The kernel is { 0 }
793 /// compute projector for next step.
794
1/2
✓ Branch 0 taken 142 times.
✗ Branch 1 not taken.
142 if (projector == NULL)
795
3/6
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 142 times.
✗ Branch 8 not taken.
142 d.PK.noalias() = getV2<SVD_t>(d.svd, rank);
796 else
797 d.PK.noalias() = *projector * getV2<SVD_t>(d.svd, rank);
798 142 projector = &d.PK;
799 }
800 }
801
1/2
✓ Branch 1 taken 22138 times.
✗ Branch 2 not taken.
22138 expandDqSmall();
802 22138 }
803
804 22138 void HierarchicalIterative::expandDqSmall() const {
805 44276 Eigen::MatrixBlockView<vector_t, Eigen::Dynamic, 1, false, true>(
806
1/2
✓ Branch 4 taken 22138 times.
✗ Branch 5 not taken.
22138 dq_, freeVariables_.nbIndices(), freeVariables_.indices()) = dqSmall_;
807 22138 }
808
809 3 std::ostream& HierarchicalIterative::print(std::ostream& os) const {
810 3 os << "HierarchicalIterative, " << stacks_.size() << " level." << iendl
811 3 << "max iter: " << maxIterations()
812 3 << ", error threshold: " << errorThreshold() << iendl << "dimension "
813 3 << dimension() << iendl << "reduced dimension " << reducedDimension()
814 3 << iendl << "free variables: " << freeVariables_ << incindent;
815 const std::size_t end =
816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 (lastIsOptional_ ? stacks_.size() - 1 : stacks_.size());
817
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 for (std::size_t i = 0; i < stacks_.size(); ++i) {
818 const ImplicitConstraintSet::Implicits_t constraints(
819
1/2
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
3 stacks_[i].constraints());
820 3 const Data& d = datas_[i];
821
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
3 os << iendl << "Level " << i;
822
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
3 if (lastIsOptional_ && i == end) os << " (optional)";
823
4/8
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
3 os << ": Stack of " << constraints.size() << " functions" << incindent;
824 3 size_type rv = 0, rq = 0;
825
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
8 for (std::size_t j = 0; j < constraints.size(); ++j) {
826 5 const DifferentiableFunctionPtr_t& f(constraints[j]->functionPtr());
827
6/12
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
✓ Branch 18 taken 5 times.
✗ Branch 19 not taken.
5 os << iendl << j << ": [" << rv << ", " << f->outputDerivativeSize()
828
5/10
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 5 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
5 << "]," << incindent << *f << iendl << "Rhs: "
829
4/8
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
5 << condensed(d.rightHandSide.vector().segment(rq, f->outputSize()))
830
4/8
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
5 << iendl << "active rows: " << condensed(constraints[j]->activeRows())
831
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 << decindent;
832 5 rv += f->outputDerivativeSize();
833 5 rq += f->outputSize();
834 }
835
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 os << decendl;
836
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 os << "Equality idx: " << d.equalityIndices;
837
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
3 os << iendl << "Active rows: " << d.activeRowsOfJ;
838 3 }
839 3 return os << decindent;
840 }
841
842 template HierarchicalIterative::Status HierarchicalIterative::solve(
843 vectorOut_t arg, lineSearch::Constant lineSearch) const;
844 template HierarchicalIterative::Status HierarchicalIterative::solve(
845 vectorOut_t arg, lineSearch::Backtracking lineSearch) const;
846 template HierarchicalIterative::Status HierarchicalIterative::solve(
847 vectorOut_t arg, lineSearch::FixedSequence lineSearch) const;
848 template HierarchicalIterative::Status HierarchicalIterative::solve(
849 vectorOut_t arg, lineSearch::ErrorNormBased lineSearch) const;
850
851 template <class Archive>
852 2 void HierarchicalIterative::load(Archive& ar, const unsigned int version) {
853 (void)version;
854
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(squaredErrorThreshold_);
855
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(inequalityThreshold_);
856
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(maxIterations_);
857
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(configSpace_);
858
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(lastIsOptional_);
859
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(saturate_);
860
861
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 saturation_.resize(configSpace_->nq());
862
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 qSat_.resize(configSpace_->nq());
863
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 OM_.resize(configSpace_->nv());
864
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 OP_.resize(configSpace_->nv());
865 // Initialize freeVariables_ to all indices.
866
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 freeVariables_.addRow(0, configSpace_->nv());
867
868 2 NumericalConstraints_t constraints;
869 2 std::vector<std::size_t> priorities;
870
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& boost::serialization::make_nvp("constraints_", constraints);
871
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(priorities);
872
873
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
8 for (std::size_t i = 0; i < constraints.size(); ++i)
874
1/2
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
6 add(constraints[i], priorities[i]);
875 // TODO load the right hand side.
876 }
877
878 template <class Archive>
879 2 void HierarchicalIterative::save(Archive& ar,
880 const unsigned int version) const {
881 (void)version;
882
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(squaredErrorThreshold_);
883
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(inequalityThreshold_);
884
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(maxIterations_);
885
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(configSpace_);
886
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(lastIsOptional_);
887
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(saturate_);
888
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(constraints_);
889
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 std::vector<std::size_t> priorities(constraints_.size());
890
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
8 for (std::size_t i = 0; i < constraints_.size(); ++i) {
891 6 const DifferentiableFunctionPtr_t& f = constraints_[i]->functionPtr();
892 std::map<DifferentiableFunctionPtr_t, std::size_t>::const_iterator c(
893
1/2
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
6 find_if(priority_.begin(), priority_.end(),
894 5 [&f](const priorityIt_t& arg) { return *arg.first == *f; }));
895
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
6 if (c == priority_.end())
896 2 priorities[i] = 0;
897 else
898 4 priorities[i] = c->second;
899 }
900
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 ar& BOOST_SERIALIZATION_NVP(priorities);
901 // TODO save the right hand side.
902 }
903
904 HPP_SERIALIZATION_SPLIT_IMPLEMENT(HierarchicalIterative);
905 } // namespace solver
906 } // namespace constraints
907 } // namespace hpp
908
909 12 BOOST_CLASS_EXPORT(hpp::constraints::solver::saturation::Bounds)
910 12 BOOST_CLASS_EXPORT(hpp::constraints::solver::saturation::Device)
911
912 namespace boost {
913 namespace serialization {
914 using namespace hpp::constraints::solver;
915
916 template <class Archive>
917 4 void serialize(Archive&, saturation::Base&, const unsigned int) {}
918 template <class Archive>
919 4 void serialize(Archive& ar, saturation::Device& o, const unsigned int version) {
920 (void)version;
921
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 ar& make_nvp("base", base_object<saturation::Base>(o));
922
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 ar& make_nvp("device", o.device);
923 }
924 template <class Archive>
925 void serialize(Archive& ar, saturation::Bounds& o, const unsigned int version) {
926 (void)version;
927 ar& make_nvp("base", base_object<saturation::Base>(o));
928 hpp::serialization::remove_duplicate::serialize_vector(ar, "lb", o.lb,
929 version);
930 hpp::serialization::remove_duplicate::serialize_vector(ar, "ub", o.ub,
931 version);
932 }
933 } // namespace serialization
934 } // namespace boost
935