A C++ header-only library reimplementing R's lhs package. The library is very much work in progress and currently only supports random (derived from R package), maximin (derived from construction and optimisation code in the R package) and centred (derived from Rust implementation) samples. Additional implementations might be ported as necessary, but do not hold your breath.
The library is header-only, so you only need to copy the include folder and add it to you #include
path. For Cmake builds, we have added CMakeLists.txt, which does this for you.
The library will create Latin hypercube samples in the form of matrix instances. Each row of the matrices represent a single sample whereas each column represents a parameter. There are usually two types of samples, the ones yielding integer matrices and the ones yielding floating-point matrices. In case of the former, the matrix elements represent zero-based indices into the parameter ranges, whatever these may be. For instance, if a parameter is a numeric value, the index represents the selected qantile of the overall range. If you have categorical parameters, it might represent the category. The floating-point samples are typically from a unit hypercube. You may scale them as necessary.
The following most basic code creates a four samples with three parameters on a unit hypercube:
auto lhs = visus::lhs::random<float>(4, 3);
You can also provide your own random number generator like this, for instance if you need to have a specific random seed:
auto lhs = visus::lhs::random<float>(4, 3, false, std::mt19937(42));
Finally, it is possible to specify a specific random number distribution, which should, however, typically be a std::uniform_real_distribution
within [0, 1]. The ability to change this is used for testing and should typically not be required for end users:
auto lhs = visus::lhs::random(4, 3, false, std::mt19937(42), std::uniform_real_distribution<float>(0.0f, 1.0f));
A centred sample can be created like this:
auto lhs = visus::lhs::centred<float>(4, 3);
You can perform maximin optimisation (maximise the pairwise distance between the samples) on an existing sample:
auto lhs = visus::lhs::random<float>(4, 3);
visus::lhs::maximin(lhs);
The following most basic code creates four samples with values wihtin [0, 4[ for the three parameters:
auto lhs = visus::lhs::random<std::size_t>(4, 3);
The library provides a sample convenience function that allows users to create samples of differently shaped parameters in the form of std::tuple
s. It is based on scaling a unit hypercube sample to the user-defined ranges. The following code creates four samples of a categorical parameter, an range of consecutive integer values and a range of floating-point values:
auto lhs = visus::lhs::sample(
[](const std::size_t parameters) {
// Request four sample points. The number of columns must be 'parameters'.
return visus::lhs::random<float>(4, parameters);
},
std::vector<std::string>({ "Category 1", "Category 2" }),
visus::lhs::make_range(1, 100),
visus::lhs::make_range(0.0f, 1.0f));
The first parameter is a callback that creates the unit hypercube sample. This way, it is possible for you to choose how the Latin hypercube sample is created. However, it is mandatory that the sample returned (i) is from a unit hypercube, (ii) returns a floating-point matrix and (iii) has the requested number of columns, which is equivalent to the number of parameters specified after the callback (three in the case of the example). The number of rows of the matrix returned determines the number of sample points and can be chosen freely.
This work was partially funded by Deutsche Forschungsgemeinschaft (DFG) as part of SFB/Transregio 161 (project ID 251654672).