codac 2.0.0
Loading...
Searching...
No Matches
codac2_arith_mul.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include "codac2_Interval.h"
14#include "codac2_IntervalRow.h"
16#include "codac2_AnalyticType.h"
18#include "codac2_arith_add.h"
19
20#include "codac2_linear_ctc.h"
21#include "codac2_GaussJordan.h"
23
24namespace codac2
25{
26 struct MulOp
27 {
28 template<typename X1,typename X2>
29 static std::string str(const X1& x1, const X2& x2)
30 {
31 return x1->str(!x1->is_str_leaf()) + "*" + x2->str(!x2->is_str_leaf());
32 }
33
34 template<typename X1, typename X2>
35 static std::pair<Index,Index> output_shape(const X1& s1, const X2& s2)
36 {
37 auto shape1 = s1->output_shape();
38 auto shape2 = s2->output_shape();
39
40 if(shape1.first == 1 && shape1.second == 1)
41 return shape2;
42
43 else if(shape2.first == 1 && shape2.second == 1)
44 return shape1;
45
46 else
47 {
48 assert(shape1.second == shape2.first);
49 return { shape1.first, shape2.second };
50 }
51 }
52
53 static Interval fwd(const Interval& x1, const Interval& x2);
54 static ScalarType fwd_natural(const ScalarType& x1, const ScalarType& x2);
55 static ScalarType fwd_centered(const ScalarType& x1, const ScalarType& x2);
56 static void bwd(const Interval& y, Interval& x1, Interval& x2);
57
58 static IntervalVector fwd(const Interval& x1, const IntervalVector& x2);
59 static VectorType fwd_natural(const ScalarType& x1, const VectorType& x2);
60 static VectorType fwd_centered(const ScalarType& x1, const VectorType& x2);
61 static void bwd(const IntervalVector& y, Interval& x1, IntervalVector& x2);
62
63 static IntervalVector fwd(const IntervalVector& x1, const Interval& x2);
64 static VectorType fwd_natural(const VectorType& x1, const ScalarType& x2);
65 static VectorType fwd_centered(const VectorType& x1, const ScalarType& x2);
66 static void bwd(const IntervalVector& y, IntervalVector& x1, Interval& x2);
67
68 static Interval fwd(const IntervalRow& x1, const IntervalVector& x2);
69 //static ScalarType fwd(const RowType& x1, const VectorType& x2); // RowType not yet defined
70 static void bwd(const Interval& y, IntervalRow& x1, IntervalVector& x2);
71
72 static IntervalMatrix fwd(const Interval& x1, const IntervalMatrix& x2);
73 static MatrixType fwd_natural(const ScalarType& x1, const MatrixType& x2);
74 static MatrixType fwd_centered(const ScalarType& x1, const MatrixType& x2);
75 static void bwd(const IntervalMatrix& y, Interval& x1, IntervalMatrix& x2);
76
77 static IntervalVector fwd(const IntervalMatrix& x1, const IntervalVector& x2);
78 static VectorType fwd_natural(const MatrixType& x1, const VectorType& x2);
79 static VectorType fwd_centered(const MatrixType& x1, const VectorType& x2);
80 static void bwd(const IntervalVector& y, IntervalMatrix& x1, IntervalVector& x2);
81
82 static IntervalMatrix fwd(const IntervalMatrix& x1, const IntervalMatrix& x2);
83 static MatrixType fwd_natural(const MatrixType& x1, const MatrixType& x2);
84 static MatrixType fwd_centered(const MatrixType& x1, const MatrixType& x2);
85 static void bwd(const IntervalMatrix& y, IntervalMatrix& x1, IntervalMatrix& x2);
86 };
87
88 // operator*
89 // The following functions can be used to build analytic expressions.
90
91 inline ScalarExpr
92 operator*(const ScalarExpr& x1, const ScalarExpr& x2)
93 {
94 return { std::make_shared<AnalyticOperationExpr<MulOp,ScalarType,ScalarType,ScalarType>>(x1,x2) };
95 }
96
97 inline VectorExpr
98 operator*(const ScalarExpr& x1, const VectorExpr& x2)
99 {
100 return { std::make_shared<AnalyticOperationExpr<MulOp,VectorType,ScalarType,VectorType>>(x1,x2) };
101 }
102
103 inline VectorExpr
104 operator*(const VectorExpr& x1, const ScalarExpr& x2)
105 {
106 return { std::make_shared<AnalyticOperationExpr<MulOp,VectorType,VectorType,ScalarType>>(x1,x2) };
107 }
108
109 inline MatrixExpr
110 operator*(const ScalarExpr& x1, const MatrixExpr& x2)
111 {
112 return { std::make_shared<AnalyticOperationExpr<MulOp,MatrixType,ScalarType,MatrixType>>(x1,x2) };
113 }
114
115 inline VectorExpr
116 operator*(const MatrixExpr& x1, const VectorExpr& x2)
117 {
118 return { std::make_shared<AnalyticOperationExpr<MulOp,VectorType,MatrixType,VectorType>>(x1,x2) };
119 }
120
121 inline MatrixExpr
122 operator*(const MatrixExpr& x1, const MatrixExpr& x2)
123 {
124 return { std::make_shared<AnalyticOperationExpr<MulOp,MatrixType,MatrixType,MatrixType>>(x1,x2) };
125 }
126
127 // Inline functions
128
129 inline Interval MulOp::fwd(const Interval& x1, const Interval& x2)
130 {
131 return x1 * x2;
132 }
133
134 inline ScalarType MulOp::fwd_natural(const ScalarType& x1, const ScalarType& x2)
135 {
136 return {
137 fwd(x1.a, x2.a),
138 x1.def_domain && x2.def_domain
139 };
140 }
141
142 inline ScalarType MulOp::fwd_centered(const ScalarType& x1, const ScalarType& x2)
143 {
144 if(centered_form_not_available_for_args(x1,x2))
145 return fwd_natural(x1,x2);
146
147 assert(x1.da.rows() == 1);
148 assert(x1.da.rows() == x2.da.rows() && x1.da.cols() == x2.da.cols());
149
150 IntervalMatrix d(1,x1.da.cols());
151 for(Index i = 0 ; i < d.size() ; i++)
152 d(0,i) = x1.da(0,i)*x2.a + x1.a*x2.da(0,i);
153
154 return {
155 fwd(x1.m, x2.m),
156 fwd(x1.a, x2.a),
157 d,
158 x1.def_domain && x2.def_domain
159 };
160 }
161
162 inline void MulOp::bwd(const Interval& y, Interval& x1, Interval& x2)
163 {
164 x1 = gaol::div_rel(y, x2, x1);
165 x2 = gaol::div_rel(y, x1, x2);
166 }
167
168 inline IntervalVector MulOp::fwd(const Interval& x1, const IntervalVector& x2)
169 {
170 return x1 * x2;
171 }
172
173 inline VectorType MulOp::fwd_natural(const ScalarType& x1, const VectorType& x2)
174 {
175 return {
176 fwd(x1.a, x2.a),
177 x1.def_domain && x2.def_domain
178 };
179 }
180
181 inline VectorType MulOp::fwd_centered(const ScalarType& x1, const VectorType& x2)
182 {
183 if(centered_form_not_available_for_args(x1,x2))
184 return fwd_natural(x1,x2);
185
186 assert(x1.da.rows() == 1);
187 assert(x1.da.cols() == x2.da.cols());
188 assert(x2.a.size() == x2.da.rows());
189
190 IntervalMatrix d(x2.da.rows(),x2.da.cols());
191 for(Index i = 0 ; i < d.rows() ; i++)
192 for(Index j = 0 ; j < d.cols() ; j++)
193 d(i,j) = x1.da(0,j)*x2.a[i]+x1.a*x2.da(i,j);
194
195 return {
196 fwd(x1.m, x2.m),
197 fwd(x1.a, x2.a),
198 d,
199 x1.def_domain && x2.def_domain
200 };
201 }
202
203 inline void MulOp::bwd(const IntervalVector& y, Interval& x1, IntervalVector& x2)
204 {
205 assert(y.size() == x2.size());
206 for(Index i = 0 ; i < x2.size() ; i++)
207 MulOp::bwd(y[i], x1, x2[i]);
208 }
209
210 inline IntervalVector MulOp::fwd(const IntervalVector& x1, const Interval& x2)
211 {
212 return MulOp::fwd(x2,x1);
213 }
214
215 inline VectorType MulOp::fwd_natural(const VectorType& x1, const ScalarType& x2)
216 {
217 return MulOp::fwd_natural(x2,x1);
218 }
219
220 inline VectorType MulOp::fwd_centered(const VectorType& x1, const ScalarType& x2)
221 {
222 return MulOp::fwd_centered(x2,x1);
223 }
224
225 inline void MulOp::bwd(const IntervalVector& y, IntervalVector& x1, Interval& x2)
226 {
227 MulOp::bwd(y, x2, x1);
228 }
229
230 inline Interval MulOp::fwd(const IntervalRow& x1, const IntervalVector& x2)
231 {
232 assert(x1.size() == x2.size());
233 Interval s(0.);
234 for(Index i = 0 ; i < x1.size() ; i++)
235 s += x1[i]*x2[i];
236 return s;
237 }
238
239 //ScalarType MulOp::fwd(const RowType& x1, const VectorType& x2)
240 //{
241 // // RowType not yet defined
242 //}
243
244 inline IntervalMatrix MulOp::fwd(const Interval& x1, const IntervalMatrix& x2)
245 {
246 return x1 * x2;
247 }
248
249 inline MatrixType MulOp::fwd_natural(const ScalarType& x1, const MatrixType& x2)
250 {
251 return {
252 fwd(x1.a, x2.a),
253 x1.def_domain && x2.def_domain
254 };
255 }
256
257 inline MatrixType MulOp::fwd_centered(const ScalarType& x1, const MatrixType& x2)
258 {
259 if(centered_form_not_available_for_args(x1,x2))
260 return fwd_natural(x1,x2);
261
262 assert(x2.da.cols() == x1.da.cols());
263 IntervalMatrix d(x2.da.rows(),x2.da.cols());
264 for (Index j=0; j<d.cols(); j++)
265 for (Index i=0; i<d.rows(); i++) {
266 d(i,j) = x1.da(0,j)*x2.a.reshaped<Eigen::ColMajor>()[i]+x1.a*x2.da(i,j);
267 }
268
269 return {
270 fwd(x1.m, x2.m),
271 fwd(x1.a, x2.a),
272 d,
273 x1.def_domain && x2.def_domain
274 };
275 }
276
277 inline void MulOp::bwd([[maybe_unused]] const IntervalMatrix& y, [[maybe_unused]] Interval& x1, [[maybe_unused]] IntervalMatrix& x2)
278 {
279 // todo
280 }
281
282 inline IntervalVector MulOp::fwd(const IntervalMatrix& x1, const IntervalVector& x2)
283 {
284 assert(x1.cols() == x2.size());
285 return x1 * x2;
286 }
287
288 inline VectorType MulOp::fwd_natural(const MatrixType& x1, const VectorType& x2)
289 {
290 return {
291 fwd(x1.a, x2.a),
292 x1.def_domain && x2.def_domain
293 };
294 }
295
296 inline VectorType MulOp::fwd_centered(const MatrixType& x1, const VectorType& x2)
297 {
298 if(centered_form_not_available_for_args(x1,x2))
299 return fwd_natural(x1,x2);
300
301 assert(x2.da.cols() == x1.da.cols());
302 IntervalMatrix d = IntervalMatrix::zero(x1.a.rows(),x1.da.cols());
303 for (Index j=0; j<d.cols(); j++)
304 for (Index i=0; i<d.rows(); i++) {
305 for (Index k=0; k<x2.a.size(); k++) {
306 d(i,j) += x1.da(i+k*x1.a.rows(),j)*x2.a[k]+x1.a(i,k)*x2.da(k,j);
307 }
308 }
309
310 return {
311 fwd(x1.m, x2.m),
312 fwd(x1.a, x2.a),
313 d,
314 x1.def_domain && x2.def_domain
315 };
316 }
317
318 inline IntervalMatrix MulOp::fwd(const IntervalMatrix& x1, const IntervalMatrix& x2)
319 {
320 assert(x1.cols() == x2.rows());
321 return x1 * x2;
322 }
323
324 inline MatrixType MulOp::fwd_natural(const MatrixType& x1, const MatrixType& x2)
325 {
326 return {
327 fwd(x1.a, x2.a),
328 x1.def_domain && x2.def_domain
329 };
330 }
331
332 inline MatrixType MulOp::fwd_centered(const MatrixType& x1, const MatrixType& x2)
333 {
334 if(centered_form_not_available_for_args(x1,x2))
335 return fwd_natural(x1,x2);
336
337 assert(x2.da.cols() == x1.da.cols());
338 IntervalMatrix d = IntervalMatrix::zero(x1.a.rows()*x2.a.cols(),x1.da.cols());
339 for (Index j=0; j<d.cols(); j++)
340 for (Index i=0; i<d.rows(); i++)
341 {
342 Index row_i = i%x1.a.rows();
343 Index col_i = i/x1.a.rows();
344 for (Index k=0; k<x2.a.rows(); k++) {
345 d(i,j) += x1.da(row_i+k*x1.a.rows(),j)*x2.a(k,col_i)
346 +x1.a(row_i,k)*x2.da(k+col_i*x2.a.rows(),j);
347 }
348 }
349
350 return {
351 fwd(x1.m, x2.m),
352 fwd(x1.a, x2.a),
353 d,
354 x1.def_domain && x2.def_domain
355 };
356 }
357
358 inline void MulOp::bwd(const IntervalMatrix& y, IntervalMatrix& x1, IntervalMatrix& x2)
359 {
360 assert(x1.rows() == x2.cols());
361 assert(y.rows() == x1.rows() && y.cols() == x2.cols());
362
363 IntvFullPivLU LUdec(x1);
364 LUdec.solve(y,x2);
365 if (x2.is_empty()) { x1.set_empty(); return; }
366 IntvFullPivLU LUdec2(IntervalMatrix(x2.transpose()));
367 IntervalMatrix tX1 = x1.transpose();
368 LUdec2.solve(y.transpose(),tX1);
369 x1 = tX1.transpose();
370 if (x1.is_empty()) { x2.set_empty(); return; }
371 }
372}
Interval class, for representing closed and connected subsets of .
Definition codac2_Interval.h:49
Definition codac2_OctaSym.h:21
Interval operator*(const Interval &x, double y)
Returns with .
Definition codac2_Interval_impl.h:445
Eigen::Matrix< Interval, 1,-1 > IntervalRow
Alias for a dynamic-size row vector of intervals.
Definition codac2_IntervalRow.h:24
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