Skip to content

Commit f83f4b8

Browse files
committed
Initial CRHMC with Cooling Non-SphericalGaussians
1 parent d424f3e commit f83f4b8

File tree

9 files changed

+851
-2
lines changed

9 files changed

+851
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# VolEsti (volume computation and sampling library)
2+
3+
# Copyright (c) 2012-2024 Vissarion Fisikopoulos
4+
# Copyright (c) 2018-2024 Apostolos Chalkis
5+
# Copyright (c) 2024 Vladimir Necula
6+
7+
# Contributed and/or modified by Vladimir Necula, as part of Google Summer of
8+
# Code 2024 program.
9+
10+
# Licensed under GNU LGPL.3, see LICENCE file
11+
12+
project( VolEsti )
13+
14+
15+
CMAKE_MINIMUM_REQUIRED(VERSION 3.11)
16+
17+
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
18+
19+
# Locate Intel MKL root (in case it is enabled)
20+
if (APPLE)
21+
set(MKLROOT /opt/intel/oneapi/mkl/latest)
22+
elseif(UNIX)
23+
#set(MKLROOT /opt/intel/oneapi/mkl/latest)
24+
set(MKLROOT $ENV{HOME}/intel/mkl)
25+
endif()
26+
27+
if(COMMAND cmake_policy)
28+
cmake_policy(SET CMP0003 NEW)
29+
endif(COMMAND cmake_policy)
30+
31+
32+
option(DISABLE_NLP_ORACLES "Disable non-linear oracles (used in collocation)" ON)
33+
option(BUILTIN_EIGEN "Use eigen from ../../external" OFF)
34+
option(USE_MKL "Use MKL library to build eigen" OFF)
35+
36+
37+
if(DISABLE_NLP_ORACLES)
38+
add_definitions(-DDISABLE_NLP_ORACLES)
39+
else()
40+
find_library(IFOPT NAMES libifopt_core.so PATHS /usr/local/lib)
41+
find_library(IFOPT_IPOPT NAMES libifopt_ipopt.so PATHS /usr/local/lib)
42+
find_library(GMP NAMES libgmp.so PATHS /usr/lib/x86_64-linux-gnu /usr/lib/i386-linux-gnu)
43+
find_library(MPSOLVE NAMES libmps.so PATHS /usr/local/lib)
44+
find_library(PTHREAD NAMES libpthread.so PATHS /usr/lib/x86_64-linux-gnu /usr/lib/i386-linux-gnu)
45+
find_library(FFTW3 NAMES libfftw3.so.3 PATHS /usr/lib/x86_64-linux-gnu /usr/lib/i386-linux-gnu)
46+
47+
if (NOT IFOPT)
48+
49+
message(FATAL_ERROR "This program requires the ifopt library, and will not be compiled.")
50+
51+
elseif (NOT GMP)
52+
53+
message(FATAL_ERROR "This program requires the gmp library, and will not be compiled.")
54+
55+
elseif (NOT MPSOLVE)
56+
57+
message(FATAL_ERROR "This program requires the mpsolve library, and will not be compiled.")
58+
59+
elseif (NOT FFTW3)
60+
61+
message(FATAL_ERROR "This program requires the fftw3 library, and will not be compiled.")
62+
63+
else()
64+
message(STATUS "Library ifopt found: ${IFOPT}")
65+
message(STATUS "Library gmp found: ${GMP}")
66+
message(STATUS "Library mpsolve found: ${MPSOLVE}")
67+
message(STATUS "Library fftw3 found:" ${FFTW3})
68+
69+
endif(NOT IFOPT)
70+
71+
endif(DISABLE_NLP_ORACLES)
72+
73+
include("../../external/cmake-files/Eigen.cmake")
74+
GetEigen()
75+
76+
include("../../external/cmake-files/Boost.cmake")
77+
GetBoost()
78+
79+
include("../../external/cmake-files/LPSolve.cmake")
80+
GetLPSolve()
81+
82+
include("../../external/cmake-files/QD.cmake")
83+
GetQD()
84+
85+
# Find lpsolve library
86+
find_library(LP_SOLVE NAMES liblpsolve55.so PATHS /usr/lib/lp_solve)
87+
88+
if (NOT LP_SOLVE)
89+
message(FATAL_ERROR "This program requires the lp_solve library, and will not be compiled.")
90+
else ()
91+
message(STATUS "Library lp_solve found: ${LP_SOLVE}")
92+
93+
set(CMAKE_EXPORT_COMPILE_COMMANDS "ON")
94+
95+
if (USE_MKL)
96+
find_library(BLAS NAMES libblas.so libblas.dylib PATHS /usr/local/Cellar/lapack/3.9.1_1/lib /usr/lib/x86_64-linux-gnu /usr/lib/i386-linux-gnu /usr/local/Cellar/openblas/0.3.15_1/lib /usr/lib)
97+
find_library(GFORTRAN NAME libgfortran.dylib PATHS /usr/local/Cellar/gcc/10.2.0_4/lib/gcc/10)
98+
find_library(LAPACK NAME liblapack.dylib PATHS /usr/lib)
99+
find_library(OPENMP NAME libiomp5.dylib PATHS /opt/intel/oneapi/compiler/2021.1.1/mac/compiler/lib)
100+
101+
include_directories (BEFORE ${MKLROOT}/include)
102+
set(PROJECT_LIBS ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} ${GFORTRAN_LIBRARIES})
103+
set(MKL_LINK "-L${MKLROOT}/lib -Wl,-rpath,${MKLROOT}/lib -lmkl_intel_ilp64 -lmkl_sequential -lmkl_core -lpthread -lm -ldl")
104+
add_definitions(-DEIGEN_USE_MKL_ALL)
105+
else()
106+
set(MKL_LINK "")
107+
endif(USE_MKL)
108+
109+
include_directories (BEFORE ../../external)
110+
include_directories (BEFORE ../../external/minimum_ellipsoid)
111+
include_directories (BEFORE ../../include/)
112+
113+
# for Eigen
114+
if (${CMAKE_VERSION} VERSION_LESS "3.12.0")
115+
add_compile_options(-D "EIGEN_NO_DEBUG")
116+
else ()
117+
add_compile_definitions("EIGEN_NO_DEBUG")
118+
endif ()
119+
120+
121+
add_definitions(${CMAKE_CXX_FLAGS} "-std=c++17") # enable C++17 standard
122+
set(ADDITIONAL_FLAGS "-march=native -DSIMD_LEN=0 -DTIME_KEEPING")
123+
add_definitions(${CMAKE_CXX_FLAGS} "-O3 -DTIME_KEEPING" ${ADDITIONAL_FLAGS}) # optimization of the compiler
124+
#add_definitions(${CXX_COVERAGE_COMPILE_FLAGS} "-lgsl")
125+
add_definitions(${CXX_COVERAGE_COMPILE_FLAGS} "-lm")
126+
add_definitions(${CXX_COVERAGE_COMPILE_FLAGS} "-ldl")
127+
add_definitions(${CXX_COVERAGE_COMPILE_FLAGS} "-DBOOST_NO_AUTO_PTR")
128+
129+
add_executable(volume_example volume_example.cpp)
130+
target_link_libraries(volume_example QD_LIB ${MKL_LINK} ${LP_SOLVE})
131+
132+
endif()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// VolEsti (volume computation and sampling library)
2+
3+
// Copyright (c) 2012-2024 Vissarion Fisikopoulos
4+
// Copyright (c) 2018-2024 Apostolos Chalkis
5+
// Copyright (c) 2024 Vladimir Necula
6+
7+
// Contributed and/or modified by Vladimir Necula, as part of Google Summer of
8+
// Code 2024 program.
9+
10+
// Licensed under GNU LGPL.3, see LICENCE file
11+
12+
#include "generators/known_polytope_generators.h"
13+
#include "generators/h_polytopes_generator.h"
14+
#include "random_walks/random_walks.hpp"
15+
#include "volume/volume_cooling_nonspherical_gaussians_crhmc.hpp"
16+
#include "volume/volume_cooling_gaussians.hpp"
17+
#include <iostream>
18+
#include <fstream>
19+
#include <Eigen/Dense>
20+
#include <vector>
21+
#include "misc/misc.h"
22+
23+
const unsigned int FIXED_SEED = 42;
24+
25+
typedef double NT;
26+
typedef Cartesian<NT> Kernel;
27+
typedef typename Kernel::Point Point;
28+
typedef BoostRandomNumberGenerator<boost::mt11213b, NT, FIXED_SEED> RandomNumberGenerator;
29+
typedef HPolytope<Point> HPOLYTOPE;
30+
31+
NT nonspherical_crhmc_volume(HPOLYTOPE& polytope) {
32+
int walk_len = 10;
33+
NT e = 0.1;
34+
RandomNumberGenerator rng;
35+
// NT volume = volume_cooling_gaussians<GaussianBallWalk, RandomNumberGenerator>(polytope, e, walk_len);
36+
NT volume = non_spherical_crhmc_volume_cooling_gaussians<HPOLYTOPE, RandomNumberGenerator>(polytope, rng, e, walk_len);
37+
return volume;
38+
}
39+
40+
NT spherical_gaussians_volume(HPOLYTOPE& polytope) {
41+
int walk_len = 10;
42+
NT e = 0.1;
43+
RandomNumberGenerator rng;
44+
NT volume = volume_cooling_gaussians<GaussianCDHRWalk, RandomNumberGenerator>(polytope, e, walk_len);
45+
return volume;
46+
}
47+
48+
int main() {
49+
50+
HPOLYTOPE cube3 = generate_cube<HPOLYTOPE>(3, false);
51+
std::cout << "Cube3 \n";
52+
std::cout << "Calculated Volume With Gaussian CDHR: " << spherical_gaussians_volume(cube3) << "\n";
53+
std::cout << "Calculated Volume With CRHMC: " << nonspherical_crhmc_volume(cube3) << "\n";
54+
std::cout << "Expected Volume: " << std::pow(2, 3) << "\n\n";
55+
56+
HPOLYTOPE cube4 = generate_cube<HPOLYTOPE>(4, false);
57+
std::cout << "Cube4 \n";
58+
std::cout << "Calculated Volume With Gaussian CDHR: " << spherical_gaussians_volume(cube4) << "\n";
59+
std::cout << "Calculated Volume With CRHMC: " << nonspherical_crhmc_volume(cube4) << "\n";
60+
std::cout << "Expected Volume: " << std::pow(2, 4) << "\n\n";
61+
62+
HPOLYTOPE skinnycube3 = generate_skinny_cube<HPOLYTOPE>(3, false);
63+
std::cout << "SkinnyCube3 \n";
64+
std::cout << "Calculated Volume With Gaussian CDHR: " << spherical_gaussians_volume(skinnycube3) << "\n";
65+
std::cout << "Calculated Volume With CRHMC: " << nonspherical_crhmc_volume(skinnycube3) << "\n";
66+
std::cout << "Expected Volume: " << 200 * std::pow(2, 2) << "\n\n";
67+
68+
return 0;
69+
}

