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