diff --git a/include/convex_bodies/hpolytope.h b/include/convex_bodies/hpolytope.h index ab5cff80a..bfd506a53 100644 --- a/include/convex_bodies/hpolytope.h +++ b/include/convex_bodies/hpolytope.h @@ -63,6 +63,7 @@ class HPolytope { VT b; // vector b, s.t.: Ax<=b std::pair _inner_ball; bool normalized = false; // true if the polytope is normalized + bool has_ball = false; public: //TODO: the default implementation of the Big3 should be ok. Recheck. @@ -81,7 +82,7 @@ class HPolytope { // Copy constructor HPolytope(HPolytope const& p) : - _d{p._d}, A{p.A}, b{p.b}, _inner_ball{p._inner_ball}, normalized{p.normalized} + _d{p._d}, A{p.A}, b{p.b}, _inner_ball{p._inner_ball}, normalized{p.normalized}, has_ball{p.has_ball} { } @@ -98,7 +99,7 @@ class HPolytope { A(i - 1, j - 1) = -Pin[i][j]; } } - _inner_ball.second = -1; + has_ball = false; //_inner_ball = ComputeChebychevBall(A, b); } @@ -111,6 +112,7 @@ class HPolytope { void set_InnerBall(std::pair const& innerball) //const { _inner_ball = innerball; + has_ball = true; } void set_interior_point(Point const& r) @@ -120,11 +122,12 @@ class HPolytope { //Compute Chebyshev ball of H-polytope P:= Ax<=b //Use LpSolve library - std::pair ComputeInnerBall(bool const &force = false) + std::pair ComputeInnerBall() { normalize(); - if (force || _inner_ball.second <= NT(0)) { - + if (!has_ball) { + + has_ball = true; NT const tol = 1e-08; std::tuple inner_ball = max_inscribed_ball(A, b, 5000, tol); @@ -138,7 +141,7 @@ class HPolytope { _inner_ball = ComputeChebychevBall(A, b); // use lpsolve library #else std::cerr << "lpsolve is disabled, unable to compute inner ball"; - _inner_ball.second = -1.0; + has_ball = false; #endif } else { _inner_ball.first = Point(std::get<0>(inner_ball)); @@ -195,7 +198,7 @@ class HPolytope { { A = A2; normalized = false; - _inner_ball.second = -1.0; + has_ball = false; } @@ -203,7 +206,7 @@ class HPolytope { void set_vec(VT const& b2) { b = b2; - _inner_ball.second = -1.0; + has_ball = false; } Point get_mean_of_vertices() const @@ -847,7 +850,7 @@ class HPolytope { A = (A * T).sparseView(); } normalized = false; - _inner_ball.second = -1.0; + has_ball = false; } @@ -856,7 +859,7 @@ class HPolytope { void shift(const VT &c) { b -= A*c; - _inner_ball.second = -1.0; + has_ball = false; } @@ -886,6 +889,8 @@ class HPolytope { void normalize() { + if(normalized) + return; NT row_norm; for (int i = 0; i < A.rows(); ++i) { row_norm = A.row(i).norm(); @@ -939,7 +944,7 @@ class HPolytope { } template - NT compute_reflection(Point &v, const Point &, MT const &AE, VT const &AEA, NT const &vEv, update_parameters const ¶ms) const { + NT compute_reflection(Point &v, const Point &, DenseMT const &AE, VT const &AEA, NT const &vEv, update_parameters const ¶ms) const { Point a((-2.0 * params.inner_vi_ak) * A.row(params.facet_prev)); VT x = v.getCoefficients(); diff --git a/include/random_walks/gaussian_accelerated_billiard_walk.hpp b/include/random_walks/gaussian_accelerated_billiard_walk.hpp index ff7a85d60..9efbcf92f 100644 --- a/include/random_walks/gaussian_accelerated_billiard_walk.hpp +++ b/include/random_walks/gaussian_accelerated_billiard_walk.hpp @@ -61,19 +61,21 @@ struct GaussianAcceleratedBilliardWalk template < typename Polytope, - typename RandomNumberGenerator + typename RandomNumberGenerator, + typename E_type = typename Polytope::DenseMT > struct Walk { typedef typename Polytope::PointType Point; - typedef typename Polytope::MT MT; + typedef typename Polytope::MT A_type; + typedef typename Polytope::DenseMT DenseMT; typedef typename Polytope::VT VT; typedef typename Point::FT NT; - void computeLcov(const MT E) + void computeLcov(const E_type E) { - if constexpr (std::is_same >::value) { - Eigen::SimplicialLLT lltofE; + if constexpr (std::is_same >::value) { + Eigen::SimplicialLLT lltofE; lltofE.compute(E); if (lltofE.info() != Eigen::Success) { throw std::runtime_error("First Cholesky decomposition failed for sparse matrix!"); @@ -81,14 +83,14 @@ struct GaussianAcceleratedBilliardWalk Eigen::SparseMatrix I(E.cols(), E.cols()); I.setIdentity(); Eigen::SparseMatrix E_inv = lltofE.solve(I); - Eigen::SimplicialLLT lltofEinv; + Eigen::SimplicialLLT lltofEinv; lltofEinv.compute(E_inv); if (lltofE.info() != Eigen::Success) { throw std::runtime_error("Second Cholesky decomposition failed for sparse matrix!"); } _L_cov = lltofEinv.matrixL(); } else { - Eigen::LLT lltOfE(E.llt().solve(MT::Identity(E.cols(), E.cols()))); // compute the Cholesky decomposition of inv(E) + Eigen::LLT lltOfE(E.llt().solve(E_type::Identity(E.cols(), E.cols()))); // compute the Cholesky decomposition of inv(E) if (lltOfE.info() != Eigen::Success) { throw std::runtime_error("Cholesky decomposition failed for dense matrix!"); } @@ -99,7 +101,7 @@ struct GaussianAcceleratedBilliardWalk template Walk(GenericPolytope& P, Point const& p, - MT const& E, // covariance matrix representing the Gaussian distribution + E_type const& E, // covariance matrix representing the Gaussian distribution RandomNumberGenerator &rng) { if(!P.is_normalized()) { @@ -109,7 +111,7 @@ struct GaussianAcceleratedBilliardWalk _L = compute_diameter::template compute(P); computeLcov(E); _E = E; - if constexpr (std::is_same>::value) { + if constexpr (std::is_same>::value) { _AA = P.get_mat() * P.get_mat().transpose(); } else { _AA.noalias() = P.get_mat() * P.get_mat().transpose(); @@ -121,7 +123,7 @@ struct GaussianAcceleratedBilliardWalk template Walk(GenericPolytope& P, Point const& p, - MT const& E, // covariance matrix representing the Gaussian distribution + E_type const& E, // covariance matrix representing the Gaussian distribution RandomNumberGenerator &rng, parameters const& params) { @@ -134,7 +136,7 @@ struct GaussianAcceleratedBilliardWalk ::template compute(P); computeLcov(E); _E = E; - if constexpr (std::is_same>::value) { + if constexpr (std::is_same>::value) { _AA = P.get_mat() * P.get_mat().transpose(); } else { _AA.noalias() = P.get_mat() * P.get_mat().transpose(); @@ -230,18 +232,14 @@ struct GaussianAcceleratedBilliardWalk _lambdas.setZero(P.num_of_hyperplanes()); _Av.setZero(P.num_of_hyperplanes()); _p = p; - if constexpr (std::is_same>::value) { - _AE = P.get_mat() * _E; - } else { - _AE.noalias() = P.get_mat() * _E; - } - //_AEA = _AE.cwiseProduct(P.get_mat()).rowwise().sum(); - + _AE.noalias() = (DenseMT)(P.get_mat() * _E); + _AEA = _AE.cwiseProduct((DenseMT)P.get_mat()).rowwise().sum(); + /* _AEA.resize(P.num_of_hyperplanes()); for(int i = 0; i < P.num_of_hyperplanes(); ++i) { _AEA(i) = _AE.row(i).dot(P.get_mat().row(i)); - } + }*/ _v = GetDirection::apply(n, rng, false); _v = Point(_L_cov.template triangularView() * _v.getCoefficients()); @@ -293,10 +291,10 @@ struct GaussianAcceleratedBilliardWalk Point _p; Point _v; NT _lambda_prev; - MT _AA; - MT _L_cov; // LL' = inv(E) - MT _AE; - MT _E; + A_type _AA; + E_type _L_cov; // LL' = inv(E) + DenseMT _AE; + E_type _E; VT _AEA; unsigned int _rho; update_parameters _update_parameters; diff --git a/test/sampling_test.cpp b/test/sampling_test.cpp index 05284259c..9263a2f82 100644 --- a/test/sampling_test.cpp +++ b/test/sampling_test.cpp @@ -349,7 +349,7 @@ void call_test_gabw(){ std::cout << "psrf = " << score.maxCoeff() << std::endl; CHECK(score.maxCoeff() < 1.1); - + RNGType Srng(d); typedef Eigen::SparseMatrix SparseMT; typedef HPolytope SparseHpoly; @@ -366,7 +366,8 @@ void call_test_gabw(){ typedef typename GaussianAcceleratedBilliardWalk::template Walk < SparseHpoly, - RNGType + RNGType, + SparseMT > sparsewalk; typedef MultivariateGaussianRandomPointGenerator SparseRandomPointGenerator; @@ -377,16 +378,20 @@ void call_test_gabw(){ const SparseMT SE = get<0>(ellipsoid).sparseView(); SparseRandomPointGenerator::apply(SP, p, SE, numpoints, 1, Points, - push_back_policy, rng); + push_back_policy, Srng); jj = 0; + MT Ssamples(d, numpoints); for (typename std::list::iterator rpit = Points.begin(); rpit != Points.end(); rpit++, jj++) - samples.col(jj) = (*rpit).getCoefficients(); + Ssamples.col(jj) = (*rpit).getCoefficients(); - score = univariate_psrf(samples); + score = univariate_psrf(Ssamples); std::cout << "psrf = " << score.maxCoeff() << std::endl; CHECK(score.maxCoeff() < 1.1); + NT delta = (samples - Ssamples).maxCoeff(); + std::cout << "\ndelta = " << delta << std::endl; + CHECK(delta < 0.00001); }