1#ifndef ZONOOPT_INTERVAL_UTILITIES_HPP_
2#define ZONOOPT_INTERVAL_UTILITIES_HPP_
22#include <Eigen/Sparse>
32 using namespace detail;
46 template <
typename Derived>
118 y_min() = std::min({
a, b, c,
d});
119 y_max() = std::max({
a, b, c,
d});
151 min = std::numeric_limits<zono_float>::infinity();
152 max = -std::numeric_limits<zono_float>::infinity();
154 else if (
min > 0 ||
max < 0)
162 max = std::numeric_limits<zono_float>::infinity();
167 min = -std::numeric_limits<zono_float>::infinity();
171 min = -std::numeric_limits<zono_float>::infinity();
172 max = std::numeric_limits<zono_float>::infinity();
195 y_min() = std::max(
x1.y_min(),
x2.y_min());
196 y_max() = std::min(
x1.y_max(),
x2.y_max());
242 if (x.y_max() - x.y_min() >= two*pi)
264 y_max() = ((
l < pi/two && pi/two < u) || (
l < -3*pi/two && -3*pi/two < u)) ? one : std::max(std::sin(u), std::sin(
l));
265 y_min() = ((
l < -pi/two && -pi/two < u) || (
l < 3*pi/two && 3*pi/two < u)) ? -one : std::min(std::sin(u), std::sin(
l));
276 x_sin.set(x.y_min() + pi/two, x.y_max() + pi/two);
286 if (x.y_max() - x.y_min() >= pi)
288 y_max() = std::numeric_limits<zono_float>::infinity();
289 y_min() = -std::numeric_limits<zono_float>::infinity();
308 if ((
l < -pi/two && -pi/two < u) || (
l < pi/two && pi/two < u))
310 y_max() = std::numeric_limits<zono_float>::infinity();
311 y_min() = -std::numeric_limits<zono_float>::infinity();
315 y_max() = std::tan(u);
327 assert(x.y_min() >= -one && x.y_min() <= one);
328 assert(x.y_max() >= -one && x.y_max() <= one);
329 y_min() = std::asin(x.y_min());
330 y_max() = std::asin(x.y_max());
339 assert(x.y_min() >= -one && x.y_min() <= one);
340 assert(x.y_max() >= -one && x.y_max() <= one);
341 y_min() = std::acos(x.y_max());
342 y_max() = std::acos(x.y_min());
351 y_min() = std::atan(x.y_min());
352 y_max() = std::atan(x.y_max());
361 y_min() = std::exp(x.y_min());
362 y_max() = std::exp(x.y_max());
519 return (
ub +
lb) / two;
536 return "Interval: [" + std::to_string(
lb) +
", " + std::to_string(
ub) +
"]";
661 template <
typename Derived>
734 x_lb.resize(
static_cast<Eigen::Index
>(
size));
735 x_ub.resize(
static_cast<Eigen::Index
>(
size));
742 explicit Box(
const std::vector<Interval>& vals)
744 x_lb.resize(
static_cast<Eigen::Index
>(vals.size()));
745 x_ub.resize(
static_cast<Eigen::Index
>(vals.size()));
747 for (Eigen::Index i=0; i<static_cast<Eigen::Index>(vals.size()); i++)
749 this->
x_lb(i) = vals[i].y_min();
750 this->
x_ub(i) = vals[i].y_max();
759 Box(
const Eigen::Vector<zono_float, -1>&
x_lb,
const Eigen::Vector<zono_float, -1>&
x_ub)
762 throw std::invalid_argument(
"x_l and x_u must have the same size");
809 if (i >=
static_cast<size_t>(
x_lb.size()))
810 throw std::out_of_range(
"Index out of range");
821 if (i >=
static_cast<size_t>(
x_lb.size()))
822 throw std::out_of_range(
"Index out of range");
823 return Interval(
x_lb(
static_cast<Eigen::Index
>(i)),
x_ub(
static_cast<Eigen::Index
>(i)));
841 virtual void project(Eigen::Ref<Eigen::Vector<zono_float, -1>> x)
const
843 if (x.size() !=
x_lb.size())
844 throw std::invalid_argument(
"x must have the same size as the Box");
845 x = x.cwiseMax(
x_lb).cwiseMin(
x_ub);
854 return new Box(*
this);
880 for (Eigen::Index i=0; i<
x_lb.size(); i++)
894 for (Eigen::Index i=0; i<static_cast<Eigen::Index>(this->
size()); i++)
896 c(i) = (*this)[i].center();
911 throw std::invalid_argument(
"Box addition: inconsistent dimensions");
913 for (
size_t i=0; i<this->
size(); ++i)
915 out[i] = (*this)[i] + other[i];
928 throw std::invalid_argument(
"Box subtraction: inconsistent dimensions");
930 for (
size_t i=0; i<this->
size(); ++i)
932 out[i] = (*this)[i] - other[i];
945 throw std::invalid_argument(
"Box multiplication: inconsistent dimensions");
947 for (
size_t i=0; i<this->
size(); ++i)
949 out[i] = (*this)[i] * other[i];
962 for (
size_t i=0; i<this->
size(); ++i)
964 out[i] = (*this)[i]*alpha;
977 throw std::invalid_argument(
"Box division: inconsistent dimensions");
979 for (
size_t i=0; i<this->
size(); ++i)
981 out[i] = (*this)[i] / other[i];
999 bool contract(
const Eigen::SparseMatrix<zono_float, Eigen::RowMajor>& A,
const Eigen::Vector<zono_float, -1>& b,
const int iter)
1002 throw std::invalid_argument(
"iter must be positive");
1005 std::set<int> constraints;
1006 for (
int i=0; i<A.rows(); i++)
1008 constraints.insert(i);
1012 return contract_helper(A, b, iter, constraints);
1028 bool contract_subset(
const Eigen::SparseMatrix<zono_float, Eigen::RowMajor>& A_rm,
const Eigen::Vector<zono_float, -1>& b,
int iter,
1029 const Eigen::SparseMatrix<zono_float>& A,
const std::set<int>& inds,
int tree_search_depth)
1032 throw std::invalid_argument(
"iter must be positive");
1033 if (A_rm.rows() != A.rows() || A_rm.cols() != A.cols())
1034 throw std::invalid_argument(
"A_rm must equal A");
1037 std::set<int> all_constraints, all_vars;
1039 get_vars_cons(A, A_rm, all_constraints, all_vars, inds, 0, tree_search_depth);
1042 return contract_helper(A_rm, b, iter, all_constraints);
1053 if (A.cols() !=
x_lb.size())
1054 throw std::invalid_argument(
"Matrix A must have the same number of columns as the size of the Box");
1060 for (
int i=0; i<A.rows(); i++)
1063 for (
int j=0; j<A.cols(); j++)
1065 y[i].add_assign(y[i], ((*
this)[j]*A(i, j)).as_view());
1079 if (A.cols() !=
x_lb.size())
1080 throw std::invalid_argument(
"Matrix A must have the same number of columns as the size of the Box");
1086 for (
int i=0; i<A.rows(); i++)
1089 for (Eigen::SparseMatrix<zono_float, Eigen::RowMajor>::InnerIterator it(A, i); it; ++it)
1091 y[i].add_assign(y[i], ((*
this)[it.col()]*it.value()).as_view());
1105 if (x.size() !=
x_lb.size())
1106 throw std::invalid_argument(
"Vector x must have the same size as the Box");
1112 for (
int i=0; i<this->
x_lb.size(); i++)
1121 void permute(
const Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic>& P)
1133 std::stringstream ss;
1134 ss <<
"Box: " << std::endl;
1135 for (Eigen::Index i=0; i<
x_lb.size(); i++)
1137 ss <<
" " << (*this)[i] << std::endl;
1175 bool contract_helper(
const Eigen::SparseMatrix<zono_float, Eigen::RowMajor>& A,
const Eigen::Vector<zono_float, -1>& b,
const int iter,
1176 const std::set<int>& constraints)
1178 for (
int i=0; i<iter; i++)
1181 for (
const int k : constraints)
1185 std::vector<int> cols;
1186 for (Eigen::SparseMatrix<zono_float, Eigen::RowMajor>::InnerIterator it(A, k); it; ++it)
1188 y.
add_assign(y, (*
this)[it.col()].to_interval()*it.value());
1189 cols.push_back(
static_cast<int>(it.col()));
1199 for (
const int col : cols)
1203 for (Eigen::SparseMatrix<zono_float, Eigen::RowMajor>::InnerIterator it(A, k); it; ++it)
1205 if (it.col() != col)
1207 x.
add_assign(x, (*
this)[it.col()].to_interval()*(-it.value()));
1216 (*this)[col].intersect_assign((*
this)[col], (x * (one/a_col)).as_view());
1234 void get_vars_cons(
const Eigen::SparseMatrix<zono_float>& A,
const Eigen::SparseMatrix<zono_float, Eigen::RowMajor>& A_rm,
1235 std::set<int>& constraints, std::set<int>& vars,
const std::set<int>& new_vars,
int depth,
int max_depth)
1238 vars.insert(new_vars.begin(), new_vars.end());
1241 std::set<int> new_constraints;
1242 for (
const int i : new_vars)
1244 for (Eigen::SparseMatrix<zono_float>::InnerIterator it(A, i); it; ++it)
1246 if (!constraints.count(
static_cast<int>(it.row())))
1248 new_constraints.insert(
static_cast<int>(it.row()));
1254 std::set<int> new_new_vars;
1255 for (
const int i : new_constraints)
1257 for (Eigen::SparseMatrix<zono_float, Eigen::RowMajor>::InnerIterator it(A_rm, i); it; ++it)
1259 if (!vars.count(
static_cast<int>(it.col())))
1261 new_new_vars.insert(
static_cast<int>(it.col()));
1267 constraints.insert(new_constraints.begin(), new_constraints.end());
1271 if (depth < max_depth && new_new_vars.empty())
1272 get_vars_cons(A, A_rm, constraints, vars, new_new_vars, depth, max_depth);
Box (i.e., interval vector) class.
Definition Intervals.hpp:718
Box(const std::vector< Interval > &vals)
Constructor using vector of intervals.
Definition Intervals.hpp:742
Interval dot(const Eigen::Vector< zono_float, -1 > &x) const
Linear map with vector.
Definition Intervals.hpp:1102
std::string print() const
Print method.
Definition Intervals.hpp:1131
Interval operator[](const size_t i) const
Element-wise access.
Definition Intervals.hpp:819
Box linear_map(const Eigen::Matrix< zono_float, -1, -1 > &A) const
Linear map of box based on interval arithmetic.
Definition Intervals.hpp:1050
Eigen::Vector< zono_float, -1 > x_ub
vector of upper bounds
Definition Intervals.hpp:1161
Eigen::Vector< zono_float, -1 > x_lb
vector of lower bounds
Definition Intervals.hpp:1158
Box(const size_t size)
Default construct with size specified.
Definition Intervals.hpp:732
virtual Box * clone() const
Clone operation.
Definition Intervals.hpp:852
Box operator/(const Box &other) const
elementwise division
Definition Intervals.hpp:974
Box & operator=(const Box &other)
Copy assignment.
Definition Intervals.hpp:779
Box()=default
Default constructor.
const Eigen::Vector< zono_float, -1 > & upper() const
Get upper bounds.
Definition Intervals.hpp:868
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:1028
Eigen::Vector< zono_float, -1 > center() const
get center of box
Definition Intervals.hpp:891
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:999
virtual void project(Eigen::Ref< Eigen::Vector< zono_float, -1 > > x) const
Projects vector onto the Box.
Definition Intervals.hpp:841
void permute(const Eigen::PermutationMatrix< Eigen::Dynamic, Eigen::Dynamic > &P)
Permutes in place using permutation matrix, i.e., [x] <- P*[x].
Definition Intervals.hpp:1121
Box operator*(zono_float alpha) const
elementwise multiplication with scalar
Definition Intervals.hpp:959
size_t size() const
get size of Box object
Definition Intervals.hpp:830
friend std::ostream & operator<<(std::ostream &os, const Box &box)
print to ostream
Definition Intervals.hpp:1148
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:759
IntervalView operator[](const size_t i)
Element-wise access, used for assignment.
Definition Intervals.hpp:807
Box operator-(const Box &other) const
elementwise subtraction
Definition Intervals.hpp:925
Box operator*(const Box &other) const
elementwise multiplication
Definition Intervals.hpp:942
zono_float width() const
Get width of box.
Definition Intervals.hpp:877
virtual ~Box()=default
Virtual destructor.
const Eigen::Vector< zono_float, -1 > & lower() const
Get lower bounds.
Definition Intervals.hpp:862
Box operator+(const Box &other) const
elementwise addition
Definition Intervals.hpp:908
Box linear_map(const Eigen::SparseMatrix< zono_float, Eigen::RowMajor > &A) const
Linear map of box based on interval arithmetic.
Definition Intervals.hpp:1076
Box(const Box &other)
Copy constructor.
Definition Intervals.hpp:794
#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:48
void add_assign(const Derived &x1, const Derived &x2)
sets interval to x1 + x2
Definition Intervals.hpp:89
void arccos_assign(const Derived &x)
compute interval containing arccos(x) over x
Definition Intervals.hpp:337
void cos_assign(const Derived &x)
compute interval containing cos(x) over x
Definition Intervals.hpp:273
void inverse()
sets interval to its inverse
Definition Intervals.hpp:144
void subtract_assign(const Derived &x1, const Derived &x2)
sets interval to x1 - x2
Definition Intervals.hpp:100
void divide_assign(const Derived &x1, const Derived &x2)
sets interval to x1 / x2
Definition Intervals.hpp:181
void arctan_assign(const Derived &x)
compute interval containing arctan(x) over x
Definition Intervals.hpp:349
void set(const zono_float min, const zono_float max)
Sets interval bounds.
Definition Intervals.hpp:78
zono_float & y_max()
Returns reference to interval upper bound.
Definition Intervals.hpp:59
void sin_assign(const Derived &x)
compute interval containing sin(x) over x
Definition Intervals.hpp:240
void intersect_assign(const Derived &x1, const Derived &x2)
sets interval to intersection of x1 and x2
Definition Intervals.hpp:193
void exp_assign(const Derived &x)
compute interval containing exp(x) over x
Definition Intervals.hpp:359
void multiply_assign(const Derived &x1, const Derived &x2)
sets interval to x1 * x2
Definition Intervals.hpp:111
zono_float & y_min()
Returns reference to interval lower bound.
Definition Intervals.hpp:53
void tan_assign(const Derived &x)
compute interval containing tan(x) over x
Definition Intervals.hpp:284
void arcsin_assign(const Derived &x)
compute interval containing arcsin(x) over x
Definition Intervals.hpp:325
bool is_single_valued() const
checks whether interval is single-valued (i.e., width is 0 within numerical tolerance)
Definition Intervals.hpp:222
zono_float width() const
get width of interval (ub - lb)
Definition Intervals.hpp:231
const zono_float & y_min() const
Returns const reference to interval lower bound.
Definition Intervals.hpp:65
void multiply_assign(const Derived &x1, zono_float alpha)
sets interval to alpha * x1
Definition Intervals.hpp:127
bool contains(zono_float y) const
checks whether interval contains a value
Definition Intervals.hpp:213
bool is_empty() const
checks whether interval is empty
Definition Intervals.hpp:203
const zono_float & y_max() const
Returns const reference to interval upper bound.
Definition Intervals.hpp:71
IntervalView class.
Definition Intervals.hpp:635
zono_float & get_y_min()
get reference to lower bound
Definition Intervals.hpp:682
IntervalView & operator=(const IntervalBase< Derived > &other)
Assignment operator.
Definition Intervals.hpp:662
const zono_float & get_y_max() const
get const reference to upper bound
Definition Intervals.hpp:700
zono_float & get_y_max()
get reference to upper bound
Definition Intervals.hpp:688
Interval to_interval() const
convert to Interval class
Definition Intervals.hpp:704
const zono_float & get_y_min() const
get const reference to lower bound
Definition Intervals.hpp:694
zono_float * lb_ptr
pointer to lower bound
Definition Intervals.hpp:639
IntervalView(zono_float *y_min, zono_float *y_max)
constructor for IntervalView
Definition Intervals.hpp:651
zono_float * ub_ptr
pointer to upper bound
Definition Intervals.hpp:642
Interval class.
Definition Intervals.hpp:372
Interval(zono_float y_min, zono_float y_max)
Interval constructor.
Definition Intervals.hpp:391
const zono_float & get_y_max() const
get const reference to upper bound
Definition Intervals.hpp:426
std::string print() const
print method for Interval
Definition Intervals.hpp:534
zono_float & get_y_max()
get reference to upper bound
Definition Intervals.hpp:414
Interval()
default constructor
Definition Intervals.hpp:384
Interval intersect(const Interval &other) const
interval intersection
Definition Intervals.hpp:506
Interval arctan() const
compute interval containing arctan(x) for all x in interval
Definition Intervals.hpp:610
Interval exp() const
compute interval containing exp(x) for all x in interval
Definition Intervals.hpp:621
Interval operator+(const Interval &other) const
interval addition
Definition Intervals.hpp:435
Interval arcsin() const
compute interval containing arcsin(x) for all x in interval
Definition Intervals.hpp:588
Interval operator*(zono_float alpha) const
interval multiplication with scalar
Definition Intervals.hpp:471
zono_float lb
lower bound
Definition Intervals.hpp:375
Interval operator*(const Interval &other) const
interval multiplication
Definition Intervals.hpp:459
IntervalView as_view()
IntervalView interface for Interval.
Definition Intervals.hpp:709
const zono_float & get_y_min() const
get const reference to lower bound
Definition Intervals.hpp:420
friend std::ostream & operator<<(std::ostream &os, const Interval &interval)
print to ostream
Definition Intervals.hpp:545
Interval tan() const
compute interval containing tan(x) for all x in interval
Definition Intervals.hpp:577
Interval inv() const
interval inverse
Definition Intervals.hpp:482
Interval operator-(const Interval &other) const
interval subtraction
Definition Intervals.hpp:447
Interval operator/(const Interval &other) const
interval division
Definition Intervals.hpp:494
zono_float center() const
get center of interval
Definition Intervals.hpp:517
zono_float ub
upper bound
Definition Intervals.hpp:378
zono_float & get_y_min()
get reference to lower bound
Definition Intervals.hpp:408
Interval sin() const
compute interval containing sin(x) for all x in interval
Definition Intervals.hpp:555
Interval cos() const
compute interval containing cos(x) for all x in interval
Definition Intervals.hpp:566
Interval * clone() const
Clone Interval object.
Definition Intervals.hpp:397
Interval arccos() const
compute interval containing arccos(x) for all x in interval
Definition Intervals.hpp:599