GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/costs/cost-sum.hxx
Date: 2025-02-24 23:41:29
Exec Total Coverage
Lines: 146 171 85.4%
Branches: 114 466 24.5%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2023, LAAS-CNRS, University of Edinburgh,
5 // Heriot-Watt University
6 // Copyright note valid unless otherwise stated in individual files.
7 // All rights reserved.
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #include <iostream>
11
12 #include "crocoddyl/core/utils/exception.hpp"
13
14 namespace crocoddyl {
15
16 template <typename Scalar>
17 1798 CostModelSumTpl<Scalar>::CostModelSumTpl(std::shared_ptr<StateAbstract> state,
18 const std::size_t nu)
19 1798 : state_(state), nu_(nu), nr_(0), nr_total_(0) {}
20
21 template <typename Scalar>
22 65 CostModelSumTpl<Scalar>::CostModelSumTpl(std::shared_ptr<StateAbstract> state)
23 65 : state_(state), nu_(state->get_nv()), nr_(0), nr_total_(0) {}
24
25 template <typename Scalar>
26 1865 CostModelSumTpl<Scalar>::~CostModelSumTpl() {}
27
28 template <typename Scalar>
29 6125 void CostModelSumTpl<Scalar>::addCost(const std::string& name,
30 std::shared_ptr<CostModelAbstract> cost,
31 const Scalar weight, const bool active) {
32
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 6125 times.
6125 if (cost->get_nu() != nu_) {
33 throw_pretty(
34 name
35 << " cost item doesn't have the same control dimension (it should be " +
36 std::to_string(nu_) + ")");
37 }
38 std::pair<typename CostModelContainer::iterator, bool> ret =
39
3/6
✓ Branch 1 taken 6125 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6125 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6125 times.
✗ Branch 8 not taken.
6125 costs_.insert(std::make_pair(
40 name, std::make_shared<CostItem>(name, cost, weight, active)));
41
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6122 times.
6125 if (ret.second == false) {
42 std::cerr << "Warning: we couldn't add the " << name
43
4/8
✓ 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.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
3 << " cost item, it already existed." << std::endl;
44
2/2
✓ Branch 0 taken 6119 times.
✓ Branch 1 taken 3 times.
6122 } else if (active) {
45 6119 nr_ += cost->get_activation()->get_nr();
46 6119 nr_total_ += cost->get_activation()->get_nr();
47
1/2
✓ Branch 1 taken 6119 times.
✗ Branch 2 not taken.
6119 active_set_.insert(name);
48
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 } else if (!active) {
49 3 nr_total_ += cost->get_activation()->get_nr();
50
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 inactive_set_.insert(name);
51 }
52 6125 }
53
54 template <typename Scalar>
55 151 void CostModelSumTpl<Scalar>::removeCost(const std::string& name) {
56
1/2
✓ Branch 1 taken 151 times.
✗ Branch 2 not taken.
151 typename CostModelContainer::iterator it = costs_.find(name);
57
2/2
✓ Branch 2 taken 148 times.
✓ Branch 3 taken 3 times.
151 if (it != costs_.end()) {
58 148 nr_ -= it->second->cost->get_activation()->get_nr();
59 148 nr_total_ -= it->second->cost->get_activation()->get_nr();
60
1/2
✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
148 costs_.erase(it);
61
1/2
✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
148 active_set_.erase(name);
62
1/2
✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
148 inactive_set_.erase(name);
63 } else {
64 std::cerr << "Warning: we couldn't remove the " << name
65
4/8
✓ 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.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
3 << " cost item, it doesn't exist." << std::endl;
66 }
67 151 }
68
69 template <typename Scalar>
70 21 void CostModelSumTpl<Scalar>::changeCostStatus(const std::string& name,
71 const bool active) {
72
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
21 typename CostModelContainer::iterator it = costs_.find(name);
73
2/2
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 3 times.
21 if (it != costs_.end()) {
74
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 15 times.
18 if (active && !it->second->active) {
75 3 nr_ += it->second->cost->get_activation()->get_nr();
76
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 active_set_.insert(name);
77
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 inactive_set_.erase(name);
78 3 it->second->active = active;
79
3/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
15 } else if (!active && it->second->active) {
80 15 nr_ -= it->second->cost->get_activation()->get_nr();
81
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 active_set_.erase(name);
82
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 inactive_set_.insert(name);
83 15 it->second->active = active;
84 }
85 } else {
86 std::cerr << "Warning: we couldn't change the status of the " << name
87
4/8
✓ 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.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
3 << " cost item, it doesn't exist." << std::endl;
88 }
89 21 }
90
91 template <typename Scalar>
92 77890 void CostModelSumTpl<Scalar>::calc(const std::shared_ptr<CostDataSum>& data,
93 const Eigen::Ref<const VectorXs>& x,
94 const Eigen::Ref<const VectorXs>& u) {
95
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 77890 times.
77890 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
96 throw_pretty(
97 "Invalid argument: " << "x has wrong dimension (it should be " +
98 std::to_string(state_->get_nx()) + ")");
99 }
100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77890 times.
77890 if (static_cast<std::size_t>(u.size()) != nu_) {
101 throw_pretty(
102 "Invalid argument: " << "u has wrong dimension (it should be " +
103 std::to_string(nu_) + ")");
104 }
105
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 77890 times.
77890 if (data->costs.size() != costs_.size()) {
106 throw_pretty("Invalid argument: "
107 << "it doesn't match the number of cost datas and models");
108 }
109 77890 data->cost = Scalar(0.);
110
111 77890 typename CostModelContainer::iterator it_m, end_m;
112 77890 typename CostDataContainer::iterator it_d, end_d;
113 155780 for (it_m = costs_.begin(), end_m = costs_.end(), it_d = data->costs.begin(),
114 77890 end_d = data->costs.end();
115
5/6
✓ Branch 3 taken 77890 times.
✓ Branch 4 taken 353435 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 77890 times.
✓ Branch 8 taken 353435 times.
✓ Branch 9 taken 77890 times.
431325 it_m != end_m || it_d != end_d; ++it_m, ++it_d) {
116 353435 const std::shared_ptr<CostItem>& m_i = it_m->second;
117
2/2
✓ Branch 1 taken 353423 times.
✓ Branch 2 taken 12 times.
353435 if (m_i->active) {
118 353423 const std::shared_ptr<CostDataAbstract>& d_i = it_d->second;
119
1/18
✗ Branch 3 not taken.
✓ Branch 4 taken 353423 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
353423 assert_pretty(it_m->first == it_d->first,
120 "it doesn't match the cost name between model and data ("
121 << it_m->first << " != " << it_d->first << ")");
122
123
1/2
✓ Branch 3 taken 353423 times.
✗ Branch 4 not taken.
353423 m_i->cost->calc(d_i, x, u);
124 353423 data->cost += m_i->weight * d_i->cost;
125 }
126 }
127 77890 }
128
129 template <typename Scalar>
130 14176 void CostModelSumTpl<Scalar>::calc(const std::shared_ptr<CostDataSum>& data,
131 const Eigen::Ref<const VectorXs>& x) {
132
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 14176 times.
14176 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
133 throw_pretty(
134 "Invalid argument: " << "x has wrong dimension (it should be " +
135 std::to_string(state_->get_nx()) + ")");
136 }
137
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 14176 times.
14176 if (data->costs.size() != costs_.size()) {
138 throw_pretty("Invalid argument: "
139 << "it doesn't match the number of cost datas and models");
140 }
141 14176 data->cost = Scalar(0.);
142
143 14176 typename CostModelContainer::iterator it_m, end_m;
144 14176 typename CostDataContainer::iterator it_d, end_d;
145 28352 for (it_m = costs_.begin(), end_m = costs_.end(), it_d = data->costs.begin(),
146 14176 end_d = data->costs.end();
147
5/6
✓ Branch 3 taken 14176 times.
✓ Branch 4 taken 69443 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14176 times.
✓ Branch 8 taken 69443 times.
✓ Branch 9 taken 14176 times.
83619 it_m != end_m || it_d != end_d; ++it_m, ++it_d) {
148 69443 const std::shared_ptr<CostItem>& m_i = it_m->second;
149
2/2
✓ Branch 1 taken 69437 times.
✓ Branch 2 taken 6 times.
69443 if (m_i->active) {
150 69437 const std::shared_ptr<CostDataAbstract>& d_i = it_d->second;
151
1/18
✗ Branch 3 not taken.
✓ Branch 4 taken 69437 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
69437 assert_pretty(it_m->first == it_d->first,
152 "it doesn't match the cost name between model and data ("
153 << it_m->first << " != " << it_d->first << ")");
154
155
1/2
✓ Branch 3 taken 69437 times.
✗ Branch 4 not taken.
69437 m_i->cost->calc(d_i, x);
156 69437 data->cost += m_i->weight * d_i->cost;
157 }
158 }
159 14176 }
160
161 template <typename Scalar>
162 13746 void CostModelSumTpl<Scalar>::calcDiff(const std::shared_ptr<CostDataSum>& data,
163 const Eigen::Ref<const VectorXs>& x,
164 const Eigen::Ref<const VectorXs>& u) {
165
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 13746 times.
13746 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
166 throw_pretty(
167 "Invalid argument: " << "x has wrong dimension (it should be " +
168 std::to_string(state_->get_nx()) + ")");
169 }
170
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13746 times.
13746 if (static_cast<std::size_t>(u.size()) != nu_) {
171 throw_pretty(
172 "Invalid argument: " << "u has wrong dimension (it should be " +
173 std::to_string(nu_) + ")");
174 }
175
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 13746 times.
13746 if (data->costs.size() != costs_.size()) {
176 throw_pretty("Invalid argument: "
177 << "it doesn't match the number of cost datas and models");
178 }
179
1/2
✓ Branch 2 taken 13746 times.
✗ Branch 3 not taken.
13746 data->Lx.setZero();
180
1/2
✓ Branch 2 taken 13746 times.
✗ Branch 3 not taken.
13746 data->Lu.setZero();
181
1/2
✓ Branch 2 taken 13746 times.
✗ Branch 3 not taken.
13746 data->Lxx.setZero();
182
1/2
✓ Branch 2 taken 13746 times.
✗ Branch 3 not taken.
13746 data->Lxu.setZero();
183
1/2
✓ Branch 2 taken 13746 times.
✗ Branch 3 not taken.
13746 data->Luu.setZero();
184
185 13746 typename CostModelContainer::iterator it_m, end_m;
186 13746 typename CostDataContainer::iterator it_d, end_d;
187 27492 for (it_m = costs_.begin(), end_m = costs_.end(), it_d = data->costs.begin(),
188 13746 end_d = data->costs.end();
189
5/6
✓ Branch 3 taken 13746 times.
✓ Branch 4 taken 59550 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 13746 times.
✓ Branch 8 taken 59550 times.
✓ Branch 9 taken 13746 times.
73296 it_m != end_m || it_d != end_d; ++it_m, ++it_d) {
190 59550 const std::shared_ptr<CostItem>& m_i = it_m->second;
191
2/2
✓ Branch 1 taken 59544 times.
✓ Branch 2 taken 6 times.
59550 if (m_i->active) {
192 59544 const std::shared_ptr<CostDataAbstract>& d_i = it_d->second;
193
1/18
✗ Branch 3 not taken.
✓ Branch 4 taken 59544 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
59544 assert_pretty(it_m->first == it_d->first,
194 "it doesn't match the cost name between model and data ("
195 << it_m->first << " != " << it_d->first << ")");
196
197
1/2
✓ Branch 3 taken 59544 times.
✗ Branch 4 not taken.
59544 m_i->cost->calcDiff(d_i, x, u);
198
2/4
✓ Branch 3 taken 59544 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 59544 times.
✗ Branch 8 not taken.
59544 data->Lx += m_i->weight * d_i->Lx;
199
2/4
✓ Branch 3 taken 59544 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 59544 times.
✗ Branch 8 not taken.
59544 data->Lu += m_i->weight * d_i->Lu;
200
2/4
✓ Branch 3 taken 59544 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 59544 times.
✗ Branch 8 not taken.
59544 data->Lxx += m_i->weight * d_i->Lxx;
201
2/4
✓ Branch 3 taken 59544 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 59544 times.
✗ Branch 8 not taken.
59544 data->Lxu += m_i->weight * d_i->Lxu;
202
2/4
✓ Branch 3 taken 59544 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 59544 times.
✗ Branch 8 not taken.
59544 data->Luu += m_i->weight * d_i->Luu;
203 }
204 }
205 13746 }
206
207 template <typename Scalar>
208 625 void CostModelSumTpl<Scalar>::calcDiff(const std::shared_ptr<CostDataSum>& data,
209 const Eigen::Ref<const VectorXs>& x) {
210
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 625 times.
625 if (static_cast<std::size_t>(x.size()) != state_->get_nx()) {
211 throw_pretty(
212 "Invalid argument: " << "x has wrong dimension (it should be " +
213 std::to_string(state_->get_nx()) + ")");
214 }
215
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 625 times.
625 if (data->costs.size() != costs_.size()) {
216 throw_pretty("Invalid argument: "
217 << "it doesn't match the number of cost datas and models");
218 }
219
1/2
✓ Branch 2 taken 625 times.
✗ Branch 3 not taken.
625 data->Lx.setZero();
220
1/2
✓ Branch 2 taken 625 times.
✗ Branch 3 not taken.
625 data->Lxx.setZero();
221
222 625 typename CostModelContainer::iterator it_m, end_m;
223 625 typename CostDataContainer::iterator it_d, end_d;
224 1250 for (it_m = costs_.begin(), end_m = costs_.end(), it_d = data->costs.begin(),
225 625 end_d = data->costs.end();
226
5/6
✓ Branch 3 taken 625 times.
✓ Branch 4 taken 2816 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 625 times.
✓ Branch 8 taken 2816 times.
✓ Branch 9 taken 625 times.
3441 it_m != end_m || it_d != end_d; ++it_m, ++it_d) {
227 2816 const std::shared_ptr<CostItem>& m_i = it_m->second;
228
2/2
✓ Branch 1 taken 2810 times.
✓ Branch 2 taken 6 times.
2816 if (m_i->active) {
229 2810 const std::shared_ptr<CostDataAbstract>& d_i = it_d->second;
230
1/18
✗ Branch 3 not taken.
✓ Branch 4 taken 2810 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
2810 assert_pretty(it_m->first == it_d->first,
231 "it doesn't match the cost name between model and data ("
232 << it_m->first << " != " << it_d->first << ")");
233
234
1/2
✓ Branch 3 taken 2810 times.
✗ Branch 4 not taken.
2810 m_i->cost->calcDiff(d_i, x);
235
2/4
✓ Branch 3 taken 2810 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 2810 times.
✗ Branch 8 not taken.
2810 data->Lx += m_i->weight * d_i->Lx;
236
2/4
✓ Branch 3 taken 2810 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 2810 times.
✗ Branch 8 not taken.
2810 data->Lxx += m_i->weight * d_i->Lxx;
237 }
238 }
239 625 }
240
241 template <typename Scalar>
242 96256 std::shared_ptr<CostDataSumTpl<Scalar> > CostModelSumTpl<Scalar>::createData(
243 DataCollectorAbstract* const data) {
244 return std::allocate_shared<CostDataSum>(
245
1/2
✓ Branch 2 taken 96256 times.
✗ Branch 3 not taken.
192512 Eigen::aligned_allocator<CostDataSum>(), this, data);
246 }
247
248 template <typename Scalar>
249 const std::shared_ptr<StateAbstractTpl<Scalar> >&
250 771392 CostModelSumTpl<Scalar>::get_state() const {
251 771392 return state_;
252 }
253
254 template <typename Scalar>
255 const typename CostModelSumTpl<Scalar>::CostModelContainer&
256 628332 CostModelSumTpl<Scalar>::get_costs() const {
257 628332 return costs_;
258 }
259
260 template <typename Scalar>
261 771482 std::size_t CostModelSumTpl<Scalar>::get_nu() const {
262 771482 return nu_;
263 }
264
265 template <typename Scalar>
266 1513 std::size_t CostModelSumTpl<Scalar>::get_nr() const {
267 1513 return nr_;
268 }
269
270 template <typename Scalar>
271 15 std::size_t CostModelSumTpl<Scalar>::get_nr_total() const {
272 15 return nr_total_;
273 }
274
275 template <typename Scalar>
276 3 const std::set<std::string>& CostModelSumTpl<Scalar>::get_active_set() const {
277 3 return active_set_;
278 }
279
280 template <typename Scalar>
281 3 const std::set<std::string>& CostModelSumTpl<Scalar>::get_inactive_set() const {
282 3 return inactive_set_;
283 }
284
285 template <typename Scalar>
286 bool CostModelSumTpl<Scalar>::getCostStatus(const std::string& name) const {
287 typename CostModelContainer::const_iterator it = costs_.find(name);
288 if (it != costs_.end()) {
289 return it->second->active;
290 } else {
291 std::cerr << "Warning: we couldn't get the status of the " << name
292 << " cost item, it doesn't exist." << std::endl;
293 return false;
294 }
295 }
296
297 template <typename Scalar>
298 3 std::ostream& operator<<(std::ostream& os,
299 const CostModelSumTpl<Scalar>& model) {
300 3 const std::set<std::string>& active = model.get_active_set();
301 3 const std::set<std::string>& inactive = model.get_inactive_set();
302 3 os << "CostModelSum:" << std::endl;
303 3 os << " Active:" << std::endl;
304 3 for (std::set<std::string>::const_iterator it = active.begin();
305
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 it != active.end(); ++it) {
306 const std::shared_ptr<typename CostModelSumTpl<Scalar>::CostItem>&
307 cost_item = model.get_costs().find(*it)->second;
308 if (it != --active.end()) {
309 os << " " << *it << ": " << *cost_item << std::endl;
310 } else {
311 os << " " << *it << ": " << *cost_item << std::endl;
312 }
313 }
314 3 os << " Inactive:" << std::endl;
315 3 for (std::set<std::string>::const_iterator it = inactive.begin();
316
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 it != inactive.end(); ++it) {
317 const std::shared_ptr<typename CostModelSumTpl<Scalar>::CostItem>&
318 cost_item = model.get_costs().find(*it)->second;
319 if (it != --inactive.end()) {
320 os << " " << *it << ": " << *cost_item << std::endl;
321 } else {
322 os << " " << *it << ": " << *cost_item;
323 }
324 }
325 3 return os;
326 }
327
328 } // namespace crocoddyl
329