Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
cmake_minimum_required(VERSION 3.10)
project(VolestiBenchmark)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
add_compile_options(-O3)

add_compile_definitions(EIGEN_NO_DEBUG)
add_compile_definitions(BOOST_NO_AUTO_PTR)
add_compile_definitions(DISABLE_NLP_ORACLES)

find_package(Boost REQUIRED COMPONENTS program_options)
find_package(Eigen3 3.3 REQUIRED NO_MODULE)

find_library(LP_SOLVE NAMES liblpsolve55.so
PATHS /usr/lib/lp_solve /usr/local/lib)
find_path(LP_SOLVE_INCLUDE_DIR NAMES lp_lib.h
PATH_SUFFIXES lpsolve lp_solve)

find_library(QD_LIB NAMES qd)

if(NOT LP_SOLVE)
message(WARNING "lp_solve not found. ComputeInnerBall() might fail to link.")
else()
message(STATUS "Library lp_solve found: ${LP_SOLVE}")
endif()

if(NOT LP_SOLVE_INCLUDE_DIR)
message(WARNING "lp_solve headers not found (lp_lib.h). Adjust include paths if needed.")
else()
message(STATUS "lp_solve headers found: ${LP_SOLVE_INCLUDE_DIR}")
endif()

if(NOT QD_LIB)
message(WARNING "qd library not found. CRHMC / dd_real math will fail to link.")
else()
message(STATUS "Library qd found: ${QD_LIB}")
endif()

include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/../include
${CMAKE_CURRENT_SOURCE_DIR}/../external
${CMAKE_CURRENT_SOURCE_DIR}/../include/generators
${CMAKE_CURRENT_SOURCE_DIR}/../include/convex_bodies
${CMAKE_CURRENT_SOURCE_DIR}/../include/random_walks
${CMAKE_CURRENT_SOURCE_DIR}/../include/preprocess
)

if(LP_SOLVE_INCLUDE_DIR)
include_directories(${LP_SOLVE_INCLUDE_DIR})
endif()

set(SOURCES
src/benchmark_main.cpp
src/benchmark_run.cpp
src/walk_parameters.cpp
src/benchmark_utils.cpp
src/walk_result.cpp
src/walk_registry.cpp
)

add_executable(benchmark_run ${SOURCES})

target_link_libraries(benchmark_run
Boost::program_options
Eigen3::Eigen
m
)

if(LP_SOLVE)
target_link_libraries(benchmark_run ${LP_SOLVE})
endif()

if(QD_LIB)
target_link_libraries(benchmark_run ${QD_LIB})
endif()
100 changes: 100 additions & 0 deletions benchmark/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Volesti Benchmark Suite

This project is a benchmarking suite for testing various random walk algorithms on high-dimensional convex polytopes found inside the volesti library

## Usage

Create a build folder, and run Cmake and Make. Make sure all the needed libraries are installed.

```bash
mkdir build && cd build
cmake ..
make
```

Then, just run the executable:

```bash
./benchmark_run
```

## Command-Line Arguments

While not necessary, the executable accepts the following optional parameters

### `-h` or `--help`

Prints the help message and available options, then exits safely.

---

### `-c <path>` or `--config <path>`

Specify a custom path to your JSON configuration file.

- **Default:** `../config/walk_config.json`

---

### `-d <number>` or `--dim <number>`

Set the dimension for generating standard polytopes (e.g., Cube, Simplex).

- **Default:** The `"dimension"` value in your JSON config.
- **Note:** *Custom Polytopes* will use its own dimesnion based on the csv files.

---

### `-p <name>` or `--polytope <name>`

Choose the mathematical shape of the polytope.

- **Valid Options:** Cube, Simplex, Birkhoff, Cross, OrderPolytope, Custom

---

### `-w <name>` or `--walk <name>`

Specify exactly which random walk to run. Walk names are case-sensitive.

