Skip to content

Commit

Permalink
Refactoring polytopes (#82)
Browse files Browse the repository at this point in the history
* Eliminating "init" and refactoring of the constructors
and introducing std::make_pair
* Add implementation for the Big3
* Eliminate calls to Hpolytope.init
* Eliminate free_them_all function call
* fix R tests and improve c++ polytope generators
* fix errors in R interface and cross polytope generator
* Polishing according to the review in the PR.
* fix bugs on zonotope destructor
* remove Chebychev ball computation from the constructor
Co-authored-by: TSIGARIDAS Elias <[email protected]>
Co-authored-by: Tolis <[email protected]>
  • Loading branch information
elias-tsigaridas authored Sep 29, 2020
1 parent 6b07cf5 commit e547120
Show file tree
Hide file tree
Showing 54 changed files with 843 additions and 760 deletions.
2 changes: 1 addition & 1 deletion R-proj/R/RcppExports.R
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ rounding <- function(P, method = NULL, seed = NULL) {
#' \dQuote{Billiard walk - a new sampling algorithm for control and optimization,} \emph{IFAC Proceedings Volumes,} 2014.},
#'
#' @references \cite{Y. Chen, R. Dwivedi, M. J. Wainwright and B. Yu,
#' \dQuote{Vaidya walk: A sampling algorithm based on the volumetric barrier,} \emph{55th Annual Allerton Conference on Communication, Control, and Computing,} 2017.}
#' \dQuote{Fast MCMC Sampling Algorithms on Polytopes,} \emph{Journal of Machine Learning Research,} 2018.}
#'
#' @return A \eqn{d\times n} matrix that contains, column-wise, the sampled points from the convex polytope P.
#' @examples
Expand Down
11 changes: 2 additions & 9 deletions R-proj/man/compute_indicators.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion R-proj/man/copula.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion R-proj/man/sample_points.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions R-proj/man/writeSdpaFormatFile.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion R-proj/man/zonotope_approximation.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion R-proj/src/Makevars
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PKG_CPPFLAGS=-I../../external/boost -I../../external/LPsolve_src/run_headers -I../../external/minimum_ellipsoid -I../../include
PKG_CPPFLAGS= -I../../external/boost -I../../external/LPsolve_src/run_headers -I../../external/minimum_ellipsoid -I../../include

PKG_CXXFLAGS= -lm -ldl -Wno-ignored-attributes -DBOOST_NO_AUTO_PTR -DDISABLE_NLP_ORACLES

Expand Down
5 changes: 2 additions & 3 deletions R-proj/src/exact_vol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,10 @@ double exact_vol(Rcpp::Nullable<Rcpp::Reference> P) {

} else if (type == 3) {

typedef Zonotope <Point> zonotope;
zonotope ZP;
typedef Zonotope<Point> zonotope;
dim = Rcpp::as<Rcpp::Reference>(P).field("dimension");

ZP.init(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("G")),
zonotope ZP(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("G")),
VT::Ones(Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("G")).rows()));
vol = exact_zonotope_vol<NT>(ZP);

Expand Down
19 changes: 6 additions & 13 deletions R-proj/src/inner_ball.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ Rcpp::NumericVector inner_ball(Rcpp::Reference P,
switch (type) {
case 1: {
// Hpolytope
Hpolytope HP;
HP.init(n, Rcpp::as<MT>(P.field("A")), Rcpp::as<VT>(P.field("b")));
Hpolytope HP(n, Rcpp::as<MT>(P.field("A")), Rcpp::as<VT>(P.field("b")));
if (lp_solve) {
InnerBall = ComputeChebychevBall<NT, Point>(HP.get_mat(), HP.get_vec());
} else {
Expand All @@ -67,29 +66,23 @@ Rcpp::NumericVector inner_ball(Rcpp::Reference P,
}
case 2: {
// Vpolytope
Vpolytope VP;
VP.init(n, Rcpp::as<MT>(P.field("V")), VT::Ones(Rcpp::as<MT>(P.field("V")).rows()));
Vpolytope VP(n, Rcpp::as<MT>(P.field("V")), VT::Ones(Rcpp::as<MT>(P.field("V")).rows()));
InnerBall = VP.ComputeInnerBall();
if (InnerBall.second < 0.0) throw Rcpp::exception("Unable to compute a feasible point.");
break;
}
case 3: {
// Zonotope
zonotope ZP;
InnerBall = ZP.ComputeInnerBall();
ZP.init(n, Rcpp::as<MT>(P.field("G")), VT::Ones(Rcpp::as<MT>(P.field("G")).rows()));
zonotope ZP(n, Rcpp::as<MT>(P.field("G")), VT::Ones(Rcpp::as<MT>(P.field("G")).rows()));
InnerBall = ZP.ComputeInnerBall();
if (InnerBall.second < 0.0) throw Rcpp::exception("Unable to compute a feasible point.");
break;
}
case 4: {
// Intersection of two V-polytopes
Vpolytope VP1;
Vpolytope VP2;
InterVP VPcVP;
VP1.init(n, Rcpp::as<MT>(P.field("V1")), VT::Ones(Rcpp::as<MT>(P.field("V1")).rows()));
VP2.init(n, Rcpp::as<MT>(P.field("V2")), VT::Ones(Rcpp::as<MT>(P.field("V2")).rows()));
VPcVP.init(VP1, VP2);
Vpolytope VP1(n, Rcpp::as<MT>(P.field("V1")), VT::Ones(Rcpp::as<MT>(P.field("V1")).rows()));
Vpolytope VP2(n, Rcpp::as<MT>(P.field("V2")), VT::Ones(Rcpp::as<MT>(P.field("V2")).rows()));
InterVP VPcVP(VP1, VP2);
if (!VPcVP.is_feasible()) throw Rcpp::exception("Empty set!");
InnerBall = VPcVP.ComputeInnerBall();
if (InnerBall.second < 0.0) throw Rcpp::exception("Unable to compute a feasible point.");
Expand Down
18 changes: 9 additions & 9 deletions R-proj/src/poly_gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ Rcpp::NumericMatrix poly_gen (int kind_gen, bool Vpoly_gen, bool Zono_gen, int d
switch (kind_gen) {

case 1:
return extractMatPoly(gen_cube<Vpolytope>(dim_gen, true));
return extractMatPoly(generate_cube<Vpolytope>(dim_gen, true));

case 2:
return extractMatPoly(gen_cross<Vpolytope>(dim_gen, true));
return extractMatPoly(generate_cross<Vpolytope>(dim_gen, true));

case 3:
return extractMatPoly(gen_simplex<Vpolytope>(dim_gen, true));
return extractMatPoly(generate_simplex<Vpolytope>(dim_gen, true));

case 4:
return extractMatPoly(random_vpoly<Vpolytope, RNGType>(dim_gen, m_gen, seed_rcpp));
Expand All @@ -85,25 +85,25 @@ Rcpp::NumericMatrix poly_gen (int kind_gen, bool Vpoly_gen, bool Zono_gen, int d
switch (kind_gen) {

case 1:
return extractMatPoly(gen_cube<Hpolytope>(dim_gen, false));
return extractMatPoly(generate_cube<Hpolytope>(dim_gen, false));

case 2:
return extractMatPoly(gen_cross<Hpolytope>(dim_gen, false));
return extractMatPoly(generate_cross<Hpolytope>(dim_gen, false));

case 3:
return extractMatPoly(gen_simplex<Hpolytope>(dim_gen, false));
return extractMatPoly(generate_simplex<Hpolytope>(dim_gen, false));

case 4:
return extractMatPoly(gen_prod_simplex<Hpolytope>(dim_gen));
return extractMatPoly(generate_prod_simplex<Hpolytope>(dim_gen));

case 5:
return extractMatPoly(gen_skinny_cube<Hpolytope>(dim_gen));
return extractMatPoly(generate_skinny_cube<Hpolytope>(dim_gen));

case 6:
return extractMatPoly(random_hpoly<Hpolytope, RNGType>(dim_gen, m_gen, seed_rcpp));

case 7:
return extractMatPoly(gen_birk<Hpolytope>(dim_gen));
return extractMatPoly(generate_birkhoff<Hpolytope>(dim_gen));

}
}
Expand Down
11 changes: 3 additions & 8 deletions R-proj/src/rotating.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ Rcpp::NumericMatrix rotating (Rcpp::Reference P, Rcpp::Nullable<Rcpp::NumericMat
switch (type) {
case 1: {
// Hpolytope
Hpolytope HP;
HP.init(n, Rcpp::as<MT>(P.field("A")), Rcpp::as<VT>(P.field("b")));
Hpolytope HP(n, Rcpp::as<MT>(P.field("A")), Rcpp::as<VT>(P.field("b")));
if (T.isNotNull()) {
TransorfMat = Rcpp::as<MT>(T);
HP.linear_transformIt(TransorfMat.inverse());
Expand All @@ -67,8 +66,7 @@ Rcpp::NumericMatrix rotating (Rcpp::Reference P, Rcpp::Nullable<Rcpp::NumericMat
}
case 2: {
// Vpolytope
Vpolytope VP;
VP.init(n, Rcpp::as<MT>(P.field("V")), VT::Ones(Rcpp::as<MT>(P.field("V")).rows()));
Vpolytope VP(n, Rcpp::as<MT>(P.field("V")), VT::Ones(Rcpp::as<MT>(P.field("V")).rows()));
if (T.isNotNull()) {
TransorfMat = Rcpp::as<MT>(T);
VP.linear_transformIt(TransorfMat.inverse());
Expand All @@ -80,8 +78,7 @@ Rcpp::NumericMatrix rotating (Rcpp::Reference P, Rcpp::Nullable<Rcpp::NumericMat
}
case 3: {
// Zonotope
zonotope ZP;
ZP.init(n, Rcpp::as<MT>(P.field("G")), VT::Ones(Rcpp::as<MT>(P.field("G")).rows()));
zonotope ZP(n, Rcpp::as<MT>(P.field("G")), VT::Ones(Rcpp::as<MT>(P.field("G")).rows()));
if (T.isNotNull()) {
TransorfMat = Rcpp::as<MT>(T);
ZP.linear_transformIt(TransorfMat.inverse());
Expand All @@ -96,8 +93,6 @@ Rcpp::NumericMatrix rotating (Rcpp::Reference P, Rcpp::Nullable<Rcpp::NumericMat
}
}



TransorfMat.conservativeResize(n+1, n);
TransorfMat.row(n) = VT::Ones(n);
MT res(TransorfMat.rows(), Rcpp::as<MT>(Mat).rows()+n);
Expand Down
20 changes: 8 additions & 12 deletions R-proj/src/rounding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,23 +90,18 @@ Rcpp::List rounding (Rcpp::Reference P,
rng.set_seed(seed_rcpp);
}

Hpolytope HP;
Vpolytope VP;
zonotope ZP;

std::pair <Point, NT> InnerBall;
Rcpp::NumericMatrix Mat;

std::tuple<MT, VT, NT> round_res;
switch (type) {
case 1: {
// Hpolytope
if (Rcpp::as<MT>(P.field("Aeq")).rows() == 0) {
// full dimensional
HP.init(n, Rcpp::as<MT>(P.field("A")), Rcpp::as<VT>(P.field("b")));
} else {
// low dimensional

if (Rcpp::as<MT>(P.field("Aeq")).rows() > 0) {
throw Rcpp::exception("volesti supports rounding for full dimensional polytopes. Maybe call function get_full_dimensional_polytope()");
}
}
Hpolytope HP(n, Rcpp::as<MT>(P.field("A")), Rcpp::as<VT>(P.field("b")));
InnerBall = HP.ComputeInnerBall();
if (InnerBall.second < 0.0) throw Rcpp::exception("Unable to compute a feasible point.");
if (method_rcpp.compare(std::string("max_ellipsoid")) == 0) {
Expand All @@ -119,7 +114,7 @@ Rcpp::List rounding (Rcpp::Reference P,
}
case 2: {
// Vpolytope
VP.init(n, Rcpp::as<MT>(P.field("V")), VT::Ones(Rcpp::as<MT>(P.field("V")).rows()));
Vpolytope VP(n, Rcpp::as<MT>(P.field("V")), VT::Ones(Rcpp::as<MT>(P.field("V")).rows()));
InnerBall = VP.ComputeInnerBall();
if (InnerBall.second < 0.0) throw Rcpp::exception("Unable to compute a feasible point.");
round_res = apply_rounding<MT, VT, BilliardWalk>(VP, method_rcpp, walkL, InnerBall, rng);
Expand All @@ -128,7 +123,7 @@ Rcpp::List rounding (Rcpp::Reference P,
}
case 3: {
// Zonotope
ZP.init(n, Rcpp::as<MT>(P.field("G")), VT::Ones(Rcpp::as<MT>(P.field("G")).rows()));
zonotope ZP(n, Rcpp::as<MT>(P.field("G")), VT::Ones(Rcpp::as<MT>(P.field("G")).rows()));
InnerBall = ZP.ComputeInnerBall();
if (InnerBall.second < 0.0) throw Rcpp::exception("Unable to compute a feasible point.");
round_res = apply_rounding<MT, VT, BilliardWalk>(ZP, method_rcpp, walkL, InnerBall, rng);
Expand All @@ -143,4 +138,5 @@ Rcpp::List rounding (Rcpp::Reference P,
return Rcpp::List::create(Rcpp::Named("Mat") = Mat, Rcpp::Named("T") = Rcpp::wrap(std::get<0>(round_res)),
Rcpp::Named("shift") = Rcpp::wrap(std::get<1>(round_res)),
Rcpp::Named("round_value") = std::get<2>(round_res));

}
23 changes: 8 additions & 15 deletions R-proj/src/sample_points.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ Rcpp::NumericMatrix sample_points(Rcpp::Nullable<Rcpp::Reference> P,
typedef Eigen::Matrix<NT,Eigen::Dynamic,1> VT;
typedef Eigen::Matrix<NT,Eigen::Dynamic,Eigen::Dynamic> MT;

unsigned int type = Rcpp::as<Rcpp::Reference>(P).field("type"),dim = Rcpp::as<Rcpp::Reference>(P).field("dimension"),
unsigned int type = Rcpp::as<Rcpp::Reference>(P).field("type"), dim = Rcpp::as<Rcpp::Reference>(P).field("dimension"),
walkL = 1, numpoints, nburns = 0;

RNGType rng(dim);
Expand All @@ -207,11 +207,6 @@ Rcpp::NumericMatrix sample_points(Rcpp::Nullable<Rcpp::Reference> P,
rng.set_seed(seed_rcpp);
}

Hpolytope HP;
Vpolytope VP;
zonotope ZP;
InterVP VPcVP;

NT radius = 1.0, L;
bool set_mode = false, gaussian = false, set_starting_point = false, set_L = false;

Expand Down Expand Up @@ -357,7 +352,7 @@ Rcpp::NumericMatrix sample_points(Rcpp::Nullable<Rcpp::Reference> P,
switch(type) {
case 1: {
// Hpolytope
HP.init(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("A")),
Hpolytope HP(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("A")),
Rcpp::as<VT>(Rcpp::as<Rcpp::Reference>(P).field("b")));

InnerBall = HP.ComputeInnerBall();
Expand All @@ -379,7 +374,7 @@ Rcpp::NumericMatrix sample_points(Rcpp::Nullable<Rcpp::Reference> P,
}
case 2: {
// Vpolytope
VP.init(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("V")),
Vpolytope VP(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("V")),
VT::Ones(Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("V")).rows()));

InnerBall = VP.ComputeInnerBall();
Expand All @@ -400,7 +395,7 @@ Rcpp::NumericMatrix sample_points(Rcpp::Nullable<Rcpp::Reference> P,
}
case 3: {
// Zonotope
ZP.init(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("G")),
zonotope ZP(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("G")),
VT::Ones(Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("G")).rows()));

InnerBall = ZP.ComputeInnerBall();
Expand All @@ -415,19 +410,17 @@ Rcpp::NumericMatrix sample_points(Rcpp::Nullable<Rcpp::Reference> P,
StartingPoint = StartingPoint - mode;
ZP.shift(mode.getCoefficients());
}
sample_from_polytope(ZP, type, rng, randPoints, walkL, numpoints, gaussian, a, L,
sample_from_polytope(ZP, type, rng, randPoints, walkL, numpoints, gaussian, a, L,
StartingPoint, nburns, set_L, walk);
break;
}
case 4: {
// Intersection of two V-polytopes
Vpolytope VP1;
Vpolytope VP2;
VP1.init(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("V1")),
Vpolytope VP1(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("V1")),
VT::Ones(Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("V1")).rows()));
VP2.init(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("V2")),
Vpolytope VP2(dim, Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("V2")),
VT::Ones(Rcpp::as<MT>(Rcpp::as<Rcpp::Reference>(P).field("V2")).rows()));
VPcVP.init(VP1, VP2);
InterVP VPcVP(VP1, VP2);

if (!VPcVP.is_feasible()) throw Rcpp::exception("Empty set!");
InnerBall = VPcVP.ComputeInnerBall();
Expand Down
Loading

0 comments on commit e547120

Please sign in to comment.