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