1#ifndef ZONOOPT_INTERVAL_UTILITIES_HPP_
2#define ZONOOPT_INTERVAL_UTILITIES_HPP_
22#include <Eigen/Sparse>
31 #define M_PI 3.14159265358979323846
48 template <
typename Derived>
120 y_min() = std::min({
a, b, c,
d});
121 y_max() = std::max({
a, b, c,
d});
153 min = std::numeric_limits<zono_float>::infinity();
154 max = -std::numeric_limits<zono_float>::infinity();
156 else if (
min > 0 ||
max < 0)
164 max = std::numeric_limits<zono_float>::infinity();
169 min = -std::numeric_limits<zono_float>::infinity();
173 min = -std::numeric_limits<zono_float>::infinity();
174 max = std::numeric_limits<zono_float>::infinity();
197 y_min() = std::max(
x1.y_min(),
x2.y_min());
198 y_max() = std::min(
x1.y_max(),
x2.y_max());
244 if (x.y_max() - x.y_min() >= 2*
M_PI)
266 y_max() = ((
l <
M_PI/2 &&
M_PI/2 < u) || (
l < -3*
M_PI/2 && -3*
M_PI/2 < u)) ? 1 : std::max(std::sin(u), std::sin(
l));
267 y_min() = ((
l < -
M_PI/2 && -
M_PI/2 < u) || (
l < 3*
M_PI/2 && 3*
M_PI/2 < u)) ? -1 : std::min(std::sin(u), std::sin(
l));
288 if (x.y_max() - x.y_min() >=
M_PI)
290 y_max() = std::numeric_limits<zono_float>::infinity();
291 y_min() = -std::numeric_limits<zono_float>::infinity();
312 y_max() = std::numeric_limits<zono_float>::infinity();
313 y_min() = -std::numeric_limits<zono_float>::infinity();
317 y_max() = std::tan(u);
329 assert(x.y_min() >= -1 && x.y_min() <= 1);
330 assert(x.y_max() >= -1 && x.y_max() <= 1);
331 y_min() = std::asin(x.y_min());
332 y_max() = std::asin(x.y_max());
341 assert(x.y_min() >= -1 && x.y_min() <= 1);
342 assert(x.y_max() >= -1 && x.y_max() <= 1);
343 y_min() = std::acos(x.y_max());
344 y_max() = std::acos(x.y_min());
353 y_min() = std::atan(x.y_min());
354 y_max() = std::atan(x.y_max());
363 y_min() = std::exp(x.y_min());
364 y_max() = std::exp(x.y_max());
521 return (
ub +
lb) / 2;
538 return "Interval: [" + std::to_string(
lb) +
", " + std::to_string(
ub) +
"]";
663 template <
typename Derived>
736 x_lb.resize(
static_cast<Eigen::Index
>(
size));
737 x_ub.resize(
static_cast<Eigen::Index
>(
size));
744 explicit Box(
const std::vector<Interval>& vals)
746 x_lb.resize(
static_cast<Eigen::Index
>(vals.size()));
747 x_ub.resize(
static_cast<Eigen::Index
>(vals.size()));
749 for (Eigen::Index i=0; i<vals.size(); i++)
751 this->
x_lb(i) = vals[i].y_min();
752 this->
x_ub(i) = vals[i].y_max();
761 Box(
const Eigen::Vector<zono_float, -1>&
x_lb,
const Eigen::Vector<zono_float, -1>&
x_ub)
764 throw std::invalid_argument(
"x_l and x_u must have the same size");
811 if (i >=
x_lb.size())
812 throw std::out_of_range(
"Index out of range");
823 if (i >=
x_lb.size())
824 throw std::out_of_range(
"Index out of range");
825 return Interval(
x_lb(
static_cast<Eigen::Index
>(i)),
x_ub(
static_cast<Eigen::Index
>(i)));
843 virtual void project(Eigen::Ref<Eigen::Vector<zono_float, -1>> x)
const
845 if (x.size() !=
x_lb.size())
846 throw std::invalid_argument(
"x must have the same size as the Box");
847 x = x.cwiseMax(
x_lb).cwiseMin(
x_ub);
856 return new Box(*
this);
882 for (Eigen::Index i=0; i<
x_lb.size(); i++)
896 for (Eigen::Index i=0; i<this->
size(); i++)
898 c(i) = (*this)[i].center();
913 throw std::invalid_argument(
"Box addition: inconsistent dimensions");
915 for (
size_t i=0; i<this->
size(); ++i)
917 out[i] = (*this)[i] + other[i];
930 throw std::invalid_argument(
"Box subtraction: inconsistent dimensions");
932 for (
size_t i=0; i<this->
size(); ++i)
934 out[i] = (*this)[i] - other[i];
947 throw std::invalid_argument(
"Box multiplication: inconsistent dimensions");
949 for (
size_t i=0; i<this->
size(); ++i)
951 out[i] = (*this)[i] * other[i];
964 for (
size_t i=0; i<this->
size(); ++i)
966 out[i] = (*this)[i]*alpha;
979 throw std::invalid_argument(
"Box division: inconsistent dimensions");
981 for (
size_t i=0; i<this->
size(); ++i)
983 out[i] = (*this)[i] / other[i];
1001 bool contract(
const Eigen::SparseMatrix<zono_float, Eigen::RowMajor>& A,
const Eigen::Vector<zono_float, -1>& b,
const int iter)
1004 throw std::invalid_argument(
"iter must be positive");
1007 std::set<int> constraints;
1008 for (
int i=0; i<A.rows(); i++)
1010 constraints.insert(i);
1014 return contract_helper(A, b, iter, constraints);
1030 bool contract_subset(
const Eigen::SparseMatrix<zono_float, Eigen::RowMajor>& A_rm,
const Eigen::Vector<zono_float, -1>& b,
int iter,
1031 const Eigen::SparseMatrix<zono_float>& A,
const std::set<int>& inds,
int tree_search_depth)
1034 throw std::invalid_argument(
"iter must be positive");
1035 if (A_rm.rows() != A.rows() || A_rm.cols() != A.cols())
1036 throw std::invalid_argument(
"A_rm must equal A");
1039 std::set<int> all_constraints, all_vars;
1041 get_vars_cons(A, A_rm, all_constraints, all_vars, inds, 0, tree_search_depth);
1044 return contract_helper(A_rm, b, iter, all_constraints);
1055 if (A.cols() !=
x_lb.size())
1056 throw std::invalid_argument(
"Matrix A must have the same number of columns as the size of the Box");
1062 for (
int i=0; i<A.rows(); i++)
1065 for (
int j=0; j<A.cols(); j++)
1067 y[i].add_assign(y[i], ((*
this)[j]*A(i, j)).as_view());
1081 if (A.cols() !=
x_lb.size())
1082 throw std::invalid_argument(
"Matrix A must have the same number of columns as the size of the Box");
1088 for (
int i=0; i<A.rows(); i++)
1091 for (Eigen::SparseMatrix<zono_float, Eigen::RowMajor>::InnerIterator it(A, i); it; ++it)
1093 y[i].add_assign(y[i], ((*
this)[it.col()]*it.value()).as_view());
1107 if (x.size() !=
x_lb.size())
1108 throw std::invalid_argument(
"Vector x must have the same size as the Box");
1114 for (
int i=0; i<this->
x_lb.size(); i++)
1123 void permute(
const Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic>& P)
1135 std::stringstream ss;
1136 ss <<
"Box: " << std::endl;
1137 for (
size_t i=0; i<
x_lb.size(); i++)
1139 ss <<
" " << (*this)[i] << std::endl;
1177 bool contract_helper(
const Eigen::SparseMatrix<zono_float, Eigen::RowMajor>& A,
const Eigen::Vector<zono_float, -1>& b,
const int iter,
1178 const std::set<int>& constraints)
1180 for (
int i=0; i<iter; i++)
1183 for (
const int k : constraints)
1187 std::vector<int> cols;
1188 for (Eigen::SparseMatrix<zono_float, Eigen::RowMajor>::InnerIterator it(A, k); it; ++it)
1190 y.
add_assign(y, (*
this)[it.col()].to_interval()*it.value());
1191 cols.push_back(
static_cast<int>(it.col()));
1201 for (
const int col : cols)
1205 for (Eigen::SparseMatrix<zono_float, Eigen::RowMajor>::InnerIterator it(A, k); it; ++it)
1207 if (it.col() != col)
1209 x.
add_assign(x, (*
this)[it.col()].to_interval()*(-it.value()));
1218 (*this)[col].intersect_assign((*
this)[col], (x * (1/a_col)).as_view());
1236 void get_vars_cons(
const Eigen::SparseMatrix<zono_float>& A,
const Eigen::SparseMatrix<zono_float, Eigen::RowMajor>& A_rm,
1237 std::set<int>& constraints, std::set<int>& vars,
const std::set<int>& new_vars,
int depth,
int max_depth)
1240 vars.insert(new_vars.begin(), new_vars.end());
1243 std::set<int> new_constraints;
1244 for (
const int i : new_vars)
1246 for (Eigen::SparseMatrix<zono_float>::InnerIterator it(A, i); it; ++it)
1248 if (!constraints.count(
static_cast<int>(it.row())))
1250 new_constraints.insert(
static_cast<int>(it.row()));
1256 std::set<int> new_new_vars;
1257 for (
const int i : new_constraints)
1259 for (Eigen::SparseMatrix<zono_float, Eigen::RowMajor>::InnerIterator it(A_rm, i); it; ++it)
1261 if (!vars.count(
static_cast<int>(it.col())))
1263 new_new_vars.insert(
static_cast<int>(it.col()));
1269 constraints.insert(new_constraints.begin(), new_constraints.end());
1273 if (depth < max_depth && new_new_vars.empty())
1274 get_vars_cons(A, A_rm, constraints, vars, new_new_vars, depth, max_depth);
#define M_PI
Definition Intervals.hpp:31
Box (i.e., interval vector) class.
Definition Intervals.hpp:720
Box(const std::vector< Interval > &vals)
Constructor using vector of intervals.
Definition Intervals.hpp:744
Interval dot(const Eigen::Vector< zono_float, -1 > &x) const
Linear map with vector.
Definition Intervals.hpp:1104
std::string print() const
Print method.
Definition Intervals.hpp:1133
Interval operator[](const size_t i) const
Element-wise access.
Definition Intervals.hpp:821
Box linear_map(const Eigen::Matrix< zono_float, -1, -1 > &A) const
Linear map of box based on interval arithmetic.
Definition Intervals.hpp:1052
Eigen::Vector< zono_float, -1 > x_ub
vector of upper bounds
Definition Intervals.hpp:1163
Eigen::Vector< zono_float, -1 > x_lb
vector of lower bounds
Definition Intervals.hpp:1160
Box(const size_t size)
Default construct with size specified.
Definition Intervals.hpp:734
virtual Box * clone() const
Clone operation.
Definition Intervals.hpp:854
Box operator/(const Box &other) const
elementwise division
Definition Intervals.hpp:976
Box & operator=(const Box &other)
Copy assignment.
Definition Intervals.hpp:781
Box()=default
Default constructor.
const Eigen::Vector< zono_float, -1 > & upper() const
Get upper bounds.
Definition Intervals.hpp:870
bool contract_subset(const Eigen::SparseMatrix< zono_float, Eigen::RowMajor > &A_rm, const Eigen::Vector< zono_float, -1 > &b, int iter, const Eigen::SparseMatrix< zono_float > &A, const std::set< int > &inds, int tree_search_depth)
Interval contractor over a subset of the dimensions of the box.
Definition Intervals.hpp:1030
Eigen::Vector< zono_float, -1 > center() const
get center of box
Definition Intervals.hpp:893
bool contract(const Eigen::SparseMatrix< zono_float, Eigen::RowMajor > &A, const Eigen::Vector< zono_float, -1 > &b, const int iter)
Interval contractor.
Definition Intervals.hpp:1001
virtual void project(Eigen::Ref< Eigen::Vector< zono_float, -1 > > x) const
Projects vector onto the Box.
Definition Intervals.hpp:843
void permute(const Eigen::PermutationMatrix< Eigen::Dynamic, Eigen::Dynamic > &P)
Permutes in place using permutation matrix, i.e., [x] <- P*[x].
Definition Intervals.hpp:1123
Box operator*(zono_float alpha) const
elementwise multiplication with scalar
Definition Intervals.hpp:961
size_t size() const
get size of Box object
Definition Intervals.hpp:832
friend std::ostream & operator<<(std::ostream &os, const Box &box)
print to ostream
Definition Intervals.hpp:1150
Box(const Eigen::Vector< zono_float, -1 > &x_lb, const Eigen::Vector< zono_float, -1 > &x_ub)
Constructor from intervals of lower and upper bounds.
Definition Intervals.hpp:761
IntervalView operator[](const size_t i)
Element-wise access, used for assignment.
Definition Intervals.hpp:809
Box operator-(const Box &other) const
elementwise subtraction
Definition Intervals.hpp:927
Box operator*(const Box &other) const
elementwise multiplication
Definition Intervals.hpp:944
zono_float width() const
Get width of box.
Definition Intervals.hpp:879
virtual ~Box()=default
Virtual destructor.
const Eigen::Vector< zono_float, -1 > & lower() const
Get lower bounds.
Definition Intervals.hpp:864
Box operator+(const Box &other) const
elementwise addition
Definition Intervals.hpp:910
Box linear_map(const Eigen::SparseMatrix< zono_float, Eigen::RowMajor > &A) const
Linear map of box based on interval arithmetic.
Definition Intervals.hpp:1078
Box(const Box &other)
Copy constructor.
Definition Intervals.hpp:796
#define zono_float
Defines the floating-point type used in ZonoOpt.
Definition ZonoOpt.hpp:43
#define zono_eps
Defines the precision used for floating point comparisons in ZonoOpt.
Definition ZonoOpt.hpp:51
Base class for Interval and IntervalView.
Definition Intervals.hpp:50
void add_assign(const Derived &x1, const Derived &x2)
sets interval to x1 + x2
Definition Intervals.hpp:91
void arccos_assign(const Derived &x)
compute interval containing arccos(x) over x
Definition Intervals.hpp:339
void cos_assign(const Derived &x)
compute interval containing cos(x) over x
Definition Intervals.hpp:275
void inverse()
sets interval to its inverse
Definition Intervals.hpp:146
void subtract_assign(const Derived &x1, const Derived &x2)
sets interval to x1 - x2
Definition Intervals.hpp:102
void divide_assign(const Derived &x1, const Derived &x2)
sets interval to x1 / x2
Definition Intervals.hpp:183
void arctan_assign(const Derived &x)
compute interval containing arctan(x) over x
Definition Intervals.hpp:351
void set(const zono_float min, const zono_float max)
Sets interval bounds.
Definition Intervals.hpp:80
zono_float & y_max()
Returns reference to interval upper bound.
Definition Intervals.hpp:61
void sin_assign(const Derived &x)
compute interval containing sin(x) over x
Definition Intervals.hpp:242
void intersect_assign(const Derived &x1, const Derived &x2)
sets interval to intersection of x1 and x2
Definition Intervals.hpp:195
void exp_assign(const Derived &x)
compute interval containing exp(x) over x
Definition Intervals.hpp:361
void multiply_assign(const Derived &x1, const Derived &x2)
sets interval to x1 * x2
Definition Intervals.hpp:113
zono_float & y_min()
Returns reference to interval lower bound.
Definition Intervals.hpp:55
void tan_assign(const Derived &x)
compute interval containing tan(x) over x
Definition Intervals.hpp:286
void arcsin_assign(const Derived &x)
compute interval containing arcsin(x) over x
Definition Intervals.hpp:327
bool is_single_valued() const
checks whether interval is single-valued (i.e., width is 0 within numerical tolerance)
Definition Intervals.hpp:224
zono_float width() const
get width of interval (ub - lb)
Definition Intervals.hpp:233
const zono_float & y_min() const
Returns const reference to interval lower bound.
Definition Intervals.hpp:67
void multiply_assign(const Derived &x1, zono_float alpha)
sets interval to alpha * x1
Definition Intervals.hpp:129
bool contains(zono_float y) const
checks whether interval contains a value
Definition Intervals.hpp:215
bool is_empty() const
checks whether interval is empty
Definition Intervals.hpp:205
const zono_float & y_max() const
Returns const reference to interval upper bound.
Definition Intervals.hpp:73
IntervalView class.
Definition Intervals.hpp:637
zono_float & get_y_min()
get reference to lower bound
Definition Intervals.hpp:684
IntervalView & operator=(const IntervalBase< Derived > &other)
Assignment operator.
Definition Intervals.hpp:664
const zono_float & get_y_max() const
get const reference to upper bound
Definition Intervals.hpp:702
zono_float & get_y_max()
get reference to upper bound
Definition Intervals.hpp:690
Interval to_interval() const
convert to Interval class
Definition Intervals.hpp:706
const zono_float & get_y_min() const
get const reference to lower bound
Definition Intervals.hpp:696
zono_float * lb_ptr
pointer to lower bound
Definition Intervals.hpp:641
IntervalView(zono_float *y_min, zono_float *y_max)
constructor for IntervalView
Definition Intervals.hpp:653
zono_float * ub_ptr
pointer to upper bound
Definition Intervals.hpp:644
Interval class.
Definition Intervals.hpp:374
Interval(zono_float y_min, zono_float y_max)
Interval constructor.
Definition Intervals.hpp:393
const zono_float & get_y_max() const
get const reference to upper bound
Definition Intervals.hpp:428
std::string print() const
print method for Interval
Definition Intervals.hpp:536
zono_float & get_y_max()
get reference to upper bound
Definition Intervals.hpp:416
Interval()
default constructor
Definition Intervals.hpp:386
Interval intersect(const Interval &other) const
interval intersection
Definition Intervals.hpp:508
Interval arctan() const
compute interval containing arctan(x) for all x in interval
Definition Intervals.hpp:612
Interval exp() const
compute interval containing exp(x) for all x in interval
Definition Intervals.hpp:623
Interval operator+(const Interval &other) const
interval addition
Definition Intervals.hpp:437
Interval arcsin() const
compute interval containing arcsin(x) for all x in interval
Definition Intervals.hpp:590
Interval operator*(zono_float alpha) const
interval multiplication with scalar
Definition Intervals.hpp:473
zono_float lb
lower bound
Definition Intervals.hpp:377
Interval operator*(const Interval &other) const
interval multiplication
Definition Intervals.hpp:461
IntervalView as_view()
IntervalView interface for Interval.
Definition Intervals.hpp:711
const zono_float & get_y_min() const
get const reference to lower bound
Definition Intervals.hpp:422
friend std::ostream & operator<<(std::ostream &os, const Interval &interval)
print to ostream
Definition Intervals.hpp:547
Interval tan() const
compute interval containing tan(x) for all x in interval
Definition Intervals.hpp:579
Interval inv() const
interval inverse
Definition Intervals.hpp:484
Interval operator-(const Interval &other) const
interval subtraction
Definition Intervals.hpp:449
Interval operator/(const Interval &other) const
interval division
Definition Intervals.hpp:496
zono_float center() const
get center of interval
Definition Intervals.hpp:519
zono_float ub
upper bound
Definition Intervals.hpp:380
zono_float & get_y_min()
get reference to lower bound
Definition Intervals.hpp:410
Interval sin() const
compute interval containing sin(x) for all x in interval
Definition Intervals.hpp:557
Interval cos() const
compute interval containing cos(x) for all x in interval
Definition Intervals.hpp:568
Interval * clone() const
Clone Interval object.
Definition Intervals.hpp:399
Interval arccos() const
compute interval containing arccos(x) for all x in interval
Definition Intervals.hpp:601