codac 1.5.6
Loading...
Searching...
No Matches
codac2_Tube.h
Go to the documentation of this file.
1
12#ifndef __CODAC2_TUBE_H__
13#define __CODAC2_TUBE_H__
14
15#include <list>
16#include <memory>
17#include "codac_TFnc.h"
18#include "codac2_TSlice.h"
19#include "codac_Tube.h" // to be removed
20#include "codac_TubeVector.h" // to be removed
23#include "codac2_TDomain.h"
24#include "codac_ConvexPolygon.h"
25
26namespace codac2
27{
28 using codac::TFnc;
29 using codac::BoolInterval;
30
31 template<class T>
32 class Slice;
33 template<class T>
34 class TubeEvaluation;
35 template<class T>
36 class ConstTubeEvaluation;
37 template<class T>
38 class TubeComponent;
39
40
41 template<class T>
42 class Tube : public AbstractSlicedTube, public AbstractConstTube<T,Tube<T>>
43 {
44 public:
45
46 explicit Tube(const std::shared_ptr<TDomain>& tdomain) :
47 Tube(tdomain, T())
48 { }
49
50 explicit Tube(const std::shared_ptr<TDomain>& tdomain, const TFnc& f) :
51 Tube(tdomain, (std::is_same<T,Interval>::value ? T() : T(f.image_dim())))
52 {
53 assert(f.nb_var() == 0 && "function's inputs must be limited to system variable");
54 if constexpr(std::is_same<T,Interval>::value) {
55 assert(f.image_dim() == 1);
56 }
57
58 for(auto& s : *this)
59 {
60 if constexpr(std::is_same<T,Interval>::value)
61 s.set(f.eval(s.t0_tf()));
62
63 else
64 s.set(f.eval_vector(s.t0_tf()));
65
66 if(s.is_empty())
67 std::cout << "IS EMPTY: " << s << std::endl;
68 }
69 }
70
71 explicit Tube(const std::shared_ptr<TDomain>& tdomain, const T& default_value) :
72 AbstractSlicedTube(tdomain)
73 {
74 for(std::list<TSlice>::iterator it = _tdomain->_tslices.begin();
75 it != _tdomain->_tslices.end(); ++it)
76 {
77 it->_slices.insert(
78 std::pair<const AbstractSlicedTube*,std::shared_ptr<Slice<T>>>(this,
79 std::make_shared<Slice<T>>(default_value, *this, it)));
80 }
81 }
82
83 Tube(const Tube<T>& x) :
84 AbstractSlicedTube(x.tdomain())
85 {
86 for(std::list<TSlice>::iterator it = _tdomain->_tslices.begin();
87 it != _tdomain->_tslices.end(); ++it)
88 {
89 std::shared_ptr<Slice<T>> s_ptr = std::make_shared<Slice<T>>(x(it), *this);
90 it->_slices.insert(std::pair<const AbstractSlicedTube*,std::shared_ptr<Slice<T>>>(this, s_ptr));
91 }
92 }
93
94 ~Tube()
95 {
96 for(auto& s : _tdomain->_tslices)
97 s._slices.erase(this);
98 }
99
100 Tube& operator=(const Tube& x)
101 {
102 if(_tdomain != x._tdomain)
103 throw std::exception(); // todo: better exception
104
105 for(auto it = _tdomain->_tslices.begin();
106 it != _tdomain->_tslices.end(); ++it)
107 (*this)(it).set(x(it).codomain());
108
109 return *this;
110 }
111
112 virtual Interval t0_tf() const
113 {
114 return AbstractSlicedTube::t0_tf();
115 }
116
117 size_t size() const
118 {
119 // todo: define size() method in Interval class
120 if constexpr(std::is_same<T,Interval>::value)
121 return 1;
122 else
123 return first_slice().size();
124 }
125
126 size_t nb_slices() const
127 {
128 return _tdomain->nb_tslices();
129 }
130
131 double volume() const
132 {
133 double volume = 0.;
134 for(const auto& s : *this)
135 volume += s.volume();
136 return volume;
137 }
138
139 virtual const std::shared_ptr<AbstractSlice>& first_abstract_slice_ptr() const
140 {
141 return _tdomain->tslices().front().slices().at(this);
142 }
143
144 virtual const std::shared_ptr<AbstractSlice>& last_abstract_slice_ptr() const
145 {
146 return _tdomain->tslices().back().slices().at(this);
147 }
148
149 const std::shared_ptr<Slice<T>> first_slice_ptr() const
150 {
151 return std::static_pointer_cast<Slice<T>>(first_abstract_slice_ptr());
152 }
153
154 const Slice<T>& first_slice() const
155 {
156 return *first_slice_ptr();
157 }
158
159 Slice<T>& first_slice()
160 {
161 return const_cast<Slice<T>&>(
162 static_cast<const Tube&>(*this).first_slice());
163 }
164
165 const std::shared_ptr<Slice<T>> last_slice_ptr() const
166 {
167 return std::static_pointer_cast<Slice<T>>(last_abstract_slice_ptr());
168 }
169
170 const Slice<T>& last_slice() const
171 {
172 return *last_slice_ptr();
173 }
174
175 Slice<T>& last_slice()
176 {
177 return const_cast<Slice<T>&>(
178 static_cast<const Tube&>(*this).last_slice());
179 }
180
181 bool is_empty() const
182 {
183 // Fast evaluation by considering gates first, then envelopes,
184 // which allows to quickly identify an empty set
185 for(const auto& s : *this)
186 if(s.is_gate() && s.is_empty())
187 return true;
188 for(const auto& s : *this)
189 if(!s.is_gate() && s.is_empty())
190 return true;
191 return false;
192 }
193
194 bool is_unbounded() const
195 {
196 for(const auto& s : *this)
197 if(s.is_unbounded())
198 return true;
199 return false;
200 }
201
202 BoolInterval contains(const TrajectoryVector& x) const
203 {
204 assert(x.tdomain() == tdomain()->t0_tf());
205
206 BoolInterval result = BoolInterval::YES;
207 for(const auto& s : *this)
208 {
209 if(s.is_gate()) continue;
210 BoolInterval b = s.contains(x);
211 if(b == BoolInterval::NO) return BoolInterval::NO;
212 else if(b == BoolInterval::MAYBE) result = BoolInterval::MAYBE;
213 }
214
215 return result;
216 }
217
218 T codomain() const
219 {
220 T codomain = first_slice().codomain();
221 codomain.set_empty();
222 for(const auto& s : *this)
223 codomain |= s.codomain();
224 return codomain;
225 }
226
227 // Remove this? (direct access with () )
228 std::shared_ptr<Slice<T>> slice_ptr(const std::list<TSlice>::iterator& it)
229 {
230 return std::static_pointer_cast<Slice<T>>(it->slices().at(this));
231 }
232
233 Slice<T>& operator()(const std::list<TSlice>::iterator& it)
234 {
235 return const_cast<Slice<T>&>(
236 static_cast<const Tube&>(*this).operator()(it));
237 }
238
239 const Slice<T>& operator()(const std::list<TSlice>::iterator& it) const
240 {
241 return *std::static_pointer_cast<Slice<T>>(it->slices().at(this));
242 }
243
244 TubeEvaluation<T> operator()(double t)
245 {
246 return TubeEvaluation<T>(this, t);
247 }
248
249 const TubeEvaluation<T> operator()(double t) const
250 {
251 return ConstTubeEvaluation<T>(this, t);
252 }
253
254 TubeEvaluation<T> operator()(const Interval& t)
255 {
256 return TubeEvaluation<T>(this, t);
257 }
258
259 const TubeEvaluation<T> operator()(const Interval& t) const
260 {
261 return TubeEvaluation<T>(this, t);
262 }
263
264 T eval(double t) const
265 {
266 if(!tdomain()->t0_tf().contains(t))
267 {
268 if constexpr(!std::is_same<T,codac::IntervalVector>::value)
269 return T();
270 else
271 return T(size());
272 }
273 std::list<TSlice>::iterator it_t = _tdomain->iterator_tslice(t);
274 assert(it_t != _tdomain->_tslices.end());
275 T x = std::static_pointer_cast<Slice<T>>(it_t->_slices.at(this))->codomain();
276 if(!it_t->is_gate() && t==it_t->t0_tf().lb() && it_t!=_tdomain->_tslices.begin())
277 x &= std::static_pointer_cast<Slice<T>>((--it_t)->_slices.at(this))->codomain();
278 return x;
279 }
280
281 T eval(const Interval& t) const
282 {
283 if(!tdomain()->t0_tf().is_superset(t))
284 {
285 if constexpr(!std::is_same<T,codac::IntervalVector>::value)
286 return T();
287 else
288 return T(size());
289 }
290
291 if(t.is_degenerated())
292 return eval(t.lb());
293
294 std::list<TSlice>::iterator it = _tdomain->iterator_tslice(t.lb());
295 T codomain = std::static_pointer_cast<Slice<T>>(it->_slices.at(this))->codomain();
296
297 while(it != std::next(_tdomain->iterator_tslice(t.ub())))
298 {
299 if(it->t0_tf().lb() == t.ub()) break;
300 codomain |= std::static_pointer_cast<Slice<T>>(it->_slices.at(this))->codomain();
301 it++;
302 }
303
304 return codomain;
305 }
306
307 void set(const T& codomain)
308 {
309 if constexpr(std::is_same<T,codac::IntervalVector>::value) {
310 assert((size_t)codomain.size() == size());
311 }
312 for(auto& s : *this)
313 if(!s.is_gate())
314 s.set(codomain);
315 for(auto& s : *this)
316 if(s.is_gate())
317 s.set(codomain);
318 }
319
320 void set(const T& codomain, double t)
321 {
322 if constexpr(std::is_same<T,codac::IntervalVector>::value) {
323 assert((size_t)codomain.size() == size());
324 }
325 std::list<TSlice>::iterator it = _tdomain->sample(t,true);
326 (*this)(it).set(codomain);
327 }
328
329 const Tube<T>& inflate(double rad)
330 {
331 for(auto& s : *this)
332 if(!s.is_gate())
333 s.inflate(rad);
334 for(auto& s : *this)
335 if(s.is_gate())
336 s.inflate(rad);
337 return *this;
338 }
339
340 TubeComponent<T> operator[](size_t i)
341 {
342 assert(i >= 0 && i < size());
343 return TubeComponent<T>(*this, i);
344 }
345
346 bool operator==(const Tube& x) const
347 {
348 if(!TDomain::are_same(tdomain(), x.tdomain()))
349 return false;
350
351 std::list<TSlice>::iterator it_this = _tdomain->_tslices.begin();
352 std::list<TSlice>::const_iterator it_x = x.tdomain()->tslices().cbegin();
353
354 while(it_this != _tdomain->tslices().end())
355 {
356 if(*std::static_pointer_cast<Slice<T>>(it_this->_slices.at(this)) !=
357 *std::static_pointer_cast<Slice<T>>(it_x->slices().at(&x)))
358 return false;
359 it_this++; it_x++;
360 }
361
362 return true;
363 }
364
365 Tube operator&=(const Tube& x)
366 {
367 assert(TDomain::are_same(tdomain(), x.tdomain()));
368 std::list<TSlice>::iterator it_this = _tdomain->_tslices.begin();
369 std::list<TSlice>::const_iterator it_x = x.tdomain()->tslices().cbegin();
370
371 while(it_this != _tdomain->tslices().end())
372 {
373 std::shared_ptr<Slice<T>> s = std::static_pointer_cast<Slice<T>>(it_this->_slices.at(this));
374 s->set(s->codomain() & std::static_pointer_cast<Slice<T>>(it_x->slices().at(&x))->codomain());
375 it_this++; it_x++;
376 }
377
378 assert(it_x == x.tdomain()->tslices().cend());
379 return *this;
380 }
381
382 friend std::ostream& operator<<(std::ostream& os, const Tube<T>& x)
383 {
384 x.AbstractConstTube<T,Tube<T>>::print(os);
385 // Adding information related to sliced structure
386 os << ", " << x.nb_slices()
387 << " slice" << (x.nb_slices() > 1 ? "s" : "")
388 << std::flush;
389 return os;
390 }
391
392
393 public:
394
395 using base_container = std::list<TSlice>;
396
397 struct iterator : public base_container::iterator
398 {
399 using iterator_category = typename base_container::iterator::iterator_category;
400 using difference_type = typename base_container::iterator::difference_type;
401
402 using value_type = Slice<T>;
403 using pointer = Slice<T>*;
404 using reference = Slice<T>&;
405
406 public:
407
408 iterator(const Tube& x, base_container::iterator it) :
409 base_container::iterator(it), _x(x) { }
410
411 reference operator*()
412 {
413 return static_cast<reference>(*((*this)->_slices.at(&_x)));
414 }
415
416 protected:
417
418 const Tube& _x;
419 };
420
421 iterator begin() { return iterator(*this, _tdomain->_tslices.begin()); }
422 iterator end() { return iterator(*this, _tdomain->_tslices.end()); }
423
424 struct reverse_iterator : public base_container::reverse_iterator
425 {
426 using iterator_category = typename base_container::reverse_iterator::iterator_category;
427 using difference_type = typename base_container::reverse_iterator::difference_type;
428
429 using value_type = Slice<T>;
430 using pointer = Slice<T>*;
431 using reference = Slice<T>&;
432
433 public:
434
435 reverse_iterator(const Tube& x, base_container::reverse_iterator it) :
436 base_container::reverse_iterator(it), _x(x) { }
437
438 reference operator*()
439 {
440 return static_cast<reference>(*((*this)->_slices.at(&_x)));
441 }
442
443 protected:
444
445 const Tube& _x;
446 };
447
448 reverse_iterator rbegin() { return reverse_iterator(*this, _tdomain->_tslices.rbegin()); }
449 reverse_iterator rend() { return reverse_iterator(*this, _tdomain->_tslices.rend()); }
450
451 struct const_iterator : public base_container::const_iterator
452 {
453 using iterator_category = typename base_container::const_iterator::iterator_category;
454 using difference_type = typename base_container::const_iterator::difference_type;
455
456 using value_type = Slice<T>;
457 using pointer = const Slice<T>*;
458 using reference = const Slice<T>&;
459
460 public:
461
462 const_iterator(const Tube& x, base_container::const_iterator it) :
463 base_container::const_iterator(it), _x(x) { }
464
465 reference operator*() const
466 {
467 return static_cast<reference>(*((*this)->_slices.at(&_x)));
468 }
469
470 protected:
471
472 const Tube& _x;
473 };
474
475 const_iterator begin() const { return const_iterator(*this, _tdomain->_tslices.cbegin()); }
476 const_iterator end() const { return const_iterator(*this, _tdomain->_tslices.cend()); }
477 };
478
479 codac::Tube to_codac1(const codac2::Tube<Interval>& x);
480 codac::TubeVector to_codac1(const codac2::Tube<codac::IntervalVector>& x);
481 codac::TubeVector to_codac1_poly(const codac2::Tube<codac::ConvexPolygon>& x);
482 codac2::Tube<Interval> to_codac2(const codac::Tube& x);
483 codac2::Tube<codac::IntervalVector> to_codac2(const codac::TubeVector& x);
484 codac2::Tube<codac::ConvexPolygon> to_codac2_poly(const codac::TubeVector& x);
485
486
487 #include "codac2_TubeEvaluation.h"
488 #include "codac2_TubeComponent.h"
489
490} // namespace codac
491
492#endif
One dimensional tube , defined as an interval of scalar trajectories.
Definition codac_Tube.h:48
n-dimensional tube , defined as an interval of n-dimensional trajectories
Definition codac_TubeVector.h:39