diff --git a/.gitignore b/.gitignore index 75e5d999c..ff5600a3f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ test/Testing/Temporary/CTestCostData.txt build/ .vscode .DS_Store -.cache \ No newline at end of file +.cache +shell.nix \ No newline at end of file diff --git a/include/convex_bodies/hpolytope.h b/include/convex_bodies/hpolytope.h index 9cabcd9ab..b4a69ce98 100644 --- a/include/convex_bodies/hpolytope.h +++ b/include/convex_bodies/hpolytope.h @@ -580,17 +580,23 @@ class HPolytope { NT inner_prev = params.inner_vi_ak; NT* Av_data = Av.data(); + // Updating Av due to the change in direction caused by the previous reflection // Av += (-2.0 * inner_prev) * AA.col(params.facet_prev) for (Eigen::SparseMatrix::InnerIterator it(AA, params.facet_prev); it; ++it) { + // val(row) - params.moved_dist = The distance until we would hit the facet given by row + // all those values are stored inside distances_set for quick retrieval of the minimum + // Before updating Av(row) // val(row) = (b(row) - Ar(row)) / Av(row) + params.moved_dist // (val(row) - params.moved_dist) = (b(row) - Ar(row)) / Av(row) // (val(row) - params.moved_dist) * Av(row) = b(row) - Ar(row) + // b(row) - Ar(row) = (val(row) - params.moved_dist) * Av(row) *(Av_data + it.row()) += (-2.0 * inner_prev) * it.value(); + // After updating Av(row) // b(row) - Ar(row) = (old_val(row) - params.moved_dist) * old_Av(row) // new_val(row) = (b(row) - Ar(row) ) / new_Av(row) + params.moved_dist // new_val(row) = ((old_val(row) - params.moved_dist) * old_Av(row)) / new_Av(row) + params.moved_dist @@ -608,8 +614,12 @@ class HPolytope { distances_set.change_val(it.row(), val, params.moved_dist); } + // Finding the distance to the closest facet and its row std::pair ans = distances_set.get_min(); + + // Subtract params.moved_dist to obtain the actual distance to the facet ans.first -= params.moved_dist; + params.inner_vi_ak = *(Av_data + ans.second); params.facet_prev = ans.second; @@ -1002,34 +1012,59 @@ class HPolytope { return total; } + // Updates the velocity vector v and the position vector p after a reflection template void compute_reflection(Point &v, Point const&, update_parameters const& params) const { Point a((-2.0 * params.inner_vi_ak) * A.row(params.facet_prev)); v += a; } - // updates the velocity vector v and the position vector p after a reflection - // the real value of p is given by p + moved_dist * v + // Only to be called when MT is in RowMajor format + // The real value of p is given by p + params.moved_dist * v template - auto compute_reflection(Point &v, Point &p, update_parameters const& params) const - -> std::enable_if_t> && !std::is_same_v, void> { // MT must be in RowMajor format - NT* v_data = v.pointerToData(); - NT* p_data = p.pointerToData(); - for(Eigen::SparseMatrix::InnerIterator it(A, params.facet_prev); it; ++it) { - *(v_data + it.col()) += (-2.0 * params.inner_vi_ak) * it.value(); - *(p_data + it.col()) -= (-2.0 * params.inner_vi_ak * params.moved_dist) * it.value(); - } + auto compute_reflection_abw_sparse(Point &v, Point &p, update_parameters const& params) const + { + NT* v_data = v.pointerToData(); + NT* p_data = p.pointerToData(); + for(Eigen::SparseMatrix::InnerIterator it(A, params.facet_prev); it; ++it) { + *(v_data + it.col()) += (-2.0 * params.inner_vi_ak) * it.value(); + *(p_data + it.col()) -= (-2.0 * params.inner_vi_ak * params.moved_dist) * it.value(); + } } - template - NT compute_reflection(Point &v, const Point &, DenseMT const &AE, VT const &AEA, NT const &vEv, update_parameters const ¶ms) const { + // function to compute reflection for GaBW random walk + // compatible when the polytope is both dense or sparse + template + NT compute_reflection(Point &v, Point &p, NT &vEv, DenseSparseMT const &AE, VT const &AEA, update_parameters const ¶ms) const { + + NT new_vEv; + if constexpr (!std::is_same_v>) { + Point a((-2.0 * params.inner_vi_ak) * A.row(params.facet_prev)); + VT x = v.getCoefficients(); + new_vEv = vEv - (4.0 * params.inner_vi_ak) * (AE.row(params.facet_prev).dot(x) - params.inner_vi_ak * AEA(params.facet_prev)); + v += a; + } else { + + if constexpr(!std::is_same_v>) { + VT x = v.getCoefficients(); + new_vEv = vEv - (4.0 * params.inner_vi_ak) * (AE.row(params.facet_prev).dot(x) - params.inner_vi_ak * AEA(params.facet_prev)); + } else { + new_vEv = vEv + 4.0 * params.inner_vi_ak * params.inner_vi_ak * AEA(params.facet_prev); + NT* v_data = v.pointerToData(); + for(Eigen::SparseMatrix::InnerIterator it(AE, params.facet_prev); it; ++it) { + new_vEv -= 4.0 * params.inner_vi_ak * it.value() * *(v_data + it.col()); + } + } - Point a((-2.0 * params.inner_vi_ak) * A.row(params.facet_prev)); - VT x = v.getCoefficients(); - NT new_vEv = vEv - (4.0 * params.inner_vi_ak) * (AE.row(params.facet_prev).dot(x) - params.inner_vi_ak * AEA(params.facet_prev)); - v += a; + NT* v_data = v.pointerToData(); + NT* p_data = p.pointerToData(); + for(Eigen::SparseMatrix::InnerIterator it(A, params.facet_prev); it; ++it) { + *(v_data + it.col()) += (-2.0 * params.inner_vi_ak) * it.value(); + *(p_data + it.col()) -= (-2.0 * params.inner_vi_ak * params.moved_dist) * it.value(); + } + } NT coeff = std::sqrt(vEv / new_vEv); - v = v * coeff; + vEv = new_vEv; return coeff; } diff --git a/include/random_walks/accelerated_billiard_walk_utils.hpp b/include/random_walks/accelerated_billiard_walk_utils.hpp new file mode 100644 index 000000000..24cf32d76 --- /dev/null +++ b/include/random_walks/accelerated_billiard_walk_utils.hpp @@ -0,0 +1,133 @@ +// VolEsti (volume computation and sampling library) + +// Copyright (c) 2012-2020 Vissarion Fisikopoulos +// Copyright (c) 2018-2020 Apostolos Chalkis +// Copyright (c) 2024 Luca Perju + +// Licensed under GNU LGPL.3, see LICENCE file + +#ifndef ACCELERATED_BILLIARD_WALK_UTILS_HPP +#define ACCELERATED_BILLIARD_WALK_UTILS_HPP + +#include +#include + +const double eps = 1e-10; + +// data structure which maintains the values of (b - Ar)/Av, and can extract the minimum positive value and the facet associated with it +// vec[i].first contains the value of (b(i) - Ar(i))/Av(i) + moved_dist, where moved_dist is the total distance that the point has travelled so far +// The heap will only contain the values from vec which are greater than moved_dist (so that they are positive) +template +class BoundaryOracleHeap { +public: + int n, heap_size; + std::vector> heap; + std::vector> vec; + +private: + int siftDown(int index) { + while((index << 1) + 1 < heap_size) { + int child = (index << 1) + 1; + if(child + 1 < heap_size && heap[child + 1].first < heap[child].first - eps) { + child += 1; + } + if(heap[child].first < heap[index].first - eps) + { + std::swap(heap[child], heap[index]); + std::swap(vec[heap[child].second].second, vec[heap[index].second].second); + index = child; + } else { + return index; + } + } + return index; + } + + int siftUp(int index) { + while(index > 0 && heap[(index - 1) >> 1].first - eps > heap[index].first) { + std::swap(heap[(index - 1) >> 1], heap[index]); + std::swap(vec[heap[(index - 1) >> 1].second].second, vec[heap[index].second].second); + index = (index - 1) >> 1; + } + return index; + } + + // takes the index of a facet, and (in case it is in the heap) removes it from the heap. + void remove (int index) { + index = vec[index].second; + if(index == -1) { + return; + } + std::swap(heap[heap_size - 1], heap[index]); + std::swap(vec[heap[heap_size - 1].second].second, vec[heap[index].second].second); + vec[heap[heap_size - 1].second].second = -1; + heap_size -= 1; + index = siftDown(index); + siftUp(index); + } + + // inserts a new value into the heap, with its associated facet + void insert (const std::pair val) { + vec[val.second].second = heap_size; + vec[val.second].first = val.first; + heap[heap_size++] = val; + siftUp(heap_size - 1); + } + +public: + BoundaryOracleHeap() {} + + BoundaryOracleHeap(int n) : n(n), heap_size(0) { + heap.resize(n); + vec.resize(n); + } + + // rebuilds the heap with the existing values from vec + // O(n) + void rebuild (const NT &moved_dist) { + heap_size = 0; + for(int i = 0; i < n; ++i) { + vec[i].second = -1; + if(vec[i].first - eps > moved_dist) { + vec[i].second = heap_size; + heap[heap_size++] = {vec[i].first, i}; + } + } + for(int i = heap_size - 1; i >= 0; --i) { + siftDown(i); + } + } + + // returns (b(i) - Ar(i))/Av(i) + moved_dist + // O(1) + NT get_val (const int &index) { + return vec[index].first; + } + + // returns the nearest facet + // O(1) + std::pair get_min () { + return heap[0]; + } + + // changes the stored value for a given facet, and updates the heap accordingly + // O(logn) + void change_val(const int& index, const NT& new_val, const NT& moved_dist) { + if(new_val < moved_dist - eps) { + vec[index].first = new_val; + remove(index); + } else { + if(vec[index].second == -1) { + insert({new_val, index}); + } else { + heap[vec[index].second].first = new_val; + vec[index].first = new_val; + siftDown(vec[index].second); + siftUp(vec[index].second); + } + } + } +}; + + +#endif diff --git a/include/random_walks/gaussian_accelerated_billiard_walk.hpp b/include/random_walks/gaussian_accelerated_billiard_walk.hpp index 532d7672e..7f33f1fff 100644 --- a/include/random_walks/gaussian_accelerated_billiard_walk.hpp +++ b/include/random_walks/gaussian_accelerated_billiard_walk.hpp @@ -21,6 +21,7 @@ #include "generators/boost_random_number_generator.hpp" #include "sampling/ellipsoid.hpp" #include "random_walks/uniform_billiard_walk.hpp" +#include "random_walks/accelerated_billiard_walk_utils.hpp" #include "random_walks/compute_diameter.hpp" @@ -47,12 +48,13 @@ struct GaussianAcceleratedBilliardWalk struct update_parameters { update_parameters() - : facet_prev(0), hit_ball(false), inner_vi_ak(0.0), ball_inner_norm(0.0) + : facet_prev(0), hit_ball(false), inner_vi_ak(0.0), ball_inner_norm(0.0), moved_dist(0.0) {} int facet_prev; bool hit_ball; double inner_vi_ak; double ball_inner_norm; + double moved_dist; }; parameters param; @@ -67,9 +69,16 @@ struct GaussianAcceleratedBilliardWalk struct Walk { typedef typename Polytope::PointType Point; - typedef typename Polytope::DenseMT DenseMT; + typedef typename Polytope::MT MT; + typedef typename Eigen::Matrix DenseMT; typedef typename Polytope::VT VT; typedef typename Point::FT NT; + // We do sparse computations iff MT is sparse rowMajor + static constexpr bool SPARSE = std::is_same_v>; + // AA is sparse colMajor if MT is sparse rowMajor, and Dense otherwise + using AA_type = std::conditional_t< SPARSE, typename Eigen::SparseMatrix, DenseMT >; + // AE is sparse rowMajor if (MT is sparse rowMajor and E is sparse), and Dense otherwise + using AE_type = std::conditional_t< SPARSE && std::is_base_of, E_type>::value, typename Eigen::SparseMatrix, DenseMT >; void computeLcov(const E_type E) { @@ -110,7 +119,11 @@ struct GaussianAcceleratedBilliardWalk _L = compute_diameter::template compute(P); computeLcov(E); _E = E; - _AA.noalias() = (DenseMT)(P.get_mat() * P.get_mat().transpose()); + if constexpr (SPARSE) { + _AA = (P.get_mat() * P.get_mat().transpose()); + } else { + _AA.noalias() = (P.get_mat() * P.get_mat().transpose()); + } _rho = 1000 * P.dimension(); // upper bound for the number of reflections (experimental) initialize(P, p, rng); } @@ -131,7 +144,11 @@ struct GaussianAcceleratedBilliardWalk ::template compute(P); computeLcov(E); _E = E; - _AA.noalias() = (DenseMT)(P.get_mat() * P.get_mat().transpose()); + if constexpr (SPARSE) { + _AA = (P.get_mat() * P.get_mat().transpose()); + } else { + _AA.noalias() = (DenseMT)(P.get_mat() * P.get_mat().transpose()); + } _rho = 1000 * P.dimension(); // upper bound for the number of reflections (experimental) initialize(P, p, rng); } @@ -162,13 +179,7 @@ struct GaussianAcceleratedBilliardWalk Point p0 = _p; it = 0; - std::pair pbpair; - if(!was_reset) { - pbpair = P.line_positive_intersect(_p, _v, _lambdas, _Av, _lambda_prev, _update_parameters); - } else { - pbpair = P.line_first_positive_intersect(_p, _v, _lambdas, _Av, _update_parameters); - was_reset = false; - } + std::pair pbpair = P.line_first_positive_intersect(_p, _v, _lambdas, _Av, _update_parameters); if (T <= pbpair.first) { _p += (T * _v); @@ -177,18 +188,40 @@ struct GaussianAcceleratedBilliardWalk } _lambda_prev = dl * pbpair.first; - _p += (_lambda_prev * _v); + if constexpr (SPARSE) { + typename Point::Coeff b; + NT* b_data; + b = P.get_vec(); + b_data = b.data(); + _update_parameters.moved_dist = _lambda_prev; + NT* Ar_data = _lambdas.data(); + NT* Av_data = _Av.data(); + for(int i = 0; i < P.num_of_hyperplanes(); ++i) { + _distances_set.vec[i].first = ( *(b_data + i) - (*(Ar_data + i)) ) / (*(Av_data + i)); + } + // rebuild the heap with the new values of (b - Ar) / Av + _distances_set.rebuild(_update_parameters.moved_dist); + } else { + _p += (_lambda_prev * _v); + } T -= _lambda_prev; - coef = P.compute_reflection(_v, _p, _AE, _AEA, vEv, _update_parameters); + + T = T * coef; + coef = P.compute_reflection(_v, _p, vEv, _AE, _AEA, _update_parameters); + T = T / coef; + it++; while (it < _rho) { - std::pair pbpair - = P.line_positive_intersect(_p, _v, _lambdas, _Av, _lambda_prev, _AA, _update_parameters); - _Av *= coef; - _update_parameters.inner_vi_ak *= coef; - pbpair.first /= coef; + std::pair pbpair; + if constexpr (SPARSE) { + pbpair = P.line_positive_intersect(_p, _lambdas, _Av, _lambda_prev, + _distances_set, _AA, _update_parameters); + } else { + pbpair = P.line_positive_intersect(_p, _v, _lambdas, _Av, _lambda_prev, + _AA, _update_parameters); + } if (T <= pbpair.first) { _p += (T * _v); @@ -196,14 +229,23 @@ struct GaussianAcceleratedBilliardWalk break; } _lambda_prev = dl * pbpair.first; - _p += (_lambda_prev * _v); + if constexpr (SPARSE) { + _update_parameters.moved_dist += _lambda_prev; + } else { + _p += (_lambda_prev * _v); + } T -= _lambda_prev; - coef = P.compute_reflection(_v, _p, _AE, _AEA, vEv, _update_parameters); + + T = T * coef; + coef = P.compute_reflection(_v, _p, vEv, _AE, _AEA, _update_parameters); + T = T / coef; + it++; } + _p += _update_parameters.moved_dist * _v; + _update_parameters.moved_dist = 0.0; if (it == _rho){ _p = p0; - was_reset = true; } } @@ -219,21 +261,24 @@ struct GaussianAcceleratedBilliardWalk { unsigned int n = P.dimension(); const NT dl = 0.995; - was_reset = false; _lambdas.setZero(P.num_of_hyperplanes()); _Av.setZero(P.num_of_hyperplanes()); _p = p; - _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)); - }*/ + DenseMT temp_AE; + temp_AE.noalias() = (DenseMT)(P.get_mat() * _E); + _AEA = temp_AE.cwiseProduct((DenseMT)P.get_mat()).rowwise().sum(); + if constexpr (std::is_same_v) + _AE = temp_AE; + else + _AE = temp_AE.sparseView(); + } + _distances_set = BoundaryOracleHeap(P.num_of_hyperplanes()); + _v = GetDirection::apply(n, rng, false); _v = Point(_L_cov.template triangularView() * _v.getCoefficients()); + NT T = -std::log(rng.sample_urdist()) * _L; Point p0 = _p; @@ -251,15 +296,15 @@ struct GaussianAcceleratedBilliardWalk _lambda_prev = dl * pbpair.first; _p += (_lambda_prev * _v); T -= _lambda_prev; - coef = P.compute_reflection(_v, _p, _AE, _AEA, vEv, _update_parameters); + + T = T * coef; + coef = P.compute_reflection(_v, _p, vEv, _AE, _AEA, _update_parameters); + T = T / coef; while (it <= _rho) { std::pair pbpair = P.line_positive_intersect(_p, _v, _lambdas, _Av, _lambda_prev, _AA, _update_parameters); - _Av *= coef; - _update_parameters.inner_vi_ak *= coef; - pbpair.first /= coef; if (T <= pbpair.first) { _p += (T * _v); @@ -273,7 +318,11 @@ struct GaussianAcceleratedBilliardWalk _lambda_prev = dl * pbpair.first; _p += (_lambda_prev * _v); T -= _lambda_prev; - coef = P.compute_reflection(_v, _p, _AE, _AEA, vEv, _update_parameters); + + T = T * coef; + coef = P.compute_reflection(_v, _p, vEv, _AE, _AEA, _update_parameters); + T = T / coef; + it++; } } @@ -282,16 +331,16 @@ struct GaussianAcceleratedBilliardWalk Point _p; Point _v; NT _lambda_prev; - DenseMT _AA; + AA_type _AA; E_type _L_cov; // LL' = inv(E) - DenseMT _AE; + AE_type _AE; E_type _E; VT _AEA; unsigned int _rho; update_parameters _update_parameters; typename Point::Coeff _lambdas; typename Point::Coeff _Av; - bool was_reset; + BoundaryOracleHeap _distances_set; }; }; diff --git a/include/random_walks/uniform_accelerated_billiard_walk.hpp b/include/random_walks/uniform_accelerated_billiard_walk.hpp index f91abee4b..f7ef15aed 100644 --- a/include/random_walks/uniform_accelerated_billiard_walk.hpp +++ b/include/random_walks/uniform_accelerated_billiard_walk.hpp @@ -13,125 +13,7 @@ #include "sampling/sphere.hpp" #include -#include -#include - -const double eps = 1e-10; - -// data structure which maintains the values of (b - Ar)/Av, and can extract the minimum positive value and the facet associated with it -// vec[i].first contains the value of (b(i) - Ar(i))/Av(i) + moved_dist, where moved_dist is the total distance that the point has travelled so far -// The heap will only contain the values from vec which are greater than moved_dist (so that they are positive) -template -class BoundaryOracleHeap { -public: - int n, heap_size; - std::vector> heap; - std::vector> vec; - -private: - int siftDown(int index) { - while((index << 1) + 1 < heap_size) { - int child = (index << 1) + 1; - if(child + 1 < heap_size && heap[child + 1].first < heap[child].first - eps) { - child += 1; - } - if(heap[child].first < heap[index].first - eps) - { - std::swap(heap[child], heap[index]); - std::swap(vec[heap[child].second].second, vec[heap[index].second].second); - index = child; - } else { - return index; - } - } - return index; - } - - int siftUp(int index) { - while(index > 0 && heap[(index - 1) >> 1].first - eps > heap[index].first) { - std::swap(heap[(index - 1) >> 1], heap[index]); - std::swap(vec[heap[(index - 1) >> 1].second].second, vec[heap[index].second].second); - index = (index - 1) >> 1; - } - return index; - } - - // takes the index of a facet, and (in case it is in the heap) removes it from the heap. - void remove (int index) { - index = vec[index].second; - if(index == -1) { - return; - } - std::swap(heap[heap_size - 1], heap[index]); - std::swap(vec[heap[heap_size - 1].second].second, vec[heap[index].second].second); - vec[heap[heap_size - 1].second].second = -1; - heap_size -= 1; - index = siftDown(index); - siftUp(index); - } - - // inserts a new value into the heap, with its associated facet - void insert (const std::pair val) { - vec[val.second].second = heap_size; - vec[val.second].first = val.first; - heap[heap_size++] = val; - siftUp(heap_size - 1); - } - -public: - BoundaryOracleHeap() {} - - BoundaryOracleHeap(int n) : n(n), heap_size(0) { - heap.resize(n); - vec.resize(n); - } - - // rebuilds the heap with the existing values from vec - // O(n) - void rebuild (const NT &moved_dist) { - heap_size = 0; - for(int i = 0; i < n; ++i) { - vec[i].second = -1; - if(vec[i].first - eps > moved_dist) { - vec[i].second = heap_size; - heap[heap_size++] = {vec[i].first, i}; - } - } - for(int i = heap_size - 1; i >= 0; --i) { - siftDown(i); - } - } - - // returns (b(i) - Ar(i))/Av(i) + moved_dist - // O(1) - NT get_val (const int &index) { - return vec[index].first; - } - - // returns the nearest facet - // O(1) - std::pair get_min () { - return heap[0]; - } - - // changes the stored value for a given facet, and updates the heap accordingly - // O(logn) - void change_val(const int& index, const NT& new_val, const NT& moved_dist) { - if(new_val < moved_dist - eps) { - vec[index].first = new_val; - remove(index); - } else { - if(vec[index].second == -1) { - insert({new_val, index}); - } else { - heap[vec[index].second].first = new_val; - vec[index].first = new_val; - siftDown(vec[index].second); - siftUp(vec[index].second); - } - } - } -}; +#include "random_walks/accelerated_billiard_walk_utils.hpp" // Billiard walk which accelarates each step for uniform distribution @@ -181,8 +63,10 @@ struct AcceleratedBilliardWalk typedef typename Polytope::MT MT; typedef typename Eigen::Matrix DenseMT; typedef typename Point::FT NT; - using AA_type = std::conditional_t< std::is_same_v>, typename Eigen::SparseMatrix, DenseMT >; + // We do sparse computations iff MT is sparse rowMajor + static constexpr bool SPARSE = std::is_same_v>; // AA is sparse colMajor if MT is sparse rowMajor, and Dense otherwise + using AA_type = std::conditional_t< SPARSE, typename Eigen::SparseMatrix, DenseMT >; template Walk(GenericPolytope &P, Point const& p, RandomNumberGenerator &rng) @@ -193,7 +77,7 @@ struct AcceleratedBilliardWalk _update_parameters = update_parameters(); _L = compute_diameter ::template compute(P); - if constexpr (std::is_same>::value) { + if constexpr (SPARSE) { _AA = (P.get_mat() * P.get_mat().transpose()); } else { _AA.noalias() = (DenseMT)(P.get_mat() * P.get_mat().transpose()); @@ -213,7 +97,7 @@ struct AcceleratedBilliardWalk _L = params.set_L ? params.m_L : compute_diameter ::template compute(P); - if constexpr (std::is_same>::value) { + if constexpr (SPARSE) { _AA = (P.get_mat() * P.get_mat().transpose()); } else { _AA.noalias() = (DenseMT)(P.get_mat() * P.get_mat().transpose()); @@ -237,7 +121,7 @@ struct AcceleratedBilliardWalk int it; typename Point::Coeff b; NT* b_data; - if constexpr (std::is_same>::value) { + if constexpr (SPARSE) { b = P.get_vec(); b_data = b.data(); } @@ -258,7 +142,7 @@ struct AcceleratedBilliardWalk } _lambda_prev = dl * pbpair.first; - if constexpr (std::is_same>::value) { + if constexpr (SPARSE) { _update_parameters.moved_dist = _lambda_prev; NT* Ar_data = _lambdas.data(); NT* Av_data = _Av.data(); @@ -271,13 +155,17 @@ struct AcceleratedBilliardWalk _p += (_lambda_prev * _v); } T -= _lambda_prev; - P.compute_reflection(_v, _p, _update_parameters); + if constexpr (SPARSE) { + P.compute_reflection_abw_sparse(_v, _p, _update_parameters); + } else { + P.compute_reflection(_v, _p, _update_parameters); + } it++; while (it < _rho) - { + { std::pair pbpair; - if constexpr (std::is_same>::value) { + if constexpr (SPARSE) { pbpair = P.line_positive_intersect(_p, _lambdas, _Av, _lambda_prev, _distances_set, _AA, _update_parameters); } else { @@ -290,13 +178,17 @@ struct AcceleratedBilliardWalk break; } _lambda_prev = dl * pbpair.first; - if constexpr (std::is_same>::value) { + if constexpr (SPARSE) { _update_parameters.moved_dist += _lambda_prev; } else { _p += (_lambda_prev * _v); } T -= _lambda_prev; - P.compute_reflection(_v, _p, _update_parameters); + if constexpr (SPARSE) { + P.compute_reflection_abw_sparse(_v, _p, _update_parameters); + } else { + P.compute_reflection(_v, _p, _update_parameters); + } it++; } _p += _update_parameters.moved_dist * _v; @@ -418,7 +310,11 @@ struct AcceleratedBilliardWalk _lambda_prev = dl * pbpair.first; _p += (_lambda_prev * _v); T -= _lambda_prev; - P.compute_reflection(_v, _p, _update_parameters); + if constexpr (SPARSE) { + P.compute_reflection_abw_sparse(_v, _p, _update_parameters); + } else { + P.compute_reflection(_v, _p, _update_parameters); + } while (it <= _rho) { @@ -436,7 +332,11 @@ struct AcceleratedBilliardWalk _lambda_prev = dl * pbpair.first; _p += (_lambda_prev * _v); T -= _lambda_prev; - P.compute_reflection(_v, _p, _update_parameters); + if constexpr (SPARSE) { + P.compute_reflection_abw_sparse(_v, _p, _update_parameters); + } else { + P.compute_reflection(_v, _p, _update_parameters); + } it++; } } diff --git a/test/sampling_test.cpp b/test/sampling_test.cpp index a15f40102..ba71d1398 100644 --- a/test/sampling_test.cpp +++ b/test/sampling_test.cpp @@ -320,8 +320,11 @@ void call_test_gabw(){ Point StartingPoint(d); std::list randPoints; + std::chrono::time_point start, stop; + start = std::chrono::high_resolution_clock::now(); + std::cout << "--- Testing Gaussian Accelerated Billiard Walk for Skinny-H-cube10" << std::endl; - P = generate_skinny_cube(10); + P = generate_skinny_cube(d); Point p = P.ComputeInnerBall().first; @@ -340,6 +343,11 @@ void call_test_gabw(){ RandomPointGenerator::apply(P, p, E, numpoints, 1, randPoints, push_back_policy, rng); + stop = std::chrono::high_resolution_clock::now(); + + std::chrono::duration total_time = stop - start; + std::cout << "Done in " << total_time.count() << '\n'; + MT samples(d, numpoints); unsigned int jj = 0; for (typename std::list::iterator rpit = randPoints.begin(); rpit != randPoints.end(); rpit++, jj++) @@ -352,11 +360,11 @@ void call_test_gabw(){ RNGType Srng(d); typedef Eigen::SparseMatrix SparseMT; - typedef HPolytope SparseHpoly; + typedef HPolytope> SparseHpoly; std::list Points; SparseHpoly SP; - SP = generate_skinny_cube(10); + SP = generate_skinny_cube(d); std::cout << "--- Testing Gaussian Accelerated Billiard Walk for Sparse Skinny-H-cube10" << std::endl; @@ -371,15 +379,21 @@ void call_test_gabw(){ > sparsewalk; typedef MultivariateGaussianRandomPointGenerator SparseRandomPointGenerator; + start = std::chrono::high_resolution_clock::now(); ellipsoid = compute_inscribed_ellipsoid - (SP.get_mat(), SP.get_vec(), p.getCoefficients(), 500, std::pow(10, -6.0), std::pow(10, -4.0)); + ((SparseMT)SP.get_mat(), SP.get_vec(), p.getCoefficients(), 500, std::pow(10, -6.0), std::pow(10, -4.0)); const SparseMT SE = get<0>(ellipsoid).sparseView(); SparseRandomPointGenerator::apply(SP, p, SE, numpoints, 1, Points, push_back_policy, Srng); + stop = std::chrono::high_resolution_clock::now(); + + total_time = stop - start; + std::cout << "Done in " << total_time.count() << '\n'; + jj = 0; MT Ssamples(d, numpoints); for (typename std::list::iterator rpit = Points.begin(); rpit != Points.end(); rpit++, jj++)