codac  1.5.7
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 
26 namespace 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