17#ifndef __CODAC2_INTERVALMATRIX_H__
18#define __CODAC2_INTERVALMATRIX_H__
22#include <codac2_eigen.h>
23#include <ibex_LargestFirst.h>
30 template<
int R=Dynamic,
int C=Dynamic>
31 class IntervalMatrix_ :
public Eigen::Matrix<Interval,R,C>
36 : Eigen::Matrix<Interval,R,C>()
41 explicit IntervalMatrix_(
size_t nb_rows,
size_t nb_cols)
42 : Eigen::Matrix<Interval,R,C>(nb_rows, nb_cols)
44 assert(R == Dynamic || R == (
int)nb_rows);
45 assert(C == Dynamic || C == (
int)nb_cols);
48 explicit IntervalMatrix_(
size_t nb_rows,
size_t nb_cols,
const Interval& x)
49 : IntervalMatrix_<R,C>(nb_rows, nb_cols)
54 explicit IntervalMatrix_(
size_t nb_rows,
size_t nb_cols,
const double bounds[][2])
55 : IntervalMatrix_<R,C>(nb_rows, nb_cols)
58 for(
size_t i = 0 ; i < nb_rows ; i++)
59 for(
size_t j = 0 ; j < nb_cols ; j++)
62 (*this)(i,j) = Interval::zero();
64 (*
this)(i,j) = Interval(bounds[k][0],bounds[k][1]);
67 assert(k == this->size());
70 explicit IntervalMatrix_(
const double bounds[][2])
71 : IntervalMatrix_<R,C>(R, C, bounds)
74 explicit IntervalMatrix_(
const Matrix_<R,C>& lb,
const Matrix_<R,C>& ub)
75 : IntervalMatrix_<R,C>(lb.rows(), lb.cols())
77 assert(lb.rows() == ub.rows() && lb.cols() == ub.cols());
78 for(
size_t i = 0 ; i < this->rows() ; i++)
79 for(
size_t j = 0 ; j < this->cols() ; j++)
80 (*
this)(i,j) = Interval(lb(i,j),ub(i,j));
83 explicit IntervalMatrix_(
const IntervalMatrix_<R,C>& x)
84 : IntervalMatrix_<R,C>(x.rows(), x.cols())
86 for(
size_t i = 0 ; i < size() ; i++)
87 *(this->data()+i) = *(x.data()+i);
90 IntervalMatrix_(std::initializer_list<std::initializer_list<Interval>> l)
91 : IntervalMatrix_<R,C>()
93 assert((R == Dynamic || (
int)l.size() == R) &&
"ill-formed matrix");
95 for(
const auto& ri : l) {
96 assert((cols == -1 || cols == (
int)ri.size()) &&
"ill-formed matrix");
97 cols = (int)ri.size();
99 this->resize(l.size(),cols);
101 for(
const auto& ri : l)
104 for(
const auto& ci : ri)
111 template<
typename OtherDerived>
112 IntervalMatrix_(
const Eigen::MatrixBase<OtherDerived>& other)
113 : Eigen::Matrix<Interval,R,C>(other.template cast<Interval>())
117 template<
typename OtherDerived>
118 IntervalMatrix_& operator=(
const Eigen::MatrixBase<OtherDerived>& other)
120 this->Eigen::Matrix<Interval,R,C>::operator=(other);
124 constexpr size_t size()
const
126 return this->Eigen::Matrix<Interval,R,C>::size();
129 void resize(
size_t nb_rows,
size_t nb_cols)
133 this->Eigen::Matrix<Interval,R,C>::resize(nb_rows, nb_cols);
134 for(
size_t i = 0 ; i < std::min((
size_t)copy.rows(),nb_rows) ; i++)
135 for(
size_t j = 0 ; j < std::min((
size_t)copy.cols(),nb_cols) ; j++)
136 (*
this)(i,j) = copy(i,j);
139 bool is_empty()
const
141 for(
size_t i = 0 ; i < size() ; i++)
142 if((this->data()+i)->is_empty())
147 static IntervalMatrix_<R,C> empty_set(
size_t nb_rows = R,
size_t nb_cols = C)
149 return IntervalMatrix_<R,C>(nb_rows, nb_cols, Interval::empty_set());
152 static IntervalMatrix_ eye()
154 return Eigen::Matrix<Interval,R,C>::Identity();
159 if(is_empty())
return true;
160 for(
size_t i = 0 ; i < size() ; i++)
161 if((this->data()+i)->is_degenerated())
166 bool is_unbounded()
const
168 if(is_empty())
return false;
169 for(
size_t i = 0 ; i < size() ; i++)
170 if((this->data()+i)->is_unbounded())
175 bool is_subset(
const IntervalMatrix_<R,C>& x)
const
177 if(is_empty())
return true;
178 if(x.is_empty())
return false;
179 for(
size_t i = 0 ; i < size() ; i++)
180 if(!(this->data()+i)->is_subset(*(x.data()+i)))
185 bool is_strict_subset(
const IntervalMatrix_<R,C>& x)
const
187 if(x.is_empty())
return false;
188 if(is_empty())
return true;
189 bool one_dim_strict_subset =
false;
190 for(
size_t i = 0 ; i < size() ; i++)
192 if((this->data()+i)->is_strict_subset(*(x.data()+i)))
193 one_dim_strict_subset =
true;
194 if(!(this->data()+i)->is_subset(*(x.data()+i)))
197 return one_dim_strict_subset;
200 bool is_superset(
const IntervalMatrix_<R,C>& x)
const
202 return x.is_subset(*
this);
205 bool is_strict_superset(
const IntervalMatrix_<R,C>& x)
const
207 return x.is_strict_subset(*
this);
210 bool contains(
const Matrix_<R,C>& x)
const
214 for(
size_t i = 0 ; i < size() ; i++)
215 if(!(this->data()+i)->contains(*(x.data()+i)))
220 bool interior_contains(
const IntervalMatrix_<R,C>& x)
const
224 for(
size_t i = 0 ; i < size() ; i++)
225 if(!(this->data()+i)->interior_contains(*(x.data()+i)))
230 bool intersects(
const IntervalMatrix_<R,C>& x)
const
232 if(is_empty() || x.is_empty())
234 for(
size_t i = 0 ; i < size() ; i++)
235 if(!(this->data()+i)->intersects(*(x.data()+i)))
240 bool overlaps(
const IntervalMatrix_<R,C>& x)
const
242 if(is_empty() || x.is_empty())
244 for(
size_t i = 0 ; i < size() ; i++)
245 if(!(this->data()+i)->overlaps(*(x.data()+i)))
250 bool is_disjoint(
const IntervalMatrix_<R,C>& x)
const
252 if(is_empty() || x.is_empty())
254 for(
size_t i = 0 ; i < size() ; i++)
255 if((this->data()+i)->is_disjoint(*(x.data()+i)))
260 bool is_bisectable()
const
262 for(
size_t i = 0 ; i < size() ; i++)
263 if((this->data()+i)->is_bisectable())
268 double min_diam()
const
270 return (this->data()+extr_diam_index(
true))->diam();
273 double max_diam()
const
275 return (this->data()+extr_diam_index(
false))->diam();
278 size_t thinnest_diam_index()
const
280 return extr_diam_index(
true);
283 size_t largest_diam_index()
const
285 return extr_diam_index(
false);
288 size_t extr_diam_index(
bool min)
const
294 double d =
min ? POS_INFINITY : -1;
295 int selected_index = -1;
296 bool unbounded =
false;
297 assert(!this->is_empty() &&
"Diameter of an empty IntervalVector is undefined");
301 for(i = 0 ; i < this->size() ; i++)
303 if((this->data()+i)->is_unbounded())
310 double w = (this->data()+i)->diam();
319 if(min && selected_index == -1)
328 if(unbounded && (!min || selected_index == -1))
330 double pt =
min ? NEG_INFINITY : POS_INFINITY;
332 for(; i < this->size() ; i++)
334 if((this->data()+i)->lb() == NEG_INFINITY)
336 if((this->data()+i)->ub() == POS_INFINITY)
344 if((min && (-(this->data()+i)->ub() > pt)) || (!
min && (-(this->data()+i)->ub() < pt)))
347 pt = -(this->data()+i)->ub();
350 else if((this->data()+i)->ub() == POS_INFINITY)
352 if((min && ((this->data()+i)->lb() > pt)) || (!
min && ((this->data()+i)->lb() < pt)))
355 pt = (this->data()+i)->lb();
361 return selected_index;
364 auto bisect(
float ratio = 0.49)
const
366 size_t i = largest_diam_index();
367 assert((this->data()+i)->is_bisectable());
368 assert(Interval(0,1).interior_contains(ratio));
370 auto p = std::make_pair(*
this,*
this);
371 auto pi = (this->data()+i)->bisect(ratio);
372 *(p.first.data()+i) = pi.first;
373 *(p.second.data()+i) = pi.second;
377 double volume()
const
382 for(
size_t i = 0 ; i < this->size() ; i++)
384 if((this->data()+i)->is_unbounded())
return POS_INFINITY;
385 if((this->data()+i)->is_degenerated())
return 0.;
386 v +=
log((this->data()+i)->diam());
391 Matrix_<R,C> lb()
const
393 assert(!this->is_empty());
394 Matrix_<R,C> lb(this->rows(), this->cols());
395 for(
size_t i = 0 ; i < this->size() ; i++)
396 *(lb.data()+i) = (this->data()+i)->lb();
400 Matrix_<R,C> ub()
const
402 assert(!this->is_empty());
403 Matrix_<R,C> ub(this->rows(), this->cols());
404 for(
size_t i = 0 ; i < this->size() ; i++)
405 *(ub.data()+i) = (this->data()+i)->ub();
409 Matrix_<R,C> mid()
const
411 assert(!this->is_empty());
412 Matrix_<R,C> mid(this->rows(), this->cols());
413 for(
size_t i = 0 ; i < this->size() ; i++)
414 *(mid.data()+i) = (this->data()+i)->mid();
418 Matrix_<R,C> rad()
const
420 assert(!this->is_empty());
421 Matrix_<R,C> rad(this->rows(), this->cols());
422 for(
size_t i = 0 ; i < this->size() ; i++)
423 *(rad.data()+i) = (this->data()+i)->rad();
427 Matrix_<R,C> diam()
const
429 assert(!this->is_empty());
430 Matrix_<R,C> diam(this->rows(), this->cols());
431 for(
size_t i = 0 ; i < this->size() ; i++)
432 *(diam.data()+i) = (this->data()+i)->diam();
436 void init(
const Interval& x)
438 for(
size_t i = 0 ; i < this->size() ; i++)
439 *(this->data()+i) = x;
444 init(Interval::empty_set());
447 auto& inflate(
double r)
450 for(
size_t i = 0 ; i < this->size() ; i++)
451 (this->data()+i)->inflate(r);
455 auto& inflate(
const Matrix_<R,C>& r)
457 assert(r.minCoeff() >= 0.);
458 for(
size_t i = 0 ; i < this->size() ; i++)
459 (this->data()+i)->inflate(*(r.data()+i));
463 bool operator==(
const IntervalMatrix_<R,C>& x)
const
465 if(x.size() != this->size() || x.rows() != this->rows() || x.cols() != this->cols())
467 if(is_empty() || x.is_empty())
468 return is_empty() && x.is_empty();
469 for(
size_t i = 0 ; i < this->size() ; i++)
470 if(*(this->data()+i) != *(x.data()+i))
475 bool operator!=(
const IntervalMatrix_<R,C>& x)
const
477 return !(*
this == x);
480 auto& operator&=(
const IntervalMatrix_<R,C>& x)
482 if(!this->is_empty())
487 for(
size_t i = 0 ; i < this->size() ; i++)
488 *(this->data()+i) &= *(x.data()+i);
493 auto& operator|=(
const IntervalMatrix_<R,C>& x)
500 for(
size_t i = 0 ; i < this->size() ; i++)
501 *(this->data()+i) |= *(x.data()+i);
506 auto operator+(
const IntervalMatrix_<R,C>& x)
const
512 auto operator-(
const IntervalMatrix_<R,C>& x)
const
518 auto operator&(
const IntervalMatrix_<R,C>& x)
const
524 auto operator|(
const IntervalMatrix_<R,C>& x)
const
530 auto& operator+=(
const IntervalMatrix_<R,C>& x)
532 (*this).noalias() += x;
536 auto& operator-=(
const IntervalMatrix_<R,C>& x)
538 (*this).noalias() -= x;
542 auto& operator+=(
const Matrix_<R,C>& x)
544 (*this).noalias() += x.template cast<Interval>();
548 auto& operator-=(
const Matrix_<R,C>& x)
550 (*this).noalias() -= x;
555 template<
int R,
int C>
556 std::ostream& operator<<(std::ostream& os,
const IntervalMatrix_<R,C>& x)
558 if(x.is_empty())
return os <<
"empty matrix";
560 for(
int i = 0 ; i < x.rows() ; i++)
563 for(
int j = 0 ; j < x.cols() ; j++)
564 os << x(i,j) << (j<x.cols()-1 ?
" ; " :
"");
566 if(i < x.rows()-1) os << std::endl;
572 template<
int R,
int C>
573 auto operator-(
const IntervalMatrix_<R,C>& x)
580 template<
int R,
int C>
581 auto operator*(
double a,
const IntervalMatrix_<R,C>& x)
583 return Interval(a)*x;
586 class IntervalMatrix :
public IntervalMatrix_<>
590 explicit IntervalMatrix(
size_t nb_rows,
size_t nb_cols)
591 : IntervalMatrix_<>(nb_rows, nb_cols)
595 explicit IntervalMatrix(
size_t nb_rows,
size_t nb_cols,
const Interval& x)
596 : IntervalMatrix_<>(nb_rows, nb_cols, x)
599 explicit IntervalMatrix(
size_t nb_rows,
size_t nb_cols,
const double bounds[][2])
600 : IntervalMatrix_<>(nb_rows, nb_cols, bounds)
603 IntervalMatrix(
const IntervalMatrix_<>& x)
604 : IntervalMatrix_<>(x)
607 IntervalMatrix(std::initializer_list<std::initializer_list<Interval>> l)
608 : IntervalMatrix_<>(l)
611 template<
int R,
int C>
612 explicit IntervalMatrix(
const Matrix_<R,C>& v)
613 : IntervalMatrix_<>(v)
616 static IntervalMatrix empty_set(
size_t nb_rows,
size_t nb_cols)
618 return IntervalMatrix_<>::empty_set(nb_rows,nb_cols);
const Trajectory log(const Trajectory &x)
const Trajectory min(const Trajectory &y, const Trajectory &x)
const Trajectory exp(const Trajectory &x)