codac 2.0.0
Loading...
Searching...
No Matches
codac2_Slice.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include "codac2_SliceBase.h"
14#include "codac2_CtcDeriv.h"
15#include "codac2_cart_prod.h"
16#include "codac2_trunc.h"
17
18namespace codac2
19{
20 template<class T>
21 class Slice : public SliceBase,
22 protected T
23 // T class inheritance is protected, because modifying a
24 // Slice's codomain can affect adjacent gates if they exist
25 {
26 public:
27
28 explicit Slice(const SlicedTubeBase& tube, const std::list<TSlice>::iterator& it_tslice, const T& codomain)
29 : SliceBase(tube, it_tslice), T(codomain)
30 { }
31
32 Slice(const Slice& s, const SlicedTubeBase& tube)
33 : SliceBase(tube, s._it_tslice), T(s.codomain())
34 { }
35
36 // Slice objects cannot be copyable or movable,
37 // as they are supposed to be connected to other Slice objects
38 Slice(const Slice& s) = delete;
39 Slice& operator=(const Slice&) = delete;
40 Slice(Slice&&) = delete;
41 Slice& operator=(Slice&&) = delete;
42
43 inline const SlicedTube<T>& tube() const
44 {
45 return static_cast<const SlicedTube<T>&>(_tube);
46 }
47
48 inline virtual std::shared_ptr<SliceBase> copy() const
49 {
50 return std::make_shared<Slice>(*this, this->_tube);
51 }
52
53 inline Index size() const
54 {
55 return this->T::size();
56 }
57
58 inline T& codomain()
59 {
60 return (T&)(*this);
61 }
62
63 inline const T& codomain() const
64 {
65 return (const T&)(*this);
66 }
67
68 inline bool is_gate() const
69 {
70 return t0_tf().is_degenerated();
71 }
72
73 inline std::shared_ptr<const Slice<T>> prev_slice() const
74 {
75 return std::static_pointer_cast<const Slice<T>>(
76 this->SliceBase::prev_slice());
77 }
78
79 inline std::shared_ptr<Slice<T>> prev_slice()
80 {
81 return std::const_pointer_cast<Slice<T>>(
82 static_cast<const Slice<T>&>(*this).prev_slice());
83 }
84
85 inline std::shared_ptr<const Slice<T>> next_slice() const
86 {
87 return std::static_pointer_cast<const Slice<T>>(
88 this->SliceBase::next_slice());
89 }
90
91 inline std::shared_ptr<Slice<T>> next_slice()
92 {
93 return std::const_pointer_cast<Slice<T>>(
94 static_cast<const Slice<T>&>(*this).next_slice());
95 }
96
97 inline T input_gate() const
98 {
99 if(!prev_slice())
100 return codomain();
101
102 else
103 {
104 if(prev_slice()->is_gate())
105 return prev_slice()->codomain();
106 else
107 return codomain() & prev_slice()->codomain();
108 }
109 }
110
111 inline T output_gate() const
112 {
113 if(!next_slice())
114 return codomain();
115
116 else
117 {
118 if(next_slice()->is_gate())
119 return next_slice()->codomain();
120 else
121 return codomain() & next_slice()->codomain();
122 }
123 }
124
125 inline std::pair<T,T> enclosed_bounds(const Interval& t) const
126 {
127 T x = *this; x.set_empty();
128 auto bounds = std::make_pair(x,x);
129
130 if(t.lb() < t0_tf().lb() || t.ub() > t0_tf().ub())
131 {
132 x.init(Interval(-oo,0));
133 bounds.first |= x;
134 x.init(Interval(0,oo));
135 bounds.second |= x;
136 }
137
138 if(t.contains(t0_tf().lb()))
139 {
140 bounds.first |= input_gate().lb();
141 bounds.second |= input_gate().ub();
142 }
143
144 if(t.contains(t0_tf().ub()))
145 {
146 bounds.first |= output_gate().lb();
147 bounds.second |= output_gate().ub();
148 }
149
150 if(t.is_subset(t0_tf()) && t != t0_tf().lb() && t != t0_tf().ub())
151 {
152 bounds.first |= this->lb();
153 bounds.second |= this->ub();
154 }
155
156 return bounds;
157 }
158
159 inline void set(const T& x, bool propagate = true)
160 {
161 assert_release(x.size() == this->size());
162 codomain() = x;
163 if(propagate)
164 update_adjacent_codomains();
165 }
166
167 inline void init()
168 {
169 this->T::init();
170 // Nothing to propagate to adjacent codomains
171 }
172
173 inline void set_empty()
174 {
175 set_empty(true);
176 }
177
178 inline bool operator==(const Slice& x) const
179 {
180 return codomain() == x.codomain();
181 }
182
183 inline ConvexPolygon polygon_slice(const Slice<T>& v) const
184 requires std::is_same_v<T,Interval>
185 {
186 const Interval& t = this->t0_tf();
187 Interval input = this->input_gate(), output = this->output_gate();
188
189 // /!\ .diam() method is not reliable (floating point result)
190 // -> We need to compute the diameter with intervals
191 Interval d = Interval(t.ub())-Interval(t.lb());
192
193 Interval proj_output = input + d * v;
194 Interval proj_input = output - d * v;
195
196 return CtcDeriv::polygon_slice(
197 t, *this,
198 input, proj_input,
199 output, proj_output,
200 v);
201 }
202
203 inline ConvexPolygon polygon_slice_i(const Slice<T>& v, Index i) const
204 requires std::is_same_v<T,IntervalVector>
205 {
206 const Interval& t = this->t0_tf();
207
208 // /!\ .diam() method is not reliable (floating point result)
209 // -> We need to compute the diameter with intervals
210 Interval d = Interval(t.ub())-Interval(t.lb());
211
212 Interval input = this->input_gate()[i], output = this->output_gate()[i];
213 Interval proj_output = input + d * v[i];
214 Interval proj_input = output - d * v[i];
215
216 return CtcDeriv::polygon_slice(
217 t, (*this)[i],
218 input, proj_input,
219 output, proj_output,
220 v[i]);
221 }
222
229 inline T operator()(double t) const
230 {
231 if(t == t0_tf().lb())
232 return input_gate();
233
234 else if(t == t0_tf().ub())
235 return output_gate();
236
237 else if(t0_tf().contains(t))
238 return codomain();
239
240 else
241 return all_reals_value();
242 }
243
250 inline T operator()(const Interval& t) const
251 {
252 if(t.is_degenerated())
253 return operator()(t.lb());
254
255 else if(t.is_subset(t0_tf()))
256 return codomain();
257
258 else
259 return all_reals_value();
260 }
261
270 inline T operator()(double t, const Slice<T>& v) const
271 requires (std::is_same_v<T,Interval> || std::is_same_v<T,IntervalVector>)
272 {
273 return operator()(Interval(t),v);
274 }
275
284 inline T operator()(const Interval& t, const Slice<T>& v) const
285 requires (std::is_same_v<T,Interval> || std::is_same_v<T,IntervalVector>)
286 {
287 if constexpr(std::is_same_v<T,Interval>)
288 return untrunc((polygon_slice(v) & ConvexPolygon(cart_prod(t,trunc(codomain())))).box()[1]);
289
290 else if constexpr(std::is_same_v<T,IntervalVector>)
291 {
292 T y = all_reals_value();
293 IntervalVector codom = codomain();
294 for(Index i = 0 ; i < size() ; i++)
295 y[i] &= untrunc((polygon_slice_i(v,i) & ConvexPolygon(cart_prod(t,trunc(codom[i])))).box()[1]);
296 return y;
297 }
298 }
299
307 inline Interval invert(const T& y, const Interval& t = Interval()) const
308 {
309 if(t.is_empty())
310 return Interval::empty();
311
312 else if(t.is_strict_superset(t0_tf()))
313 return Interval();
314
315 else if((t0_tf() & t) == t0_tf() && codomain().is_subset(y))
316 return t0_tf();
317
318 else if(t == t0_tf().lb())
319 {
320 if(y.intersects(input_gate()))
321 return t0_tf().lb();
322 else
323 return Interval::empty();
324 }
325
326 else if(t == t0_tf().ub())
327 {
328 if(y.intersects(output_gate()))
329 return t0_tf().ub();
330 else
331 return Interval::empty();
332 }
333
334 else
335 {
336 if(y.intersects(codomain()))
337 return t & t0_tf();
338 else
339 return Interval::empty();
340 }
341 }
342
353 inline Interval invert(const T& y, const Slice<T>& v, const Interval& t = Interval()) const
354 requires (std::is_same_v<T,Interval> || std::is_same_v<T,IntervalVector>)
355 {
356 if(t.is_empty() || y.is_empty())
357 return Interval::empty();
358
359 else if(!t.is_subset(t0_tf()))
360 return Interval();
361
362 else
363 {
364 if constexpr(std::is_same_v<T,Interval>)
365 return untrunc((polygon_slice(v) & ConvexPolygon(cart_prod(t,trunc(y)))).box()[0]);
366
367 else if constexpr(std::is_same_v<T,IntervalVector>)
368 {
369 Interval t_(t);
370 for(Index i = 0 ; i < size() ; i++)
371 if(!t_.is_empty())
372 t_ &= untrunc((polygon_slice_i(v,i) & ConvexPolygon(cart_prod(t_,trunc(y[i])))).box()[0]);
373 return t_;
374 }
375 }
376 }
377
378 friend inline std::ostream& operator<<(std::ostream& os, const Slice& x)
379 {
380 os << x.t0_tf()
381 << "↦" << x.codomain()
382 << std::flush;
383 return os;
384 }
385
386 inline T all_reals_value() const
387 {
388 T x = codomain();
389 x.init();
390 return x;
391 }
392
393 inline T empty_value() const
394 {
395 T x = codomain();
396 x.set_empty();
397 return x;
398 }
399
400
401 protected:
402
403 template<typename T_>
404 friend class SlicedTube;
405
406 inline void set_empty(bool propagate)
407 {
408 this->T::set_empty();
409 if(propagate)
410 update_adjacent_codomains();
411 }
412
413 inline void update_adjacent_codomains()
414 {
415 if(prev_slice())
416 {
417 assert(prev_slice()->size() == this->size());
418 if(is_gate())
419 codomain() &= prev_slice()->codomain();
420 else if(prev_slice()->is_gate())
421 prev_slice()->codomain() &= codomain();
422 }
423
424 if(next_slice())
425 {
426 assert(next_slice()->size() == this->size());
427 if(is_gate())
428 codomain() &= next_slice()->codomain();
429 else if(next_slice()->is_gate())
430 next_slice()->codomain() &= codomain();
431 }
432 }
433 };
434}
static Interval empty()
Provides an empty interval.
Definition codac2_Interval_impl.h:568
void set_empty()
Marks the interval matrix as empty.
Definition codac2_Matrix_addons_IntervalMatrixBase.h:141
auto lb() const
Returns a matrix containing the lower bounds of each interval element.
Definition codac2_MatrixBase_addons_IntervalMatrixBase.h:91
bool is_subset(const Matrix< codac2::Interval, RowsAtCompileTime, ColsAtCompileTime > &x) const
Checks whether this matrix is a subset of another interval matrix.
Definition codac2_MatrixBase_addons_IntervalMatrixBase.h:652
auto ub() const
Returns a matrix containing the upper bounds of each interval element.
Definition codac2_MatrixBase_addons_IntervalMatrixBase.h:103
bool contains(const Matrix< double, RowsAtCompileTime, ColsAtCompileTime > &x) const
Checks if this interval matrix contains the specified matrix x.
Definition codac2_MatrixBase_addons_IntervalMatrixBase.h:382
Definition codac2_OctaSym.h:21
Eigen::Matrix< Interval,-1, 1 > IntervalVector
Alias for a dynamic-size column vector of intervals.
Definition codac2_IntervalVector.h:25