codac 2.0.0
Loading...
Searching...
No Matches
codac2_vec.h
1
9
10#pragma once
11
12#include <vector>
13
14#include "codac2_Interval.h"
17#include "codac2_AnalyticType.h"
19
20namespace codac2
21{
22 struct VectorOp
23 {
24 template<typename... X>
25 static inline std::string str(const X&... x)
26 {
27 std::string s = (("\t" + x->str() + ",\n") + ...);
28 s.pop_back(); s.pop_back(); // removes last separation
29 return "[\n" + s + "\n]";
30 }
31
32 template<typename... X>
33 static std::pair<Index,Index> output_shape([[maybe_unused]] const X&... x)
34 {
35 return { sizeof...(X), 1 };
36 }
37
38 template<typename... X>
39 requires (std::is_base_of_v<Interval,X> && ...)
40 static inline IntervalVector fwd(const X&... x)
41 {
42 return IntervalVector({x...});
43 }
44
45 template<typename... X>
46 requires (std::is_base_of_v<ScalarType,X> && ...)
47 static inline VectorType fwd_natural(const X&... x)
48 {
49 bool def_domain = true;
50 ((def_domain &= x.def_domain), ...);
51
52 return {
53 fwd(x.a...),
54 def_domain
55 };
56 }
57
58 template<typename... X>
59 requires (std::is_base_of_v<ScalarType,X> && ...)
60 static inline VectorType fwd_centered(const X&... x)
61 {
62 if(centered_form_not_available_for_args(x...))
63 return fwd_natural(x...);
64
65 IntervalMatrix d(sizeof...(X),std::get<0>(std::tie(x...)).da.cols());
66 Index i = 0;
67 ((d.row(i++) = x.da), ...);
68
69 bool def_domain = true;
70 ((def_domain &= x.def_domain), ...);
71
72 return {
73 fwd(x.m...),
74 fwd(x.a...),
75 d,
76 def_domain
77 };
78 }
79
80 template<typename... X>
81 requires (std::is_base_of_v<Interval,X> && ...)
82 static inline void bwd(const IntervalVector& y, X&... x)
83 {
84 Index i = 0;
85 ((x &= y[i++]), ...);
86 }
87 };
88
89 namespace detail
90 {
91 inline void replace_scalar_child(std::shared_ptr<AnalyticExpr<ScalarType>>& x,
92 const ExprID& old_arg_id, const std::shared_ptr<ExprBase>& new_expr)
93 {
94 if(x->unique_id() == old_arg_id)
95 {
96 auto new_x = std::dynamic_pointer_cast<AnalyticExpr<ScalarType>>(new_expr);
97 assert_release(new_x);
98 x = new_x;
99 }
100
101 else
102 x->replace_arg(old_arg_id, new_expr);
103 }
104
105 class DynamicVectorExpr final : public AnalyticExpr<VectorType>
106 {
107 public:
108
109 explicit DynamicVectorExpr(const std::vector<ScalarExpr>& xs)
110 {
111 _xs.reserve(xs.size());
112 for(const auto& x : xs)
113 {
114 auto sx = std::dynamic_pointer_cast<AnalyticExpr<ScalarType>>(x);
115 assert_release(sx);
116 _xs.push_back(sx);
117 }
118 }
119
120 DynamicVectorExpr(const DynamicVectorExpr& e)
121 {
122 _xs.reserve(e._xs.size());
123 for(const auto& x : e._xs)
124 {
125 auto sx = std::dynamic_pointer_cast<AnalyticExpr<ScalarType>>(x->copy());
126 assert_release(sx);
127 _xs.push_back(sx);
128 }
129 }
130
131 std::shared_ptr<ExprBase> copy() const override
132 {
133 return std::make_shared<DynamicVectorExpr>(*this);
134 }
135
136 void replace_arg(const ExprID& old_arg_id, const std::shared_ptr<ExprBase>& new_expr) override
137 {
138 for(auto& x : _xs)
139 replace_scalar_child(x, old_arg_id, new_expr);
140 }
141
142 VectorType fwd_eval(ValuesMap& v, Index total_input_size, bool natural_eval) const override
143 {
144 if(natural_eval)
145 return this->init_value(v, natural_fwd(v, total_input_size));
146
147 std::vector<ScalarType> vals;
148 vals.reserve(_xs.size());
149 bool centered_available = true;
150 for(const auto& x : _xs)
151 {
152 vals.push_back(x->fwd_eval(v, total_input_size, false));
153 centered_available &= (vals.back().da.size() != 0);
154 }
155
156 if(!centered_available)
157 return this->init_value(v, natural_fwd(v, total_input_size));
158
159 const Index n = static_cast<Index>(_xs.size());
160 const Index input_cols = vals.empty() ? total_input_size : vals.front().da.cols();
161 IntervalVector m(n), a(n);
162 IntervalMatrix da(n, input_cols);
163 bool def_domain = true;
164
165 for(Index i = 0 ; i < n ; ++i)
166 {
167 const auto& xi = vals[static_cast<std::size_t>(i)];
168 m[i] = xi.m;
169 a[i] = xi.a;
170 da.row(i) = xi.da;
171 def_domain &= xi.def_domain;
172 }
173
174 return this->init_value(v, VectorType(m, a, da, def_domain));
175 }
176
177 void bwd_eval(ValuesMap& v) const override
178 {
179 for(const auto& x : _xs)
180 x->bwd_eval(v);
181 }
182
183 std::pair<Index,Index> output_shape() const override
184 {
185 return { static_cast<Index>(_xs.size()), 1 };
186 }
187
188 bool belongs_to_args_list(const FunctionArgsList& args) const override
189 {
190 bool ok = true;
191 for(const auto& x : _xs)
192 ok &= x->belongs_to_args_list(args);
193 return ok;
194 }
195
196 std::string str(bool in_parentheses = false) const override
197 {
198 if(_xs.empty())
199 return in_parentheses ? "([])" : "[]";
200
201 std::string s;
202 for(const auto& x : _xs)
203 s += "\t" + x->str() + ",\n";
204
205 s.pop_back();
206 s.pop_back();
207
208 s = "[\n" + s + "\n]";
209 return in_parentheses ? "(" + s + ")" : s;
210 }
211
212 bool is_str_leaf() const override
213 {
214 return false;
215 }
216
217 std::vector<std::shared_ptr<ExprBase>> children_expr_base() const override
218 {
219 std::vector<std::shared_ptr<ExprBase>> children;
220 children.reserve(_xs.size());
221 for(const auto& x : _xs)
222 children.push_back(std::dynamic_pointer_cast<ExprBase>(x));
223 return children;
224 }
225
226 private:
227
228 VectorType natural_fwd(ValuesMap& v, Index total_input_size) const
229 {
230 const Index n = static_cast<Index>(_xs.size());
231 IntervalVector a(n);
232 bool def_domain = true;
233 for(Index i = 0 ; i < n ; ++i)
234 {
235 auto xi = _xs[static_cast<std::size_t>(i)]->fwd_eval(v, total_input_size, true);
236 a[i] = xi.a;
237 def_domain &= xi.def_domain;
238 }
239
240 return { a, def_domain };
241 }
242
243 std::vector<std::shared_ptr<AnalyticExpr<ScalarType>>> _xs;
244 };
245 }
246
247 // Analytic operator
248 // The following functions can be used to build analytic expressions.
249
250 inline const ScalarExpr& _add_to_vec(const ScalarExpr& x)
251 {
252 return x;
253 }
254
255 inline ScalarExpr _add_to_vec(double x)
256 {
257 return const_value(x);
258 }
259
260 // Variadic:
261
262 template<typename... X>
263 requires ((std::is_same_v<typename ExprType<X>::Type,ScalarType>) && ...)
264 inline VectorExpr
265 vec(const X&... x)
266 {
267 return { std::make_shared<AnalyticOperationExpr<VectorOp,VectorType,typename ExprType<X>::Type...>>(_add_to_vec(x)...) };
268 }
269
270 // Dynamic:
271
272 inline VectorExpr
273 vec(const std::vector<ScalarExpr>& x)
274 {
275 return { std::make_shared<detail::DynamicVectorExpr>(x) };
276 }
277}
virtual std::vector< std::shared_ptr< ExprBase > > children_expr_base() const
Definition codac2_ExprBase.h:152
virtual std::shared_ptr< ExprBase > copy() const =0
Creates a copy of the current expression.
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
Eigen::Matrix< Interval,-1,-1 > IntervalMatrix
Alias for a dynamic-size matrix of intervals.
Definition codac2_IntervalMatrix.h:25