codac 2.0.0
Loading...
Searching...
No Matches
codac2_det.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include "codac2_Interval.h"
15#include "codac2_AnalyticType.h"
17#include "codac2_arith_sub.h"
18#include "codac2_arith_mul.h"
19#include "codac2_inversion.h"
20
21namespace codac2
22{
23 struct DetOp
24 {
25 template<typename X1>
26 static std::string str(const X1& x1)
27 {
28 return "det(" + x1->str() + ")";
29 }
30
31 template<typename X1,typename X2>
32 static std::string str(const X1& x1, const X2& x2)
33 {
34 return "det(" + x1->str() + "," + x2->str() + ")";
35 }
36
37 template<typename X1,typename X2,typename X3>
38 static std::string str(const X1& x1, const X2& x2, const X3& x3)
39 {
40 return "det(" + x1->str() + "," + x2->str() + "," + x3->str() + ")";
41 }
42
43 // For matrices
44 template<typename X1>
45 static std::pair<Index,Index> output_shape([[maybe_unused]] const X1& s1)
46 {
47 return {1,1};
48 }
49
50 static Interval fwd(const IntervalMatrix& x);
51 static ScalarType fwd_natural(const MatrixType& x);
52 static ScalarType fwd_centered(const MatrixType& x);
53 static void bwd(const Interval& y, IntervalMatrix& x);
54
55 // For two vectors (merged into a 2×2 matrix)
56 template<typename X1, typename X2>
57 static std::pair<Index,Index> output_shape([[maybe_unused]] const X1& s1, [[maybe_unused]] const X2& s2)
58 {
59 return {1,1};
60 }
61
62 static Interval fwd(const IntervalVector& x1, const IntervalVector& x2);
63 static ScalarType fwd_natural(const VectorType& x1, const VectorType& x2);
64 static ScalarType fwd_centered(const VectorType& x1, const VectorType& x2);
65 static void bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2);
66
67 // For three vectors (merged into a 3×3 matrix)
68 template<typename X1, typename X2, typename X3>
69 static std::pair<Index,Index> output_shape([[maybe_unused]] const X1& s1, [[maybe_unused]] const X2& s2, [[maybe_unused]] const X3& s3)
70 {
71 return {1,1};
72 }
73
74 static Interval fwd(const IntervalVector& x1, const IntervalVector& x2, const IntervalVector& x3);
75 static ScalarType fwd_natural(const VectorType& x1, const VectorType& x2, const VectorType& x3);
76 static ScalarType fwd_centered(const VectorType& x1, const VectorType& x2, const VectorType& x3);
77 static void bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2, IntervalVector& x3);
78 };
79
80 // Analytic operator
81 // The following functions can be used to build analytic expressions.
82
83 inline ScalarExpr
84 det(const MatrixExpr& x1)
85 {
86 return { std::make_shared<AnalyticOperationExpr<DetOp,ScalarType,MatrixType>>(x1) };
87 }
88
89 inline ScalarExpr
90 det(const VectorExpr& x1, const VectorExpr& x2)
91 {
92 return { std::make_shared<AnalyticOperationExpr<DetOp,ScalarType,VectorType,VectorType>>(x1,x2) };
93 }
94
95 inline ScalarExpr
96 det(const VectorExpr& x1, const VectorExpr& x2, const VectorExpr& x3)
97 {
98 return { std::make_shared<AnalyticOperationExpr<DetOp,ScalarType,VectorType,VectorType,VectorType>>(x1,x2,x3) };
99 }
100
101 // Inline functions
102
103 inline Interval DetOp::fwd(const IntervalMatrix& x)
104 {
105 assert_release(x.is_squared() && "can only compute determinants for a square matrix");
106// assert_release((x.rows() == 1 || x.rows() == 2) && "determinant not yet computable for n×n matrices, n>2");
107
108 if(x.rows() == 1) // 1×1 matrix
109 return x(0,0);
110
111 else if(x.rows() == 2) // 2×2 matrix
112 return x(0,0)*x(1,1)-x(0,1)*x(1,0);
113
114 else {
115 auto ret = cofactor_matrix_enclosure(x);
116 return ret.second;
117 }
118 }
119
120 inline ScalarType DetOp::fwd_natural(const MatrixType& x)
121 {
122 return {
123 fwd(x.a),
124 x.def_domain
125 };
126 }
127
128 inline ScalarType DetOp::fwd_centered(const MatrixType& x)
129 {
130 if(centered_form_not_available_for_args(x))
131 return fwd_natural(x);
132
133 if(x.a.rows()==1) {
134 return {
135 fwd(x.m),
136 fwd(x.a),
137 x.da, // keep matrix type for diff
138 x.def_domain
139 };
140 }
141
142 IntervalMatrix d(1, x.da.cols());
143 if (x.a.rows()==2) { /* otherwise, will fail afterwards */
144 for (Index i=0; i < d.cols() ; i++) {
145 d(0,i) = x.da(0,i)*x.a(1,1) + x.da(3,i)*x.a(0,0)
146 - x.da(1,i)*x.a(0,1) - x.da(2,i)*x.a(1,0);
147 /* note: ColMajor is assumed here */
148 }
149 return {
150 fwd(x.m),
151 fwd(x.a),
152 d,
153 x.def_domain
154 };
155 } else {
156 auto ret1 = cofactor_matrix_enclosure(x.a);
157 for (Index i=0; i < d.cols() ; i++)
158 d(0,i) = ret1.first.reshaped<Eigen::ColMajor>().dot(x.da.col(i));
159 return {
160 fwd(x.m),
161 ret1.second,
162 d,
163 x.def_domain
164 };
165 }
166
167 }
168
169 inline void DetOp::bwd(const Interval& y, IntervalMatrix& x)
170 {
171 assert_release(x.is_squared() && "can only compute determinants for a square matrix");
172// assert_release((x.rows() == 1 || x.rows() == 2) && "determinant not yet computable for n×n matrices, n>2");
173
174 if(x.rows() == 1) // 1×1 matrix
175 x(0,0) &= y;
176
177 else if(x.rows() == 2) // 2×2 matrix
178 {
179 Interval z1 = x(0,0)*x(1,1), z2 = x(1,0)*x(0,1);
180 SubOp::bwd(y, z1, z2);
181 MulOp::bwd(z1, x(0,0), x(1,1));
182 MulOp::bwd(z2, x(1,0), x(0,1));
183 }
184
185 else /* we only check that the determinant intersects y */
186 {
187 auto ret = cofactor_matrix_enclosure(x);
188 if (ret.second.is_disjoint(y)) x.set_empty();
189 // otherwise, do nothing
190 }
191 }
192
193 inline Interval DetOp::fwd(const IntervalVector& x1, const IntervalVector& x2)
194 {
195 assert_release(x1.size() == 2 && x2.size() == 2 && "determinant only computable for pairs of 2d vectors");
196 IntervalMatrix m(2,2);
197 m.col(0) = x1; m.col(1) = x2;
198 return DetOp::fwd(m);
199 }
200
201 inline ScalarType DetOp::fwd_natural(const VectorType& x1, const VectorType& x2)
202 {
203 IntervalMatrix a(2,2);
204 a.col(0) = x1.a; a.col(1) = x2.a;
205
206 return {
207 fwd(a),
208 x1.def_domain && x2.def_domain
209 };
210 }
211
212 inline ScalarType DetOp::fwd_centered(const VectorType& x1, const VectorType& x2)
213 {
214 if(centered_form_not_available_for_args(x1,x2))
215 return fwd_natural(x1,x2);
216
217 IntervalMatrix m(2,2);
218 m.col(0) = x1.m; m.col(1) = x2.m;
219 IntervalMatrix a(2,2);
220 a.col(0) = x1.a; a.col(1) = x2.a;
221
222 assert(x1.da.cols() == x2.da.cols());
223 IntervalMatrix d(1, x1.da.cols());
224 for (Index i=0; i < d.cols() ; i++) {
225 d(0,i) = x1.da(0,i)*x2.a[1] + x1.a[0]*x2.da(1,i)
226 - x1.da(1,i)*x2.a[0] - x1.a[1]*x2.da(0,i);
227 }
228
229 return {
230 fwd(m),
231 fwd(a),
232 d,
233 x1.def_domain && x2.def_domain
234 };
235 }
236
237 inline void DetOp::bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2)
238 {
239 assert_release(x1.size() == 2 && x2.size() == 2 && "determinant only computable for pairs of 2d vectors");
240 IntervalMatrix m(2,2);
241 m.col(0) = x1; m.col(1) = x2;
242 DetOp::bwd(y,m);
243 x1 &= m.col(0);
244 x2 &= m.col(1);
245 }
246
247 inline Interval DetOp::fwd(const IntervalVector& x1, const IntervalVector& x2, const IntervalVector& x3)
248 {
249 assert_release(x1.size() == 3 && x2.size() == 3 && x3.size() == 3 && "determinant only computable for triplet of 3d vectors");
250 IntervalMatrix m(3,3);
251 m.col(0) = x1; m.col(1) = x2; m.col(2) = x3;
252 return DetOp::fwd(m);
253 }
254
255 inline ScalarType DetOp::fwd_natural(const VectorType& x1, const VectorType& x2, const VectorType& x3)
256 {
257 IntervalMatrix a(3,3);
258 a.col(0) = x1.a; a.col(1) = x2.a; a.col(2) = x3.a;
259
260 return {
261 fwd(a),
262 x1.def_domain && x2.def_domain && x3.def_domain
263 };
264 }
265
266 inline ScalarType DetOp::fwd_centered(const VectorType& x1, const VectorType& x2, const VectorType& x3)
267 {
268 if(centered_form_not_available_for_args(x1,x2,x3))
269 return fwd_natural(x1,x2,x3);
270
271 IntervalMatrix m(3,3);
272 m.col(0) = x1.m; m.col(1) = x2.m; m.col(2) = x3.m;
273 IntervalMatrix a(3,3);
274 a.col(0) = x1.a; a.col(1) = x2.a; a.col(2) = x3.a;
275
276 assert(x1.da.cols() == x2.da.cols());
277 assert(x1.da.cols() == x3.da.cols());
278 IntervalMatrix d(1, x1.da.cols());
279 auto ret1 = cofactor_matrix_enclosure(a);
280 for (Index i=0; i < d.cols() ; i++) {
281 d(0,i) = ret1.first.col(0).dot(x1.da.col(i));
282 d(0,i) += ret1.first.col(1).dot(x2.da.col(i));
283 d(0,i) += ret1.first.col(2).dot(x3.da.col(i));
284 }
285 return {
286 fwd(m),
287 ret1.second,
288 d,
289 x1.def_domain && x2.def_domain && x3.def_domain
290 };
291 }
292
293 inline void DetOp::bwd(const Interval& y, IntervalVector& x1, IntervalVector& x2, IntervalVector& x3)
294 {
295 assert_release(x1.size() == 3 && x2.size() == 3 && x3.size() == 3 && "determinant only computable for triplet of 3d vectors");
296
297 IntervalMatrix m(3,3);
298 m.col(0) = x1; m.col(1) = x2; m.col(2) = x3;
299
300 DetOp::bwd(y,m);
301 x1 &= m.col(0);
302 x2 &= m.col(1);
303 x3 &= m.col(2);
304 }
305}
Interval class, for representing closed and connected subsets of .
Definition codac2_Interval.h:50
Definition codac2_OctaSym.h:21
std::pair< IntervalMatrix, Interval > cofactor_matrix_enclosure(const Eigen::MatrixBase< OtherDerived > &A)
compute the interval cofactor matrix, as well as the determinant, of a square matrix
Definition codac2_inversion.h:130
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