include/ode_solvers/implicit_midpoint.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ struct ImplicitMidpointODESolver {
172172
stream << '\n';
173173
}
174174
}
175+
176+
NT get_eta() const { return eta; }
175177
};
176178

177179
#endif

include/ode_solvers/oracle_functors.hpp

+73
Original file line numberDiff line numberDiff line change
@@ -394,4 +394,77 @@ struct HessianFunctor {
394394

395395
};
396396

397+
struct NonSphericalGaussianFunctor {
398+
template <typename NT, typename Point>
399+
struct parameters {
400+
Point x0;
401+
NT a;
402+
NT eta;
403+
unsigned int order;
404+
NT L;
405+
NT m;
406+
NT kappa;
407+
Eigen::Matrix<NT, Eigen::Dynamic, Eigen::Dynamic> inv_covariance_matrix;
408+
409+
parameters(Point x0_, NT a_, NT eta_, Eigen::Matrix<NT, Eigen::Dynamic, Eigen::Dynamic> inv_covariance_matrix_)
410+
: x0(x0_), a(a_), eta(eta_), order(2),
411+
L(a_), m(a_), kappa(1),
412+
inv_covariance_matrix(inv_covariance_matrix_) {};
413+
};
414+
415+
template <typename Point>
416+
struct GradientFunctor {
417+
typedef typename Point::FT NT;
418+
typedef std::vector<Point> pts;
419+
420+
parameters<NT, Point>& params;
421+
422+
GradientFunctor(parameters<NT, Point>& params_) : params(params_) {};
423+
424+
Point operator()(unsigned int const& i, pts const& xs, NT const& t) const {
425+
if (i == params.order - 1) {
426+
Point y = xs[0] - params.x0;
427+
Eigen::Matrix<NT, Eigen::Dynamic, 1> result = -2.0 * params.a * params.inv_covariance_matrix * y.getCoefficients();
428+
return Point(result);
429+
} else {
430+
return xs[i + 1];
431+
}
432+
}
433+
Point operator()(Point const& x) {
434+
Point y = x - params.x0;
435+
Eigen::Matrix<NT, Eigen::Dynamic, 1> result = -2.0 * params.a * params.inv_covariance_matrix * y.getCoefficients();
436+
return Point(result);
437+
}
438+
};
439+
440+
template <typename Point>
441+
struct FunctionFunctor {
442+
typedef typename Point::FT NT;
443+
444+
parameters<NT, Point>& params;
445+
446+
FunctionFunctor(parameters<NT, Point>& params_) : params(params_) {};
447+
448+
NT operator()(Point const& x) const {
449+
Point y = x - params.x0;
450+
Eigen::Matrix<NT, Eigen::Dynamic, 1> y_coeffs = y.getCoefficients();
451+
return params.a * y_coeffs.dot(params.inv_covariance_matrix * y_coeffs);
452+
}
453+
};
454+
455+
template <typename Point>
456+
struct HessianFunctor {
457+
typedef typename Point::FT NT;
458+
459+
parameters<NT, Point>& params;
460+
461+
HessianFunctor(parameters<NT, Point>& params_) : params(params_) {};
462+
463+
Point operator()(Point const& x) const {
464+
Eigen::Matrix<NT, Eigen::Dynamic, Eigen::Dynamic> result = 2.0 * params.a * params.inv_covariance_matrix;
465+
return Point(result);
466+
}
467+
};
468+
};
469+
397470
#endif