- **Valid Options:**
All, BallWalk, BilliardWalk, AcceleratedBilliardWalk, SparseBilliardWalk, CDHRWalk, RDHRWalk, DikinWalk, JohnWalk, VaidyaWalk, GaussianBallWalk, GaussianCDHRWalk, BilliardShakeAndBakeWalk, ShakeAndBakeWalk, BCDHRWalk, BRDHRWalk
|

## Examples

### Run the default benchmark

(Uses the configuration file to determine the experiment parameters)

```bash
./benchmark_run
```

### Test a specific algorithm at a specific dimension and a specific Polytope

(Runs only the Accelerated Billiard Walk in 25 dimensions for the Simplex polytope)

```bash
./benchmark_run -p Simplex -w AcceleratedBilliardWalk -d 25
```

### Use your custom csv polytope

```bash
./benchmark_run -p Custom -w BilliardWalk
```

### 3. Use shorthand flags for a custom configuration

(Runs the Billiard Walk in 100 dimensions using a custom JSON file)

```bash
./benchmark_run -w BilliardWalk -d 100 -c ../config/walk_config.json
```

You actually don't have to use any argument at all. Just run the "benchmark_run" file and it will retrieve all the necessary parameters from the configuration file.

## Configuration (JSON)

Algorithm-specific parameters are managed entirely via the JSON configuration file. To change them, simply edit `config/walk_config.json`.
76 changes: 76 additions & 0 deletions benchmark/config/available_choices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Available Choices

## Target ESS

The code will use a dynamic batch size in order to sample the necessary number of samples needed to reach the targert ESS

## Time limit

The maximum time the code runs. If the time runs out, the code will stop at the first available opportunity.

## Base seed

The seed used by the random number generator. Use any number you like.

## Dimension

The number of dimesnion the generated polytope will have. This only applies to polytopes generated by the generator functions. It is ignored for custom polytopes.

## Rotation angle

You can rotate the input polytope by this number over all pairs of dimensions. Angle is in degrees. Use 0 to avoid rotation.

## Polytope Choice

Choose the polytope that will be sampled from.
Available polytope choices are: Cube, Simplex, Birkhoff, Cross, OrderPolytope, Custom

## Custom A file and Custom b file

These are the names of the A and b files of your custom polytope defining the polytope Ax<=b. Csv files are expected, with no labels.
Place them inside build folder next to the executable.

## Dynamic batch size

If you have this choice to true, the code will run a dynamic batch size in order to hit target ESS.
If you have this choice to false, the code will generate exactly "samples" amount of samples, the parameter defined for each walk method.

## Write to file

Set this to true in order to create txt files holding all the generated samples. Useful for later use of the samples.

## Rounding

If this is set to true, the code will first call a rounding function on the input polytope.
The sampling will take place on the rounded polytope before the sample are reverted back to the original and returned.

## Rounding_method

Selects the rounding method. Available choices are:

- max_ellipsoid
- log_barrier
- vaidya_barrier
- volumetric_barrier

## Auto walk

If set to true, the code will decide what algorithm to use based on the input polytope.
Right now it decides only based on dimension, but will be updated in the future.

## Show console logs

Keep your console clean by removing most of the cosnole messages. You will still see the progress bar and final a few mesages.

## Show menu

If set to true, a menu will show up when you run the code. The menu will ask you to choose all the parameters you want for your experiment or show extended help. Useful for new users.

## Walks

For each walk, you can change these parameters:

- enabled: This will determine if this method will run or not when sampling
- samples: How many samples the code will take if dynamic batch size is also false. If dynamic batch size is on, target ESS will be used instead to determine when the execution stops.
- walk_len: It is a thinning parameter. The code will save the sample only after walk_len samples are sampled.
walk_len = walk_base + dim * walk_multiplier"
37 changes: 37 additions & 0 deletions benchmark/config/walk_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"global_settings": {
"target_ESS": 3000,
"time_limit_sec": 30.0,
"base_seed": 42,
"dimensions": [50],
"rotation_angle": 53,
"polytope_choice": "Cube",
"custom_A_file": "Cube_50_A.csv",
"custom_b_file": "Cube_50_b.csv",
"dynamic_batch_size": true,
"write_to_file": true,
"rounding": true,
"rounding_method": "max_ellipsoid",
"auto_walk": false,
"show_console_logs": true,
"show_menu": true
},
"walks": {
"BallWalk": { "enabled": true, "samples": 20000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"BilliardWalk": { "enabled": false, "samples": 2000, "walk_len_multiplier": 0, "walk_len_base": 1 },
"AcceleratedBilliardWalk": { "enabled": false, "samples": 2000, "walk_len_multiplier": 0, "walk_len_base": 1 },
"SparseBilliardWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 0, "walk_len_base": 1 },
"CDHRWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"RDHRWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"DikinWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"JohnWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"VaidyaWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"GaussianBallWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0, "a_i_param": 1.0 },
"GaussianCDHRWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0, "a_i_param": 1.0 },
"BilliardShakeAndBakeWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"ShakeAndBakeWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"BCDHRWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"BRDHRWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 2, "walk_len_base": 0 },
"CRHMCWalk": { "enabled": false, "samples": 1000, "walk_len_multiplier": 0, "walk_len_base": 1 }
}
}
3 changes: 3 additions & 0 deletions benchmark/include/benchmark_run.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

int run_benchmark(int argc, char** argv);
46 changes: 46 additions & 0 deletions benchmark/include/benchmark_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

#include "core_types.hpp"
#include <chrono>
#include <string>
#include <vector>

//In this file you can find the definition of supportive functions.
//Timer is a class to count the time for each random walk.
//write to file is used to write the results to a file.
//vector to eigen converts a vector in an eigen compatible form. (eigen is numpy for c++)
//determine auto walk is used to choose a walk based on the polytope structure.


class Timer {
public:
Timer(const std::string& name = "");
void start();
double stop(const std::string& label = "");
double get_total_time() const;

private:
std::string walk_name;
std::chrono::steady_clock::time_point start_time;
double total_time;
bool is_running;
};


void write_to_file(std::string filename, std::vector<Point> const& randPoints);


template <typename MT>
MT vector_to_eigen(const std::vector<Point>& someSamples) {
if (someSamples.empty()) {
return MT(); // Return empty matrix if no samples
}

MT samples(someSamples[0].dimension(), someSamples.size());
for (size_t jj = 0; jj < someSamples.size(); ++jj) {
samples.col(jj) = someSamples[jj].getCoefficients();
}
return samples;
}

std::string determine_auto_walk(unsigned int dim);
33 changes: 33 additions & 0 deletions benchmark/include/core_types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <iostream>
#include <vector>
#include <string>

#include <boost/random.hpp>
#include "Eigen/Eigen"

#include "cartesian_geom/cartesian_kernel.h"
#include "convex_bodies/hpolytope.h"
#include "random_walks/random_walks.hpp"

// In this file you can find the core type definitions and commonly used aliases
// for the project.
//
// It defines:
// Numeric type (NT) used across computations.
// Geometric kernel (Cartesian) and Point representation.
// Matrix (MT) and vector (VT) types using Eigen (similar to NumPy in C++).
// Random number generator type based on Boost.
// HPolytope type used to represent convex bodies.

typedef double NT;
typedef Cartesian<NT> Kernel;
typedef Kernel::Point Point;
typedef Eigen::Matrix<NT, Eigen::Dynamic, Eigen::Dynamic> MT;
typedef Eigen::Matrix<NT, Eigen::Dynamic, 1> VT;
typedef BoostRandomNumberGenerator<boost::mt19937, NT> RNGType;
typedef HPolytope<Point> HPOLYTOPE;

//it is only initialized once inside src/benchmark_utils.cpp
extern PushBackWalkPolicy push_back_policy;
Loading