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