include/preprocess/crhmc/opts.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ template <typename Type> class opts {
4444
bool DynamicWeight = true; //Enable the use of dynamic weights for each variable when sampling
4545
bool DynamicStepSize = true; // Enable adaptive step size that avoids low acceptance probability
4646
bool DynamicRegularizer = true; //Enable the addition of a regularization term
47+
bool etaInitialize = true; // enable eta initialization
4748
Type regularization_factor=1e-20;
4849
/*Dynamic step choices*/
4950
Type warmUpStep = 10;

include/random_walks/crhmc/additional_units/dynamic_step_size.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class dynamic_step_size {
5050
consecutiveBadStep = IVT::Zero(simdLen);
5151
rejectSinceShrink = VT::Zero(simdLen);
5252

53-
if (options.warmUpStep > 0) {
53+
if (options.warmUpStep > 0 && options.etaInitialize) {
5454
eta = 1e-3;
5555
} else {
5656
warmupFinished = true;

include/random_walks/crhmc/crhmc_walk.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ struct CRHMCWalk {
164164
inline void disable_adaptive(){
165165
update_modules=false;
166166
}
167+
NT get_current_eta() const {
168+
return solver->get_eta();
169+
}
167170
inline void apply(RandomNumberGenerator &rng,
168171
int walk_length = 1,
169172
bool metropolis_filter = true)

include/random_walks/gaussian_helpers.hpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@ NT eval_exp(Point const& p, NT const& a)
99
{
1010
return std::exp(-a * p.squared_length());
1111
}
12-
12+
template <typename Point, typename NT, typename MT>
13+
NT eval_exp(Point const& p, MT const& inv_covariance_matrix, NT const& a_next, NT const& a_curr)
14+
{
15+
Eigen::Matrix<NT, Eigen::Dynamic, 1> dist_vector = p.getCoefficients();
16+
NT mahalanobis_dist = dist_vector.transpose() * inv_covariance_matrix * dist_vector;
17+
NT log_ratio = (a_curr - a_next) * mahalanobis_dist;
18+
return std::exp(log_ratio);
19+
}
1320

1421
template <typename Point, typename NT>
1522
NT get_max(Point const& l, Point const& u, NT const& a_i)

0 commit comments

Comments
 (0)