codac 2.0.0
Loading...
Searching...
No Matches
codac2_CtcInverse.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include <map>
14#include "codac2_Ctc.h"
15#include "codac2_CtcWrapper.h"
16#include "codac2_Collection.h"
17#include "codac2_arith_mul.h"
18#include "codac2_Wrapper.h"
19
20namespace codac2
21{
22 class CtcNot;
23
24 template<typename Y>
25 class CtcInverse_// : virtual public Ctc
26 {
27 public:
28
29 template<typename C>
30 requires IsCtcBaseOrPtr<C,Y>
31 CtcInverse_(const AnalyticFunction<typename ValueType<Y>::Type>& f, const C& ctc_y, bool with_centered_form = true, bool is_not_in = false)
32 : _f(f), _ctc_y(ctc_y), _with_centered_form(with_centered_form), _is_not_in(is_not_in)
33 {
34 assert_release([&]() { return f.output_size() == size_of(ctc_y); }()
35 && "CtcInverse_: invalid dimension of image argument ('y' or 'ctc_y')");
36 }
37
38 CtcInverse_(const AnalyticFunction<typename ValueType<Y>::Type>& f, const Y& y, bool with_centered_form = true, bool is_not_in = false)
39 : CtcInverse_(f, CtcWrapper<Y>(y), with_centered_form, is_not_in)
40 { }
41
42 //std::shared_ptr<CtcBase<X>> copy() const
43 //{
44 // return std::make_shared<CtcInverse_<Y>>(*this);
45 //}
46
47 template<typename... X>
48 void contract(X&... x) const
49 {
50 return contract_(*_ctc_y.front(), x...);
51 }
52
53 template<typename... X>
54 void contract_(const Y& y, X&... x) const
55 {
56 return contract_(CtcWrapper<Y>(y), x...);
57 }
58
59 template<typename... X>
60 void contract_(const CtcBase<Y>& ctc_y, X&... x) const
61 {
62 ValuesMap v;
63 // Setting user values into a map before the tree evaluation
64 _f.fill_from_args(v, x...);
65
66 // Forward/backward algorithm:
67
68 // [1/4] Forward evaluation
69 _f.expr()->fwd_eval(v, _f.args().total_size(), !_with_centered_form);
70 auto& val_expr = _f.expr()->value(v);
71
72 if(_is_not_in && !val_expr.def_domain)
73 return; // <-- iota: if the input x is outside the definition
74 // domain of one of the involved expressions, or their combinations,
75 // then the inner contraction is disabled.
76
77 // [2/4] Performing top contraction (from the root of the tree) with
78 // the contractor expressing the output domain Y.
79 // The underlying constraint is: f(x) \in [y]
80 ctc_y.contract(val_expr.a);
81
82 // [3/4 - optional]
83 // The contraction can be significantly improved using a centered form
84 // expression (enabled by default). This step must be processed before the
85 // backward part of the FwdBwd algorithm (the .m, .a values must not be
86 // changed before the centered evaluation).
87 if(_with_centered_form && val_expr.def_domain && !val_expr.da.is_unbounded() && val_expr.da.size() != 0)
88 {
89 // todo: the above condition !val_expr.da.is_unbounded() should not be necesary,
90 // possible bug in MulOp in case of unbounded domain?
91 using X0 = std::tuple_element_t<0, std::tuple<X...>>;
92
93 if constexpr(sizeof...(X) == 1 && std::is_same_v<X0,IntervalVector>)
94 {
95 X0& x_ = std::get<0>(std::tie(x...));
96 X0 x_mid = X0(x_.mid());
97
98 assert(val_expr.a.size() == val_expr.m.size());
99 IntervalVector fm { val_expr.a - val_expr.m };
100
101 if constexpr(std::is_same_v<Y,IntervalMatrix>)
102 {
103 std::cout << "CtcInverse_: matrices expressions not (yet) supported with centered form" << std::endl;
104 }
105
106 else
107 {
108 IntervalVector p = x_ - x_mid;
109 MulOp::bwd(fm, val_expr.da, p);
110 x_ &= p + x_mid;
111 }
112 }
113
114 else
115 {
116 // Centered form not (yet) implemented for multi-nonvector-arguments
117 }
118 }
119
120 // [4/4] Backward evaluation
121 _f.expr()->bwd_eval(v);
122 _f.intersect_from_args(v, x...); // updating input values
123 }
124
125 const AnalyticFunction<typename ValueType<Y>::Type>& function() const
126 {
127 return _f;
128 }
129
130 protected:
131
132 const AnalyticFunction<typename ValueType<Y>::Type> _f;
133 const Collection<CtcBase<Y>> _ctc_y;
134 bool _with_centered_form;
135 bool _is_not_in = false;
136 };
137
138 template<typename Y,typename X=IntervalVector>
139 class CtcInverse : public Ctc<CtcInverse<Y,X>,X>, public CtcInverse_<Y>
140 {
141 public:
142
143 CtcInverse(const AnalyticFunction<typename ValueType<Y>::Type>& f, const typename Wrapper<Y>::Domain& y, bool with_centered_form = true, bool is_not_in = false)
144 : Ctc<CtcInverse<Y,X>,X>(f.args()[0]->size() /* f must have only one arg, see following assert */),
145 CtcInverse_<Y>(f, y, with_centered_form,is_not_in)
146 {
147 assert_release(f.args().size() == 1 && "f must have only one arg");
148 }
149
150 template<typename C>
151 requires IsCtcBaseOrPtr<C,Y>
152 CtcInverse(const AnalyticFunction<typename ValueType<Y>::Type>& f, const C& ctc_y, bool with_centered_form = true, bool is_not_in = false)
153 : Ctc<CtcInverse<Y,X>,X>(f.args()[0]->size() /* f must have only one arg, see following assert */),
154 CtcInverse_<Y>(f, ctc_y, with_centered_form,is_not_in)
155 {
156 assert_release(f.args().size() == 1 && "f must have only one arg");
157 }
158
159 void contract(X& x) const
160 {
161 CtcInverse_<Y>::contract(x);
162 }
163 };
164
165 // Template deduction guides
166
167 // ScalarType
168
169 CtcInverse(const AnalyticFunction<ScalarType>&, std::initializer_list<double>, bool = true, bool = false) ->
170 CtcInverse<Interval,IntervalVector>;
171
172 template<typename Y>
173 CtcInverse(const AnalyticFunction<ScalarType>&, std::initializer_list<Y>, bool = true, bool = false) ->
174 CtcInverse<Interval,IntervalVector>;
175
176 CtcInverse(const AnalyticFunction<VectorType>&, const Interval&, bool = true, bool = false) ->
177 CtcInverse<Interval,IntervalVector>;
178
179 template<typename C>
180 requires IsCtcBaseOrPtr<C,Interval>
181 CtcInverse(const AnalyticFunction<ScalarType>&, const C&, bool = true, bool = false) ->
182 CtcInverse<Interval,IntervalVector>;
183
184 // VectorType
185
186 CtcInverse(const AnalyticFunction<VectorType>&, std::initializer_list<double>, bool = true, bool = false) ->
187 CtcInverse<IntervalVector,IntervalVector>;
188
189 CtcInverse(const AnalyticFunction<VectorType>&, std::initializer_list<std::initializer_list<double>>, bool = true, bool = false) ->
190 CtcInverse<IntervalVector,IntervalVector>;
191
192 CtcInverse(const AnalyticFunction<VectorType>&, const Vector&, bool = true, bool = false) ->
193 CtcInverse<IntervalVector,IntervalVector>;
194
195 CtcInverse(const AnalyticFunction<VectorType>&, const IntervalVector&, bool = true, bool = false) ->
196 CtcInverse<IntervalVector,IntervalVector>;
197
198 template<typename OtherDerived>
199 requires (OtherDerived::RowsAtCompileTime == -1 && OtherDerived::ColsAtCompileTime == 1)
200 CtcInverse(const AnalyticFunction<VectorType>&, const Eigen::MatrixBase<OtherDerived>&, bool = true, bool = false) ->
201 CtcInverse<IntervalVector,IntervalVector>;
202
203 template<typename C>
204 requires IsCtcBaseOrPtr<C,IntervalVector>
205 CtcInverse(const AnalyticFunction<VectorType>&, const C&, bool = true, bool = false) ->
206 CtcInverse<IntervalVector,IntervalVector>;
207
208 // MatrixType
209
210 CtcInverse(const AnalyticFunction<MatrixType>&, std::initializer_list<std::initializer_list<double>>, bool = true, bool = false) ->
211 CtcInverse<IntervalMatrix,IntervalVector>;
212
213 CtcInverse(const AnalyticFunction<MatrixType>&, std::initializer_list<std::initializer_list<std::initializer_list<double>>>, bool = true, bool = false) ->
214 CtcInverse<IntervalMatrix,IntervalVector>;
215
216 template<typename OtherDerived>
217 requires (OtherDerived::RowsAtCompileTime == -1 && OtherDerived::ColsAtCompileTime == -1)
218 CtcInverse(const AnalyticFunction<VectorType>&, const Eigen::MatrixBase<OtherDerived>&, bool = true, bool = false) ->
219 CtcInverse<IntervalMatrix,IntervalVector>;
220
221 template<typename C>
222 requires IsCtcBaseOrPtr<C,IntervalMatrix>
223 CtcInverse(const AnalyticFunction<MatrixType>&, const C&, bool = true, bool = false) ->
224 CtcInverse<IntervalMatrix,IntervalVector>;
225}
Interval class, for representing closed and connected subsets of .
Definition codac2_Interval.h:62