merge master

This commit is contained in:
jeffin143
2020-10-13 01:30:15 +05:30
39 changed files with 2923 additions and 2969 deletions
-9
View File
@@ -27,10 +27,6 @@ jobs:
binding: 'go'
go.version: '1.11.0'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=ON -DBUILD_R_BINDINGS=OFF'
R:
binding: 'R'
R.version: '4.0.0'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=ON'
Markdown:
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_MARKDOWN_BINDINGS=ON -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
@@ -59,11 +55,6 @@ jobs:
python.version: '2.7'
go.version: '1.11.0'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=ON -DBUILD_R_BINDINGS=OFF'
R:
binding: 'R'
python.version: '2.7'
R.version: '4.0.0'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=ON'
steps:
- template: macos-steps.yaml
-9
View File
@@ -34,15 +34,6 @@ steps:
sudo tar -C /opt/ -xvpf julia-1.3.0-linux-x86_64.tar.gz
fi
if [ "$(binding)" == "R" ]; then
if [ "a$(R.version)" != "a" ]; then
sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu xenial-cran40/'
sudo apt-get -y update
sudo apt-get install -y r-base-core
fi
sudo Rscript -e "install.packages(c('Rcpp', 'RcppArmadillo', 'RcppEnsmallen', 'BH', 'roxygen2', 'testthat'))"
fi
# Install armadillo.
curl https://data.kurg.org/armadillo-8.400.0.tar.xz | tar -xvJ && cd armadillo*
cmake . && make && sudo make install && cd ..
-8
View File
@@ -25,14 +25,6 @@ steps:
brew cask install julia
fi
if [ "$(binding)" == "R" ]; then
if [ "a$(R.version)" != "a" ]; then
brew cask install r
fi
brew cask install gfortran
Rscript -e "install.packages(c('Rcpp', 'RcppArmadillo', 'RcppEnsmallen', 'BH', 'roxygen2', 'testthat'), repos = 'http://cran.us.r-project.org')"
fi
git clone --depth 1 https://github.com/mlpack/jenkins-conf.git conf
displayName: 'Install Build Dependencies'
+15 -9
View File
@@ -8,7 +8,7 @@ on:
- master
release:
types: [published, created, edited]
name: R CMD check mlpack
name: mlpack.mlpack
jobs:
cancel:
@@ -26,7 +26,7 @@ jobs:
access_token: ${{ secrets.GITHUB_TOKEN }}
jobR:
name: Build mlpack_r_tarball
name: mlpack R tarball
if: ${{ github.repository == 'mlpack/mlpack' }}
runs-on: ubuntu-20.04
@@ -78,11 +78,15 @@ jobs:
- name: CMake
run: |
mkdir build
cd build && cmake -DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=ON ..
cd build && cmake -DDEBUG=OFF -DPROFILE=OFF -DBUILD_CLI_EXECUTABLES=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=ON ..
- name: Build
run: |
cd build && make R -j2
cd build && make -j2
- name: Run tests via ctest
run: |
cd build && CTEST_OUTPUT_ON_FAILURE=1 ctest -T Test .
- name: Upload R packages
uses: actions/upload-artifact@v2
@@ -94,16 +98,16 @@ jobs:
needs: jobR
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
name: ${{ matrix.config.name }}
if: ${{ github.repository == 'mlpack/mlpack' }}
strategy:
fail-fast: false
matrix:
config:
- {os: windows-latest, r: '4.0'}
- {os: macOS-latest, r: 'release'}
- {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: windows-latest, r: '4.0', name: 'Windows R'}
- {os: macOS-latest, r: 'release', name: 'macOS R'}
- {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest", name: 'Linux R'}
env:
@@ -151,4 +155,6 @@ jobs:
uses: actions/upload-artifact@master
with:
name: ${{ runner.os }}-r${{ matrix.config.r }}-results
path: check
path: |
check/mlpack.Rcheck/00check.log
check/mlpack.Rcheck/00install.out
+1
View File
@@ -568,6 +568,7 @@ add_custom_target(mlpack_arma_config ALL
COMMAND ${CMAKE_COMMAND}
-D ARMADILLO_INCLUDE_DIR="${ARMADILLO_INCLUDE_DIR}"
-D OPENMP_FOUND="${OPENMP_FOUND}"
-D CMAKE_SIZEOF_VOID_P="${CMAKE_SIZEOF_VOID_P}"
-P CMake/CreateArmaConfigInfo.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Updating arma_config.hpp (if necessary)")
+2
View File
@@ -4,6 +4,8 @@
* Added Softmin activation function as layer in ann/layer.
* Fix spurious ARMA_64BIT_WORD compilation warnings on 32-bit systems (#2665).
### mlpack 3.4.1
###### 2020-09-07
* Fix incorrect parsing of required matrix/model parameters for command-line
+2 -1
View File
@@ -92,7 +92,8 @@ void PrintR(const util::BindingDetails& doc,
cout << "#'" << endl;
// Next, print information on the output options.
cout << "#' @return A list with several components:" << endl;
if (outputOptions.size() > 0)
cout << "#' @return A list with several components:" << endl;
for (size_t i = 0; i < outputOptions.size(); ++i)
{
@@ -229,7 +229,9 @@ std::string ProgramCall(const bool markdown,
// Find out if we have any output options first.
std::ostringstream ossOutput;
oss << "output <- ";
ossOutput << PrintOutputOptions(markdown, args...);
if (ossOutput.str() != "")
oss << "output <- ";
oss << programName << "(";
// Now process each input option.
+25 -9
View File
@@ -166,15 +166,31 @@ void PrintDocs(const std::string& bindingName,
}
cout << endl;
// Next, iterate through the list of output options.
cout << "### Output options" << endl;
cout << endl;
string outputInfo = PrintOutputOptionInfo();
if (outputInfo.size() > 0)
cout << outputInfo << endl;
cout << endl;
cout << "| ***name*** | ***type*** | ***description*** |" << endl;
cout << "|------------|------------|-------------------|" << endl;
// Determine if there are any output options, to see if we need
// to print the header of the output options table.
bool hasOutputOptions = false;
for (map<string, ParamData>::iterator it = parameters.begin();
it != parameters.end(); ++it)
{
if (!it->second.input)
{
hasOutputOptions = true;
break;
}
}
if (hasOutputOptions)
{
// Next, iterate through the list of output options.
cout << "### Output options" << endl;
cout << endl;
string outputInfo = PrintOutputOptionInfo();
if (outputInfo.size() > 0)
cout << outputInfo << endl;
cout << endl;
cout << "| ***name*** | ***type*** | ***description*** |" << endl;
cout << "|------------|------------|-------------------|" << endl;
}
for (map<string, ParamData>::iterator it = parameters.begin();
it != parameters.end(); ++it)
{
@@ -28,12 +28,12 @@ Softmax<InputDataType, OutputDataType>::Softmax()
template<typename InputDataType, typename OutputDataType>
template<typename InputType, typename OutputType>
void Softmax<InputDataType, OutputDataType>::Forward(
const InputType& input, OutputType& output)
const InputType& input,
OutputType& output)
{
InputType inputMax = arma::repmat(arma::max(input, 0), input.n_rows, 1);
output = inputMax + arma::log(arma::repmat(
arma::sum(arma::exp(input - inputMax), 0), input.n_rows, 1));
output = arma::exp(input - output);
InputType softmaxInput = arma::exp(input.each_row() -
arma::max(input, 0));
output = softmaxInput.each_row() / sum(softmaxInput, 0);
}
template<typename InputDataType, typename OutputDataType>
@@ -30,10 +30,9 @@ void Softmin<InputDataType, OutputDataType>::Forward(
const InputType& input,
OutputType& output)
{
InputType inputMin = arma::repmat(arma::min(input,0), input.n_rows, 1);
output = arma::repmat(arma::log(arma::sum(
arma::exp(-(input - inputMin)),0)), input.n_rows, 1);
output = arma::exp(-(input - inputMin) - output);
InputType softminInput = arma::exp(-(input.each_row() -
arma::min(input, 0)));
output = softminInput.each_row() / sum(softminInput, 0);
}
template<typename InputDataType, typename OutputDataType>
+26 -28
View File
@@ -1,30 +1,19 @@
# mlpack test executable.
add_executable(mlpack_test
async_learning_test.cpp
augmented_rnns_tasks_test.cpp
callback_test.cpp
cf_test.cpp
cli_binding_test.cpp
io_test.cpp
cosine_tree_test.cpp
dcgan_test.cpp
det_test.cpp
distribution_test.cpp
drusilla_select_test.cpp
emst_test.cpp
fastmks_test.cpp
facilities_test.cpp
gan_test.cpp
hoeffding_tree_test.cpp
hpt_test.cpp
hyperplane_test.cpp
init_rules_test.cpp
kde_test.cpp
krann_search_test.cpp
ksinit_test.cpp
lars_test.cpp
layer_names_test.cpp
lin_alg_test.cpp
linear_svm_test.cpp
lmnn_test.cpp
local_coordinate_coding_test.cpp
@@ -34,13 +23,11 @@ add_executable(mlpack_test
math_test.cpp
matrix_completion_test.cpp
maximal_inputs_test.cpp
metric_test.cpp
mlpack_test.cpp
mock_categorical_data.hpp
nbc_test.cpp
nmf_test.cpp
nystroem_method_test.cpp
octree_test.cpp
perceptron_test.cpp
prefixedoutstream_test.cpp
python_binding_test.cpp
@@ -48,33 +35,21 @@ add_executable(mlpack_test
qdafn_test.cpp
radical_test.cpp
random_test.cpp
range_search_test.cpp
rectangle_tree_test.cpp
reward_clipping_test.cpp
rl_components_test.cpp
serialization.cpp
serialization.hpp
serialization_test.cpp
sfinae_test.cpp
sort_policy_test.cpp
spill_tree_test.cpp
string_encoding_test.cpp
sumtree_test.cpp
termination_policy_test.cpp
test_function_tools.hpp
test_tools.hpp
timer_test.cpp
tree_test.cpp
tree_traits_test.cpp
ub_tree_test.cpp
union_find_test.cpp
vantage_point_tree_test.cpp
wgan_test.cpp
main_tests/cf_test.cpp
main_tests/det_test.cpp
main_tests/emst_test.cpp
main_tests/fastmks_test.cpp
main_tests/hoeffding_tree_test.cpp
main_tests/kde_test.cpp
main_tests/krann_test.cpp
main_tests/linear_svm_test.cpp
@@ -86,7 +61,6 @@ add_executable(mlpack_test
main_tests/nmf_test.cpp
main_tests/perceptron_test.cpp
main_tests/radical_test.cpp
main_tests/range_search_test.cpp
main_tests/test_helper.hpp
)
@@ -102,52 +76,76 @@ add_executable(mlpack_catch_test
ann_visitor_test.cpp
armadillo_svd_test.cpp
arma_extend_test.cpp
async_learning_test.cpp
augmented_rnns_tasks_test.cpp
bayesian_linear_regression_test.cpp
bias_svd_test.cpp
binarize_test.cpp
block_krylov_svd_test.cpp
cli_binding_test.cpp
convolutional_network_test.cpp
convolution_test.cpp
cosine_tree_test.cpp
cv_test.cpp
dbscan_test.cpp
decision_stump_test.cpp
decision_tree_test.cpp
det_test.cpp
distribution_test.cpp
gmm_test.cpp
hmm_test.cpp
feedforward_network_test.cpp
hoeffding_tree_test.cpp
image_load_test.cpp
imputation_test.cpp
io_test.cpp
kernel_pca_test.cpp
kernel_test.cpp
kernel_traits_test.cpp
kfn_test.cpp
kmeans_test.cpp
knn_test.cpp
lars_test.cpp
layer_names_test.cpp
lin_alg_test.cpp
linear_regression_test.cpp
load_save_test.cpp
loss_functions_test.cpp
main.cpp
metric_test.cpp
mean_shift_test.cpp
nca_test.cpp
octree_test.cpp
one_hot_encoding_test.cpp
pca_test.cpp
quic_svd_test.cpp
random_forest_test.cpp
randomized_svd_test.cpp
range_search_test.cpp
rbm_network_test.cpp
rectangle_tree_test.cpp
recurrent_network_test.cpp
regularized_svd_test.cpp
scaling_test.cpp
serialization_catch.cpp
serialization_catch.hpp
sfinae_test.cpp
softmax_regression_test.cpp
sort_policy_test.cpp
sparse_autoencoder_test.cpp
sparse_coding_test.cpp
spill_tree_test.cpp
split_data_test.cpp
string_encoding_test.cpp
sumtree_test.cpp
svd_batch_test.cpp
svd_incremental_test.cpp
svdplusplus_test.cpp
test_catch_tools.hpp
tree_test.cpp
tree_traits_test.cpp
ub_tree_test.cpp
vantage_point_tree_test.cpp
main_tests/adaboost_test.cpp
main_tests/gmm_generate_test.cpp
main_tests/gmm_probability_test.cpp
@@ -162,6 +160,7 @@ add_executable(mlpack_catch_test
main_tests/dbscan_test.cpp
main_tests/decision_stump_test.cpp
main_tests/decision_tree_test.cpp
main_tests/hoeffding_tree_test.cpp
main_tests/image_converter_test.cpp
main_tests/kernel_pca_test.cpp
main_tests/kfn_test.cpp
@@ -179,6 +178,7 @@ add_executable(mlpack_catch_test
main_tests/random_forest_test.cpp
main_tests/softmax_regression_test.cpp
main_tests/sparse_coding_test.cpp
main_tests/range_search_test.cpp
main_tests/test_helper.hpp
)
@@ -227,10 +227,8 @@ add_custom_command(TARGET mlpack_test
# The list of long running parallel tests
set(parallel_tests
"AsyncLearningTest;"
"LocalCoordinateCodingTest;"
"CFTest;"
"LARSTest;"
"LogisticRegressionTest;"
"LinearSVMTest")
+7 -11
View File
@@ -24,17 +24,15 @@
#include <ensmallen.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
using namespace mlpack;
using namespace mlpack::ann;
using namespace mlpack::rl;
BOOST_AUTO_TEST_SUITE(AsyncLearningTest);
// Test async one step q-learning in Cart Pole.
BOOST_AUTO_TEST_CASE(OneStepQLearningTest)
TEST_CASE("OneStepQLearningTest", "[AsyncLearningTest]")
{
/**
* This is for the Travis CI server, in your own machine you should use more
@@ -106,11 +104,11 @@ BOOST_AUTO_TEST_CASE(OneStepQLearningTest)
}
}
BOOST_REQUIRE_EQUAL(success, true);
REQUIRE(success == true);
}
// Test async one step Sarsa in Cart Pole.
BOOST_AUTO_TEST_CASE(OneStepSarsaTest)
TEST_CASE("OneStepSarsaTest", "[AsyncLearningTest]")
{
/**
* This is for the Travis CI server, in your own machine you shuold use more
@@ -184,11 +182,11 @@ BOOST_AUTO_TEST_CASE(OneStepSarsaTest)
}
}
BOOST_REQUIRE_EQUAL(success, true);
REQUIRE(success == true);
}
// Test async n step q-learning in Cart Pole.
BOOST_AUTO_TEST_CASE(NStepQLearningTest)
TEST_CASE("NStepQLearningTest", "[AsyncLearningTest]")
{
/**
* This is for the Travis CI server, in your own machine you shuold use more
@@ -233,7 +231,7 @@ BOOST_AUTO_TEST_CASE(NStepQLearningTest)
{
size_t maxEpisode = 100000;
if (testEpisodes > maxEpisode)
BOOST_REQUIRE(false);
REQUIRE(false);
testEpisodes++;
rewards[pos++] = reward;
pos %= rewards.n_elem;
@@ -249,5 +247,3 @@ BOOST_AUTO_TEST_CASE(NStepQLearningTest)
agent.Train(measure);
Log::Debug << "Total test episodes: " << testEpisodes << std::endl;
}
BOOST_AUTO_TEST_SUITE_END();
+12 -17
View File
@@ -22,8 +22,7 @@
#include <mlpack/methods/ann/augmented/tasks/add.hpp>
#include <mlpack/methods/ann/augmented/tasks/score.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
using std::vector;
using std::pair;
@@ -51,8 +50,10 @@ class HardCodedCopyModel
size_t zeroCnt = 0, oneCnt = 0;
for (size_t i = 1; i < input.n_rows; i += 2)
{
size_t& addVar = (input.at(i, 0) == 0) ? zeroCnt : oneCnt;
++addVar;
if (input.at(i, 0) == 0)
++zeroCnt;
else
++oneCnt;
}
assert(oneCnt % zeroCnt == 0);
nRepeats = oneCnt / zeroCnt;
@@ -158,7 +159,7 @@ class HardCodedAddModel
predictors = predictors.t();
predictors.reshape(3, predictors.n_elem / 3);
assert(predictors.n_rows == 3);
int num_A = 0, num_B = 0;
size_t num_A = 0, num_B = 0;
bool num = false; // True iff we have already seen the separating symbol.
size_t cnt = 0;
for (size_t i = 0; i < predictors.n_cols; ++i)
@@ -219,12 +220,11 @@ class HardCodedAddModel
}
};
BOOST_AUTO_TEST_SUITE(AugmentedRNNsTasks);
// Test of CopyTask instance generator.
// The data from generator is fed to the dummy hard-coded model above
// that should be able to solve the task perfectly.
BOOST_AUTO_TEST_CASE(CopyTaskTest)
TEST_CASE("CopyTaskTest", "[AugmentedRNNsTasks]")
{
// Check the setup on various lengths...
for (size_t maxLen = 2; maxLen <= 16; ++maxLen)
@@ -242,8 +242,7 @@ BOOST_AUTO_TEST_CASE(CopyTaskTest)
arma::field<arma::mat> predResponse;
model.Predict(testPredictor, predResponse);
// A single failure is a failure.
BOOST_REQUIRE_GE(SequencePrecision<arma::mat>(testResponse, predResponse),
0.99);
REQUIRE(SequencePrecision<arma::mat>(testResponse, predResponse) >= 0.99);
}
}
}
@@ -251,7 +250,7 @@ BOOST_AUTO_TEST_CASE(CopyTaskTest)
// Test of SortTask instance generator.
// The data from generator is fed to the dummy hard-coded model above
// that should be able to solve the task perfectly.
BOOST_AUTO_TEST_CASE(SortTaskTest)
TEST_CASE("SortTaskTest", "[AugmentedRNNsTasks]")
{
size_t bitLen = 5;
for (size_t maxLen = 2; maxLen <= 16; ++maxLen)
@@ -266,15 +265,14 @@ BOOST_AUTO_TEST_CASE(SortTaskTest)
arma::field<arma::mat> predResponse;
model.Predict(testPredictor, predResponse);
// A single failure is a failure.
BOOST_REQUIRE_GE(SequencePrecision<arma::mat>(testResponse, predResponse),
0.99);
REQUIRE(SequencePrecision<arma::mat>(testResponse, predResponse) >= 0.99);
}
}
// Test of AddTask instance generator.
// The data from generator is fed to the dummy hard-coded model above
// that should be able to solve the task perfectly.
BOOST_AUTO_TEST_CASE(AddTaskTest)
TEST_CASE("AddTaskTest", "[AugmentedRNNsTasks]")
{
for (size_t bitLen = 2; bitLen <= 16; ++bitLen)
{
@@ -288,9 +286,6 @@ BOOST_AUTO_TEST_CASE(AddTaskTest)
arma::field<arma::mat> predResponse;
model.Predict(testPredictor, predResponse);
// A single failure is a failure.
BOOST_REQUIRE_GE(SequencePrecision<arma::mat>(testResponse, predResponse),
0.99);
REQUIRE(SequencePrecision<arma::mat>(testResponse, predResponse) >= 0.99);
}
}
BOOST_AUTO_TEST_SUITE_END();
+84 -88
View File
@@ -13,8 +13,8 @@
#include <mlpack/bindings/cli/cli_option.hpp>
#include <mlpack/core/kernels/gaussian_kernel.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
#include "test_catch_tools.hpp"
using namespace std;
using namespace mlpack;
@@ -22,42 +22,40 @@ using namespace mlpack::bindings;
using namespace mlpack::bindings::cli;
using namespace mlpack::kernel;
BOOST_AUTO_TEST_SUITE(CLIBindingTest);
/**
* Ensure that we can construct a CLIOption object, and that it will add itself
* to the CLI instance.
*/
BOOST_AUTO_TEST_CASE(CLIOptionTest)
TEST_CASE("CLIOptionTest", "[CLIOptionTest]")
{
IO::ClearSettings();
CLIOption<double> co1(0.0, "test", "test2", "t", "double", false, true,
false);
// Now check that it's in CLI.
BOOST_REQUIRE_GT(IO::Parameters().count("test"), 0);
BOOST_REQUIRE_GT(IO::Aliases().count('t'), 0);
BOOST_REQUIRE_EQUAL(IO::Parameters()["test"].desc, "test2");
BOOST_REQUIRE_EQUAL(IO::Parameters()["test"].name, "test");
BOOST_REQUIRE_EQUAL(IO::Parameters()["test"].alias, 't');
BOOST_REQUIRE_EQUAL(IO::Parameters()["test"].noTranspose, false);
BOOST_REQUIRE_EQUAL(IO::Parameters()["test"].required, false);
BOOST_REQUIRE_EQUAL(IO::Parameters()["test"].input, true);
BOOST_REQUIRE_EQUAL(IO::Parameters()["test"].cppType, "double");
REQUIRE(IO::Parameters().count("test") > 0);
REQUIRE(IO::Aliases().count('t') > 0);
REQUIRE(IO::Parameters()["test"].desc == "test2");
REQUIRE(IO::Parameters()["test"].name == "test");
REQUIRE(IO::Parameters()["test"].alias == 't');
REQUIRE(IO::Parameters()["test"].noTranspose == false);
REQUIRE(IO::Parameters()["test"].required == false);
REQUIRE(IO::Parameters()["test"].input == true);
REQUIRE(IO::Parameters()["test"].cppType == "double");
CLIOption<arma::mat> co2(arma::mat(), "mat", "mat2", "m", "arma::mat", true,
true, true);
// Now check that it's in CLI.
BOOST_REQUIRE_GT(IO::Parameters().count("mat"), 0);
BOOST_REQUIRE_GT(IO::Aliases().count('m'), 0);
BOOST_REQUIRE_EQUAL(IO::Parameters()["mat"].desc, "mat2");
BOOST_REQUIRE_EQUAL(IO::Parameters()["mat"].name, "mat");
BOOST_REQUIRE_EQUAL(IO::Parameters()["mat"].alias, 'm');
BOOST_REQUIRE_EQUAL(IO::Parameters()["mat"].noTranspose, true);
BOOST_REQUIRE_EQUAL(IO::Parameters()["mat"].required, true);
BOOST_REQUIRE_EQUAL(IO::Parameters()["mat"].input, true);
BOOST_REQUIRE_EQUAL(IO::Parameters()["mat"].cppType, "arma::mat");
REQUIRE(IO::Parameters().count("mat") > 0);
REQUIRE(IO::Aliases().count('m') > 0);
REQUIRE(IO::Parameters()["mat"].desc == "mat2");
REQUIRE(IO::Parameters()["mat"].name == "mat");
REQUIRE(IO::Parameters()["mat"].alias == 'm');
REQUIRE(IO::Parameters()["mat"].noTranspose == true);
REQUIRE(IO::Parameters()["mat"].required == true);
REQUIRE(IO::Parameters()["mat"].input == true);
REQUIRE(IO::Parameters()["mat"].cppType == "arma::mat");
IO::ClearSettings();
}
@@ -65,7 +63,7 @@ BOOST_AUTO_TEST_CASE(CLIOptionTest)
/**
* Make sure GetParam() works.
*/
BOOST_AUTO_TEST_CASE(GetParamDoubleTest)
TEST_CASE("GetParamDoubleTest", "[CLIOptionTest]")
{
util::ParamData d;
double x = 5.0;
@@ -75,10 +73,10 @@ BOOST_AUTO_TEST_CASE(GetParamDoubleTest)
GetParam<double>((util::ParamData&) d, (const void*) NULL,
(void*) &output);
BOOST_REQUIRE_EQUAL(*output, 5.0);
REQUIRE(*output == 5.0);
}
BOOST_AUTO_TEST_CASE(GetParamLoadedMatTest)
TEST_CASE("GetParamLoadedMatTest", "[CLIOptionTest]")
{
util::ParamData d;
// Create value.
@@ -94,13 +92,13 @@ BOOST_AUTO_TEST_CASE(GetParamLoadedMatTest)
GetParam<arma::mat>((util::ParamData&) d, (void*) NULL,
(void*) &output);
BOOST_REQUIRE_EQUAL(output->n_rows, 5);
BOOST_REQUIRE_EQUAL(output->n_cols, 5);
REQUIRE(output->n_rows == 5);
REQUIRE(output->n_cols == 5);
for (size_t i = 0; i < 25; ++i)
BOOST_REQUIRE_EQUAL((*output)[i], 1.0);
REQUIRE((*output)[i] == 1.0);
}
BOOST_AUTO_TEST_CASE(GetParamUnloadedMatTest)
TEST_CASE("GetParamUnloadedMatTest", "[CLIOptionTest]")
{
util::ParamData d;
// Create value.
@@ -120,15 +118,15 @@ BOOST_AUTO_TEST_CASE(GetParamUnloadedMatTest)
GetParam<arma::mat>((util::ParamData&) d, (void*) NULL,
(void*) &output);
BOOST_REQUIRE_EQUAL(output->n_rows, 5);
BOOST_REQUIRE_EQUAL(output->n_cols, 5);
REQUIRE(output->n_rows == 5);
REQUIRE(output->n_cols == 5);
for (size_t i = 0; i < 25; ++i)
BOOST_REQUIRE_EQUAL((*output)[i], 1.0);
REQUIRE((*output)[i] == 1.0);
remove("test.csv");
}
BOOST_AUTO_TEST_CASE(GetParamUmatTest)
TEST_CASE("GetParamUmatTest", "[CLIOptionTest]")
{
util::ParamData d;
// Create value.
@@ -145,13 +143,13 @@ BOOST_AUTO_TEST_CASE(GetParamUmatTest)
GetParam<arma::Mat<size_t>>((util::ParamData&) d, (void*) NULL,
(void*) &output);
BOOST_REQUIRE_EQUAL(output->n_rows, 5);
BOOST_REQUIRE_EQUAL(output->n_cols, 5);
REQUIRE(output->n_rows == 5);
REQUIRE(output->n_cols == 5);
for (size_t i = 0; i < 25; ++i)
BOOST_REQUIRE_EQUAL((*output)[i], 1.0);
REQUIRE((*output)[i] == 1.0);
}
BOOST_AUTO_TEST_CASE(GetParamUnloadedUmatTest)
TEST_CASE("GetParamUnloadedUmatTest", "[CLIOptionTest]")
{
util::ParamData d;
// Create value.
@@ -171,15 +169,15 @@ BOOST_AUTO_TEST_CASE(GetParamUnloadedUmatTest)
GetParam<arma::Mat<size_t>>((util::ParamData&) d, (void*) NULL,
(void*) &output);
BOOST_REQUIRE_EQUAL(output->n_rows, 5);
BOOST_REQUIRE_EQUAL(output->n_cols, 5);
REQUIRE(output->n_rows == 5);
REQUIRE(output->n_cols == 5);
for (size_t i = 0; i < 25; ++i)
BOOST_REQUIRE_EQUAL((*output)[i], 1.0);
REQUIRE((*output)[i] == 1.0);
remove("test.csv");
}
BOOST_AUTO_TEST_CASE(GetParamDatasetInfoMatTest)
TEST_CASE("GetParamDatasetInfoMatTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -215,20 +213,20 @@ BOOST_AUTO_TEST_CASE(GetParamDatasetInfoMatTest)
GetParam<tuple<data::DatasetInfo, arma::mat>>((util::ParamData&) d,
(void*) NULL, (void*) &output);
BOOST_REQUIRE_EQUAL(get<0>(*output).Dimensionality(), 3);
BOOST_REQUIRE_EQUAL((int) get<0>(*output).Type(0),
REQUIRE(get<0>(*output).Dimensionality() == 3);
REQUIRE((int) get<0>(*output).Type(0) ==
(int) data::Datatype::numeric);
BOOST_REQUIRE_EQUAL((int) get<0>(*output).Type(1),
REQUIRE((int) get<0>(*output).Type(1) ==
(int) data::Datatype::numeric);
BOOST_REQUIRE_EQUAL((int) get<0>(*output).Type(2),
REQUIRE((int) get<0>(*output).Type(2) ==
(int) data::Datatype::categorical);
BOOST_REQUIRE_EQUAL(get<1>(*output).n_rows, 3);
BOOST_REQUIRE_EQUAL(get<1>(*output).n_cols, 7);
REQUIRE(get<1>(*output).n_rows == 3);
REQUIRE(get<1>(*output).n_cols == 7);
remove("test.csv");
}
BOOST_AUTO_TEST_CASE(GetParamModelTest)
TEST_CASE("GetParamModelTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -249,13 +247,13 @@ BOOST_AUTO_TEST_CASE(GetParamModelTest)
GetParam<GaussianKernel*>((util::ParamData&) d, (void*) NULL,
(void*) &output);
BOOST_REQUIRE_EQUAL((*output)->Bandwidth(), 5.0);
REQUIRE((*output)->Bandwidth() == 5.0);
remove("kernel.bin");
delete *output;
}
BOOST_AUTO_TEST_CASE(RawParamDoubleTest)
TEST_CASE("RawParamDoubleTest", "[CLIOptionTest]")
{
// This should function the same as GetParam for doubles.
util::ParamData d;
@@ -266,10 +264,10 @@ BOOST_AUTO_TEST_CASE(RawParamDoubleTest)
GetParam<double>((util::ParamData&) d, (const void*) NULL,
(void*) &output);
BOOST_REQUIRE_EQUAL(*output, 5.0);
REQUIRE(*output == 5.0);
}
BOOST_AUTO_TEST_CASE(RawParamMatTest)
TEST_CASE("RawParamMatTest", "[CLIOptionTest]")
{
// This should return the matrix as-is without loading.
util::ParamData d;
@@ -286,13 +284,13 @@ BOOST_AUTO_TEST_CASE(RawParamMatTest)
GetRawParam<arma::mat>((util::ParamData&) d, (void*) NULL,
(void*) &output);
BOOST_REQUIRE_EQUAL(output->n_rows, 5);
BOOST_REQUIRE_EQUAL(output->n_cols, 5);
REQUIRE(output->n_rows == 5);
REQUIRE(output->n_cols == 5);
for (size_t i = 0; i < 25; ++i)
BOOST_REQUIRE_EQUAL((*output)[i], 1.0);
REQUIRE((*output)[i] == 1.0);
}
BOOST_AUTO_TEST_CASE(GetRawParamModelTest)
TEST_CASE("GetRawParamModelTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -311,10 +309,10 @@ BOOST_AUTO_TEST_CASE(GetRawParamModelTest)
GetRawParam<tuple<GaussianKernel*, string>>((util::ParamData&) d,
(void*) NULL, (void*) &output);
BOOST_REQUIRE_EQUAL(get<0>(*output)->Bandwidth(), 5.0);
REQUIRE(get<0>(*output)->Bandwidth() == 5.0);
}
BOOST_AUTO_TEST_CASE(GetRawParamDatasetInfoTest)
TEST_CASE("GetRawParamDatasetInfoTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -339,13 +337,13 @@ BOOST_AUTO_TEST_CASE(GetRawParamDatasetInfoTest)
GetRawParam<tuple<data::DatasetInfo, arma::mat>>((util::ParamData&) d,
(void*) NULL, (void*) &output);
BOOST_REQUIRE_EQUAL(get<0>(*output).Dimensionality(), 3);
BOOST_REQUIRE_EQUAL(get<1>(*output).n_rows, 3);
BOOST_REQUIRE_EQUAL(get<1>(*output).n_cols, 3);
REQUIRE(get<0>(*output).Dimensionality() == 3);
REQUIRE(get<1>(*output).n_rows == 3);
REQUIRE(get<1>(*output).n_cols == 3);
}
// Check that we can successfully write a matrix to file.
BOOST_AUTO_TEST_CASE(OutputParamMatTest)
TEST_CASE("OutputParamMatTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -363,7 +361,7 @@ BOOST_AUTO_TEST_CASE(OutputParamMatTest)
(void*) NULL);
arma::mat m2;
BOOST_REQUIRE(data::Load("test.csv", m2));
REQUIRE(data::Load("test.csv", m2));
CheckMatrices(m, m2);
@@ -371,7 +369,7 @@ BOOST_AUTO_TEST_CASE(OutputParamMatTest)
}
// Check that we can successfully write an unsigned matrix to file.
BOOST_AUTO_TEST_CASE(OutputParamUmatTest)
TEST_CASE("OutputParamUmatTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -389,7 +387,7 @@ BOOST_AUTO_TEST_CASE(OutputParamUmatTest)
(void*) NULL);
arma::Mat<size_t> m2;
BOOST_REQUIRE(data::Load("test.csv", m2));
REQUIRE(data::Load("test.csv", m2));
CheckMatrices(m, m2);
@@ -397,7 +395,7 @@ BOOST_AUTO_TEST_CASE(OutputParamUmatTest)
}
// Check that we can successfully write a model to file.
BOOST_AUTO_TEST_CASE(OutputParamModelTest)
TEST_CASE("OutputParamModelTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -414,15 +412,15 @@ BOOST_AUTO_TEST_CASE(OutputParamModelTest)
(void*) NULL);
GaussianKernel gk2(1.0);
BOOST_REQUIRE(data::Load("kernel.bin", "model", gk2));
REQUIRE(data::Load("kernel.bin", "model", gk2));
BOOST_REQUIRE_EQUAL(gk.Bandwidth(), gk2.Bandwidth());
REQUIRE(gk.Bandwidth() == gk2.Bandwidth());
remove("kernel.bin");
}
// Test setting a primitive type parameter.
BOOST_AUTO_TEST_CASE(SetParamDoubleTest)
TEST_CASE("SetParamDoubleTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -440,11 +438,11 @@ BOOST_AUTO_TEST_CASE(SetParamDoubleTest)
GetParam<double>((util::ParamData&) d, (const void*) NULL,
(void*) &dd3);
BOOST_REQUIRE_EQUAL((*dd3), dd2);
REQUIRE((*dd3) == dd2);
}
// Test that setting a flag works.
BOOST_AUTO_TEST_CASE(SetParamBoolTest)
TEST_CASE("SetParamBoolTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -458,11 +456,11 @@ BOOST_AUTO_TEST_CASE(SetParamBoolTest)
boost::any a(b2);
SetParam<bool>((util::ParamData&) d, (const void*) &a, (void*) NULL);
BOOST_REQUIRE_EQUAL(boost::any_cast<bool>(d.value), true);
REQUIRE(boost::any_cast<bool>(d.value) == true);
}
// Test that calling SetParam on a matrix sets the string correctly.
BOOST_AUTO_TEST_CASE(SetParamMatrixTest)
TEST_CASE("SetParamMatrixTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -481,11 +479,11 @@ BOOST_AUTO_TEST_CASE(SetParamMatrixTest)
// Make sure the change went through.
tuple<arma::mat, string>& t =
*boost::any_cast<tuple<arma::mat, string>>(&d.value);
BOOST_REQUIRE_EQUAL(get<1>(t), "new.csv");
REQUIRE(get<1>(t) == "new.csv");
}
// Test that calling SetParam on a model sets the string correctly.
BOOST_AUTO_TEST_CASE(SetParamModelTest)
TEST_CASE("SetParamModelTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -505,12 +503,12 @@ BOOST_AUTO_TEST_CASE(SetParamModelTest)
tuple<GaussianKernel*, string>& t =
*boost::any_cast<tuple<GaussianKernel*, string>>(&d.value);
BOOST_REQUIRE_EQUAL(get<1>(t), "new_kernel.bin");
REQUIRE(get<1>(t) == "new_kernel.bin");
}
// Test that calling SetParam on a mat/DatasetInfo successfully sets the
// filename.
BOOST_AUTO_TEST_CASE(SetParamDatasetInfoMatTest)
TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -535,12 +533,12 @@ BOOST_AUTO_TEST_CASE(SetParamDatasetInfoMatTest)
tuple<tuple<DatasetInfo, arma::mat>, string>& t3 =
*boost::any_cast<tuple<tuple<DatasetInfo, arma::mat>, string>>(&d.value);
BOOST_REQUIRE_EQUAL(get<1>(t3), "new_filename.csv");
REQUIRE(get<1>(t3) == "new_filename.csv");
}
// Test that GetAllocatedMemory() will properly return NULL for a non-model
// type.
BOOST_AUTO_TEST_CASE(GetAllocatedMemoryNonModelTest)
TEST_CASE("GetAllocatedMemoryNonModelTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -553,7 +551,7 @@ BOOST_AUTO_TEST_CASE(GetAllocatedMemoryNonModelTest)
GetAllocatedMemory<bool>((util::ParamData&) d,
(const void*) NULL, (void*) &result);
BOOST_REQUIRE_EQUAL(result, (void*) NULL);
REQUIRE(result == (void*) NULL);
// Also test with a matrix type.
arma::mat test(10, 10, arma::fill::ones);
@@ -566,12 +564,12 @@ BOOST_AUTO_TEST_CASE(GetAllocatedMemoryNonModelTest)
GetAllocatedMemory<arma::mat>((util::ParamData&) d,
(const void*) NULL, (void*) &result);
BOOST_REQUIRE_EQUAL(result, (void*) NULL);
REQUIRE(result == (void*) NULL);
}
// Test that GetAllocatedMemory() will properly return pointers for a
// serializable model type.
BOOST_AUTO_TEST_CASE(GetAllocatedMemoryModelTest)
TEST_CASE("GetAllocatedMemoryModelTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -586,12 +584,12 @@ BOOST_AUTO_TEST_CASE(GetAllocatedMemoryModelTest)
GetAllocatedMemory<GaussianKernel*>((util::ParamData&) d,
(const void*) NULL, (void*) &result);
BOOST_REQUIRE_EQUAL(&g, (GaussianKernel*) result);
REQUIRE(&g == (GaussianKernel*) result);
}
// Test that calling DeleteAllocatedMemory() on non-model types does not delete
// pointers.
BOOST_AUTO_TEST_CASE(DeleteAllocatedMemoryNonModelTest)
TEST_CASE("DeleteAllocatedMemoryNonModelTest", "[CLIOptionTest]")
{
util::ParamData d;
@@ -613,7 +611,7 @@ BOOST_AUTO_TEST_CASE(DeleteAllocatedMemoryNonModelTest)
// Test that DeleteAllocatedMemory() will properly delete pointers for a
// serializable model type.
BOOST_AUTO_TEST_CASE(DeleteAllocatedMemoryModelTest)
TEST_CASE("DeleteAllocatedMemoryModelTest", "[CLIOptionTest]")
{
// This test will just delete it, and we'll hope that it worked and that
// valgrind won't throw any issues (so really we can't *quite* test this in
@@ -630,5 +628,3 @@ BOOST_AUTO_TEST_CASE(DeleteAllocatedMemoryModelTest)
DeleteAllocatedMemory<GaussianKernel*>((util::ParamData&) d,
(const void*) NULL, (void*) NULL);
}
BOOST_AUTO_TEST_SUITE_END();
+18 -24
View File
@@ -13,10 +13,8 @@
#include <mlpack/core.hpp>
#include <mlpack/core/tree/cosine_tree/cosine_tree.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
BOOST_AUTO_TEST_SUITE(CosineTreeTest);
#include "catch.hpp"
#include "test_catch_tools.hpp"
using namespace mlpack;
using namespace mlpack::tree;
@@ -25,7 +23,7 @@ using namespace mlpack::tree;
* Constructs a cosine tree with epsilon = 1. Checks if the root node is split
* further, as it shouldn't be.
*/
BOOST_AUTO_TEST_CASE(CosineTreeNoSplit)
TEST_CASE("CosineTreeNoSplit", "[CosineTreeTest]")
{
// Initialize constants required for the test.
const size_t numRows = 10;
@@ -44,14 +42,14 @@ BOOST_AUTO_TEST_CASE(CosineTreeNoSplit)
// Since epsilon is one, there should be no splitting and the only vector in
// the basis should come from the root node.
BOOST_REQUIRE_EQUAL(basis.n_cols, 1);
REQUIRE(basis.n_cols == 1);
}
/**
* Checks CosineTree::CosineNodeSplit() by doing a depth first search on a
* random dataset and checking if it satisfies the split condition.
*/
BOOST_AUTO_TEST_CASE(CosineNodeCosineSplit)
TEST_CASE("CosineNodeCosineSplit", "[CosineTreeTest]")
{
// Initialize constants required for the test.
const size_t numRows = 500;
@@ -96,7 +94,7 @@ BOOST_AUTO_TEST_CASE(CosineNodeCosineSplit)
rightIndices = currentRight->VectorIndices();
// The columns in the popped should be split into left and right nodes.
BOOST_REQUIRE_EQUAL(currentNode->NumColumns(), leftIndices.size() +
REQUIRE(currentNode->NumColumns() == leftIndices.size() +
rightIndices.size());
// Calculate the cosine values for each of the columns in the node.
@@ -125,12 +123,10 @@ BOOST_AUTO_TEST_CASE(CosineNodeCosineSplit)
{
// Check with some precision.
for (i = 0; i < leftIndices.size(); ++i)
BOOST_REQUIRE_LT(cosineMax - cosines(i),
cosines(i) - cosineMin + precision);
REQUIRE(cosineMax - cosines(i) < cosines(i) - cosineMin + precision);
for (j = 0, k = i; j < rightIndices.size(); ++j, ++k)
BOOST_REQUIRE_GT(cosineMax - cosines(k),
cosines(k) - cosineMin - precision);
REQUIRE(cosineMax - cosines(k) > cosines(k) - cosineMin - precision);
}
else
{
@@ -156,7 +152,7 @@ BOOST_AUTO_TEST_CASE(CosineNodeCosineSplit)
numMax2Errors++;
// One of the maximum cosine values should be correct
BOOST_REQUIRE_EQUAL(std::min(numMax1Errors, numMax2Errors), 0);
REQUIRE(std::min(numMax1Errors, numMax2Errors) == 0);
}
}
}
@@ -166,7 +162,7 @@ BOOST_AUTO_TEST_CASE(CosineNodeCosineSplit)
* Checks CosineTree::ModifiedGramSchmidt() by creating a random basis for the
* vector subspace and checking if all the vectors are orthogonal to each other.
*/
BOOST_AUTO_TEST_CASE(CosineTreeModifiedGramSchmidt)
TEST_CASE("CosineTreeModifiedGramSchmidt", "[CosineTreeTest]")
{
// Initialize constants required for the test.
const size_t numRows = 100;
@@ -201,8 +197,8 @@ BOOST_AUTO_TEST_CASE(CosineTreeModifiedGramSchmidt)
for (; j != basisQueue.end(); ++j)
{
currentNode = *j;
BOOST_REQUIRE_SMALL(arma::dot(currentNode->BasisVector(), newBasisVector),
1e-5);
REQUIRE(arma::dot(currentNode->BasisVector(), newBasisVector) ==
Approx(0.0).margin(1e-5));
}
// Add the obtained vector to the basis.
@@ -225,7 +221,7 @@ BOOST_AUTO_TEST_CASE(CosineTreeModifiedGramSchmidt)
/**
* Test the copy constructor & copy assignment using Cosine trees.
*/
BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorCosineTreeTest)
TEST_CASE("CopyConstructorAndOperatorCosineTreeTest", "[CosineTreeTest]")
{
// Initialize constants required for the test.
const size_t numRows = 10;
@@ -318,15 +314,15 @@ BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorCosineTreeTest)
for (size_t i = 0; i < v1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(v1.at(i), v2.at(i));
BOOST_REQUIRE_EQUAL(v1.at(i), v3.at(i));
REQUIRE(v1.at(i) == v2.at(i));
REQUIRE(v1.at(i) == v3.at(i));
}
}
/**
* Test the move constructor & move assignment using Cosine trees.
*/
BOOST_AUTO_TEST_CASE(MoveConstructorAndOperatorCosineTreeTest)
TEST_CASE("MoveConstructorAndOperatorCosineTreeTest", "[CosineTreeTest]")
{
// Initialize constants required for the test.
const size_t numRows = 10;
@@ -431,9 +427,7 @@ BOOST_AUTO_TEST_CASE(MoveConstructorAndOperatorCosineTreeTest)
for (size_t i = 0; i < v1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(v1.at(i), v2.at(i));
BOOST_REQUIRE_EQUAL(v1.at(i), v3.at(i));
REQUIRE(v1.at(i) == v2.at(i));
REQUIRE(v1.at(i) == v3.at(i));
}
}
BOOST_AUTO_TEST_SUITE_END();
+236 -233
View File
@@ -11,8 +11,7 @@
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#include <mlpack/core.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
// This trick does not work on Windows. We will have to comment out the tests
// that depend on it.
@@ -33,13 +32,11 @@ using namespace mlpack;
using namespace mlpack::det;
using namespace std;
BOOST_AUTO_TEST_SUITE(DETTest);
// Tests for the private functions. We cannot perform these if we are on
// Windows because we cannot make private functions accessible using the macro
// trick above.
#ifndef _WIN32
BOOST_AUTO_TEST_CASE(TestGetMaxMinVals)
TEST_CASE("TestGetMaxMinVals", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -49,15 +46,15 @@ BOOST_AUTO_TEST_CASE(TestGetMaxMinVals)
DTree<arma::mat> tree(testData);
BOOST_REQUIRE_EQUAL(tree.MaxVals()[0], 7);
BOOST_REQUIRE_EQUAL(tree.MinVals()[0], 3);
BOOST_REQUIRE_EQUAL(tree.MaxVals()[1], 7);
BOOST_REQUIRE_EQUAL(tree.MinVals()[1], 0);
BOOST_REQUIRE_EQUAL(tree.MaxVals()[2], 8);
BOOST_REQUIRE_EQUAL(tree.MinVals()[2], 1);
REQUIRE(tree.MaxVals()[0] == 7);
REQUIRE(tree.MinVals()[0] == 3);
REQUIRE(tree.MaxVals()[1] == 7);
REQUIRE(tree.MinVals()[1] == 0);
REQUIRE(tree.MaxVals()[2] == 8);
REQUIRE(tree.MinVals()[2] == 1);
}
BOOST_AUTO_TEST_CASE(TestComputeNodeError)
TEST_CASE("TestComputeNodeError", "[DETTest]")
{
arma::vec maxVals("7 7 8");
arma::vec minVals("3 0 1");
@@ -65,17 +62,18 @@ BOOST_AUTO_TEST_CASE(TestComputeNodeError)
DTree<arma::mat> testDTree(maxVals, minVals, 5);
double trueNodeError = -log(4.0) - log(7.0) - log(7.0);
BOOST_REQUIRE_CLOSE((double) testDTree.logNegError, trueNodeError, 1e-10);
REQUIRE((double) testDTree.logNegError ==
Approx(trueNodeError).epsilon(1e-12));
testDTree.start = 3;
testDTree.end = 5;
double nodeError = testDTree.LogNegativeError(5);
trueNodeError = 2 * log(2.0 / 5.0) - log(4.0) - log(7.0) - log(7.0);
BOOST_REQUIRE_CLOSE(nodeError, trueNodeError, 1e-10);
REQUIRE(nodeError == Approx(trueNodeError).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestWithinRange)
TEST_CASE("TestWithinRange", "[DETTest]")
{
arma::vec maxVals("7 7 8");
arma::vec minVals("3 0 1");
@@ -85,14 +83,14 @@ BOOST_AUTO_TEST_CASE(TestWithinRange)
arma::vec testQuery(3);
testQuery << 4.5 << 2.5 << 2;
BOOST_REQUIRE_EQUAL(testDTree.WithinRange(testQuery), true);
REQUIRE(testDTree.WithinRange(testQuery) == true);
testQuery << 8.5 << 2.5 << 2;
BOOST_REQUIRE_EQUAL(testDTree.WithinRange(testQuery), false);
REQUIRE(testDTree.WithinRange(testQuery) == false);
}
BOOST_AUTO_TEST_CASE(TestFindSplit)
TEST_CASE("TestFindSplit", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -108,20 +106,21 @@ BOOST_AUTO_TEST_CASE(TestFindSplit)
size_t trueDim = 2;
double trueSplit = 5.5;
double trueLeftError = 2 * log(2.0 / 5.0) - (log(7.0) + log(4.0) + log(4.5));
double trueRightError = 2 * log(3.0 / 5.0) - (log(7.0) + log(4.0) + log(2.5));
double trueRightError = 2 * log(3.0 / 5.0) - (log(7.0) + log(4.0) +
log(2.5));
testDTree.logVolume = log(7.0) + log(4.0) + log(7.0);
BOOST_REQUIRE(testDTree.FindSplit(
REQUIRE(testDTree.FindSplit(
testData, obDim, obSplit, obLeftError, obRightError, 1));
BOOST_REQUIRE(trueDim == obDim);
BOOST_REQUIRE_CLOSE(trueSplit, obSplit, 1e-10);
REQUIRE(trueDim == obDim);
REQUIRE(trueSplit == Approx(obSplit).epsilon(1e-12));
BOOST_REQUIRE_CLOSE(trueLeftError, obLeftError, 1e-10);
BOOST_REQUIRE_CLOSE(trueRightError, obRightError, 1e-10);
REQUIRE(trueLeftError == Approx(obLeftError).epsilon(1e-12));
REQUIRE(trueRightError == Approx(obRightError).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestSplitData)
TEST_CASE("TestSplitData", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -140,16 +139,16 @@ BOOST_AUTO_TEST_CASE(TestSplitData)
size_t splitInd = testDTree.SplitData(
testData, splitDim, trueSplitVal, oTest);
BOOST_REQUIRE_EQUAL(splitInd, 2); // 2 points on left side.
REQUIRE(splitInd == 2); // 2 points on left side.
BOOST_REQUIRE_EQUAL(oTest[0], 1);
BOOST_REQUIRE_EQUAL(oTest[1], 4);
BOOST_REQUIRE_EQUAL(oTest[2], 3);
BOOST_REQUIRE_EQUAL(oTest[3], 2);
BOOST_REQUIRE_EQUAL(oTest[4], 5);
REQUIRE(oTest[0] == 1);
REQUIRE(oTest[1] == 4);
REQUIRE(oTest[2] == 3);
REQUIRE(oTest[3] == 2);
REQUIRE(oTest[4] == 5);
}
BOOST_AUTO_TEST_CASE(TestSparseFindSplit)
TEST_CASE("TestSparseFindSplit", "[DETTest]")
{
arma::mat realData(4, 7);
@@ -173,17 +172,17 @@ BOOST_AUTO_TEST_CASE(TestSparseFindSplit)
(log(7.0) + log(6.5) + log(8.0) + log(6.0));
testDTree.logVolume = log(7.0) + log(7.0) + log(8.0) + log(6.0);
BOOST_REQUIRE(testDTree.FindSplit(
REQUIRE(testDTree.FindSplit(
testData, obDim, obSplit, obLeftError, obRightError, 1));
BOOST_REQUIRE(trueDim == obDim);
BOOST_REQUIRE_CLOSE(trueSplit, obSplit, 1e-10);
REQUIRE(trueDim == obDim);
REQUIRE(trueSplit == Approx(obSplit).epsilon(1e-12));
BOOST_REQUIRE_CLOSE(trueLeftError, obLeftError, 1e-10);
BOOST_REQUIRE_CLOSE(trueRightError, obRightError, 1e-10);
REQUIRE(trueLeftError == Approx(obLeftError).epsilon(1e-12));
REQUIRE(trueRightError == Approx(obRightError).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestSparseSplitData)
TEST_CASE("TestSparseSplitData", "[DETTest]")
{
arma::mat realData(4, 7);
@@ -205,22 +204,22 @@ BOOST_AUTO_TEST_CASE(TestSparseSplitData)
size_t splitInd = testDTree.SplitData(
testData, splitDim, trueSplitVal, oTest);
BOOST_REQUIRE_EQUAL(splitInd, 3); // 2 points on left side.
REQUIRE(splitInd == 3); // 2 points on left side.
BOOST_REQUIRE_EQUAL(oTest[0], 1);
BOOST_REQUIRE_EQUAL(oTest[1], 4);
BOOST_REQUIRE_EQUAL(oTest[2], 3);
BOOST_REQUIRE_EQUAL(oTest[3], 2);
BOOST_REQUIRE_EQUAL(oTest[4], 5);
BOOST_REQUIRE_EQUAL(oTest[5], 6);
BOOST_REQUIRE_EQUAL(oTest[6], 7);
REQUIRE(oTest[0] == 1);
REQUIRE(oTest[1] == 4);
REQUIRE(oTest[2] == 3);
REQUIRE(oTest[3] == 2);
REQUIRE(oTest[4] == 5);
REQUIRE(oTest[5] == 6);
REQUIRE(oTest[6] == 7);
}
#endif
// Tests for the public functions.
BOOST_AUTO_TEST_CASE(TestGrow)
TEST_CASE("TestGrow", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -244,34 +243,36 @@ BOOST_AUTO_TEST_CASE(TestGrow)
DTree<arma::mat> testDTree(testData);
double alpha = testDTree.Grow(testData, oTest, false, 2, 1);
BOOST_REQUIRE_EQUAL(oTest[0], 0);
BOOST_REQUIRE_EQUAL(oTest[1], 3);
BOOST_REQUIRE_EQUAL(oTest[2], 1);
BOOST_REQUIRE_EQUAL(oTest[3], 2);
BOOST_REQUIRE_EQUAL(oTest[4], 4);
REQUIRE(oTest[0] == 0);
REQUIRE(oTest[1] == 3);
REQUIRE(oTest[2] == 1);
REQUIRE(oTest[3] == 2);
REQUIRE(oTest[4] == 4);
// Test the structure of the tree.
BOOST_REQUIRE(testDTree.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree.Right()->Right()->Right() == NULL);
REQUIRE(testDTree.Left()->Left() == NULL);
REQUIRE(testDTree.Left()->Right() == NULL);
REQUIRE(testDTree.Right()->Left()->Left() == NULL);
REQUIRE(testDTree.Right()->Left()->Right() == NULL);
REQUIRE(testDTree.Right()->Right()->Left() == NULL);
REQUIRE(testDTree.Right()->Right()->Right() == NULL);
BOOST_REQUIRE(testDTree.SubtreeLeaves() == 3);
REQUIRE(testDTree.SubtreeLeaves() == 3);
BOOST_REQUIRE(testDTree.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree.SplitDim() == 2);
REQUIRE(testDTree.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree.Right()->SplitDim() == 1);
REQUIRE(testDTree.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
// Test node errors for every node (these are private functions).
#ifndef _WIN32
BOOST_REQUIRE_CLOSE(testDTree.logNegError, rootError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.Left()->logNegError, lError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.Right()->logNegError, rError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.Right()->Left()->logNegError, rlError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.Right()->Right()->logNegError, rrError, 1e-10);
REQUIRE(testDTree.logNegError == Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.Left()->logNegError == Approx(lError).epsilon(1e-12));
REQUIRE(testDTree.Right()->logNegError == Approx(rError).epsilon(1e-12));
REQUIRE(testDTree.Right()->Left()->logNegError ==
Approx(rlError).epsilon(1e-12));
REQUIRE(testDTree.Right()->Right()->logNegError ==
Approx(rrError).epsilon(1e-12));
#endif
// Test alpha.
@@ -281,10 +282,10 @@ BOOST_AUTO_TEST_CASE(TestGrow)
rAlpha = std::log(-(std::exp(rError) - (std::exp(rlError) +
std::exp(rrError))));
BOOST_REQUIRE_CLOSE(alpha, min(rootAlpha, rAlpha), 1e-10);
REQUIRE(alpha == Approx(min(rootAlpha, rAlpha)).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestPruneAndUpdate)
TEST_CASE("TestPruneAndUpdate", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -298,18 +299,19 @@ BOOST_AUTO_TEST_CASE(TestPruneAndUpdate)
double alpha = testDTree.Grow(testData, oTest, false, 2, 1);
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
BOOST_REQUIRE_CLOSE(alpha, numeric_limits<double>::max(), 1e-10);
BOOST_REQUIRE(testDTree.SubtreeLeaves() == 1);
REQUIRE(alpha == Approx(numeric_limits<double>::max()).epsilon(1e-12));
REQUIRE(testDTree.SubtreeLeaves() == 1);
double rootError = -log(4.0) - log(7.0) - log(7.0);
BOOST_REQUIRE_CLOSE(testDTree.LogNegError(), rootError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.SubtreeLeavesLogNegError(), rootError, 1e-10);
BOOST_REQUIRE(testDTree.Left() == NULL);
BOOST_REQUIRE(testDTree.Right() == NULL);
REQUIRE(testDTree.LogNegError() == Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.SubtreeLeavesLogNegError() ==
Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.Left() == NULL);
REQUIRE(testDTree.Right() == NULL);
}
BOOST_AUTO_TEST_CASE(TestComputeValue)
TEST_CASE("TestComputeValue", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -334,22 +336,22 @@ BOOST_AUTO_TEST_CASE(TestComputeValue)
double d2 = (1.0 / 5.0) / exp(log(4.0) + log(0.5) + log(2.5));
double d3 = (2.0 / 5.0) / exp(log(4.0) + log(6.5) + log(2.5));
BOOST_REQUIRE_CLOSE(d1, testDTree.ComputeValue(q1), 1e-10);
BOOST_REQUIRE_CLOSE(d2, testDTree.ComputeValue(q2), 1e-10);
BOOST_REQUIRE_CLOSE(d3, testDTree.ComputeValue(q3), 1e-10);
BOOST_REQUIRE_CLOSE(0.0, testDTree.ComputeValue(q4), 1e-10);
REQUIRE(d1 == Approx(testDTree.ComputeValue(q1)).epsilon(1e-12));
REQUIRE(d2 == Approx(testDTree.ComputeValue(q2)).epsilon(1e-12));
REQUIRE(d3 == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
double d = 1.0 / exp(log(4.0) + log(7.0) + log(7.0));
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q1), 1e-10);
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q2), 1e-10);
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q3), 1e-10);
BOOST_REQUIRE_CLOSE(0.0, testDTree.ComputeValue(q4), 1e-10);
REQUIRE(d == Approx(testDTree.ComputeValue(q1)).epsilon(1e-12));
REQUIRE(d == Approx(testDTree.ComputeValue(q2)).epsilon(1e-12));
REQUIRE(d == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestVariableImportance)
TEST_CASE("TestVariableImportance", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -377,12 +379,14 @@ BOOST_AUTO_TEST_CASE(TestVariableImportance)
testDTree.ComputeVariableImportance(imps);
BOOST_REQUIRE_CLOSE((double) 0.0, imps[0], 1e-10);
BOOST_REQUIRE_CLOSE((double) (rError - (rlError + rrError)), imps[1], 1e-10);
BOOST_REQUIRE_CLOSE((double) (rootError - (lError + rError)), imps[2], 1e-10);
REQUIRE((double) 0.0 == Approx(imps[0]).epsilon(1e-12));
REQUIRE((double) (rError - (rlError + rrError)) ==
Approx(imps[1]).epsilon(1e-12));
REQUIRE((double) (rootError - (lError + rError)) ==
Approx(imps[2]).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(TestSparsePruneAndUpdate)
TEST_CASE("TestSparsePruneAndUpdate", "[DETTest]")
{
arma::mat realData(3, 5);
@@ -399,18 +403,19 @@ BOOST_AUTO_TEST_CASE(TestSparsePruneAndUpdate)
double alpha = testDTree.Grow(testData, oTest, false, 2, 1);
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
BOOST_REQUIRE_CLOSE(alpha, numeric_limits<double>::max(), 1e-10);
BOOST_REQUIRE(testDTree.SubtreeLeaves() == 1);
REQUIRE(alpha == Approx(numeric_limits<double>::max()).epsilon(1e-12));
REQUIRE(testDTree.SubtreeLeaves() == 1);
double rootError = -log(4.0) - log(7.0) - log(7.0);
BOOST_REQUIRE_CLOSE(testDTree.LogNegError(), rootError, 1e-10);
BOOST_REQUIRE_CLOSE(testDTree.SubtreeLeavesLogNegError(), rootError, 1e-10);
BOOST_REQUIRE(testDTree.Left() == NULL);
BOOST_REQUIRE(testDTree.Right() == NULL);
REQUIRE(testDTree.LogNegError() == Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.SubtreeLeavesLogNegError() ==
Approx(rootError).epsilon(1e-12));
REQUIRE(testDTree.Left() == NULL);
REQUIRE(testDTree.Right() == NULL);
}
BOOST_AUTO_TEST_CASE(TestSparseComputeValue)
TEST_CASE("TestSparseComputeValue", "[DETTest]")
{
arma::mat realData(3, 5);
@@ -438,25 +443,25 @@ BOOST_AUTO_TEST_CASE(TestSparseComputeValue)
double d2 = (1.0 / 5.0) / exp(log(4.0) + log(0.5) + log(2.5));
double d3 = (2.0 / 5.0) / exp(log(4.0) + log(6.5) + log(2.5));
BOOST_REQUIRE_CLOSE(d1, testDTree.ComputeValue(q1), 1e-10);
BOOST_REQUIRE_CLOSE(d2, testDTree.ComputeValue(q2), 1e-10);
BOOST_REQUIRE_CLOSE(d3, testDTree.ComputeValue(q3), 1e-10);
BOOST_REQUIRE_CLOSE(0.0, testDTree.ComputeValue(q4), 1e-10);
REQUIRE(d1 == Approx(testDTree.ComputeValue(q1)).epsilon(1e-12));
REQUIRE(d2 == Approx(testDTree.ComputeValue(q2)).epsilon(1e-12));
REQUIRE(d3 == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
double d = 1.0 / exp(log(4.0) + log(7.0) + log(7.0));
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q1), 1e-10);
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q2), 1e-10);
BOOST_REQUIRE_CLOSE(d, testDTree.ComputeValue(q3), 1e-10);
BOOST_REQUIRE_CLOSE(0.0, testDTree.ComputeValue(q4), 1e-10);
REQUIRE(d == Approx(testDTree.ComputeValue(q1)).epsilon(1e-12));
REQUIRE(d == Approx(testDTree.ComputeValue(q2)).epsilon(1e-12));
REQUIRE(d == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
}
/**
* These are not yet implemented.
*
BOOST_AUTO_TEST_CASE(TestTagTree)
TEST_CASE("TestTagTree", "[DETTest]")
{
MatType testData(3, 5);
@@ -469,7 +474,7 @@ BOOST_AUTO_TEST_CASE(TestTagTree)
delete testDTree;
}
BOOST_AUTO_TEST_CASE(TestFindBucket)
TEST_CASE("TestFindBucket", "[DETTest]")
{
MatType testData(3, 5);
@@ -484,24 +489,24 @@ BOOST_AUTO_TEST_CASE(TestFindBucket)
// Test functions in dt_utils.hpp
BOOST_AUTO_TEST_CASE(TestTrainer)
TEST_CASE("TestTrainer", "[DETTest]")
{
}
BOOST_AUTO_TEST_CASE(TestPrintVariableImportance)
TEST_CASE("TestPrintVariableImportance", "[DETTest]")
{
}
BOOST_AUTO_TEST_CASE(TestPrintLeafMembership)
TEST_CASE("TestPrintLeafMembership", "[DETTest]")
{
}
*/
// Test the copy constructor and the copy operator.
BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorTest)
TEST_CASE("CopyConstructorAndOperatorTest", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -544,76 +549,76 @@ BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorTest)
delete testDTree;
// Test the data of copied tree (using copy constructor).
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[0], maxVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[0], minVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[1], maxVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[1], minVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[2], maxVals2);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[2], minVals2);
REQUIRE(testDTree2.MaxVals()[0] == maxVals0);
REQUIRE(testDTree2.MinVals()[0] == minVals0);
REQUIRE(testDTree2.MaxVals()[1] == maxVals1);
REQUIRE(testDTree2.MinVals()[1] == minVals1);
REQUIRE(testDTree2.MaxVals()[2] == maxVals2);
REQUIRE(testDTree2.MinVals()[2] == minVals2);
// Test the data of the copied tree (using the copy operator).
BOOST_REQUIRE_EQUAL(testDTree3.MaxVals()[0], maxVals0);
BOOST_REQUIRE_EQUAL(testDTree3.MinVals()[0], minVals0);
BOOST_REQUIRE_EQUAL(testDTree3.MaxVals()[1], maxVals1);
BOOST_REQUIRE_EQUAL(testDTree3.MinVals()[1], minVals1);
BOOST_REQUIRE_EQUAL(testDTree3.MaxVals()[2], maxVals2);
BOOST_REQUIRE_EQUAL(testDTree3.MinVals()[2], minVals2);
REQUIRE(testDTree3.MaxVals()[0] == maxVals0);
REQUIRE(testDTree3.MinVals()[0] == minVals0);
REQUIRE(testDTree3.MaxVals()[1] == maxVals1);
REQUIRE(testDTree3.MinVals()[1] == minVals1);
REQUIRE(testDTree3.MaxVals()[2] == maxVals2);
REQUIRE(testDTree3.MinVals()[2] == minVals2);
// Test the structure of the tree copied using the copy constructor.
BOOST_REQUIRE(testDTree2.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
REQUIRE(testDTree2.Left()->Left() == NULL);
REQUIRE(testDTree2.Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
// Test the structure of the tree copied using the copy operator.
BOOST_REQUIRE(testDTree3.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree3.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree3.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree3.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree3.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree3.Right()->Right()->Right() == NULL);
REQUIRE(testDTree3.Left()->Left() == NULL);
REQUIRE(testDTree3.Left()->Right() == NULL);
REQUIRE(testDTree3.Right()->Left()->Left() == NULL);
REQUIRE(testDTree3.Right()->Left()->Right() == NULL);
REQUIRE(testDTree3.Right()->Right()->Left() == NULL);
REQUIRE(testDTree3.Right()->Right()->Right() == NULL);
// Test the data of the tree copied using the copy constructor.
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[0], maxValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[1], maxValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[2], maxValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[0], minValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[1], minValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[2], minValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[0], maxValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[1], maxValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[2], maxValsR2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[0], minValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[1], minValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[2], minValsR2);
BOOST_REQUIRE(testDTree2.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree2.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree2.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree2.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree2.Left()->MaxVals()[0] == maxValsL0);
REQUIRE(testDTree2.Left()->MaxVals()[1] == maxValsL1);
REQUIRE(testDTree2.Left()->MaxVals()[2] == maxValsL2);
REQUIRE(testDTree2.Left()->MinVals()[0] == minValsL0);
REQUIRE(testDTree2.Left()->MinVals()[1] == minValsL1);
REQUIRE(testDTree2.Left()->MinVals()[2] == minValsL2);
REQUIRE(testDTree2.Right()->MaxVals()[0] == maxValsR0);
REQUIRE(testDTree2.Right()->MaxVals()[1] == maxValsR1);
REQUIRE(testDTree2.Right()->MaxVals()[2] == maxValsR2);
REQUIRE(testDTree2.Right()->MinVals()[0] == minValsR0);
REQUIRE(testDTree2.Right()->MinVals()[1] == minValsR1);
REQUIRE(testDTree2.Right()->MinVals()[2] == minValsR2);
REQUIRE(testDTree2.SplitDim() == 2);
REQUIRE(testDTree2.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree2.Right()->SplitDim() == 1);
REQUIRE(testDTree2.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
// Test the data of the tree copied using the copy operator.
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MaxVals()[0], maxValsL0);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MaxVals()[1], maxValsL1);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MaxVals()[2], maxValsL2);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MinVals()[0], minValsL0);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MinVals()[1], minValsL1);
BOOST_REQUIRE_EQUAL(testDTree3.Left()->MinVals()[2], minValsL2);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MaxVals()[0], maxValsR0);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MaxVals()[1], maxValsR1);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MaxVals()[2], maxValsR2);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MinVals()[0], minValsR0);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MinVals()[1], minValsR1);
BOOST_REQUIRE_EQUAL(testDTree3.Right()->MinVals()[2], minValsR2);
BOOST_REQUIRE(testDTree3.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree3.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree3.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree3.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree3.Left()->MaxVals()[0] == maxValsL0);
REQUIRE(testDTree3.Left()->MaxVals()[1] == maxValsL1);
REQUIRE(testDTree3.Left()->MaxVals()[2] == maxValsL2);
REQUIRE(testDTree3.Left()->MinVals()[0] == minValsL0);
REQUIRE(testDTree3.Left()->MinVals()[1] == minValsL1);
REQUIRE(testDTree3.Left()->MinVals()[2] == minValsL2);
REQUIRE(testDTree3.Right()->MaxVals()[0] == maxValsR0);
REQUIRE(testDTree3.Right()->MaxVals()[1] == maxValsR1);
REQUIRE(testDTree3.Right()->MaxVals()[2] == maxValsR2);
REQUIRE(testDTree3.Right()->MinVals()[0] == minValsR0);
REQUIRE(testDTree3.Right()->MinVals()[1] == minValsR1);
REQUIRE(testDTree3.Right()->MinVals()[2] == minValsR2);
REQUIRE(testDTree3.SplitDim() == 2);
REQUIRE(testDTree3.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree3.Right()->SplitDim() == 1);
REQUIRE(testDTree3.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
}
// Test the move constructor.
BOOST_AUTO_TEST_CASE(MoveConstructorTest)
TEST_CASE("MoveConstructorTest", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -653,50 +658,50 @@ BOOST_AUTO_TEST_CASE(MoveConstructorTest)
DTree<arma::mat> testDTree2(std::move(*testDTree));
// Check default values of the original tree.
BOOST_REQUIRE_EQUAL(testDTree->LogNegError(), -DBL_MAX);
BOOST_REQUIRE(testDTree->Left() == (DTree<arma::mat>*) NULL);
BOOST_REQUIRE(testDTree->Right() == (DTree<arma::mat>*) NULL);
REQUIRE(testDTree->LogNegError() == -DBL_MAX);
REQUIRE(testDTree->Left() == (DTree<arma::mat>*) NULL);
REQUIRE(testDTree->Right() == (DTree<arma::mat>*) NULL);
// Delete the original tree.
delete testDTree;
// Test the data of the moved tree.
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[0], maxVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[0], minVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[1], maxVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[1], minVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[2], maxVals2);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[2], minVals2);
REQUIRE(testDTree2.MaxVals()[0] == maxVals0);
REQUIRE(testDTree2.MinVals()[0] == minVals0);
REQUIRE(testDTree2.MaxVals()[1] == maxVals1);
REQUIRE(testDTree2.MinVals()[1] == minVals1);
REQUIRE(testDTree2.MaxVals()[2] == maxVals2);
REQUIRE(testDTree2.MinVals()[2] == minVals2);
// Test the structure of the moved tree.
BOOST_REQUIRE(testDTree2.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
REQUIRE(testDTree2.Left()->Left() == NULL);
REQUIRE(testDTree2.Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
// Test the data of the moved tree.
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[0], maxValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[1], maxValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[2], maxValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[0], minValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[1], minValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[2], minValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[0], maxValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[1], maxValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[2], maxValsR2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[0], minValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[1], minValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[2], minValsR2);
BOOST_REQUIRE(testDTree2.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree2.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree2.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree2.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree2.Left()->MaxVals()[0] == maxValsL0);
REQUIRE(testDTree2.Left()->MaxVals()[1] == maxValsL1);
REQUIRE(testDTree2.Left()->MaxVals()[2] == maxValsL2);
REQUIRE(testDTree2.Left()->MinVals()[0] == minValsL0);
REQUIRE(testDTree2.Left()->MinVals()[1] == minValsL1);
REQUIRE(testDTree2.Left()->MinVals()[2] == minValsL2);
REQUIRE(testDTree2.Right()->MaxVals()[0] == maxValsR0);
REQUIRE(testDTree2.Right()->MaxVals()[1] == maxValsR1);
REQUIRE(testDTree2.Right()->MaxVals()[2] == maxValsR2);
REQUIRE(testDTree2.Right()->MinVals()[0] == minValsR0);
REQUIRE(testDTree2.Right()->MinVals()[1] == minValsR1);
REQUIRE(testDTree2.Right()->MinVals()[2] == minValsR2);
REQUIRE(testDTree2.SplitDim() == 2);
REQUIRE(testDTree2.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree2.Right()->SplitDim() == 1);
REQUIRE(testDTree2.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
}
// Test the move operator.
BOOST_AUTO_TEST_CASE(MoveOperatorTest)
TEST_CASE("MoveOperatorTest", "[DETTest]")
{
arma::mat testData(3, 5);
@@ -736,46 +741,44 @@ BOOST_AUTO_TEST_CASE(MoveOperatorTest)
DTree<arma::mat> testDTree2 = std::move(*testDTree);
// Check default values of the original tree.
BOOST_REQUIRE_EQUAL(testDTree->LogNegError(), -DBL_MAX);
BOOST_REQUIRE(testDTree->Left() == (DTree<arma::mat>*) NULL);
BOOST_REQUIRE(testDTree->Right() == (DTree<arma::mat>*) NULL);
REQUIRE(testDTree->LogNegError() == -DBL_MAX);
REQUIRE(testDTree->Left() == (DTree<arma::mat>*) NULL);
REQUIRE(testDTree->Right() == (DTree<arma::mat>*) NULL);
// Delete the original tree.
delete testDTree;
// Test the data of the moved tree.
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[0], maxVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[0], minVals0);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[1], maxVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[1], minVals1);
BOOST_REQUIRE_EQUAL(testDTree2.MaxVals()[2], maxVals2);
BOOST_REQUIRE_EQUAL(testDTree2.MinVals()[2], minVals2);
REQUIRE(testDTree2.MaxVals()[0] == maxVals0);
REQUIRE(testDTree2.MinVals()[0] == minVals0);
REQUIRE(testDTree2.MaxVals()[1] == maxVals1);
REQUIRE(testDTree2.MinVals()[1] == minVals1);
REQUIRE(testDTree2.MaxVals()[2] == maxVals2);
REQUIRE(testDTree2.MinVals()[2] == minVals2);
// Test the structure of the moved tree.
BOOST_REQUIRE(testDTree2.Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
BOOST_REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
REQUIRE(testDTree2.Left()->Left() == NULL);
REQUIRE(testDTree2.Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Left()->Left() == NULL);
REQUIRE(testDTree2.Right()->Left()->Right() == NULL);
REQUIRE(testDTree2.Right()->Right()->Left() == NULL);
REQUIRE(testDTree2.Right()->Right()->Right() == NULL);
// Test the data of moved tree.
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[0], maxValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[1], maxValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MaxVals()[2], maxValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[0], minValsL0);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[1], minValsL1);
BOOST_REQUIRE_EQUAL(testDTree2.Left()->MinVals()[2], minValsL2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[0], maxValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[1], maxValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MaxVals()[2], maxValsR2);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[0], minValsR0);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[1], minValsR1);
BOOST_REQUIRE_EQUAL(testDTree2.Right()->MinVals()[2], minValsR2);
BOOST_REQUIRE(testDTree2.SplitDim() == 2);
BOOST_REQUIRE_CLOSE(testDTree2.SplitValue(), 5.5, 1e-5);
BOOST_REQUIRE(testDTree2.Right()->SplitDim() == 1);
BOOST_REQUIRE_CLOSE(testDTree2.Right()->SplitValue(), 0.5, 1e-5);
REQUIRE(testDTree2.Left()->MaxVals()[0] == maxValsL0);
REQUIRE(testDTree2.Left()->MaxVals()[1] == maxValsL1);
REQUIRE(testDTree2.Left()->MaxVals()[2] == maxValsL2);
REQUIRE(testDTree2.Left()->MinVals()[0] == minValsL0);
REQUIRE(testDTree2.Left()->MinVals()[1] == minValsL1);
REQUIRE(testDTree2.Left()->MinVals()[2] == minValsL2);
REQUIRE(testDTree2.Right()->MaxVals()[0] == maxValsR0);
REQUIRE(testDTree2.Right()->MaxVals()[1] == maxValsR1);
REQUIRE(testDTree2.Right()->MaxVals()[2] == maxValsR2);
REQUIRE(testDTree2.Right()->MinVals()[0] == minValsR0);
REQUIRE(testDTree2.Right()->MinVals()[1] == minValsR1);
REQUIRE(testDTree2.Right()->MinVals()[2] == minValsR2);
REQUIRE(testDTree2.SplitDim() == 2);
REQUIRE(testDTree2.SplitValue() == Approx(5.5).epsilon(1e-7));
REQUIRE(testDTree2.Right()->SplitDim() == 1);
REQUIRE(testDTree2.Right()->SplitValue() == Approx(0.5).epsilon(1e-7));
}
BOOST_AUTO_TEST_SUITE_END();
File diff suppressed because it is too large Load Diff
+162 -161
View File
@@ -17,9 +17,9 @@
#include <mlpack/methods/hoeffding_trees/binary_numeric_split.hpp>
#include <mlpack/methods/hoeffding_trees/hoeffding_tree_model.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "serialization.hpp"
#include "catch.hpp"
#include "test_catch_tools.hpp"
#include "serialization_catch.hpp"
#include <stack>
@@ -30,9 +30,7 @@ using namespace mlpack::math;
using namespace mlpack::data;
using namespace mlpack::tree;
BOOST_AUTO_TEST_SUITE(HoeffdingTreeTest);
BOOST_AUTO_TEST_CASE(GiniImpurityPerfectSimpleTest)
TEST_CASE("GiniImpurityPerfectSimpleTest", "[HoeffdingTreeTest]")
{
// Make a simple test for Gini impurity with one class. In this case it
// should always be 0. We'll assemble the count matrix by hand.
@@ -44,10 +42,10 @@ BOOST_AUTO_TEST_CASE(GiniImpurityPerfectSimpleTest)
counts(1, 1) = 0; // 0 points in category 1 with class 1.
// Since the split gets us nothing, there should be no gain.
BOOST_REQUIRE_SMALL(GiniImpurity::Evaluate(counts), 1e-10);
REQUIRE(GiniImpurity::Evaluate(counts) == Approx(0.0).margin(1e-10));
}
BOOST_AUTO_TEST_CASE(GiniImpurityImperfectSimpleTest)
TEST_CASE("GiniImpurityImperfectSimpleTest", "[HoeffdingTreeTest]")
{
// Make a simple test where a split will give us perfect classification.
arma::Mat<size_t> counts(2, 2); // 2 categories, 2 classes.
@@ -60,10 +58,10 @@ BOOST_AUTO_TEST_CASE(GiniImpurityImperfectSimpleTest)
// The impurity before the split should be 0.5^2 + 0.5^2 = 0.5.
// The impurity after the split should be 0.
// So the gain should be 0.5.
BOOST_REQUIRE_CLOSE(GiniImpurity::Evaluate(counts), 0.5, 1e-5);
REQUIRE(GiniImpurity::Evaluate(counts) == Approx(0.5).epsilon(1e-7));
}
BOOST_AUTO_TEST_CASE(GiniImpurityBadSplitTest)
TEST_CASE("GiniImpurityBadSplitTest", "[HoeffdingTreeTest]")
{
// Make a simple test where a split gets us nothing.
arma::Mat<size_t> counts(2, 2);
@@ -72,14 +70,14 @@ BOOST_AUTO_TEST_CASE(GiniImpurityBadSplitTest)
counts(1, 0) = 5;
counts(1, 1) = 5;
BOOST_REQUIRE_SMALL(GiniImpurity::Evaluate(counts), 1e-10);
REQUIRE(GiniImpurity::Evaluate(counts) == Approx(0.0).margin(1e-10));
}
/**
* A hand-crafted more difficult test for the Gini impurity, where four
* categories and three classes are available.
*/
BOOST_AUTO_TEST_CASE(GiniImpurityThreeClassTest)
TEST_CASE("GiniImpurityThreeClassTest", "[HoeffdingTreeTest]")
{
arma::Mat<size_t> counts(3, 4);
@@ -106,34 +104,34 @@ BOOST_AUTO_TEST_CASE(GiniImpurityThreeClassTest)
// (category 2) 0.28571 * 0.66667 -
// (category 2) 0.23810 * 0.34
// = 0.26145
BOOST_REQUIRE_CLOSE(GiniImpurity::Evaluate(counts), 0.26145, 1e-3);
REQUIRE(GiniImpurity::Evaluate(counts) == Approx(0.26145).epsilon(1e-5));
}
BOOST_AUTO_TEST_CASE(GiniImpurityZeroTest)
TEST_CASE("GiniImpurityZeroTest", "[HoeffdingTreeTest]")
{
// When nothing has been seen, the gini impurity should be zero.
arma::Mat<size_t> counts = arma::zeros<arma::Mat<size_t>>(10, 10);
BOOST_REQUIRE_SMALL(GiniImpurity::Evaluate(counts), 1e-10);
REQUIRE(GiniImpurity::Evaluate(counts) == Approx(0.0).margin(1e-10));
}
/**
* Test that the range of Gini impurities is correct for a handful of class
* sizes.
*/
BOOST_AUTO_TEST_CASE(GiniImpurityRangeTest)
TEST_CASE("GiniImpurityRangeTest", "[HoeffdingTreeTest]")
{
BOOST_REQUIRE_CLOSE(GiniImpurity::Range(1), 0, 1e-5);
BOOST_REQUIRE_CLOSE(GiniImpurity::Range(2), 0.5, 1e-5);
BOOST_REQUIRE_CLOSE(GiniImpurity::Range(3), 0.66666667, 1e-5);
BOOST_REQUIRE_CLOSE(GiniImpurity::Range(4), 0.75, 1e-5);
BOOST_REQUIRE_CLOSE(GiniImpurity::Range(5), 0.8, 1e-5);
BOOST_REQUIRE_CLOSE(GiniImpurity::Range(10), 0.9, 1e-5);
BOOST_REQUIRE_CLOSE(GiniImpurity::Range(100), 0.99, 1e-5);
BOOST_REQUIRE_CLOSE(GiniImpurity::Range(1000), 0.999, 1e-5);
REQUIRE(GiniImpurity::Range(1) == Approx(0).epsilon(1e-7));
REQUIRE(GiniImpurity::Range(2) == Approx(0.5).epsilon(1e-7));
REQUIRE(GiniImpurity::Range(3) == Approx(0.66666667).epsilon(1e-7));
REQUIRE(GiniImpurity::Range(4) == Approx(0.75).epsilon(1e-7));
REQUIRE(GiniImpurity::Range(5) == Approx(0.8).epsilon(1e-7));
REQUIRE(GiniImpurity::Range(10) == Approx(0.9).epsilon(1e-7));
REQUIRE(GiniImpurity::Range(100) == Approx(0.99).epsilon(1e-7));
REQUIRE(GiniImpurity::Range(1000) == Approx(0.999).epsilon(1e-7));
}
BOOST_AUTO_TEST_CASE(HoeffdingInformationGainPerfectSimpleTest)
TEST_CASE("HoeffdingInformationGainPerfectSimpleTest", "[HoeffdingTreeTest]")
{
// Make a simple test for Gini impurity with one class. In this case it
// should always be 0. We'll assemble the count matrix by hand.
@@ -145,10 +143,11 @@ BOOST_AUTO_TEST_CASE(HoeffdingInformationGainPerfectSimpleTest)
counts(1, 1) = 0; // 0 points in category 1 with class 1.
// Since the split gets us nothing, there should be no gain.
BOOST_REQUIRE_SMALL(HoeffdingInformationGain::Evaluate(counts), 1e-10);
REQUIRE(HoeffdingInformationGain::Evaluate(counts) ==
Approx(0.0).margin(1e-10));
}
BOOST_AUTO_TEST_CASE(HoeffdingInformationGainImperfectSimpleTest)
TEST_CASE("HoeffdingInformationGainImperfectSimpleTest", "[HoeffdingTreeTest]")
{
// Make a simple test where a split will give us perfect classification.
arma::Mat<size_t> counts(2, 2); // 2 categories, 2 classes.
@@ -161,10 +160,11 @@ BOOST_AUTO_TEST_CASE(HoeffdingInformationGainImperfectSimpleTest)
// The impurity before the split should be 0.5 log2(0.5) + 0.5 log2(0.5) = -1.
// The impurity after the split should be 0.
// So the gain should be 1.
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Evaluate(counts), 1.0, 1e-5);
REQUIRE(HoeffdingInformationGain::Evaluate(counts) ==
Approx(1.0).epsilon(1e-7));
}
BOOST_AUTO_TEST_CASE(HoeffdingInformationGainBadSplitTest)
TEST_CASE("HoeffdingInformationGainBadSplitTest", "[HoeffdingTreeTest]")
{
// Make a simple test where a split gets us nothing.
arma::Mat<size_t> counts(2, 2);
@@ -173,14 +173,14 @@ BOOST_AUTO_TEST_CASE(HoeffdingInformationGainBadSplitTest)
counts(1, 0) = 5;
counts(1, 1) = 5;
BOOST_REQUIRE_SMALL(HoeffdingInformationGain::Evaluate(counts), 1e-10);
REQUIRE(HoeffdingInformationGain::Evaluate(counts) == Approx(0.0).margin(1e-10));
}
/**
* A hand-crafted more difficult test for the Gini impurity, where four
* categories and three classes are available.
*/
BOOST_AUTO_TEST_CASE(HoeffdingInformationGainThreeClassTest)
TEST_CASE("HoeffdingInformationGainThreeClassTest", "[HoeffdingTreeTest]")
{
arma::Mat<size_t> counts(3, 4);
@@ -207,39 +207,39 @@ BOOST_AUTO_TEST_CASE(HoeffdingInformationGainThreeClassTest)
// (category 2) 0.28571 * -1.5850 -
// (category 3) 0.23810 * -0.92193
// = 0.64116649
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Evaluate(counts), 0.64116649,
1e-5);
REQUIRE(HoeffdingInformationGain::Evaluate(counts) ==
Approx(0.64116649).epsilon(1e-7));
}
BOOST_AUTO_TEST_CASE(HoeffdingInformationGainZeroTest)
TEST_CASE("HoeffdingInformationGainZeroTest", "[HoeffdingTreeTest]")
{
// When nothing has been seen, the information gain should be zero.
arma::Mat<size_t> counts = arma::zeros<arma::Mat<size_t>>(10, 10);
BOOST_REQUIRE_SMALL(HoeffdingInformationGain::Evaluate(counts), 1e-10);
REQUIRE(HoeffdingInformationGain::Evaluate(counts) == Approx(0.0).margin(1e-10));
}
/**
* Test that the range of information gains is correct for a handful of class
* sizes.
*/
BOOST_AUTO_TEST_CASE(HoeffdingInformationGainRangeTest)
TEST_CASE("HoeffdingInformationGainRangeTest", "[HoeffdingTreeTest]")
{
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Range(1), 0, 1e-5);
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Range(2), 1.0, 1e-5);
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Range(3), 1.5849625, 1e-5);
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Range(4), 2, 1e-5);
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Range(5), 2.32192809, 1e-5);
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Range(10), 3.32192809, 1e-5);
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Range(100), 6.64385619, 1e-5);
BOOST_REQUIRE_CLOSE(HoeffdingInformationGain::Range(1000), 9.96578428, 1e-5);
REQUIRE(HoeffdingInformationGain::Range(1) == Approx(0).epsilon(1e-7));
REQUIRE(HoeffdingInformationGain::Range(2) == Approx(1.0).epsilon(1e-7));
REQUIRE(HoeffdingInformationGain::Range(3) == Approx(1.5849625).epsilon(1e-7));
REQUIRE(HoeffdingInformationGain::Range(4) == Approx(2).epsilon(1e-7));
REQUIRE(HoeffdingInformationGain::Range(5) == Approx(2.32192809).epsilon(1e-7));
REQUIRE(HoeffdingInformationGain::Range(10) == Approx(3.32192809).epsilon(1e-7));
REQUIRE(HoeffdingInformationGain::Range(100) == Approx(6.64385619).epsilon(1e-7));
REQUIRE(HoeffdingInformationGain::Range(1000) == Approx(9.96578428).epsilon(1e-7));
}
/**
* Feed the HoeffdingCategoricalSplit class many examples, all from the same
* class, and verify that the majority class is correct.
*/
BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitMajorityClassTest)
TEST_CASE("HoeffdingCategoricalSplitMajorityClassTest", "[HoeffdingTreeTest]")
{
// Ten categories, three classes.
HoeffdingCategoricalSplit<GiniImpurity> split(10, 3);
@@ -247,14 +247,15 @@ BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitMajorityClassTest)
for (size_t i = 0; i < 500; ++i)
{
split.Train(mlpack::math::RandInt(0, 10), 1);
BOOST_REQUIRE_EQUAL(split.MajorityClass(), 1);
REQUIRE(split.MajorityClass() == 1);
}
}
/**
* A harder majority class example.
*/
BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitHarderMajorityClassTest)
TEST_CASE("HoeffdingCategoricalSplitHarderMajorityClassTest",
"[HoeffdingTreeTest]")
{
// Ten categories, three classes.
HoeffdingCategoricalSplit<GiniImpurity> split(10, 3);
@@ -264,7 +265,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitHarderMajorityClassTest)
{
split.Train(mlpack::math::RandInt(0, 10), 1);
split.Train(mlpack::math::RandInt(0, 10), 2);
BOOST_REQUIRE_EQUAL(split.MajorityClass(), 1);
REQUIRE(split.MajorityClass() == 1);
}
}
@@ -272,7 +273,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitHarderMajorityClassTest)
* Ensure that the fitness function is positive when we pass some data that
* would result in an improvement if it was split.
*/
BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitEasyFitnessCheck)
TEST_CASE("HoeffdingCategoricalSplitEasyFitnessCheck", "[HoeffdingTreeTest]")
{
HoeffdingCategoricalSplit<GiniImpurity> split(5, 3);
@@ -289,23 +290,24 @@ BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitEasyFitnessCheck)
double bestGain, secondBestGain;
split.EvaluateFitnessFunction(bestGain, secondBestGain);
BOOST_REQUIRE_GT(bestGain, 0.0);
BOOST_REQUIRE_SMALL(secondBestGain, 1e-10);
REQUIRE(bestGain > 0.0);
REQUIRE(secondBestGain == Approx(0.0).margin(1e-10));
}
/**
* Ensure that the fitness function returns 0 (no improvement) when a split
* would not get us any improvement.
*/
BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitNoImprovementFitnessTest)
TEST_CASE("HoeffdingCategoricalSplitNoImprovementFitnessTest",
"[HoeffdingTreeTest]")
{
HoeffdingCategoricalSplit<GiniImpurity> split(2, 2);
// No training has yet happened, so a split would get us nothing.
double bestGain, secondBestGain;
split.EvaluateFitnessFunction(bestGain, secondBestGain);
BOOST_REQUIRE_SMALL(bestGain, 1e-10);
BOOST_REQUIRE_SMALL(secondBestGain, 1e-10);
REQUIRE(bestGain == Approx(0.0).margin(1e-10));
REQUIRE(secondBestGain == Approx(0.0).margin(1e-10));
split.Train(0, 0);
split.Train(1, 0);
@@ -314,14 +316,14 @@ BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitNoImprovementFitnessTest)
// Now, a split still gets us only 50% accuracy in each split bin.
split.EvaluateFitnessFunction(bestGain, secondBestGain);
BOOST_REQUIRE_SMALL(bestGain, 1e-10);
BOOST_REQUIRE_SMALL(secondBestGain, 1e-10);
REQUIRE(bestGain == Approx(0.0).margin(1e-10));
REQUIRE(secondBestGain == Approx(0.0).margin(1e-10));
}
/**
* Test that when we do split, we get reasonable split information.
*/
BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitSplitTest)
TEST_CASE("HoeffdingCategoricalSplitSplitTest", "[HoeffdingTreeTest]")
{
HoeffdingCategoricalSplit<GiniImpurity> split(3, 3); // 3 categories.
@@ -334,17 +336,17 @@ BOOST_AUTO_TEST_CASE(HoeffdingCategoricalSplitSplitTest)
arma::Col<size_t> childMajorities;
split.Split(childMajorities, splitInfo);
BOOST_REQUIRE_EQUAL(childMajorities.n_elem, 3);
BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(0), 0);
BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(1), 1);
BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(2), 2);
REQUIRE(childMajorities.n_elem == 3);
REQUIRE(splitInfo.CalculateDirection(0) == 0);
REQUIRE(splitInfo.CalculateDirection(1) == 1);
REQUIRE(splitInfo.CalculateDirection(2) == 2);
}
/**
* If we feed the HoeffdingTree a ton of points of the same class, it should
* not suggest that we split.
*/
BOOST_AUTO_TEST_CASE(HoeffdingTreeNoSplitTest)
TEST_CASE("HoeffdingTreeNoSplitTest", "[HoeffdingTreeTest]")
{
// Make all dimensions categorical.
data::DatasetInfo info(3);
@@ -370,7 +372,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeNoSplitTest)
testPoint(2) = mlpack::math::RandInt(0, 2);
split.Train(testPoint, 0); // Always label 0.
BOOST_REQUIRE_EQUAL(split.SplitCheck(), 0);
REQUIRE(split.SplitCheck() == 0);
}
}
@@ -378,7 +380,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeNoSplitTest)
* If we feed the HoeffdingTree a ton of points of two different classes, it
* should very clearly suggest that we split (eventually).
*/
BOOST_AUTO_TEST_CASE(HoeffdingTreeEasySplitTest)
TEST_CASE("HoeffdingTreeEasySplitTest", "[HoeffdingTreeTest]")
{
// It'll be a two-dimensional dataset with two categories each. In the first
// dimension, category 0 will only receive points with class 0, and category 1
@@ -399,14 +401,14 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeEasySplitTest)
}
// Now it should be ready to split.
BOOST_REQUIRE_EQUAL(tree.SplitCheck(), 2);
BOOST_REQUIRE_EQUAL(tree.SplitDimension(), 0);
REQUIRE(tree.SplitCheck() == 2);
REQUIRE(tree.SplitDimension() == 0);
}
/**
* If we force a success probability of 1, it should never split.
*/
BOOST_AUTO_TEST_CASE(HoeffdingTreeProbability1SplitTest)
TEST_CASE("HoeffdingTreeProbability1SplitTest", "[HoeffdingTreeTest]")
{
// It'll be a two-dimensional dataset with two categories each. In the first
// dimension, category 0 will only receive points with class 0, and category 1
@@ -427,8 +429,8 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeProbability1SplitTest)
}
// But because the success probability is 1, it should never split.
BOOST_REQUIRE_EQUAL(split.SplitCheck(), 0);
BOOST_REQUIRE_EQUAL(split.SplitDimension(), size_t(-1));
REQUIRE(split.SplitCheck() == 0);
REQUIRE(split.SplitDimension() == size_t(-1));
}
/**
@@ -436,7 +438,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeProbability1SplitTest)
* perfect classification, another gives almost perfect classification (with 10%
* error). Splits should occur after many samples.
*/
BOOST_AUTO_TEST_CASE(HoeffdingTreeAlmostPerfectSplit)
TEST_CASE("HoeffdingTreeAlmostPerfectSplit", "[HoeffdingTreeTest]")
{
// Two categories and two dimensions.
data::DatasetInfo info(2);
@@ -462,16 +464,16 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeAlmostPerfectSplit)
}
// Ensure that splitting should happen.
BOOST_REQUIRE_EQUAL(split.SplitCheck(), 2);
REQUIRE(split.SplitCheck() == 2);
// Make sure that it's split on the correct dimension.
BOOST_REQUIRE_EQUAL(split.SplitDimension(), 1);
REQUIRE(split.SplitDimension() == 1);
}
/**
* Test that the HoeffdingTree class will not split if the two features are
* equally good.
*/
BOOST_AUTO_TEST_CASE(HoeffdingTreeEqualSplitTest)
TEST_CASE("HoeffdingTreeEqualSplitTest", "[HoeffdingTreeTest]")
{
// Two categories and two dimensions.
data::DatasetInfo info(2);
@@ -490,7 +492,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeEqualSplitTest)
}
// Ensure that splitting should not happen.
BOOST_REQUIRE_EQUAL(split.SplitCheck(), 0);
REQUIRE(split.SplitCheck() == 0);
}
// This is used in the next test.
@@ -503,7 +505,7 @@ using HoeffdingSizeTNumericSplit = HoeffdingNumericSplit<FitnessFunction,
* that it can properly classify all of the training points. (The dataset is
* perfectly separable.)
*/
BOOST_AUTO_TEST_CASE(HoeffdingTreeSimpleDatasetTest)
TEST_CASE("HoeffdingTreeSimpleDatasetTest", "[HoeffdingTreeTest]")
{
DatasetInfo info(3);
info.MapString<size_t>("cat0", 0);
@@ -550,10 +552,10 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeSimpleDatasetTest)
streamTree.Train(dataset.col(i), labels[i]);
// Each tree should have a single split.
BOOST_REQUIRE_EQUAL(batchTree.NumChildren(), 3);
BOOST_REQUIRE_EQUAL(streamTree.NumChildren(), 3);
BOOST_REQUIRE_EQUAL(batchTree.SplitDimension(), 1);
BOOST_REQUIRE_EQUAL(streamTree.SplitDimension(), 1);
REQUIRE(batchTree.NumChildren() == 3);
REQUIRE(streamTree.NumChildren() == 3);
REQUIRE(batchTree.SplitDimension() == 1);
REQUIRE(streamTree.SplitDimension() == 1);
// Now, classify all the points in the dataset.
arma::Row<size_t> batchLabels(9000);
@@ -565,15 +567,15 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeSimpleDatasetTest)
for (size_t i = 0; i < 9000; ++i)
{
BOOST_REQUIRE_EQUAL(labels[i], streamLabels[i]);
BOOST_REQUIRE_EQUAL(labels[i], batchLabels[i]);
REQUIRE(labels[i] == streamLabels[i]);
REQUIRE(labels[i] == batchLabels[i]);
}
}
/**
* Make sure that a tree that does not split on anything.
*/
BOOST_AUTO_TEST_CASE(NumDescendantsTest1)
TEST_CASE("NumDescendantsTest1", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat dataset(3, 500);
@@ -593,13 +595,13 @@ BOOST_AUTO_TEST_CASE(NumDescendantsTest1)
for (size_t i = 0; i < 500; ++i)
streamTree.Train(dataset.col(i), labels[i]);
// As there is just one label, there are no descendants.
BOOST_REQUIRE_EQUAL(streamTree.NumDescendants(), 0);
REQUIRE(streamTree.NumDescendants() == 0);
}
/**
* Test that a tree that does split has some descendants.
*/
BOOST_AUTO_TEST_CASE(NumDescendantsTest2)
TEST_CASE("NumDescendantsTest2", "[HoeffdingTreeTest]")
{
DatasetInfo info(3);
info.MapString<size_t>("cat0", 0);
@@ -641,14 +643,14 @@ BOOST_AUTO_TEST_CASE(NumDescendantsTest2)
HoeffdingCategoricalSplit> TreeType;
TreeType batchTree(dataset, info, labels, 3, false);
BOOST_REQUIRE_EQUAL(batchTree.NumDescendants(), 3);
REQUIRE(batchTree.NumDescendants() == 3);
}
/**
* Test that the HoeffdingNumericSplit class has a fitness function value of 0
* before it's seen enough points.
*/
BOOST_AUTO_TEST_CASE(HoeffdingNumericSplitFitnessFunctionTest)
TEST_CASE("HoeffdingNumericSplitFitnessFunctionTest", "[HoeffdingTreeTest]")
{
HoeffdingNumericSplit<GiniImpurity> split(5, 10, 100);
@@ -659,22 +661,23 @@ BOOST_AUTO_TEST_CASE(HoeffdingNumericSplitFitnessFunctionTest)
split.Train(mlpack::math::Random(), mlpack::math::RandInt(5));
double bestGain, secondBestGain;
split.EvaluateFitnessFunction(bestGain, secondBestGain);
BOOST_REQUIRE_SMALL(bestGain, 1e-10);
BOOST_REQUIRE_SMALL(secondBestGain, 1e-10);
REQUIRE(bestGain == Approx(0.0).margin(1e-10));
REQUIRE(secondBestGain == Approx(0.0).margin(1e-10));
}
}
/**
* Make sure the majority class is correct in the samples before binning.
*/
BOOST_AUTO_TEST_CASE(HoeffdingNumericSplitPreBinningMajorityClassTest)
TEST_CASE("HoeffdingNumericSplitPreBinningMajorityClassTest",
"[HoeffdingTreeTest]")
{
HoeffdingNumericSplit<GiniImpurity> split(3, 10, 100);
for (size_t i = 0; i < 100; ++i)
{
split.Train(mlpack::math::Random(), 1);
BOOST_REQUIRE_EQUAL(split.MajorityClass(), 1);
REQUIRE(split.MajorityClass() == 1);
}
}
@@ -683,7 +686,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingNumericSplitPreBinningMajorityClassTest)
* HoeffdingNumericSplit bins it reasonably into two bins and returns sensible
* Gini impurity numbers.
*/
BOOST_AUTO_TEST_CASE(HoeffdingNumericSplitBimodalTest)
TEST_CASE("HoeffdingNumericSplitBimodalTest", "[HoeffdingTreeTest]")
{
// 2 classes, 2 bins, 200 samples before binning.
HoeffdingNumericSplit<GiniImpurity> split(2, 2, 200);
@@ -696,32 +699,32 @@ BOOST_AUTO_TEST_CASE(HoeffdingNumericSplitBimodalTest)
// Push the majority class to 1.
split.Train(-mlpack::math::Random() - 0.3, 1);
BOOST_REQUIRE_EQUAL(split.MajorityClass(), 1);
REQUIRE(split.MajorityClass() == 1);
// Push the majority class back to 0.
split.Train(mlpack::math::Random() + 0.3, 0);
split.Train(mlpack::math::Random() + 0.3, 0);
BOOST_REQUIRE_EQUAL(split.MajorityClass(), 0);
REQUIRE(split.MajorityClass() == 0);
// Now the binning should be complete, and so the impurity should be
// (0.5 * (1 - 0.5)) * 2 = 0.50 (it will be 0 in the two created children).
double bestGain, secondBestGain;
split.EvaluateFitnessFunction(bestGain, secondBestGain);
BOOST_REQUIRE_CLOSE(bestGain, 0.50, 0.03);
BOOST_REQUIRE_SMALL(secondBestGain, 1e-10);
REQUIRE(bestGain == Approx(0.50).epsilon(0.0003));
REQUIRE(secondBestGain == Approx(0.0).margin(1e-10));
// Make sure that if we do create children, that the correct number of
// children is created, and that the bins end up in the right place.
NumericSplitInfo<> info;
arma::Col<size_t> childMajorities;
split.Split(childMajorities, info);
BOOST_REQUIRE_EQUAL(childMajorities.n_elem, 2);
REQUIRE(childMajorities.n_elem == 2);
// Now check the split info.
for (size_t i = 0; i < 10; ++i)
{
BOOST_REQUIRE_NE(info.CalculateDirection(mlpack::math::Random() + 0.3),
info.CalculateDirection(-mlpack::math::Random() - 0.3));
REQUIRE(info.CalculateDirection(mlpack::math::Random() + 0.3) !=
info.CalculateDirection(-mlpack::math::Random() - 0.3));
}
}
@@ -730,7 +733,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingNumericSplitBimodalTest)
* less than 1.0 is class 0 and anything greater is class 1. Then make sure it
* can perform a perfect split.
*/
BOOST_AUTO_TEST_CASE(BinaryNumericSplitSimpleSplitTest)
TEST_CASE("BinaryNumericSplitSimpleSplitTest", "[HoeffdingTreeTest]")
{
BinaryNumericSplit<GiniImpurity> split(2); // 2 classes.
@@ -745,8 +748,8 @@ BOOST_AUTO_TEST_CASE(BinaryNumericSplitSimpleSplitTest)
// impurity for the children is 0.
double bestGain, secondBestGain;
split.EvaluateFitnessFunction(bestGain, secondBestGain);
BOOST_REQUIRE_CLOSE(bestGain, 0.5, 1e-5);
BOOST_REQUIRE_GT(bestGain, secondBestGain);
REQUIRE(bestGain == Approx(0.5).epsilon(1e-7));
REQUIRE(bestGain > secondBestGain);
}
// Now, when we ask it to split, ensure that the split value is reasonable.
@@ -754,21 +757,21 @@ BOOST_AUTO_TEST_CASE(BinaryNumericSplitSimpleSplitTest)
BinaryNumericSplitInfo<> splitInfo;
split.Split(childMajorities, splitInfo);
BOOST_REQUIRE_EQUAL(childMajorities[0], 0);
BOOST_REQUIRE_EQUAL(childMajorities[1], 1);
BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(0.5), 0);
BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(1.5), 1);
BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(0.0), 0);
BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(-1.0), 0);
BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(0.9), 0);
BOOST_REQUIRE_EQUAL(splitInfo.CalculateDirection(1.1), 1);
REQUIRE(childMajorities[0] == 0);
REQUIRE(childMajorities[1] == 1);
REQUIRE(splitInfo.CalculateDirection(0.5) == 0);
REQUIRE(splitInfo.CalculateDirection(1.5) == 1);
REQUIRE(splitInfo.CalculateDirection(0.0) == 0);
REQUIRE(splitInfo.CalculateDirection(-1.0) == 0);
REQUIRE(splitInfo.CalculateDirection(0.9) == 0);
REQUIRE(splitInfo.CalculateDirection(1.1) == 1);
}
/**
* Create a BinaryNumericSplit object, feed it samples in the same way as
* before, but with four classes.
*/
BOOST_AUTO_TEST_CASE(BinaryNumericSplitSimpleFourClassSplitTest)
TEST_CASE("BinaryNumericSplitSimpleFourClassSplitTest", "[HoeffdingTreeTest]")
{
BinaryNumericSplit<GiniImpurity> split(4); // 4 classes.
@@ -785,8 +788,8 @@ BOOST_AUTO_TEST_CASE(BinaryNumericSplitSimpleFourClassSplitTest)
// perfect child, giving a gain of 0.75 - 3 * (1/3 * 2/3) = 0.25.
double bestGain, secondBestGain;
split.EvaluateFitnessFunction(bestGain, secondBestGain);
BOOST_REQUIRE_CLOSE(bestGain, 0.25, 1e-5);
BOOST_REQUIRE_GE(bestGain, secondBestGain);
REQUIRE(bestGain == Approx(0.25).epsilon(1e-7));
REQUIRE(bestGain >= secondBestGain);
}
// Now, when we ask it to split, ensure that the split value is reasonable.
@@ -796,14 +799,14 @@ BOOST_AUTO_TEST_CASE(BinaryNumericSplitSimpleFourClassSplitTest)
// We don't really care where it splits -- it can split anywhere. But it has
// to split in only two directions.
BOOST_REQUIRE_EQUAL(childMajorities.n_elem, 2);
REQUIRE(childMajorities.n_elem == 2);
}
/**
* Create a HoeffdingTree that uses the HoeffdingNumericSplit and make sure it
* can split meaningfully on the correct dimension.
*/
BOOST_AUTO_TEST_CASE(NumericHoeffdingTreeTest)
TEST_CASE("NumericHoeffdingTreeTest", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat dataset(3, 9000);
@@ -836,10 +839,10 @@ BOOST_AUTO_TEST_CASE(NumericHoeffdingTreeTest)
streamTree.Train(dataset.col(i), labels[i]);
// Each tree should have at least one split.
BOOST_REQUIRE_GT(batchTree.NumChildren(), 0);
BOOST_REQUIRE_GT(streamTree.NumChildren(), 0);
BOOST_REQUIRE_EQUAL(batchTree.SplitDimension(), 1);
BOOST_REQUIRE_EQUAL(streamTree.SplitDimension(), 1);
REQUIRE(batchTree.NumChildren() > 0);
REQUIRE(streamTree.NumChildren() > 0);
REQUIRE(batchTree.SplitDimension() == 1);
REQUIRE(streamTree.SplitDimension() == 1);
// Now, classify all the points in the dataset.
arma::Row<size_t> batchLabels(9000);
@@ -860,15 +863,15 @@ BOOST_AUTO_TEST_CASE(NumericHoeffdingTreeTest)
}
// 66% accuracy shouldn't be too much to ask...
BOOST_REQUIRE_GT(streamCorrect, 6000);
BOOST_REQUIRE_GT(batchCorrect, 6000);
REQUIRE(streamCorrect > 6000);
REQUIRE(batchCorrect > 6000);
}
/**
* The same as the previous test, but with the numeric binary split, and with a
* categorical feature.
*/
BOOST_AUTO_TEST_CASE(BinaryNumericHoeffdingTreeTest)
TEST_CASE("BinaryNumericHoeffdingTreeTest", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat dataset(4, 9000);
@@ -905,10 +908,10 @@ BOOST_AUTO_TEST_CASE(BinaryNumericHoeffdingTreeTest)
streamTree.Train(dataset.col(i), labels[i]);
// Each tree should have at least one split.
BOOST_REQUIRE_GT(batchTree.NumChildren(), 0);
BOOST_REQUIRE_GT(streamTree.NumChildren(), 0);
BOOST_REQUIRE_EQUAL(batchTree.SplitDimension(), 1);
BOOST_REQUIRE_EQUAL(streamTree.SplitDimension(), 1);
REQUIRE(batchTree.NumChildren() > 0);
REQUIRE(streamTree.NumChildren() > 0);
REQUIRE(batchTree.SplitDimension() == 1);
REQUIRE(streamTree.SplitDimension() == 1);
// Now, classify all the points in the dataset.
arma::Row<size_t> batchLabels(9000);
@@ -929,14 +932,14 @@ BOOST_AUTO_TEST_CASE(BinaryNumericHoeffdingTreeTest)
}
// Require a pretty high accuracy: 95%.
BOOST_REQUIRE_GT(streamCorrect, 8550);
BOOST_REQUIRE_GT(batchCorrect, 8550);
REQUIRE(streamCorrect > 8550);
REQUIRE(batchCorrect > 8550);
}
/**
* Test majority probabilities.
*/
BOOST_AUTO_TEST_CASE(MajorityProbabilityTest)
TEST_CASE("MajorityProbabilityTest", "[HoeffdingTreeTest]")
{
data::DatasetInfo info(1);
HoeffdingTree<> tree(info, 3);
@@ -950,15 +953,15 @@ BOOST_AUTO_TEST_CASE(MajorityProbabilityTest)
double probability;
tree.Classify(arma::vec("1"), prediction, probability);
BOOST_REQUIRE_EQUAL(prediction, 0);
BOOST_REQUIRE_CLOSE(probability, 1.0, 1e-5);
REQUIRE(prediction == 0);
REQUIRE(probability == Approx(1.0).epsilon(1e-7));
// Make it impure.
tree.Train(arma::vec("4"), 1);
tree.Classify(arma::vec("3"), prediction, probability);
BOOST_REQUIRE_EQUAL(prediction, 0);
BOOST_REQUIRE_CLOSE(probability, 0.75, 1e-5);
REQUIRE(prediction == 0);
REQUIRE(probability == Approx(0.75).epsilon(1e-7));
// Flip the majority class.
tree.Train(arma::vec("4"), 1);
@@ -967,14 +970,14 @@ BOOST_AUTO_TEST_CASE(MajorityProbabilityTest)
tree.Train(arma::vec("4"), 1);
tree.Classify(arma::vec("3"), prediction, probability);
BOOST_REQUIRE_EQUAL(prediction, 1);
BOOST_REQUIRE_CLOSE(probability, 0.625, 1e-5);
REQUIRE(prediction == 1);
REQUIRE(probability == Approx(0.625).epsilon(1e-7));
}
/**
* Make sure that batch training mode outperforms non-batch mode.
*/
BOOST_AUTO_TEST_CASE(BatchTrainingTest)
TEST_CASE("BatchTrainingTest", "[HoeffdingTreeTest]")
{
// We need to create a dataset with some amount of complexity, that must be
// split in a handful of ways to accurately classify the data. An expanding
@@ -1050,11 +1053,11 @@ BOOST_AUTO_TEST_CASE(BatchTrainingTest)
// The batch tree must be a bit better than the stream tree. But not too
// much, since the accuracy is already going to be very high.
BOOST_REQUIRE_GE(batchCorrect, streamCorrect);
REQUIRE(batchCorrect >= streamCorrect);
}
// Make sure that changing the confidence properly propagates to all leaves.
BOOST_AUTO_TEST_CASE(ConfidenceChangeTest)
TEST_CASE("ConfidenceChangeTest", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat dataset(4, 9000);
@@ -1091,7 +1094,7 @@ BOOST_AUTO_TEST_CASE(ConfidenceChangeTest)
++i;
}
BOOST_REQUIRE_LT(i, 9000);
REQUIRE(i < 9000);
// Now we have split the root node, but we need to make sure we can feed
// through the rest of the points while requiring a confidence of 1.0, and
@@ -1107,11 +1110,11 @@ BOOST_AUTO_TEST_CASE(ConfidenceChangeTest)
}
for (size_t c = 0; c < tree.NumChildren(); ++c)
BOOST_REQUIRE_EQUAL(tree.Child(c).NumChildren(), 0);
REQUIRE(tree.Child(c).NumChildren() == 0);
}
//! Make sure parameter changes are propagated to children.
BOOST_AUTO_TEST_CASE(ParameterChangeTest)
TEST_CASE("ParameterChangeTest", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat dataset(4, 9000);
@@ -1154,17 +1157,17 @@ BOOST_AUTO_TEST_CASE(ParameterChangeTest)
HoeffdingTree<>* node = stack.top();
stack.pop();
BOOST_REQUIRE_CLOSE(node->SuccessProbability(), 0.7, 1e-5);
BOOST_REQUIRE_EQUAL(node->MinSamples(), 17);
BOOST_REQUIRE_EQUAL(node->MaxSamples(), 192);
BOOST_REQUIRE_EQUAL(node->CheckInterval(), 3);
REQUIRE(node->SuccessProbability() == Approx(0.7).epsilon(1e-7));
REQUIRE(node->MinSamples() == 17);
REQUIRE(node->MaxSamples() == 192);
REQUIRE(node->CheckInterval() == 3);
for (size_t i = 0; i < node->NumChildren(); ++i)
stack.push(&node->Child(i));
}
}
BOOST_AUTO_TEST_CASE(MultipleSerializationTest)
TEST_CASE("MultipleSerializationTest", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat dataset(4, 9000);
@@ -1217,12 +1220,12 @@ BOOST_AUTO_TEST_CASE(MultipleSerializationTest)
for (size_t i = 0; i < deepPredictions.n_elem; ++i)
{
BOOST_REQUIRE_EQUAL(shallowPredictions[i], deepPredictions[i]);
REQUIRE(shallowPredictions[i] == deepPredictions[i]);
}
}
// Test the Hoeffding tree model.
BOOST_AUTO_TEST_CASE(HoeffdingTreeModelTest)
TEST_CASE("HoeffdingTreeModelTest", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat dataset(4, 3000);
@@ -1289,19 +1292,19 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeModelTest)
for (size_t i = 0; i < 3000; ++i)
{
// Check consistency of predictions.
BOOST_REQUIRE_EQUAL(predictions[i], predictions2[i]);
REQUIRE(predictions[i] == predictions2[i]);
if (labels[i] == predictions[i])
++correct;
}
// Require at least 95% accuracy.
BOOST_REQUIRE_GT(correct, 2850);
REQUIRE(correct > 2850);
}
}
// Test the Hoeffding tree model in batch mode.
BOOST_AUTO_TEST_CASE(HoeffdingTreeModelBatchTest)
TEST_CASE("HoeffdingTreeModelBatchTest", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat dataset(4, 3000);
@@ -1366,18 +1369,18 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeModelBatchTest)
for (size_t i = 0; i < 3000; ++i)
{
// Check consistency of predictions.
BOOST_REQUIRE_EQUAL(predictions[i], predictions2[i]);
REQUIRE(predictions[i] == predictions2[i]);
if (labels[i] == predictions[i])
++correct;
}
// Require at least 95% accuracy.
BOOST_REQUIRE_GT(correct, 2850);
REQUIRE(correct > 2850);
}
}
BOOST_AUTO_TEST_CASE(HoeffdingTreeModelSerializationTest)
TEST_CASE("HoeffdingTreeModelSerializationTest", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat dataset(4, 3000);
@@ -1452,15 +1455,13 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeModelSerializationTest)
for (size_t i = 0; i < 3000; ++i)
{
// Check consistency of predictions and probabilities.
BOOST_REQUIRE_EQUAL(predictions[i], predictionsXml[i]);
BOOST_REQUIRE_EQUAL(predictions[i], predictionsText[i]);
BOOST_REQUIRE_EQUAL(predictions[i], predictionsBinary[i]);
REQUIRE(predictions[i] == predictionsXml[i]);
REQUIRE(predictions[i] == predictionsText[i]);
REQUIRE(predictions[i] == predictionsBinary[i]);
BOOST_REQUIRE_CLOSE(probabilities[i], probabilitiesXml[i], 1e-5);
BOOST_REQUIRE_CLOSE(probabilities[i], probabilitiesText[i], 1e-5);
BOOST_REQUIRE_CLOSE(probabilities[i], probabilitiesBinary[i], 1e-5);
REQUIRE(probabilities[i] == Approx(probabilitiesXml[i]).epsilon(1e-7));
REQUIRE(probabilities[i] == Approx(probabilitiesText[i]).epsilon(1e-7));
REQUIRE(probabilities[i] == Approx(probabilitiesBinary[i]).epsilon(1e-7));
}
}
}
BOOST_AUTO_TEST_SUITE_END();
+204 -186
View File
@@ -29,8 +29,7 @@ static const std::string testName = "";
#include <mlpack/bindings/cli/parse_command_line.hpp>
#include <mlpack/bindings/cli/end_program.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
using namespace mlpack;
using namespace mlpack::util;
@@ -46,8 +45,6 @@ struct IOTestDestroyer
IOTestDestroyer() { IO::ClearSettings(); }
};
BOOST_FIXTURE_TEST_SUITE(IOTest, IOTestDestroyer);
/**
* Before running a test that uses the CLI options, we have to add the default
* options that are required for CLI to function, since it will be destroyed at
@@ -72,7 +69,7 @@ void AddRequiredCLIOptions()
* Tests that CLI works as intended, namely that IO::Add propagates
* successfully.
*/
BOOST_AUTO_TEST_CASE(TestCLIAdd)
TEST_CASE_METHOD(IOTestDestroyer, "TestCLIAdd", "[IOTest]")
{
AddRequiredCLIOptions();
@@ -81,19 +78,17 @@ BOOST_AUTO_TEST_CASE(TestCLIAdd)
CLIOption<bool> b(false, "global/bool", "True or false.", "a", "bool");
// IO::HasParam should return false here.
BOOST_REQUIRE(!IO::HasParam("global/bool"));
REQUIRE(!IO::HasParam("global/bool"));
// Check that our aliasing works.
BOOST_REQUIRE_EQUAL(IO::HasParam("global/bool"),
IO::HasParam("a"));
BOOST_REQUIRE_EQUAL(IO::GetParam<bool>("global/bool"),
IO::GetParam<bool>("a"));
REQUIRE(IO::HasParam("global/bool") == IO::HasParam("a"));
REQUIRE(IO::GetParam<bool>("global/bool") == IO::GetParam<bool>("a"));
}
/**
* Tests that the various PARAM_* macros work properly.
*/
BOOST_AUTO_TEST_CASE(TestOption)
TEST_CASE_METHOD(IOTestDestroyer, "TestOption", "[IOTest]")
{
AddRequiredCLIOptions();
@@ -101,13 +96,13 @@ BOOST_AUTO_TEST_CASE(TestOption)
// this.
PARAM_IN(int, "test_parent/test", "test desc", "", 42, false);
BOOST_REQUIRE_EQUAL(IO::GetParam<int>("test_parent/test"), 42);
REQUIRE(IO::GetParam<int>("test_parent/test") == 42);
}
/**
* Test that duplicate flags are filtered out correctly.
*/
BOOST_AUTO_TEST_CASE(TestDuplicateFlag)
TEST_CASE_METHOD(IOTestDestroyer, "TestDuplicateFlag", "[IOTest]")
{
AddRequiredCLIOptions();
@@ -120,14 +115,15 @@ BOOST_AUTO_TEST_CASE(TestDuplicateFlag)
argv[2] = "--test";
// This should not throw an exception.
BOOST_REQUIRE_NO_THROW(
REQUIRE_NOTHROW(
ParseCommandLine(argc, const_cast<char**>(argv)));
}
/**
* Test that duplicate options throw an exception.
*/
BOOST_AUTO_TEST_CASE(TestDuplicateParam)
TEST_CASE_METHOD(IOTestDestroyer, "TestDuplicateParam",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -141,7 +137,7 @@ BOOST_AUTO_TEST_CASE(TestDuplicateParam)
// This should throw an exception.
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(ParseCommandLine(argc, const_cast<char**>(argv)),
REQUIRE_THROWS_AS(ParseCommandLine(argc, const_cast<char**>(argv)),
std::runtime_error);
Log::Fatal.ignoreInput = false;
}
@@ -149,16 +145,17 @@ BOOST_AUTO_TEST_CASE(TestDuplicateParam)
/**
* Ensure that a Boolean option which we define is set correctly.
*/
BOOST_AUTO_TEST_CASE(TestBooleanOption)
TEST_CASE_METHOD(IOTestDestroyer, "TestBooleanOption",
"[IOTest]")
{
AddRequiredCLIOptions();
PARAM_FLAG("flag_test", "flag test description", "");
BOOST_REQUIRE_EQUAL(IO::HasParam("flag_test"), false);
REQUIRE(IO::HasParam("flag_test") == false);
// Now check that CLI reflects that it is false by default.
BOOST_REQUIRE_EQUAL(IO::GetParam<bool>("flag_test"), false);
REQUIRE(IO::GetParam<bool>("flag_test") == false);
// Now, if we specify this flag, it should be true.
int argc = 2;
@@ -168,14 +165,15 @@ BOOST_AUTO_TEST_CASE(TestBooleanOption)
ParseCommandLine(argc, const_cast<char**>(argv));
BOOST_REQUIRE_EQUAL(IO::GetParam<bool>("flag_test"), true);
BOOST_REQUIRE_EQUAL(IO::HasParam("flag_test"), true);
REQUIRE(IO::GetParam<bool>("flag_test") == true);
REQUIRE(IO::HasParam("flag_test") == true);
}
/**
* Test that a vector option works correctly.
*/
BOOST_AUTO_TEST_CASE(TestVectorOption)
TEST_CASE_METHOD(IOTestDestroyer, "TestVectorOption",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -191,20 +189,21 @@ BOOST_AUTO_TEST_CASE(TestVectorOption)
ParseCommandLine(argc, const_cast<char**>(argv));
BOOST_REQUIRE(IO::HasParam("test_vec"));
REQUIRE(IO::HasParam("test_vec"));
vector<size_t> v = IO::GetParam<vector<size_t>>("test_vec");
BOOST_REQUIRE_EQUAL(v.size(), 3);
BOOST_REQUIRE_EQUAL(v[0], 1);
BOOST_REQUIRE_EQUAL(v[1], 2);
BOOST_REQUIRE_EQUAL(v[2], 4);
REQUIRE(v.size() == 3);
REQUIRE(v[0] == 1);
REQUIRE(v[1] == 2);
REQUIRE(v[2] == 4);
}
/**
* Test that we can use a vector option by specifying it many times.
*/
BOOST_AUTO_TEST_CASE(TestVectorOption2)
TEST_CASE_METHOD(IOTestDestroyer, "TestVectorOption2",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -222,17 +221,18 @@ BOOST_AUTO_TEST_CASE(TestVectorOption2)
ParseCommandLine(argc, const_cast<char**>(argv));
BOOST_REQUIRE(IO::HasParam("test2_vec"));
REQUIRE(IO::HasParam("test2_vec"));
vector<size_t> v = IO::GetParam<vector<size_t>>("test2_vec");
BOOST_REQUIRE_EQUAL(v.size(), 3);
BOOST_REQUIRE_EQUAL(v[0], 1);
BOOST_REQUIRE_EQUAL(v[1], 2);
BOOST_REQUIRE_EQUAL(v[2], 4);
REQUIRE(v.size() == 3);
REQUIRE(v[0] == 1);
REQUIRE(v[1] == 2);
REQUIRE(v[2] == 4);
}
BOOST_AUTO_TEST_CASE(InputColVectorParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "InputColVectorParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -250,24 +250,25 @@ BOOST_AUTO_TEST_CASE(InputColVectorParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --vector parameter should exist.
BOOST_REQUIRE(IO::HasParam("vector"));
REQUIRE(IO::HasParam("vector"));
// The --vector_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("vector_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("vector_file"), runtime_error);
Log::Fatal.ignoreInput = false;
arma::vec vec1 = IO::GetParam<arma::vec>("vector");
arma::vec vec2 = IO::GetParam<arma::vec>("vector");
BOOST_REQUIRE_EQUAL(vec1.n_rows, 63);
BOOST_REQUIRE_EQUAL(vec2.n_rows, 63);
REQUIRE(vec1.n_rows == 63);
REQUIRE(vec2.n_rows == 63);
for (size_t i = 0; i < vec1.n_elem; ++i)
BOOST_REQUIRE_CLOSE(vec1[i], vec2[i], 1e-10);
REQUIRE(vec1[i] == Approx(vec2[i]).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(InputUnsignedColVectorParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "InputUnsignedColVectorParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -285,24 +286,25 @@ BOOST_AUTO_TEST_CASE(InputUnsignedColVectorParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --vector parameter should exist.
BOOST_REQUIRE(IO::HasParam("vector"));
REQUIRE(IO::HasParam("vector"));
// The --vector_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("vector_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("vector_file"), runtime_error);
Log::Fatal.ignoreInput = false;
arma::Col<size_t> vec1 = IO::GetParam<arma::Col<size_t>>("vector");
arma::Col<size_t> vec2 = IO::GetParam<arma::Col<size_t>>("vector");
BOOST_REQUIRE_EQUAL(vec1.n_rows, 63);
BOOST_REQUIRE_EQUAL(vec2.n_rows, 63);
REQUIRE(vec1.n_rows == 63);
REQUIRE(vec2.n_rows == 63);
for (size_t i = 0; i < vec1.n_elem; ++i)
BOOST_REQUIRE_EQUAL(vec1[i], vec2[i]);
REQUIRE(vec1[i] == vec2[i]);
}
BOOST_AUTO_TEST_CASE(InputRowVectorParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "InputRowVectorParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -320,24 +322,25 @@ BOOST_AUTO_TEST_CASE(InputRowVectorParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --vector parameter should exist.
BOOST_REQUIRE(IO::HasParam("row"));
REQUIRE(IO::HasParam("row"));
// The --vector_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("row_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("row_file"), runtime_error);
Log::Fatal.ignoreInput = false;
arma::rowvec vec1 = IO::GetParam<arma::rowvec>("row");
arma::rowvec vec2 = IO::GetParam<arma::rowvec>("row");
BOOST_REQUIRE_EQUAL(vec1.n_cols, 7);
BOOST_REQUIRE_EQUAL(vec2.n_cols, 7);
REQUIRE(vec1.n_cols == 7);
REQUIRE(vec2.n_cols == 7);
for (size_t i = 0; i < vec1.n_elem; ++i)
BOOST_REQUIRE_CLOSE(vec1[i], vec2[i], 1e-10);
REQUIRE(vec1[i] == Approx(vec2[i]).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(InputUnsignedRowVectorParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "InputUnsignedRowVectorParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -355,24 +358,25 @@ BOOST_AUTO_TEST_CASE(InputUnsignedRowVectorParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --vector parameter should exist.
BOOST_REQUIRE(IO::HasParam("row"));
REQUIRE(IO::HasParam("row"));
// The --vector_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("row_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("row_file"), runtime_error);
Log::Fatal.ignoreInput = false;
arma::Row<size_t> vec1 = IO::GetParam<arma::Row<size_t>>("row");
arma::Row<size_t> vec2 = IO::GetParam<arma::Row<size_t>>("row");
BOOST_REQUIRE_EQUAL(vec1.n_cols, 7);
BOOST_REQUIRE_EQUAL(vec2.n_cols, 7);
REQUIRE(vec1.n_cols == 7);
REQUIRE(vec2.n_cols == 7);
for (size_t i = 0; i < vec1.n_elem; ++i)
BOOST_REQUIRE_EQUAL(vec1[i], vec2[i]);
REQUIRE(vec1[i] == vec2[i]);
}
BOOST_AUTO_TEST_CASE(OutputColParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "OutputColParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -390,11 +394,11 @@ BOOST_AUTO_TEST_CASE(OutputColParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --vector parameter should exist.
BOOST_REQUIRE(IO::HasParam("vector"));
REQUIRE(IO::HasParam("vector"));
// The --vector_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("vector_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("vector_file"), runtime_error);
Log::Fatal.ignoreInput = false;
// Since it's an output parameter, we don't need any input and don't need to
@@ -411,15 +415,16 @@ BOOST_AUTO_TEST_CASE(OutputColParamTest)
arma::vec dataset2;
data::Load("test.csv", dataset2);
BOOST_REQUIRE_EQUAL(dataset.n_rows, dataset2.n_rows);
REQUIRE(dataset.n_rows == dataset2.n_rows);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
REQUIRE(dataset[i] == Approx(dataset2[i]).epsilon(1e-12));
// Remove the file.
remove("test.csv");
}
BOOST_AUTO_TEST_CASE(OutputUnsignedColParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "OutputUnsignedColParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -437,11 +442,11 @@ BOOST_AUTO_TEST_CASE(OutputUnsignedColParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --vector parameter should exist.
BOOST_REQUIRE(IO::HasParam("vector"));
REQUIRE(IO::HasParam("vector"));
// The --vector_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("vector_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("vector_file"), runtime_error);
Log::Fatal.ignoreInput = false;
// Since it's an output parameter, we don't need any input and don't need to
@@ -458,15 +463,16 @@ BOOST_AUTO_TEST_CASE(OutputUnsignedColParamTest)
arma::Col<size_t> dataset2;
data::Load("test.csv", dataset2);
BOOST_REQUIRE_EQUAL(dataset.n_rows, dataset2.n_rows);
REQUIRE(dataset.n_rows == dataset2.n_rows);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_EQUAL(dataset[i], dataset2[i]);
REQUIRE(dataset[i] == dataset2[i]);
// Remove the file.
remove("test.csv");
}
BOOST_AUTO_TEST_CASE(OutputRowParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "OutputRowParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -484,11 +490,11 @@ BOOST_AUTO_TEST_CASE(OutputRowParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --row parameter should exist.
BOOST_REQUIRE(IO::HasParam("row"));
REQUIRE(IO::HasParam("row"));
// The --row_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("row_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("row_file"), runtime_error);
Log::Fatal.ignoreInput = false;
// Since it's an output parameter, we don't need any input and don't need to
@@ -505,15 +511,15 @@ BOOST_AUTO_TEST_CASE(OutputRowParamTest)
arma::rowvec dataset2;
data::Load("test.csv", dataset2);
BOOST_REQUIRE_EQUAL(dataset.n_cols, dataset2.n_cols);
REQUIRE(dataset.n_cols == dataset2.n_cols);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
REQUIRE(dataset[i] == Approx(dataset2[i]).epsilon(1e-12));
// Remove the file.
remove("test.csv");
}
BOOST_AUTO_TEST_CASE(OutputUnsignedRowParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "OutputUnsignedRowParamTest", "[IOTest]")
{
AddRequiredCLIOptions();
@@ -531,11 +537,11 @@ BOOST_AUTO_TEST_CASE(OutputUnsignedRowParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --row parameter should exist.
BOOST_REQUIRE(IO::HasParam("row"));
REQUIRE(IO::HasParam("row"));
// The --row_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("row_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("row_file"), runtime_error);
Log::Fatal.ignoreInput = false;
// Since it's an output parameter, we don't need any input and don't need to
@@ -552,15 +558,16 @@ BOOST_AUTO_TEST_CASE(OutputUnsignedRowParamTest)
arma::Row<size_t> dataset2;
data::Load("test.csv", dataset2);
BOOST_REQUIRE_EQUAL(dataset.n_cols, dataset2.n_cols);
REQUIRE(dataset.n_cols == dataset2.n_cols);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_EQUAL(dataset[i], dataset2[i]);
REQUIRE(dataset[i] == dataset2[i]);
// Remove the file.
remove("test.csv");
}
BOOST_AUTO_TEST_CASE(InputMatrixParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "InputMatrixParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -579,27 +586,28 @@ BOOST_AUTO_TEST_CASE(InputMatrixParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --matrix parameter should exist.
BOOST_REQUIRE(IO::HasParam("matrix"));
REQUIRE(IO::HasParam("matrix"));
// The --matrix_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("matrix_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("matrix_file"), runtime_error);
Log::Fatal.ignoreInput = false;
arma::mat dataset = IO::GetParam<arma::mat>("matrix");
arma::mat dataset2 = IO::GetParam<arma::mat>("matrix");
BOOST_REQUIRE_EQUAL(dataset.n_rows, 3);
BOOST_REQUIRE_EQUAL(dataset.n_cols, 1000);
BOOST_REQUIRE_EQUAL(dataset2.n_rows, 3);
BOOST_REQUIRE_EQUAL(dataset2.n_cols, 1000);
REQUIRE(dataset.n_rows == 3);
REQUIRE(dataset.n_cols == 1000);
REQUIRE(dataset2.n_rows == 3);
REQUIRE(dataset2.n_cols == 1000);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
REQUIRE(dataset[i] == Approx(dataset2[i]).epsilon(1e-12));
}
// Make sure we can correctly load required matrix parameters.
BOOST_AUTO_TEST_CASE(RequiredInputMatrixParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "RequiredInputMatrixParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -618,27 +626,28 @@ BOOST_AUTO_TEST_CASE(RequiredInputMatrixParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --matrix parameter should exist.
BOOST_REQUIRE(IO::HasParam("matrix"));
REQUIRE(IO::HasParam("matrix"));
// The --matrix_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("matrix_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("matrix_file"), runtime_error);
Log::Fatal.ignoreInput = false;
arma::mat dataset = IO::GetParam<arma::mat>("matrix");
arma::mat dataset2 = IO::GetParam<arma::mat>("matrix");
BOOST_REQUIRE_EQUAL(dataset.n_rows, 3);
BOOST_REQUIRE_EQUAL(dataset.n_cols, 1000);
BOOST_REQUIRE_EQUAL(dataset2.n_rows, 3);
BOOST_REQUIRE_EQUAL(dataset2.n_cols, 1000);
REQUIRE(dataset.n_rows == 3);
REQUIRE(dataset.n_cols == 1000);
REQUIRE(dataset2.n_rows == 3);
REQUIRE(dataset2.n_cols == 1000);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
REQUIRE(dataset[i] == Approx(dataset2[i]).epsilon(1e-12));
}
// Make sure loading required matrix options by alias succeeds.
BOOST_AUTO_TEST_CASE(RequiredInputMatrixParamAliasTest)
TEST_CASE_METHOD(IOTestDestroyer, "RequiredInputMatrixParamAliasTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -657,27 +666,28 @@ BOOST_AUTO_TEST_CASE(RequiredInputMatrixParamAliasTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --matrix parameter should exist.
BOOST_REQUIRE(IO::HasParam("matrix"));
REQUIRE(IO::HasParam("matrix"));
// The --matrix_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("matrix_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("matrix_file"), runtime_error);
Log::Fatal.ignoreInput = false;
arma::mat dataset = IO::GetParam<arma::mat>("matrix");
arma::mat dataset2 = IO::GetParam<arma::mat>("matrix");
BOOST_REQUIRE_EQUAL(dataset.n_rows, 3);
BOOST_REQUIRE_EQUAL(dataset.n_cols, 1000);
BOOST_REQUIRE_EQUAL(dataset2.n_rows, 3);
BOOST_REQUIRE_EQUAL(dataset2.n_cols, 1000);
REQUIRE(dataset.n_rows == 3);
REQUIRE(dataset.n_cols == 1000);
REQUIRE(dataset2.n_rows == 3);
REQUIRE(dataset2.n_cols == 1000);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
REQUIRE(dataset[i] == Approx(dataset2[i]).epsilon(1e-12));
}
// Make sure that when we don't pass a required matrix, parsing fails.
BOOST_AUTO_TEST_CASE(RequiredUnspecifiedInputMatrixParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "RequiredUnspecifiedInputMatrixParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -692,12 +702,13 @@ BOOST_AUTO_TEST_CASE(RequiredUnspecifiedInputMatrixParamTest)
// The const-cast is a little hacky but should be fine...
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(ParseCommandLine(argc, const_cast<char**>(argv)),
REQUIRE_THROWS_AS(ParseCommandLine(argc, const_cast<char**>(argv)),
std::exception);
Log::Fatal.ignoreInput = false;
}
BOOST_AUTO_TEST_CASE(InputMatrixNoTransposeParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "InputMatrixNoTransposeParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -716,26 +727,27 @@ BOOST_AUTO_TEST_CASE(InputMatrixNoTransposeParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --matrix parameter should exist.
BOOST_REQUIRE(IO::HasParam("matrix"));
REQUIRE(IO::HasParam("matrix"));
// The --matrix_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("matrix_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("matrix_file"), runtime_error);
Log::Fatal.ignoreInput = false;
arma::mat dataset = IO::GetParam<arma::mat>("matrix");
arma::mat dataset2 = IO::GetParam<arma::mat>("matrix");
BOOST_REQUIRE_EQUAL(dataset.n_rows, 1000);
BOOST_REQUIRE_EQUAL(dataset.n_cols, 3);
BOOST_REQUIRE_EQUAL(dataset2.n_rows, 1000);
BOOST_REQUIRE_EQUAL(dataset2.n_cols, 3);
REQUIRE(dataset.n_rows == 1000);
REQUIRE(dataset.n_cols == 3);
REQUIRE(dataset2.n_rows == 1000);
REQUIRE(dataset2.n_cols == 3);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
REQUIRE(dataset[i] == Approx(dataset2[i]).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(OutputMatrixParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "OutputMatrixParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -753,11 +765,11 @@ BOOST_AUTO_TEST_CASE(OutputMatrixParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --matrix parameter should exist.
BOOST_REQUIRE(IO::HasParam("matrix"));
REQUIRE(IO::HasParam("matrix"));
// The --matrix_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("matrix_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("matrix_file"), runtime_error);
Log::Fatal.ignoreInput = false;
// Since it's an output parameter, we don't need any input and don't need to
@@ -774,16 +786,16 @@ BOOST_AUTO_TEST_CASE(OutputMatrixParamTest)
arma::mat dataset2;
data::Load("test.csv", dataset2);
BOOST_REQUIRE_EQUAL(dataset.n_cols, dataset2.n_cols);
BOOST_REQUIRE_EQUAL(dataset.n_rows, dataset2.n_rows);
REQUIRE(dataset.n_cols == dataset2.n_cols);
REQUIRE(dataset.n_rows == dataset2.n_rows);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
REQUIRE(dataset[i] == Approx(dataset2[i]).epsilon(1e-12));
// Remove the file.
remove("test.csv");
}
BOOST_AUTO_TEST_CASE(OutputMatrixNoTransposeParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "OutputMatrixNoTransposeParamTest", "[IOTest]")
{
AddRequiredCLIOptions();
@@ -801,11 +813,11 @@ BOOST_AUTO_TEST_CASE(OutputMatrixNoTransposeParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// The --matrix parameter should exist.
BOOST_REQUIRE(IO::HasParam("matrix"));
REQUIRE(IO::HasParam("matrix"));
// The --matrix_file parameter should not exist (it should be transparent from
// inside the program).
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(IO::HasParam("matrix_file"), runtime_error);
REQUIRE_THROWS_AS(IO::HasParam("matrix_file"), runtime_error);
Log::Fatal.ignoreInput = false;
// Since it's an output parameter, we don't need any input and don't need to
@@ -822,16 +834,17 @@ BOOST_AUTO_TEST_CASE(OutputMatrixNoTransposeParamTest)
arma::mat dataset2;
data::Load("test.csv", dataset2, true, false);
BOOST_REQUIRE_EQUAL(dataset.n_cols, dataset2.n_cols);
BOOST_REQUIRE_EQUAL(dataset.n_rows, dataset2.n_rows);
REQUIRE(dataset.n_cols == dataset2.n_cols);
REQUIRE(dataset.n_rows == dataset2.n_rows);
for (size_t i = 0; i < dataset.n_elem; ++i)
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
REQUIRE(dataset[i] == Approx(dataset2[i]).epsilon(1e-12));
// Remove the file.
remove("test.csv");
}
BOOST_AUTO_TEST_CASE(IntParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "IntParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -846,11 +859,12 @@ BOOST_AUTO_TEST_CASE(IntParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
BOOST_REQUIRE(IO::HasParam("int"));
BOOST_REQUIRE_EQUAL(IO::GetParam<int>("int"), 3);
REQUIRE(IO::HasParam("int"));
REQUIRE(IO::GetParam<int>("int") == 3);
}
BOOST_AUTO_TEST_CASE(StringParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "StringParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -865,11 +879,12 @@ BOOST_AUTO_TEST_CASE(StringParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
BOOST_REQUIRE(IO::HasParam("string"));
BOOST_REQUIRE_EQUAL(IO::GetParam<string>("string"), string("3"));
REQUIRE(IO::HasParam("string"));
REQUIRE(IO::GetParam<string>("string") == string("3"));
}
BOOST_AUTO_TEST_CASE(DoubleParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "DoubleParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -884,11 +899,11 @@ BOOST_AUTO_TEST_CASE(DoubleParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
BOOST_REQUIRE(IO::HasParam("double"));
BOOST_REQUIRE_CLOSE(IO::GetParam<double>("double"), 3.12, 1e-10);
REQUIRE(IO::HasParam("double"));
REQUIRE(IO::GetParam<double>("double") == Approx(3.12).epsilon(1e-12));
}
BOOST_AUTO_TEST_CASE(RequiredOptionTest)
TEST_CASE_METHOD(IOTestDestroyer, "RequiredOptionTest", "[IOTest]")
{
AddRequiredCLIOptions();
@@ -900,12 +915,13 @@ BOOST_AUTO_TEST_CASE(RequiredOptionTest)
int argc = 1;
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(ParseCommandLine(argc, const_cast<char**>(argv)),
REQUIRE_THROWS_AS(ParseCommandLine(argc, const_cast<char**>(argv)),
runtime_error);
Log::Fatal.ignoreInput = false;
}
BOOST_AUTO_TEST_CASE(UnknownOptionTest)
TEST_CASE_METHOD(IOTestDestroyer, "UnknownOptionTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -916,7 +932,7 @@ BOOST_AUTO_TEST_CASE(UnknownOptionTest)
int argc = 2;
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(ParseCommandLine(argc, const_cast<char**>(argv)),
REQUIRE_THROWS_AS(ParseCommandLine(argc, const_cast<char**>(argv)),
runtime_error);
Log::Fatal.ignoreInput = false;
}
@@ -924,7 +940,8 @@ BOOST_AUTO_TEST_CASE(UnknownOptionTest)
/**
* Test that GetPrintableParam() works.
*/
BOOST_AUTO_TEST_CASE(UnmappedParamTest)
TEST_CASE_METHOD(IOTestDestroyer, "UnmappedParamTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -949,15 +966,15 @@ BOOST_AUTO_TEST_CASE(UnmappedParamTest)
ParseCommandLine(argc, const_cast<char**>(argv));
// Now check that we can get unmapped parameters.
BOOST_REQUIRE_EQUAL(IO::GetPrintableParam<arma::mat>("matrix"),
REQUIRE(IO::GetPrintableParam<arma::mat>("matrix") ==
"'test_data_3_1000.csv' (3x1000 matrix)");
// This will have size 0x0 since it's an output parameter, and it hasn't been
// set since ParseCommandLine() was called.
BOOST_REQUIRE_EQUAL(IO::GetPrintableParam<arma::mat>("matrix2"),
REQUIRE(IO::GetPrintableParam<arma::mat>("matrix2") ==
"'file2.csv' (0x0 matrix)");
BOOST_REQUIRE_EQUAL(IO::GetPrintableParam<GaussianKernel*>("kernel"),
REQUIRE(IO::GetPrintableParam<GaussianKernel*>("kernel") ==
"kernel.txt");
BOOST_REQUIRE_EQUAL(IO::GetPrintableParam<GaussianKernel*>("kernel2"),
REQUIRE(IO::GetPrintableParam<GaussianKernel*>("kernel2") ==
"kernel2.txt");
remove("kernel.txt");
@@ -967,7 +984,7 @@ BOOST_AUTO_TEST_CASE(UnmappedParamTest)
* Test that we can serialize a model and then deserialize it through the CLI
* interface.
*/
BOOST_AUTO_TEST_CASE(SerializationTest)
TEST_CASE_METHOD(IOTestDestroyer, "IOSerializationTest", "[IOTest]")
{
AddRequiredCLIOptions();
@@ -1001,7 +1018,7 @@ BOOST_AUTO_TEST_CASE(SerializationTest)
// Load the kernel from file.
GaussianKernel* gk2 = IO::GetParam<GaussianKernel*>("kernel");
BOOST_REQUIRE_CLOSE(gk2->Bandwidth(), 0.5, 1e-5);
REQUIRE(gk2->Bandwidth() == Approx(0.5).epsilon(1e-7));
// Clean up the memory...
delete gk2;
@@ -1013,7 +1030,8 @@ BOOST_AUTO_TEST_CASE(SerializationTest)
/**
* Test that an exception is thrown when a required model is not specified.
*/
BOOST_AUTO_TEST_CASE(RequiredModelTest)
TEST_CASE_METHOD(IOTestDestroyer, "RequiredModelTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -1026,7 +1044,7 @@ BOOST_AUTO_TEST_CASE(RequiredModelTest)
int argc = 1;
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(ParseCommandLine(argc, const_cast<char**>(argv)),
REQUIRE_THROWS_AS(ParseCommandLine(argc, const_cast<char**>(argv)),
runtime_error);
Log::Fatal.ignoreInput = false;
}
@@ -1034,7 +1052,8 @@ BOOST_AUTO_TEST_CASE(RequiredModelTest)
/**
* Test that we can load both a dataset and its associated info.
*/
BOOST_AUTO_TEST_CASE(MatrixAndDatasetInfoTest)
TEST_CASE_METHOD(IOTestDestroyer, "MatrixAndDatasetInfoTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -1074,32 +1093,32 @@ BOOST_AUTO_TEST_CASE(MatrixAndDatasetInfoTest)
DatasetInfo info = move(get<0>(IO::GetParam<TupleType>("dataset")));
arma::mat dataset = move(get<1>(IO::GetParam<TupleType>("dataset")));
BOOST_REQUIRE_EQUAL(info.Dimensionality(), 3);
REQUIRE(info.Dimensionality() == 3);
BOOST_REQUIRE(info.Type(0) == Datatype::categorical);
BOOST_REQUIRE_EQUAL(info.NumMappings(0), 3);
BOOST_REQUIRE(info.Type(1) == Datatype::numeric);
BOOST_REQUIRE(info.Type(2) == Datatype::categorical);
BOOST_REQUIRE_EQUAL(info.NumMappings(2), 2);
REQUIRE(info.Type(0) == Datatype::categorical);
REQUIRE(info.NumMappings(0) == 3);
REQUIRE(info.Type(1) == Datatype::numeric);
REQUIRE(info.Type(2) == Datatype::categorical);
REQUIRE(info.NumMappings(2) == 2);
BOOST_REQUIRE_EQUAL(dataset.n_rows, 3);
BOOST_REQUIRE_EQUAL(dataset.n_cols, 4);
REQUIRE(dataset.n_rows == 3);
REQUIRE(dataset.n_cols == 4);
// The first dimension must all be different (except the ones that are the
// same).
BOOST_REQUIRE_EQUAL(dataset(0, 0), dataset(0, 3));
BOOST_REQUIRE_NE(dataset(0, 0), dataset(0, 1));
BOOST_REQUIRE_NE(dataset(0, 1), dataset(0, 2));
BOOST_REQUIRE_NE(dataset(0, 2), dataset(0, 0));
REQUIRE(dataset(0, 0) == dataset(0, 3));
REQUIRE(dataset(0, 0) != dataset(0, 1));
REQUIRE(dataset(0, 1) != dataset(0, 2));
REQUIRE(dataset(0, 2) != dataset(0, 0));
BOOST_REQUIRE_CLOSE(dataset(1, 0), 1.0, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(1, 1), 2.34, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(1, 2), 1.03e5, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(1, 3), -1.3, 1e-5);
REQUIRE(dataset(1, 0) == Approx(1.0).epsilon(1e-7));
REQUIRE(dataset(1, 1) == Approx(2.34).epsilon(1e-7));
REQUIRE(dataset(1, 2) == Approx(1.03e5).epsilon(1e-7));
REQUIRE(dataset(1, 3) == Approx(-1.3).epsilon(1e-7));
BOOST_REQUIRE_EQUAL(dataset(2, 0), dataset(2, 2));
BOOST_REQUIRE_EQUAL(dataset(2, 1), dataset(2, 3));
BOOST_REQUIRE_NE(dataset(2, 0), dataset(2, 1));
REQUIRE(dataset(2, 0) == dataset(2, 2));
REQUIRE(dataset(2, 1) == dataset(2, 3));
REQUIRE(dataset(2, 0) != dataset(2, 1));
remove("test.arff");
}
@@ -1107,7 +1126,7 @@ BOOST_AUTO_TEST_CASE(MatrixAndDatasetInfoTest)
/**
* Test that we can access a parameter before we load it.
*/
BOOST_AUTO_TEST_CASE(RawIntegralParameter)
TEST_CASE_METHOD(IOTestDestroyer, "RawIntegralParameter", "[IOTest]")
{
AddRequiredCLIOptions();
@@ -1123,14 +1142,14 @@ BOOST_AUTO_TEST_CASE(RawIntegralParameter)
IO::GetRawParam<double>("double") = 3.0;
// Now when we get it, it should be what we just set it to.
BOOST_REQUIRE_CLOSE(IO::GetParam<double>("double"), 3.0, 1e-5);
REQUIRE(IO::GetParam<double>("double") == Approx(3.0).epsilon(1e-7));
}
/**
* Test that we can load a dataset with a pre-set mapping through
* IO::GetRawParam().
*/
BOOST_AUTO_TEST_CASE(RawDatasetInfoLoadParameter)
TEST_CASE_METHOD(IOTestDestroyer, "RawDatasetInfoLoadParameter", "[IOTest]")
{
AddRequiredCLIOptions();
@@ -1181,18 +1200,18 @@ BOOST_AUTO_TEST_CASE(RawDatasetInfoLoadParameter)
std::get<1>(IO::GetParam<tuple<DatasetInfo, arma::mat>>("tuple"));
// Check the values.
BOOST_REQUIRE_CLOSE(dataset(0, 0), 2.0, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(1, 0), 1.0, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(2, 0), 1.0, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(0, 1), 1.0, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(1, 1), 2.34, 1e-5);
BOOST_REQUIRE_SMALL(dataset(2, 1), 1e-5);
BOOST_REQUIRE_SMALL(dataset(0, 2), 1e-5);
BOOST_REQUIRE_CLOSE(dataset(1, 2), 1.03e+5, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(2, 2), 1.0, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(0, 3), 2.0, 1e-5);
BOOST_REQUIRE_CLOSE(dataset(1, 3), -1.3, 1e-5);
BOOST_REQUIRE_SMALL(dataset(2, 3), 1e-5);
REQUIRE(dataset(0, 0) == Approx(2.0).epsilon(1e-7));
REQUIRE(dataset(1, 0) == Approx(1.0).epsilon(1e-7));
REQUIRE(dataset(2, 0) == Approx(1.0).epsilon(1e-7));
REQUIRE(dataset(0, 1) == Approx(1.0).epsilon(1e-7));
REQUIRE(dataset(1, 1) == Approx(2.34).epsilon(1e-7));
REQUIRE(dataset(2, 1) == Approx(0.0).margin(1e-5));
REQUIRE(dataset(0, 2) == Approx(0.0).margin(1e-5));
REQUIRE(dataset(1, 2) == Approx(1.03e+5).epsilon(1e-7));
REQUIRE(dataset(2, 2) == Approx(1.0).epsilon(1e-7));
REQUIRE(dataset(0, 3) == Approx(2.0).epsilon(1e-7));
REQUIRE(dataset(1, 3) == Approx(-1.3).epsilon(1e-7));
REQUIRE(dataset(2, 3) == Approx(0.0).margin(1e-5));
remove("test.arff");
}
@@ -1200,7 +1219,8 @@ BOOST_AUTO_TEST_CASE(RawDatasetInfoLoadParameter)
/**
* Make sure typenames are properly stored.
*/
BOOST_AUTO_TEST_CASE(CppNameTest)
TEST_CASE_METHOD(IOTestDestroyer, "CppNameTest",
"[IOTest]")
{
AddRequiredCLIOptions();
@@ -1209,9 +1229,7 @@ BOOST_AUTO_TEST_CASE(CppNameTest)
PARAM_DOUBLE_IN("double", "Test double", "d", 0.0);
// Check that the C++ typenames are right.
BOOST_REQUIRE_EQUAL(IO::Parameters().at("matrix").cppType, "arma::mat");
BOOST_REQUIRE_EQUAL(IO::Parameters().at("help").cppType, "bool");
BOOST_REQUIRE_EQUAL(IO::Parameters().at("double").cppType, "double");
REQUIRE(IO::Parameters().at("matrix").cppType == "arma::mat");
REQUIRE(IO::Parameters().at("help").cppType == "bool");
REQUIRE(IO::Parameters().at("double").cppType == "double");
}
BOOST_AUTO_TEST_SUITE_END();
+44 -49
View File
@@ -10,19 +10,15 @@
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
// Note: We don't use BOOST_REQUIRE_CLOSE in the code below because we need
// to use FPC_WEAK, and it's not at all intuitive how to do that.
#include <mlpack/methods/lars/lars.hpp>
#include <mlpack/core/data/load.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
#include "test_catch_tools.hpp"
using namespace mlpack;
using namespace mlpack::regression;
BOOST_AUTO_TEST_SUITE(LARSTest);
void GenerateProblem(
arma::mat& X, arma::rowvec& y, size_t nPoints, size_t nDims)
{
@@ -40,17 +36,18 @@ void LARSVerifyCorrectness(arma::vec beta, arma::vec errCorr, double lambda)
if (beta(j) == 0)
{
// Make sure that |errCorr(j)| <= lambda.
BOOST_REQUIRE_SMALL(std::max(fabs(errCorr(j)) - lambda, 0.0), tol);
REQUIRE(std::max(fabs(errCorr(j)) - lambda, 0.0) ==
Approx(0.0).margin(tol));
}
else if (beta(j) < 0)
{
// Make sure that errCorr(j) == lambda.
BOOST_REQUIRE_SMALL(errCorr(j) - lambda, tol);
REQUIRE(errCorr(j) - lambda == Approx(0.0).margin(tol));
}
else // beta(j) > 0
{
// Make sure that errCorr(j) == -lambda.
BOOST_REQUIRE_SMALL(errCorr(j) + lambda, tol);
REQUIRE(errCorr(j) + lambda == Approx(0.0).margin(tol));
}
}
}
@@ -85,23 +82,23 @@ void LassoTest(size_t nPoints, size_t nDims, bool elasticNet, bool useCholesky)
}
}
BOOST_AUTO_TEST_CASE(LARSTestLassoCholesky)
TEST_CASE("LARSTestLassoCholesky", "[LARSTest]")
{
LassoTest(100, 10, false, true);
}
BOOST_AUTO_TEST_CASE(LARSTestLassoGram)
TEST_CASE("LARSTestLassoGram", "[LARSTest]")
{
LassoTest(100, 10, false, false);
}
BOOST_AUTO_TEST_CASE(LARSTestElasticNetCholesky)
TEST_CASE("LARSTestElasticNetCholesky", "[LARSTest]")
{
LassoTest(100, 10, true, true);
}
BOOST_AUTO_TEST_CASE(LARSTestElasticNetGram)
TEST_CASE("LARSTestElasticNetGram", "[LARSTest]")
{
LassoTest(100, 10, true, false);
}
@@ -109,7 +106,7 @@ BOOST_AUTO_TEST_CASE(LARSTestElasticNetGram)
// Ensure that LARS doesn't crash when the data has linearly dependent features
// (meaning that there is a singularity). This test uses the Cholesky
// factorization.
BOOST_AUTO_TEST_CASE(CholeskySingularityTest)
TEST_CASE("CholeskySingularityTest", "[LARSTest]")
{
arma::mat X;
arma::mat Y;
@@ -133,7 +130,7 @@ BOOST_AUTO_TEST_CASE(CholeskySingularityTest)
}
// Same as the above test but with no cholesky factorization.
BOOST_AUTO_TEST_CASE(NoCholeskySingularityTest)
TEST_CASE("NoCholeskySingularityTest", "[LARSTest]")
{
arma::mat X;
arma::mat Y;
@@ -158,7 +155,7 @@ BOOST_AUTO_TEST_CASE(NoCholeskySingularityTest)
}
// Make sure that Predict() provides reasonable enough solutions.
BOOST_AUTO_TEST_CASE(PredictTest)
TEST_CASE("PredictTest", "[LARSTest]")
{
for (size_t i = 0; i < 2; ++i)
{
@@ -185,20 +182,20 @@ BOOST_AUTO_TEST_CASE(PredictTest)
lars.Predict(X, predictions);
arma::vec adjPred = X * predictions.t();
BOOST_REQUIRE_EQUAL(predictions.n_elem, 1000);
REQUIRE(predictions.n_elem == 1000);
for (size_t i = 0; i < betaOptPred.n_elem; ++i)
{
if (std::abs(betaOptPred[i]) < 1e-5)
BOOST_REQUIRE_SMALL(adjPred[i], 1e-5);
REQUIRE(adjPred[i] == Approx(0.0).margin(1e-5));
else
BOOST_REQUIRE_CLOSE(adjPred[i], betaOptPred[i], 1e-5);
REQUIRE(adjPred[i] == Approx(betaOptPred[i]).epsilon(1e-7));
}
}
}
}
}
BOOST_AUTO_TEST_CASE(PredictRowMajorTest)
TEST_CASE("PredictRowMajorTest", "[LARSTest]")
{
arma::mat X;
arma::rowvec y;
@@ -217,20 +214,20 @@ BOOST_AUTO_TEST_CASE(PredictRowMajorTest)
lars.Predict(X, colMajorPred);
lars.Predict(X.t(), rowMajorPred, true);
BOOST_REQUIRE_EQUAL(colMajorPred.n_elem, rowMajorPred.n_elem);
REQUIRE(colMajorPred.n_elem == rowMajorPred.n_elem);
for (size_t i = 0; i < colMajorPred.n_elem; ++i)
{
if (std::abs(colMajorPred[i]) < 1e-5)
BOOST_REQUIRE_SMALL(rowMajorPred[i], 1e-5);
REQUIRE(rowMajorPred[i] == Approx(0.0).margin(1e-5));
else
BOOST_REQUIRE_CLOSE(colMajorPred[i], rowMajorPred[i], 1e-5);
REQUIRE(colMajorPred[i] == Approx(rowMajorPred[i]).epsilon(1e-7));
}
}
/**
* Make sure that if we train twice, there is no issue.
*/
BOOST_AUTO_TEST_CASE(RetrainTest)
TEST_CASE("RetrainTest", "[LARSTest]")
{
arma::mat origX;
arma::rowvec origY;
@@ -257,7 +254,7 @@ BOOST_AUTO_TEST_CASE(RetrainTest)
* Make sure if we train twice using the Cholesky decomposition, there is no
* issue.
*/
BOOST_AUTO_TEST_CASE(RetrainCholeskyTest)
TEST_CASE("RetrainCholeskyTest", "[LARSTest]")
{
arma::mat origX;
arma::rowvec origY;
@@ -284,7 +281,7 @@ BOOST_AUTO_TEST_CASE(RetrainCholeskyTest)
* Make sure that we get correct solution coefficients when running training
* and accessing solution coefficients separately.
*/
BOOST_AUTO_TEST_CASE(TrainingAndAccessingBetaTest)
TEST_CASE("TrainingAndAccessingBetaTest", "[LARSTest]")
{
arma::mat X;
arma::rowvec y;
@@ -298,16 +295,16 @@ BOOST_AUTO_TEST_CASE(TrainingAndAccessingBetaTest)
LARS lars2;
lars2.Train(X, y);
BOOST_REQUIRE_EQUAL(beta.n_elem, lars2.Beta().n_elem);
REQUIRE(beta.n_elem == lars2.Beta().n_elem);
for (size_t i = 0; i < beta.n_elem; ++i)
BOOST_REQUIRE_CLOSE(beta[i], lars2.Beta()[i], 1e-5);
REQUIRE(beta[i] == Approx(lars2.Beta()[i]).epsilon(1e-7));
}
/**
* Make sure that we learn the same when running training separately and through
* constructor. Test it with default parameters.
*/
BOOST_AUTO_TEST_CASE(TrainingConstructorWithDefaultsTest)
TEST_CASE("TrainingConstructorWithDefaultsTest", "[LARSTest]")
{
arma::mat X;
arma::rowvec y;
@@ -320,16 +317,16 @@ BOOST_AUTO_TEST_CASE(TrainingConstructorWithDefaultsTest)
LARS lars2(X, y);
BOOST_REQUIRE_EQUAL(beta.n_elem, lars2.Beta().n_elem);
REQUIRE(beta.n_elem == lars2.Beta().n_elem);
for (size_t i = 0; i < beta.n_elem; ++i)
BOOST_REQUIRE_CLOSE(beta[i], lars2.Beta()[i], 1e-5);
REQUIRE(beta[i] == Approx(lars2.Beta()[i]).epsilon(1e-7));
}
/**
* Make sure that we learn the same when running training separately and through
* constructor. Test it with non default parameters.
*/
BOOST_AUTO_TEST_CASE(TrainingConstructorWithNonDefaultsTest)
TEST_CASE("TrainingConstructorWithNonDefaultsTest", "[LARSTest]")
{
arma::mat X;
arma::rowvec y;
@@ -347,15 +344,15 @@ BOOST_AUTO_TEST_CASE(TrainingConstructorWithNonDefaultsTest)
LARS lars2(X, y, transposeData, useCholesky, lambda1, lambda2);
BOOST_REQUIRE_EQUAL(beta.n_elem, lars2.Beta().n_elem);
REQUIRE(beta.n_elem == lars2.Beta().n_elem);
for (size_t i = 0; i < beta.n_elem; ++i)
BOOST_REQUIRE_CLOSE(beta[i], lars2.Beta()[i], 1e-5);
REQUIRE(beta[i] == Approx(lars2.Beta()[i]).epsilon(1e-7));
}
/**
* Test that LARS::Train() returns finite error value.
*/
BOOST_AUTO_TEST_CASE(LARSTrainReturnCorrelation)
TEST_CASE("LARSTrainReturnCorrelation", "[LARSTest]")
{
arma::mat X;
arma::mat Y;
@@ -373,35 +370,35 @@ BOOST_AUTO_TEST_CASE(LARSTrainReturnCorrelation)
arma::vec betaOpt1;
double error = lars1.Train(X, y, betaOpt1);
BOOST_REQUIRE_EQUAL(std::isfinite(error), true);
REQUIRE(std::isfinite(error) == true);
// Test without Cholesky decomposition and with lasso.
LARS lars2(false, lambda1, 0.0);
arma::vec betaOpt2;
error = lars2.Train(X, y, betaOpt2);
BOOST_REQUIRE_EQUAL(std::isfinite(error), true);
REQUIRE(std::isfinite(error) == true);
// Test with Cholesky decomposition and with elasticnet.
LARS lars3(true, lambda1, lambda2);
arma::vec betaOpt3;
error = lars3.Train(X, y, betaOpt3);
BOOST_REQUIRE_EQUAL(std::isfinite(error), true);
REQUIRE(std::isfinite(error) == true);
// Test without Cholesky decomposition and with elasticnet.
LARS lars4(false, lambda1, lambda2);
arma::vec betaOpt4;
error = lars4.Train(X, y, betaOpt4);
BOOST_REQUIRE_EQUAL(std::isfinite(error), true);
REQUIRE(std::isfinite(error) == true);
}
/**
* Test that LARS::ComputeError() returns error value less than 1
* and greater than 0.
*/
BOOST_AUTO_TEST_CASE(LARSTestComputeError)
TEST_CASE("LARSTestComputeError", "[LARSTest]")
{
arma::mat X;
arma::mat Y;
@@ -416,15 +413,15 @@ BOOST_AUTO_TEST_CASE(LARSTestComputeError)
double train1 = lars1.Train(X, y, betaOpt1);
double cost = lars1.ComputeError(X, y);
BOOST_REQUIRE_EQUAL(cost <= 1, true);
BOOST_REQUIRE_EQUAL(cost >= 0, true);
BOOST_REQUIRE_EQUAL(cost == train1, true);
REQUIRE(cost <= 1);
REQUIRE(cost >= 0);
REQUIRE(cost == train1);
}
/**
* Simple test for LARS copy constructor.
*/
BOOST_AUTO_TEST_CASE(LARSCopyConstructorTest)
TEST_CASE("LARSCopyConstructorTest", "[LARSTest]")
{
arma::mat features, Y;
arma::rowvec targets;
@@ -447,13 +444,13 @@ BOOST_AUTO_TEST_CASE(LARSCopyConstructorTest)
// The output of both models should be the same.
CheckMatrices(predictions, predictionsFromCopiedModel);
// Check if we can train the model again.
BOOST_REQUIRE_NO_THROW(models[0].Train(features, targets));
REQUIRE_NOTHROW(models[0].Train(features, targets));
// Check if we can train the copied model.
mlpack::regression::LARS glm2(false, 0.1, 0.1);
models.emplace_back(glm2); // Call the copy constructor.
BOOST_REQUIRE_NO_THROW(glm2.Train(features, targets));
BOOST_REQUIRE_NO_THROW(models[1].Train(features, targets));
REQUIRE_NOTHROW(glm2.Train(features, targets));
REQUIRE_NOTHROW(models[1].Train(features, targets));
// Create a copy using assignment operator.
mlpack::regression::LARS glm3 = glm2;
@@ -462,5 +459,3 @@ BOOST_AUTO_TEST_CASE(LARSCopyConstructorTest)
// The output of both models should be the same.
CheckMatrices(predictions, predictionsFromCopiedModel);
}
BOOST_AUTO_TEST_SUITE_END();
+66 -71
View File
@@ -15,18 +15,15 @@
#include <mlpack/methods/ann/layer/layer_types.hpp>
#include <mlpack/methods/ann/layer_names.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
using namespace mlpack;
using namespace ann;
BOOST_AUTO_TEST_SUITE(LayerNamesTest);
/**
* Test if the LayerNameVisitor works properly.
*/
BOOST_AUTO_TEST_CASE(LayerNameVisitorTest)
TEST_CASE("LayerNameVisitorTest", "[LayerNamesTest]")
{
LayerTypes<> atrousConvolution = new AtrousConvolution<>();
LayerTypes<> alphaDropout = new AlphaDropout<>();
@@ -63,70 +60,70 @@ BOOST_AUTO_TEST_CASE(LayerNameVisitorTest)
// Bilinear interpolation is not yet supported by the string converter.
LayerTypes<> unsupportedLayer = new BilinearInterpolation<>();
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
atrousConvolution) == "atrousconvolution");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
alphaDropout) == "alphadropout");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
batchNorm) == "batchnorm");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
constant) == "constant");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
convolution) == "convolution");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
dropConnect) == "dropconnect");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
dropout) == "dropout");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
flexibleReLU) == "flexiblerelu");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
layerNorm) == "layernorm");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
linear) == "linear");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
linearNoBias) == "linearnobias");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
maxPooling) == "maxpooling");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
meanPooling) == "meanpooling");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
multiplyConstant) == "multiplyconstant");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
reLULayer) == "relu");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
transposedConvolution) == "transposedconvolution");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
identityLayer) == "identity");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
tanHLayer) == "tanh");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
eLU) == "elu");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
hardTanH) == "hardtanh");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
leakyReLU) == "leakyrelu");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
pReLU) == "prelu");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
sigmoidLayer) == "sigmoid");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
logSoftMax) == "logsoftmax");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
unsupportedLayer) == "unsupported");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
lstmLayer) == "lstm");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
creluLayer) == "crelu");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
highwayLayer) == "highway");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
gruLayer) == "gru");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
glimpseLayer) == "glimpse");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
fastlstmLayer) == "fastlstm");
BOOST_REQUIRE(boost::apply_visitor(LayerNameVisitor(),
weightnormLayer) == "weightnorm");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
atrousConvolution) == "atrousconvolution");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
alphaDropout) == "alphadropout");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
batchNorm) == "batchnorm");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
constant) == "constant");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
convolution) == "convolution");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
dropConnect) == "dropconnect");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
dropout) == "dropout");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
flexibleReLU) == "flexiblerelu");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
layerNorm) == "layernorm");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
linear) == "linear");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
linearNoBias) == "linearnobias");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
maxPooling) == "maxpooling");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
meanPooling) == "meanpooling");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
multiplyConstant) == "multiplyconstant");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
reLULayer) == "relu");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
transposedConvolution) == "transposedconvolution");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
identityLayer) == "identity");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
tanHLayer) == "tanh");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
eLU) == "elu");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
hardTanH) == "hardtanh");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
leakyReLU) == "leakyrelu");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
pReLU) == "prelu");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
sigmoidLayer) == "sigmoid");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
logSoftMax) == "logsoftmax");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
unsupportedLayer) == "unsupported");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
lstmLayer) == "lstm");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
creluLayer) == "crelu");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
highwayLayer) == "highway");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
gruLayer) == "gru");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
glimpseLayer) == "glimpse");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
fastlstmLayer) == "fastlstm");
REQUIRE(boost::apply_visitor(LayerNameVisitor(),
weightnormLayer) == "weightnorm");
// Delete all instances.
boost::apply_visitor(DeleteVisitor(), atrousConvolution);
boost::apply_visitor(DeleteVisitor(), alphaDropout);
@@ -161,5 +158,3 @@ BOOST_AUTO_TEST_CASE(LayerNameVisitorTest)
boost::apply_visitor(DeleteVisitor(), fastlstmLayer);
boost::apply_visitor(DeleteVisitor(), weightnormLayer);
}
BOOST_AUTO_TEST_SUITE_END();
+45 -38
View File
@@ -14,20 +14,18 @@
#include <mlpack/core.hpp>
#include <mlpack/core/math/lin_alg.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
#include "test_catch_tools.hpp"
using namespace arma;
using namespace mlpack;
using namespace mlpack::math;
BOOST_AUTO_TEST_SUITE(LinAlgTest);
/**
* Test for linalg__private::Center(). There are no edge cases here, so we'll
* just try it once for now.
*/
BOOST_AUTO_TEST_CASE(TestCenterA)
TEST_CASE("TestCenterA", "[LinAlgTest]")
{
mat tmp(5, 5);
// [[0 0 0 0 0]
@@ -51,11 +49,16 @@ BOOST_AUTO_TEST_CASE(TestCenterA)
// [-6 -3 0 3 6 ]
// [-8 -4 0 4 8]]
for (int row = 0; row < 5; row++)
{
for (int col = 0; col < 5; col++)
BOOST_REQUIRE_CLOSE(tmp_out(row, col), (double) (col - 2) * row, 1e-5);
{
REQUIRE(tmp_out(row, col) ==
Approx((double) (col - 2) * row).epsilon(1e-7));
}
}
}
BOOST_AUTO_TEST_CASE(TestCenterB)
TEST_CASE("TestCenterB", "[LinAlgTest]")
{
mat tmp(5, 6);
for (int row = 0; row < 5; row++)
@@ -74,11 +77,16 @@ BOOST_AUTO_TEST_CASE(TestCenterB)
// [-7.5 -4.5 -1.5 1.5 1.5 4.5]
// [-10 -6 -2 2 6 10 ]]
for (int row = 0; row < 5; row++)
{
for (int col = 0; col < 6; col++)
BOOST_REQUIRE_CLOSE(tmp_out(row, col), (double) (col - 2.5) * row, 1e-5);
{
REQUIRE(tmp_out(row, col) ==
Approx((double) (col - 2.5) * row).epsilon(1e-7));
}
}
}
BOOST_AUTO_TEST_CASE(TestOrthogonalize)
TEST_CASE("TestOrthogonalize", "[LinAlgTest]")
{
// Generate a random matrix; then, orthogonalize it and test if it's
// orthogonal.
@@ -96,18 +104,18 @@ BOOST_AUTO_TEST_CASE(TestOrthogonalize)
if (row == col)
{
if (std::abs(test(row, col)) > 1e-10)
BOOST_REQUIRE_CLOSE(test(row, col), ival, 1e-10);
REQUIRE(test(row, col) == Approx(ival).epsilon(1e-11));
}
else
{
BOOST_REQUIRE_SMALL(test(row, col), 1e-10);
REQUIRE(test(row, col) == Approx(0.0).margin(1e-10));
}
}
}
}
// Test RemoveRows().
BOOST_AUTO_TEST_CASE(TestRemoveRows)
TEST_CASE("TestRemoveRows", "[LinAlgTest]")
{
// Run this test several times.
for (size_t run = 0; run < 10; ++run)
@@ -150,7 +158,7 @@ BOOST_AUTO_TEST_CASE(TestRemoveRows)
else
{
// Compare.
BOOST_REQUIRE_EQUAL(accu(input.row(row) == output.row(outputRow)), 200);
REQUIRE(accu(input.row(row) == output.row(outputRow)) == 200);
// Increment output row counter.
++outputRow;
@@ -159,7 +167,7 @@ BOOST_AUTO_TEST_CASE(TestRemoveRows)
}
}
BOOST_AUTO_TEST_CASE(TestSvecSmat)
TEST_CASE("TestSvecSmat", "[LinAlgTest]")
{
arma::mat X(3, 3);
X(0, 0) = 0; X(0, 1) = 1, X(0, 2) = 2;
@@ -168,23 +176,24 @@ BOOST_AUTO_TEST_CASE(TestSvecSmat)
arma::vec sx;
Svec(X, sx);
BOOST_REQUIRE_CLOSE(sx(0), 0, 1e-7);
BOOST_REQUIRE_CLOSE(sx(1), M_SQRT2 * 1., 1e-7);
BOOST_REQUIRE_CLOSE(sx(2), M_SQRT2 * 2., 1e-7);
BOOST_REQUIRE_CLOSE(sx(3), 3., 1e-7);
BOOST_REQUIRE_CLOSE(sx(4), M_SQRT2 * 4., 1e-7);
BOOST_REQUIRE_CLOSE(sx(5), 5., 1e-7);
REQUIRE(sx(0) == Approx(0).epsilon(1e-9));
REQUIRE(sx(1) == Approx(M_SQRT2 * 1.).epsilon(1e-9));
REQUIRE(sx(2) == Approx(M_SQRT2 * 2.).epsilon(1e-9));
REQUIRE(sx(3) == Approx(3.).epsilon(1e-9));
REQUIRE(sx(4) == Approx(M_SQRT2 * 4.).epsilon(1e-9));
REQUIRE(sx(5) == Approx(5.).epsilon(1e-9));
arma::mat Xtest;
Smat(sx, Xtest);
BOOST_REQUIRE_EQUAL(Xtest.n_rows, 3);
BOOST_REQUIRE_EQUAL(Xtest.n_cols, 3);
REQUIRE(Xtest.n_rows == 3);
REQUIRE(Xtest.n_cols == 3);
for (size_t i = 0; i < 3; ++i)
for (size_t j = 0; j < 3; ++j)
BOOST_REQUIRE_CLOSE(X(i, j), Xtest(i, j), 1e-7);
REQUIRE(X(i, j) == Approx(Xtest(i, j)).epsilon(1e-9));
}
BOOST_AUTO_TEST_CASE(TestSparseSvec)
TEST_CASE("TestSparseSvec", "[LinAlgTest]")
{
arma::sp_mat X;
X.zeros(3, 3);
@@ -200,15 +209,15 @@ BOOST_AUTO_TEST_CASE(TestSparseSvec)
const double v4 = sx(4);
const double v5 = sx(5);
BOOST_REQUIRE_CLOSE(v0, 0, 1e-7);
BOOST_REQUIRE_CLOSE(v1, M_SQRT2 * 1., 1e-7);
BOOST_REQUIRE_CLOSE(v2, 0, 1e-7);
BOOST_REQUIRE_CLOSE(v3, 0, 1e-7);
BOOST_REQUIRE_CLOSE(v4, 0, 1e-7);
BOOST_REQUIRE_CLOSE(v5, 0, 1e-7);
REQUIRE(v0 == Approx(0).epsilon(1e-9));
REQUIRE(v1 == Approx(M_SQRT2 * 1.).epsilon(1e-9));
REQUIRE(v2 == Approx(0).epsilon(1e-9));
REQUIRE(v3 == Approx(0).epsilon(1e-9));
REQUIRE(v4 == Approx(0).epsilon(1e-9));
REQUIRE(v5 == Approx(0).epsilon(1e-9));
}
BOOST_AUTO_TEST_CASE(TestSymKronIdSimple)
TEST_CASE("TestSymKronIdSimple", "[LinAlgTest]")
{
arma::mat A(3, 3);
A(0, 0) = 1; A(0, 1) = 2, A(0, 2) = 3;
@@ -226,12 +235,12 @@ BOOST_AUTO_TEST_CASE(TestSymKronIdSimple)
arma::vec rhs;
Svec(Rhs, rhs);
BOOST_REQUIRE_EQUAL(lhs.n_elem, rhs.n_elem);
REQUIRE(lhs.n_elem == rhs.n_elem);
for (size_t j = 0; j < lhs.n_elem; ++j)
BOOST_REQUIRE_CLOSE(lhs(j), rhs(j), 1e-5);
REQUIRE(lhs(j) == Approx(rhs(j)).epsilon(1e-7));
}
BOOST_AUTO_TEST_CASE(TestSymKronId)
TEST_CASE("TestSymKronId", "[LinAlgTest]")
{
const size_t n = 10;
arma::mat A = arma::randu<arma::mat>(n, n);
@@ -252,10 +261,8 @@ BOOST_AUTO_TEST_CASE(TestSymKronId)
arma::vec rhs;
Svec(Rhs, rhs);
BOOST_REQUIRE_EQUAL(lhs.n_elem, rhs.n_elem);
REQUIRE(lhs.n_elem == rhs.n_elem);
for (size_t j = 0; j < lhs.n_elem; ++j)
BOOST_REQUIRE_CLOSE(lhs(j), rhs(j), 1e-5);
REQUIRE(lhs(j) == Approx(rhs(j)).epsilon(1e-7));
}
}
BOOST_AUTO_TEST_SUITE_END();
@@ -18,8 +18,8 @@ static const std::string testName = "HoeffdingTree";
#include <mlpack/methods/hoeffding_trees/hoeffding_tree_main.cpp>
#include "test_helper.hpp"
#include <boost/test/unit_test.hpp>
#include "../test_tools.hpp"
#include "../catch.hpp"
#include "../test_catch_tools.hpp"
using namespace mlpack;
using namespace data;
@@ -41,27 +41,25 @@ struct HoeffdingTreeTestFixture
}
};
BOOST_FIXTURE_TEST_SUITE(HoeffdingTreeMainTest,
HoeffdingTreeTestFixture);
/**
* Check that number of output points and
* number of input points are equal.
*/
BOOST_AUTO_TEST_CASE(HoeffdingTreeOutputDimensionTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingTreeOutputDimensionTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
size_t testSize = testData.n_cols;
@@ -75,36 +73,34 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeOutputDimensionTest)
mlpackMain();
// Check that number of output points are equal to number of input points.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_cols, testSize);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("probabilities").n_cols,
testSize);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_cols == testSize);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_cols == testSize);
// Check number of output rows equals 1 for probabilities and predictions.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_rows, 1);
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::mat>("probabilities").n_rows, 1);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_rows == 1);
}
/**
* Check that number of output points and number
* of input points are equal for categorical dataset.
*/
BOOST_AUTO_TEST_CASE(HoeffdingTreeCategoricalOutputDimensionTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture,
"HoeffdingTreeCategoricalOutputDimensionTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
if (!data::Load("braziltourism.arff", inputData, info))
BOOST_FAIL("Cannot load train dataset braziltourism.arff!");
FAIL("Cannot load train dataset braziltourism.arff!");
arma::Row<size_t> labels;
if (!data::Load("braziltourism_labels.txt", labels))
BOOST_FAIL("Cannot load labels for braziltourism_labels.txt");
FAIL("Cannot load labels for braziltourism_labels.txt");
arma::mat testData;
if (!data::Load("braziltourism_test.arff", testData, info))
BOOST_FAIL("Cannot load test dataset braziltourism_test.arff!");
FAIL("Cannot load test dataset braziltourism_test.arff!");
size_t testSize = testData.n_cols;
@@ -118,36 +114,33 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeCategoricalOutputDimensionTest)
mlpackMain();
// Check that number of output points are equal to number of input points.
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::Row<size_t>>
("predictions").n_cols, testSize);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("probabilities").n_cols,
testSize);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_cols == testSize);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_cols == testSize);
// Check number of output rows equals 1 for probabilities and predictions.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_rows, 1);
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::mat>("probabilities").n_rows, 1);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_rows == 1);
}
/**
* Check whether providing labels explicitly and extracting from last
* dimension give the same output.
*/
BOOST_AUTO_TEST_CASE(HoeffdingTreeLabelLessTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingTreeLabelLessTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Append labels to the training set.
inputData.resize(inputData.n_rows+1, inputData.n_cols);
@@ -165,17 +158,13 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeLabelLessTest)
mlpackMain();
// Check that number of output points are equal to number of input points.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_cols, testSize);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("probabilities").n_cols,
testSize);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_cols == testSize);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_cols == testSize);
// Check number of output rows equals number of classes in case of
// probabilities and 1 for predictions.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_rows, 1);
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::mat>("probabilities").n_rows, 1);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_rows == 1);
// Reset passed parameters.
IO::GetSingleton().Parameters()["training"].wasPassed = false;
@@ -199,16 +188,12 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeLabelLessTest)
mlpackMain();
// Check that number of output points are equal to number of input points.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_cols, testSize);
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::mat>("probabilities").n_cols, testSize);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_cols == testSize);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_cols == testSize);
// Check number of output rows equals 1 for probabilities and predictions.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_rows, 1);
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::mat>("probabilities").n_rows, 1);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_rows == 1);
// Check that initial and current predictions are same.
CheckMatrices(
@@ -220,20 +205,21 @@ BOOST_AUTO_TEST_CASE(HoeffdingTreeLabelLessTest)
/**
* Ensure that saved model can be used again.
*/
BOOST_AUTO_TEST_CASE(HoeffdingModelReuseTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingModelReuseTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
size_t testSize = testData.n_cols;
@@ -257,7 +243,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingModelReuseTest)
IO::GetSingleton().Parameters()["test"].wasPassed = false;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input trained model.
SetInputParam("test", std::make_tuple(info, testData));
@@ -267,15 +253,12 @@ BOOST_AUTO_TEST_CASE(HoeffdingModelReuseTest)
mlpackMain();
// Check that number of output points are equal to number of input points.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_cols, testSize);
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::mat>("probabilities").n_cols, testSize);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_cols == testSize);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_cols == testSize);
// Check number of output rows equals 1 for probabilities and predictions.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_rows, 1);
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("probabilities").n_rows, 1);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_rows == 1);
// Check that initial predictions and predictions using saved model are same.
CheckMatrices(
@@ -287,20 +270,21 @@ BOOST_AUTO_TEST_CASE(HoeffdingModelReuseTest)
/**
* Ensure that saved model trained on categorical dataset can be used again.
*/
BOOST_AUTO_TEST_CASE(HoeffdingModelCategoricalReuseTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingModelCategoricalReuseTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
if (!data::Load("braziltourism.arff", inputData, info))
BOOST_FAIL("Cannot load train dataset braziltourism.arff!");
FAIL("Cannot load train dataset braziltourism.arff!");
arma::Row<size_t> labels;
if (!data::Load("braziltourism_labels.txt", labels))
BOOST_FAIL("Cannot load labels for braziltourism_labels.txt");
FAIL("Cannot load labels for braziltourism_labels.txt");
arma::mat testData;
if (!data::Load("braziltourism_test.arff", testData, info))
BOOST_FAIL("Cannot load test dataset braziltourism_test.arff!");
FAIL("Cannot load test dataset braziltourism_test.arff!");
size_t testSize = testData.n_cols;
@@ -324,7 +308,7 @@ BOOST_AUTO_TEST_CASE(HoeffdingModelCategoricalReuseTest)
probabilities = std::move(IO::GetParam<arma::mat>("probabilities"));
if (!data::Load("braziltourism_test.arff", testData, info))
BOOST_FAIL("Cannot load test dataset braziltourism_test.arff!");
FAIL("Cannot load test dataset braziltourism_test.arff!");
// Input trained model.
SetInputParam("test", std::make_tuple(info, testData));
@@ -334,16 +318,12 @@ BOOST_AUTO_TEST_CASE(HoeffdingModelCategoricalReuseTest)
mlpackMain();
// Check that number of output points are equal to number of input points.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_cols, testSize);
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::mat>("probabilities").n_cols, testSize);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_cols == testSize);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_cols == testSize);
// Check number of output rows equals 1 for probabilities and predictions.
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::Row<size_t>>("predictions").n_rows, 1);
BOOST_REQUIRE_EQUAL(
IO::GetParam<arma::mat>("probabilities").n_rows, 1);
REQUIRE(IO::GetParam<arma::Row<size_t>>("predictions").n_rows == 1);
REQUIRE(IO::GetParam<arma::mat>("probabilities").n_rows == 1);
// Check that initial predictions and predictions using saved model are same.
CheckMatrices(
@@ -355,21 +335,22 @@ BOOST_AUTO_TEST_CASE(HoeffdingModelCategoricalReuseTest)
/**
* Ensure that small min_samples creates larger model.
*/
BOOST_AUTO_TEST_CASE(HoeffdingMinSamplesTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingMinSamplesTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
int nodes;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -395,13 +376,13 @@ BOOST_AUTO_TEST_CASE(HoeffdingMinSamplesTest)
bindings::tests::CleanMemory();
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -416,29 +397,29 @@ BOOST_AUTO_TEST_CASE(HoeffdingMinSamplesTest)
mlpackMain();
// Check that small min_samples creates larger model.
BOOST_REQUIRE_LT(
(IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes(),
REQUIRE((IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes() <
nodes);
}
/**
* Ensure that large max_samples creates smaller model.
*/
BOOST_AUTO_TEST_CASE(HoeffdingMaxSamplesTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingMaxSamplesTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
int nodes;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -464,13 +445,13 @@ BOOST_AUTO_TEST_CASE(HoeffdingMaxSamplesTest)
bindings::tests::CleanMemory();
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -485,28 +466,29 @@ BOOST_AUTO_TEST_CASE(HoeffdingMaxSamplesTest)
mlpackMain();
// Check that large max_samples creates smaller model.
BOOST_REQUIRE_LT(nodes,
REQUIRE(nodes <
(IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes());
}
/**
* Ensure that small confidence value creates larger model.
*/
BOOST_AUTO_TEST_CASE(HoeffdingConfidenceTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingConfidenceTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
int nodes;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -531,13 +513,13 @@ BOOST_AUTO_TEST_CASE(HoeffdingConfidenceTest)
bindings::tests::CleanMemory();
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -551,28 +533,29 @@ BOOST_AUTO_TEST_CASE(HoeffdingConfidenceTest)
mlpackMain();
// Check that higher confidence creates smaller tree.
BOOST_REQUIRE_LT(nodes,
REQUIRE(nodes <
(IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes());
}
/**
* Ensure that large number of passes creates larger model.
*/
BOOST_AUTO_TEST_CASE(HoeffdingPassesTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingPassesTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
int nodes;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -597,13 +580,13 @@ BOOST_AUTO_TEST_CASE(HoeffdingPassesTest)
bindings::tests::CleanMemory();
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -618,27 +601,29 @@ BOOST_AUTO_TEST_CASE(HoeffdingPassesTest)
mlpackMain();
// Check that model with larger number of passes has greater number of nodes.
BOOST_REQUIRE_LT(nodes,
REQUIRE(nodes <
(IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes());
}
/**
* Ensure that the root node has 2 children when splitting strategy is binary.
*/
BOOST_AUTO_TEST_CASE(HoeffdingBinarySplittingStrategyTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture,
"HoeffdingBinarySplittingStrategyTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -655,28 +640,30 @@ BOOST_AUTO_TEST_CASE(HoeffdingBinarySplittingStrategyTest)
mlpackMain();
// Check that number of children is 2.
BOOST_REQUIRE_EQUAL(
(IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes()-1, 2);
REQUIRE(
(IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes() - 1 == 2);
}
/**
* Ensure that the number of children varies with varying 'bins' in domingos.
*/
BOOST_AUTO_TEST_CASE(HoeffdingDomingosSplittingStrategyTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture,
"HoeffdingDomingosSplittingStrategyTest",
"[HoeffdingTreeMainTest][BindingTest]")
{
arma::mat inputData;
DatasetInfo info;
int nodes;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -705,13 +692,13 @@ BOOST_AUTO_TEST_CASE(HoeffdingDomingosSplittingStrategyTest)
bindings::tests::CleanMemory();
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
// Input training data.
SetInputParam("training", std::make_tuple(info, inputData));
@@ -727,30 +714,31 @@ BOOST_AUTO_TEST_CASE(HoeffdingDomingosSplittingStrategyTest)
mlpackMain();
// Check that both models have different number of nodes.
BOOST_CHECK_NE(
(IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes(), nodes);
CHECK((IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes() !=
nodes);
}
/**
* Ensure that the model doesn't split if observations before binning
* is greater than total number of samples passed.
*/
BOOST_AUTO_TEST_CASE(HoeffdingBinningTest)
TEST_CASE_METHOD(HoeffdingTreeTestFixture, "HoeffdingBinningTest",
"[HoeffdingTreeMainTest][BindingTests]")
{
arma::mat inputData;
arma::mat modData;
arma::Row<size_t> modLabels;
DatasetInfo info;
if (!data::Load("vc2.csv", inputData, info))
BOOST_FAIL("Cannot load train dataset vc2.csv!");
FAIL("Cannot load train dataset vc2.csv!");
arma::Row<size_t> labels;
if (!data::Load("vc2_labels.txt", labels))
BOOST_FAIL("Cannot load labels for vc2_labels.txt");
FAIL("Cannot load labels for vc2_labels.txt");
arma::mat testData;
if (!data::Load("vc2_test.csv", testData, info))
BOOST_FAIL("Cannot load test dataset vc2.csv!");
FAIL("Cannot load test dataset vc2.csv!");
modData = inputData.cols(0, 49);
modLabels = labels.cols(0, 49);
@@ -772,8 +760,6 @@ BOOST_AUTO_TEST_CASE(HoeffdingBinningTest)
mlpackMain();
// Check that no splitting has happened.
BOOST_REQUIRE_EQUAL(
(IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes(), 1);
REQUIRE((IO::GetParam<HoeffdingTreeModel*>("output_model"))->NumNodes()
== 1);
}
BOOST_AUTO_TEST_SUITE_END();
@@ -17,7 +17,7 @@ static const std::string testName = "RangeSearchMain";
#include "test_helper.hpp"
#include <mlpack/methods/range_search/range_search_main.cpp>
#include "range_search_utils.hpp"
#include <boost/test/unit_test.hpp>
#include "../catch.hpp"
using namespace mlpack;
@@ -37,34 +37,35 @@ struct RangeSearchTestFixture
}
};
BOOST_FIXTURE_TEST_SUITE(RangeSearchMainTest, RangeSearchTestFixture);
/**
* Check that we have to specify a reference set or input model.
*/
BOOST_AUTO_TEST_CASE(RangeSearchNoReference)
TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchNoReference",
"[RangeSearchMainTest][BindingTests]")
{
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
Log::Fatal.ignoreInput = false;
}
/**
* Check that we cannot pass an incorrect parameter.
*/
BOOST_AUTO_TEST_CASE(RangeSearchWrongParameter)
TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchWrongParameter",
"[RangeSearchMainTest][BindingTests]")
{
string wrongString = "abc";
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(SetInputParam("RST", wrongString), std::runtime_error);
REQUIRE_THROWS_AS(SetInputParam("RST", wrongString), std::runtime_error);
Log::Fatal.ignoreInput = false;
}
/**
* Check that we have to specify a query if an input model is specified.
*/
BOOST_AUTO_TEST_CASE(RangeSearchInputModelNoQuery)
TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchInputModelNoQuery",
"[RangeSearchMainTest][BindingTests]")
{
arma::mat inputData;
double minVal = 0, maxVal = 3;
@@ -72,7 +73,7 @@ BOOST_AUTO_TEST_CASE(RangeSearchInputModelNoQuery)
string neighborsFile = "neighbors.csv";
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
SetInputParam("reference", move(inputData));
SetInputParam("min", minVal);
@@ -86,7 +87,7 @@ BOOST_AUTO_TEST_CASE(RangeSearchInputModelNoQuery)
SetInputParam("input_model", move(IO::GetParam<RSModel*>("output_model")));
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
Log::Fatal.ignoreInput = false;
remove(neighborsFile.c_str());
@@ -96,7 +97,8 @@ BOOST_AUTO_TEST_CASE(RangeSearchInputModelNoQuery)
/**
* Check that we cannot specify a tree type which is not available or wrong.
*/
BOOST_AUTO_TEST_CASE(RangeSearchDifferentTree)
TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchDifferentTree",
"[RangeSearchMainTest][BindingTests]")
{
arma::mat inputData;
double minVal = 0, maxVal = 3;
@@ -104,7 +106,7 @@ BOOST_AUTO_TEST_CASE(RangeSearchDifferentTree)
string neighborsFile = "neighbors.csv";
string wrongTreeType = "RST";
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
SetInputParam("reference", move(inputData));
SetInputParam("min", minVal);
@@ -114,7 +116,7 @@ BOOST_AUTO_TEST_CASE(RangeSearchDifferentTree)
SetInputParam("tree_type", wrongTreeType);
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
Log::Fatal.ignoreInput = false;
remove(neighborsFile.c_str());
@@ -124,7 +126,8 @@ BOOST_AUTO_TEST_CASE(RangeSearchDifferentTree)
/**
* Check that we cannot specify both a reference set and input model.
*/
BOOST_AUTO_TEST_CASE(RangeSearchBothReferenceAndModel)
TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchBothReferenceAndModel",
"[RangeSearchMainTest][BindingTests]")
{
arma::mat inputData, queryData;
double minVal = 0, maxVal = 3;
@@ -132,9 +135,9 @@ BOOST_AUTO_TEST_CASE(RangeSearchBothReferenceAndModel)
string neighborsFile = "neighbors.csv";
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
if (!data::Load("iris_test.csv", queryData))
BOOST_FAIL("Unable to load dataset iris_test.csv!");
FAIL("Unable to load dataset iris_test.csv!");
SetInputParam("reference", move(inputData));
SetInputParam("min", minVal);
@@ -149,7 +152,7 @@ BOOST_AUTO_TEST_CASE(RangeSearchBothReferenceAndModel)
SetInputParam("query", move(queryData));
Log::Fatal.ignoreInput = true;
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
Log::Fatal.ignoreInput = false;
remove(neighborsFile.c_str());
@@ -161,7 +164,8 @@ BOOST_AUTO_TEST_CASE(RangeSearchBothReferenceAndModel)
* by comparing with pre-calculated neighbor and distance values, when no query
* set is specified.
*/
BOOST_AUTO_TEST_CASE(RangeSearchTest)
TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchTest",
"[RangeSearchMainTest][BindingTests]")
{
arma::mat x = {{0, 3, 3, 4, 3, 1},
{4, 4, 4, 5, 5, 2},
@@ -208,7 +212,8 @@ BOOST_AUTO_TEST_CASE(RangeSearchTest)
* Check that the correct output is returned for a small synthetic input case,
* when a query set is provided.
*/
BOOST_AUTO_TEST_CASE(RangeSeachTestwithQuery)
TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSeachTestwithQuery",
"[RangeSearchMainTest][BindingTests]")
{
arma::mat queryData = {{5, 3, 1}, {4, 2, 4}, {3, 1, 7}};
arma::mat x = {{0, 3, 3, 4, 3, 1},
@@ -252,7 +257,8 @@ BOOST_AUTO_TEST_CASE(RangeSeachTestwithQuery)
* Train a model using a synthetic dataset and then output the model, and ensure
* it can be used again.
*/
BOOST_AUTO_TEST_CASE(ModelCheck)
TEST_CASE_METHOD(RangeSearchTestFixture, "ModelCheck",
"[RangeSearchMainTest][BindingTests]")
{
arma::mat inputData, queryData;
double minVal = 0, maxVal = 3;
@@ -262,9 +268,9 @@ BOOST_AUTO_TEST_CASE(ModelCheck)
vector<vector<double>> distances, distancetemp;
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
if (!data::Load("iris_test.csv", queryData))
BOOST_FAIL("Unable to load dataset iris_test.csv!");
FAIL("Unable to load dataset iris_test.csv!");
SetInputParam("reference", move(inputData));
SetInputParam("min", minVal);
@@ -292,8 +298,8 @@ BOOST_AUTO_TEST_CASE(ModelCheck)
CheckMatrices(neighbors, neighborsTemp);
CheckMatrices(distances, distancetemp);
BOOST_REQUIRE_EQUAL(ModelToString(outputModel),
ModelToString(IO::GetParam<RSModel*>("output_model")));
REQUIRE(ModelToString(outputModel) ==
ModelToString(IO::GetParam<RSModel*>("output_model")));
remove(neighborsFile.c_str());
remove(distanceFile.c_str());
@@ -303,11 +309,12 @@ BOOST_AUTO_TEST_CASE(ModelCheck)
* Check that the models are different but the results are the same for three
* different leaf size parameters.
*/
BOOST_AUTO_TEST_CASE(LeafValueTesting)
TEST_CASE_METHOD(RangeSearchTestFixture, "LeafValueTesting",
"[RangeSearchMainTest][BindingTests]")
{
arma::mat inputData;
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
string distanceFile = "distances.csv";
string neighborsFile = "neighbors.csv";
@@ -349,8 +356,8 @@ BOOST_AUTO_TEST_CASE(LeafValueTesting)
CheckMatrices(neighbors, neighborsTemp);
CheckMatrices(distances, distancestemp);
BOOST_REQUIRE_NE(ModelToString(outputModel1),
ModelToString(IO::GetParam<RSModel*>("output_model")));
REQUIRE(ModelToString(outputModel1) !=
ModelToString(IO::GetParam<RSModel*>("output_model")));
if (i != leafSizes.size() - 1)
delete IO::GetParam<RSModel*>("output_model");
@@ -367,7 +374,8 @@ BOOST_AUTO_TEST_CASE(LeafValueTesting)
* different tree types. We use the default kd-tree as the base model to
* compare against.
*/
BOOST_AUTO_TEST_CASE(TreeTypeTesting)
TEST_CASE_METHOD(RangeSearchTestFixture, "TreeTypeTesting",
"[RangeSearchMainTest][BindingTests]")
{
string distanceFile = "distances.csv";
string neighborsFile = "neighbors.csv";
@@ -381,9 +389,9 @@ BOOST_AUTO_TEST_CASE(TreeTypeTesting)
"max-rp", "ub", "oct"};
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
if (!data::Load("iris_test.csv", queryData))
BOOST_FAIL("Unable to load dataset iris_test.csv!");
FAIL("Unable to load dataset iris_test.csv!");
// Define base parameters with the kd-tree.
SetInputParam("tree_type", trees[0]);
@@ -403,9 +411,9 @@ BOOST_AUTO_TEST_CASE(TreeTypeTesting)
for (size_t i = 1; i < trees.size(); ++i)
{
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
if (!data::Load("iris_test.csv", queryData))
BOOST_FAIL("Unable to load dataset iris_test.csv!");
FAIL("Unable to load dataset iris_test.csv!");
SetInputParam("min", minVal);
SetInputParam("max", maxVal);
@@ -422,8 +430,8 @@ BOOST_AUTO_TEST_CASE(TreeTypeTesting)
CheckMatrices(neighbors, neighborsTemp);
CheckMatrices(distances, distancestemp);
BOOST_REQUIRE_NE(ModelToString(outputModel1),
ModelToString(IO::GetParam<RSModel*>("output_model")));
REQUIRE(ModelToString(outputModel1) !=
ModelToString(IO::GetParam<RSModel*>("output_model")));
if (i != trees.size() - 1)
delete IO::GetParam<RSModel*>("output_model");
@@ -439,7 +447,8 @@ BOOST_AUTO_TEST_CASE(TreeTypeTesting)
* Project the data onto a random basis and ensure that this gives identical
* results to non-projected data but different models.
*/
BOOST_AUTO_TEST_CASE(RandomBasisTesting)
TEST_CASE_METHOD(RangeSearchTestFixture, "RandomBasisTesting",
"[RangeSearchMainTest][BindingTests]")
{
string distanceFile = "distances.csv";
string neighborsFile = "neighbors.csv";
@@ -447,9 +456,9 @@ BOOST_AUTO_TEST_CASE(RandomBasisTesting)
arma::mat queryData, inputData;
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
if (!data::Load("iris_test.csv", queryData))
BOOST_FAIL("Unable to load dataset iris_test.csv!");
FAIL("Unable to load dataset iris_test.csv!");
SetInputParam("min", minVal);
SetInputParam("max", maxVal);
@@ -470,8 +479,8 @@ BOOST_AUTO_TEST_CASE(RandomBasisTesting)
mlpackMain();
BOOST_REQUIRE_NE(ModelToString(outputModel),
ModelToString(IO::GetParam<RSModel*>("output_model")));
REQUIRE(ModelToString(outputModel) !=
ModelToString(IO::GetParam<RSModel*>("output_model")));
delete outputModel;
@@ -482,7 +491,8 @@ BOOST_AUTO_TEST_CASE(RandomBasisTesting)
/**
* Ensure that naive mode gives the same result, but different models.
*/
BOOST_AUTO_TEST_CASE(NaiveModeTest)
TEST_CASE_METHOD(RangeSearchTestFixture, "NaiveModeTest",
"[RangeSearchMainTest][BindingTests]")
{
string distanceFile = "distances.csv";
string neighborsFile = "neighbors.csv";
@@ -493,9 +503,9 @@ BOOST_AUTO_TEST_CASE(NaiveModeTest)
vector<vector<double>> distances, distancestemp;
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
if (!data::Load("iris_test.csv", queryData))
BOOST_FAIL("Unable to load dataset iris_test.csv!");
FAIL("Unable to load dataset iris_test.csv!");
SetInputParam("min", minVal);
SetInputParam("max", maxVal);
@@ -524,8 +534,8 @@ BOOST_AUTO_TEST_CASE(NaiveModeTest)
CheckMatrices(neighbors, neighborsTemp);
CheckMatrices(distances, distancestemp);
BOOST_REQUIRE_NE(ModelToString(outputModel),
ModelToString(IO::GetParam<RSModel*>("output_model")));
REQUIRE(ModelToString(outputModel) !=
ModelToString(IO::GetParam<RSModel*>("output_model")));
delete outputModel;
@@ -536,7 +546,8 @@ BOOST_AUTO_TEST_CASE(NaiveModeTest)
/**
* Ensure that single-tree mode gives the same result but different models.
*/
BOOST_AUTO_TEST_CASE(SingleModeTest)
TEST_CASE_METHOD(RangeSearchTestFixture, "SingleModeTest",
"[RangeSearchMainTest][BindingTests]")
{
string distanceFile = "distances.csv";
string neighborsFile = "neighbors.csv";
@@ -547,9 +558,9 @@ BOOST_AUTO_TEST_CASE(SingleModeTest)
vector<vector<double>> distances, distancestemp;
if (!data::Load("iris.csv", inputData))
BOOST_FAIL("Unable to load dataset iris.csv!");
FAIL("Unable to load dataset iris.csv!");
if (!data::Load("iris_test.csv", queryData))
BOOST_FAIL("Unable to load dataset iris_test.csv!");
FAIL("Unable to load dataset iris_test.csv!");
SetInputParam("min", minVal);
SetInputParam("max", maxVal);
@@ -577,13 +588,11 @@ BOOST_AUTO_TEST_CASE(SingleModeTest)
CheckMatrices(neighbors, neighborsTemp);
CheckMatrices(distances, distancestemp);
BOOST_REQUIRE_NE(ModelToString(outputModel),
ModelToString(IO::GetParam<RSModel*>("output_model")));
REQUIRE(ModelToString(outputModel) !=
ModelToString(IO::GetParam<RSModel*>("output_model")));
delete outputModel;
remove(neighborsFile.c_str());
remove(distanceFile.c_str());
}
BOOST_AUTO_TEST_SUITE_END();
@@ -12,10 +12,10 @@
#ifndef MLPACK_TESTS_MAIN_TESTS_RANGE_SEARCH_TEST_UTILS_HPP
#define MLPACK_TESTS_MAIN_TESTS_RANGE_SEARCH_TEST_UTILS_HPP
#include <boost/test/unit_test.hpp>
#include <mlpack/methods/range_search/rs_model.hpp>
#include <mlpack/core.hpp>
#include <mlpack/core/util/mlpack_main.hpp>
#include "../catch.hpp"
/**
* Convert a model to a string using the text_oarchive of boost::serialization.
@@ -42,15 +42,15 @@ inline void CheckMatrices(std::vector<std::vector<double>>& vec1,
std::vector<std::vector<double>>& vec2,
const double tolerance = 1e-3)
{
BOOST_REQUIRE_EQUAL(vec1.size() , vec2.size());
REQUIRE(vec1.size() == vec2.size());
for (size_t i = 0; i < vec1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(vec1[i].size(), vec2[i].size());
REQUIRE(vec1[i].size() == vec2[i].size());
std::sort(vec1[i].begin(), vec1[i].end());
std::sort(vec2[i].begin(), vec2[i].end());
for (size_t j = 0 ; j < vec1[i].size(); ++j)
{
BOOST_REQUIRE_CLOSE(vec1[i][j], vec2[i][j], tolerance);
REQUIRE(vec1[i][j] == Approx(vec2[i][j]).epsilon(tolerance));
}
}
}
@@ -64,15 +64,15 @@ inline void CheckMatrices(std::vector<std::vector<double>>& vec1,
inline void CheckMatrices(std::vector<std::vector<size_t>>& vec1,
std::vector<std::vector<size_t>>& vec2)
{
BOOST_REQUIRE_EQUAL(vec1.size() , vec2.size());
REQUIRE(vec1.size() == vec2.size());
for (size_t i = 0; i < vec1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(vec1[i].size(), vec2[i].size());
REQUIRE(vec1[i].size() == vec2[i].size());
std::sort(vec1[i].begin(), vec1[i].end());
std::sort(vec2[i].begin(), vec2[i].end());
for (size_t j = 0; j < vec1[i].size(); ++j)
{
BOOST_REQUIRE_EQUAL(vec1[i][j], vec2[i][j]);
REQUIRE(vec1[i][j] == vec2[i][j]);
}
}
}
+52 -54
View File
@@ -10,21 +10,19 @@
*/
#include <mlpack/core.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <boost/test/unit_test.hpp>
#include "catch.hpp"
#include <mlpack/core/metrics/iou_metric.hpp>
#include <mlpack/core/metrics/non_maximal_supression.hpp>
#include <mlpack/core/metrics/bleu.hpp>
#include "test_tools.hpp"
#include "test_catch_tools.hpp"
using namespace std;
using namespace mlpack::metric;
BOOST_AUTO_TEST_SUITE(MetricTest);
/**
* Simple test for L-1 metric.
*/
BOOST_AUTO_TEST_CASE(L1MetricTest)
TEST_CASE("L1MetricTest", "[MetricTest]")
{
arma::vec a1(5);
a1.randn();
@@ -40,17 +38,17 @@ BOOST_AUTO_TEST_CASE(L1MetricTest)
ManhattanDistance lMetric;
BOOST_REQUIRE_CLOSE((double) arma::accu(arma::abs(a1 - b1)),
lMetric.Evaluate(a1, b1), 1e-5);
REQUIRE((double) arma::accu(arma::abs(a1 - b1)) ==
Approx(lMetric.Evaluate(a1, b1)).epsilon(1e-7));
BOOST_REQUIRE_CLOSE((double) arma::accu(arma::abs(a2 - b2)),
lMetric.Evaluate(a2, b2), 1e-5);
REQUIRE((double) arma::accu(arma::abs(a2 - b2)) ==
Approx(lMetric.Evaluate(a2, b2)).epsilon(1e-7));
}
/**
* Simple test for L-2 metric.
*/
BOOST_AUTO_TEST_CASE(L2MetricTest)
TEST_CASE("L2MetricTest", "[MetricTest]")
{
arma::vec a1(5);
a1.randn();
@@ -66,17 +64,17 @@ BOOST_AUTO_TEST_CASE(L2MetricTest)
EuclideanDistance lMetric;
BOOST_REQUIRE_CLOSE((double) sqrt(arma::accu(arma::square(a1 - b1))),
lMetric.Evaluate(a1, b1), 1e-5);
REQUIRE((double) sqrt(arma::accu(arma::square(a1 - b1))) ==
Approx(lMetric.Evaluate(a1, b1)).epsilon(1e-7));
BOOST_REQUIRE_CLOSE((double) sqrt(arma::accu(arma::square(a2 - b2))),
lMetric.Evaluate(a2, b2), 1e-5);
REQUIRE((double) sqrt(arma::accu(arma::square(a2 - b2))) ==
Approx(lMetric.Evaluate(a2, b2)).epsilon(1e-7));
}
/**
* Simple test for L-Infinity metric.
*/
BOOST_AUTO_TEST_CASE(LINFMetricTest)
TEST_CASE("LINFMetricTest", "[MetricTest]")
{
arma::vec a1(5);
a1.randn();
@@ -92,50 +90,52 @@ BOOST_AUTO_TEST_CASE(LINFMetricTest)
ChebyshevDistance lMetric;
BOOST_REQUIRE_CLOSE((double) arma::as_scalar(arma::max(arma::abs(a1 - b1))),
lMetric.Evaluate(a1, b1), 1e-5);
REQUIRE((double) arma::as_scalar(arma::max(arma::abs(a1 - b1))) ==
Approx(lMetric.Evaluate(a1, b1)).epsilon(1e-7));
BOOST_REQUIRE_CLOSE((double) arma::as_scalar(arma::max(arma::abs(a2 - b2))),
lMetric.Evaluate(a2, b2), 1e-5);
REQUIRE((double) arma::as_scalar(arma::max(arma::abs(a2 - b2))) ==
Approx(lMetric.Evaluate(a2, b2)).epsilon(1e-7));
}
/**
* Simple test for IoU metric.
*/
BOOST_AUTO_TEST_CASE(IoUMetricTest)
TEST_CASE("IoUMetricTest", "[MetricTest]")
{
arma::vec bbox1(4), bbox2(4);
bbox1 << 1 << 2 << 100 << 200;
bbox2 << 1 << 2 << 100 << 200;
// IoU of same bounding boxes equals 1.0.
BOOST_REQUIRE_CLOSE(1.0, IoU<>::Evaluate(bbox1, bbox2), 1e-4);
REQUIRE(1.0 == Approx(IoU<>::Evaluate(bbox1, bbox2)).epsilon(1e-6));
// Use coordinate system to represent bounding boxes.
// Bounding boxes represent {x0, y0, x1, y1}.
bbox1 << 39 << 63 << 203 << 112;
bbox2 << 54 << 66 << 198 << 114;
// Value calculated using Python interpreter.
BOOST_REQUIRE_CLOSE(IoU<true>::Evaluate(bbox1, bbox2), 0.7980093, 1e-4);
REQUIRE(IoU<true>::Evaluate(bbox1, bbox2) ==
Approx(0.7980093).epsilon(1e-6));
bbox1 << 31 << 69 << 201 << 125;
bbox2 << 18 << 63 << 235 << 135;
// Value calculated using Python interpreter.
BOOST_REQUIRE_CLOSE(IoU<true>::Evaluate(bbox1, bbox2), 0.612479577, 1e-4);
REQUIRE(IoU<true>::Evaluate(bbox1, bbox2) ==
Approx(0.612479577).epsilon(1e-6));
// Use hieght - width representation of bounding boxes.
// Bounding boxes represent {x0, y0, h, w}.
bbox1 << 49 << 75 << 154 << 50;
bbox2 << 42 << 78 << 144 << 48;
// Value calculated using Python interpreter.
BOOST_REQUIRE_CLOSE(IoU<>::Evaluate(bbox1, bbox2), 0.7898879, 1e-4);
REQUIRE(IoU<>::Evaluate(bbox1, bbox2) == Approx(0.7898879).epsilon(1e-6));
bbox1 << 35 << 51 << 161 << 59;
bbox2 << 36 << 60 << 144 << 48;
// Value calculated using Python interpreter.
BOOST_REQUIRE_CLOSE(IoU<>::Evaluate(bbox1, bbox2), 0.7309670, 1e-4);
REQUIRE(IoU<>::Evaluate(bbox1, bbox2) == Approx(0.7309670).epsilon(1e-6));
}
BOOST_AUTO_TEST_CASE(NMSMetricTest)
TEST_CASE("NMSMetricTest", "[MetricTest]")
{
arma::mat bbox, selectedBoundingBox, desiredBoundingBox;
arma::vec bbox1(4), bbox2(4), bbox3(4);
@@ -172,13 +172,13 @@ BOOST_AUTO_TEST_CASE(NMSMetricTest)
selectedBoundingBox = bbox.cols(selectedIndices);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_cols, 2);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_rows, 4);
REQUIRE(selectedBoundingBox.n_cols == 2);
REQUIRE(selectedBoundingBox.n_rows == 4);
CheckMatrices(desiredBoundingBox, selectedBoundingBox);
for (size_t i = 0; i < desiredIndices.n_elem; i++)
{
BOOST_REQUIRE_EQUAL(desiredIndices[i], selectedIndices[i]);
REQUIRE(desiredIndices[i] == selectedIndices[i]);
}
// Clean up.
@@ -201,8 +201,8 @@ BOOST_AUTO_TEST_CASE(NMSMetricTest)
selectedBoundingBox = bbox.cols(selectedIndices);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_cols, 2);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_rows, 4);
REQUIRE(selectedBoundingBox.n_cols == 2);
REQUIRE(selectedBoundingBox.n_rows == 4);
CheckMatrices(desiredBoundingBox, selectedBoundingBox);
// Clean up.
@@ -233,8 +233,8 @@ BOOST_AUTO_TEST_CASE(NMSMetricTest)
selectedBoundingBox = bbox.cols(selectedIndices);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_cols, 2);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_rows, 4);
REQUIRE(selectedBoundingBox.n_cols == 2);
REQUIRE(selectedBoundingBox.n_rows == 4);
CheckMatrices(desiredBoundingBox, selectedBoundingBox);
// Clean up.
@@ -266,8 +266,8 @@ BOOST_AUTO_TEST_CASE(NMSMetricTest)
selectedIndices);
selectedBoundingBox = bbox.cols(selectedIndices);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_cols, 2);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_rows, 4);
REQUIRE(selectedBoundingBox.n_cols == 2);
REQUIRE(selectedBoundingBox.n_rows == 4);
CheckMatrices(desiredBoundingBox, selectedBoundingBox);
// Clean up.
@@ -297,15 +297,15 @@ BOOST_AUTO_TEST_CASE(NMSMetricTest)
selectedIndices, 0.7);
selectedBoundingBox = bbox.cols(selectedIndices);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_cols, 2);
BOOST_REQUIRE_EQUAL(selectedBoundingBox.n_rows, 4);
REQUIRE(selectedBoundingBox.n_cols == 2);
REQUIRE(selectedBoundingBox.n_rows == 4);
CheckMatrices(desiredBoundingBox, selectedBoundingBox);
}
/**
*
*/
BOOST_AUTO_TEST_CASE(BLEUScoreTest)
TEST_CASE("BLEUScoreTest", "[MetricTest]")
{
typedef typename std::vector<std::string> WordVector;
std::vector<std::vector<WordVector>> referenceCorpus
@@ -330,34 +330,32 @@ BOOST_AUTO_TEST_CASE(BLEUScoreTest)
//! We are not using smoothing function here.
bleu.Evaluate(referenceCorpus, translationCorpus);
BOOST_REQUIRE_CLOSE_FRACTION(bleu.BLEUScore(), 0.0, 1e-05);
BOOST_REQUIRE_EQUAL(bleu.BrevityPenalty(), 1.0);
BOOST_REQUIRE_EQUAL(bleu.Ratio(), 1.0);
BOOST_REQUIRE_EQUAL(bleu.TranslationLength(), 12);
BOOST_REQUIRE_EQUAL(bleu.ReferenceLength(), 12);
REQUIRE(bleu.BLEUScore() == Approx(0.0).epsilon(1e-5));
REQUIRE(bleu.BrevityPenalty() == 1.0);
REQUIRE(bleu.Ratio() == 1.0);
REQUIRE(bleu.TranslationLength() == 12);
REQUIRE(bleu.ReferenceLength() == 12);
std::vector<float> expectedPrecision = {0.666666f, 0.5555555f,
0.3333333f, 0.0f};
for (size_t i = 0; i < bleu.Precisions().size(); ++i)
{
BOOST_REQUIRE_CLOSE_FRACTION(bleu.Precisions()[i],
expectedPrecision[i], 1e-04);
REQUIRE(bleu.Precisions()[i] ==
Approx((double)expectedPrecision[i]).epsilon(1e-4));
}
//! We will use smoothing function here by setting smooth to true.
bleu.Evaluate(referenceCorpus, translationCorpus, true);
BOOST_REQUIRE_CLOSE_FRACTION(bleu.BLEUScore(), 0.459307, 1e-05);
BOOST_REQUIRE_EQUAL(bleu.BrevityPenalty(), 1.0);
BOOST_REQUIRE_EQUAL(bleu.Ratio(), 1.0);
BOOST_REQUIRE_EQUAL(bleu.TranslationLength(), 12);
BOOST_REQUIRE_EQUAL(bleu.ReferenceLength(), 12);
REQUIRE(bleu.BLEUScore() == Approx(0.459307).epsilon(1e-5));
REQUIRE(bleu.BrevityPenalty() == 1.0);
REQUIRE(bleu.Ratio() == 1.0);
REQUIRE(bleu.TranslationLength() == 12);
REQUIRE(bleu.ReferenceLength() == 12);
expectedPrecision = {0.692308f, 0.6f, 0.428571f, 0.25f};
for (size_t i = 0; i < bleu.Precisions().size(); ++i)
{
BOOST_REQUIRE_CLOSE_FRACTION(bleu.Precisions()[i],
expectedPrecision[i], 1e-04);
REQUIRE(bleu.Precisions()[i] ==
Approx(expectedPrecision[i]).epsilon(1e-4));
}
}
BOOST_AUTO_TEST_SUITE_END();
+81 -82
View File
@@ -12,9 +12,9 @@
#include <mlpack/core.hpp>
#include <mlpack/core/tree/octree.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "serialization.hpp"
#include "catch.hpp"
#include "test_catch_tools.hpp"
#include "serialization_catch.hpp"
using namespace mlpack;
using namespace mlpack::math;
@@ -22,28 +22,26 @@ using namespace mlpack::tree;
using namespace mlpack::metric;
using namespace mlpack::bound;
BOOST_AUTO_TEST_SUITE(OctreeTest);
/**
* Build a quad-tree (2-d octree) on 4 points, and guarantee four points are
* created.
*/
BOOST_AUTO_TEST_CASE(SimpleQuadtreeTest)
TEST_CASE("SimpleQuadtreeTest", "[OctreeTest]")
{
// Four corners of the unit square.
arma::mat dataset("0 0 1 1; 0 1 0 1");
Octree<> t(dataset, 1);
BOOST_REQUIRE_EQUAL(t.NumChildren(), 4);
BOOST_REQUIRE_EQUAL(t.Dataset().n_cols, 4);
BOOST_REQUIRE_EQUAL(t.Dataset().n_rows, 2);
BOOST_REQUIRE_EQUAL(t.NumDescendants(), 4);
BOOST_REQUIRE_EQUAL(t.NumPoints(), 0);
REQUIRE(t.NumChildren() == 4);
REQUIRE(t.Dataset().n_cols == 4);
REQUIRE(t.Dataset().n_rows == 2);
REQUIRE(t.NumDescendants() == 4);
REQUIRE(t.NumPoints() == 0);
for (size_t i = 0; i < 4; ++i)
{
BOOST_REQUIRE_EQUAL(t.Child(i).NumDescendants(), 1);
BOOST_REQUIRE_EQUAL(t.Child(i).NumPoints(), 1);
REQUIRE(t.Child(i).NumDescendants() == 1);
REQUIRE(t.Child(i).NumPoints() == 1);
}
}
@@ -51,62 +49,62 @@ BOOST_AUTO_TEST_CASE(SimpleQuadtreeTest)
* Build an octree on 3 points and make sure that only three children are
* created.
*/
BOOST_AUTO_TEST_CASE(OctreeMissingChildTest)
TEST_CASE("OctreeMissingChildTest", "[OctreeTest]")
{
// Only three corners of the unit square.
arma::mat dataset("0 0 1; 0 1 1");
Octree<> t(dataset, 1);
BOOST_REQUIRE_EQUAL(t.NumChildren(), 3);
BOOST_REQUIRE_EQUAL(t.Dataset().n_cols, 3);
BOOST_REQUIRE_EQUAL(t.Dataset().n_rows, 2);
BOOST_REQUIRE_EQUAL(t.NumDescendants(), 3);
BOOST_REQUIRE_EQUAL(t.NumPoints(), 0);
REQUIRE(t.NumChildren() == 3);
REQUIRE(t.Dataset().n_cols == 3);
REQUIRE(t.Dataset().n_rows == 2);
REQUIRE(t.NumDescendants() == 3);
REQUIRE(t.NumPoints() == 0);
for (size_t i = 0; i < 3; ++i)
{
BOOST_REQUIRE_EQUAL(t.Child(i).NumDescendants(), 1);
BOOST_REQUIRE_EQUAL(t.Child(i).NumPoints(), 1);
REQUIRE(t.Child(i).NumDescendants() == 1);
REQUIRE(t.Child(i).NumPoints() == 1);
}
}
/**
* Ensure that building an empty octree does not fail.
*/
BOOST_AUTO_TEST_CASE(EmptyOctreeTest)
TEST_CASE("EmptyOctreeTest", "[OctreeTest]")
{
arma::mat dataset;
Octree<> t(dataset);
BOOST_REQUIRE_EQUAL(t.NumChildren(), 0);
BOOST_REQUIRE_EQUAL(t.Dataset().n_cols, 0);
BOOST_REQUIRE_EQUAL(t.Dataset().n_rows, 0);
BOOST_REQUIRE_EQUAL(t.NumDescendants(), 0);
BOOST_REQUIRE_EQUAL(t.NumPoints(), 0);
REQUIRE(t.NumChildren() == 0);
REQUIRE(t.Dataset().n_cols == 0);
REQUIRE(t.Dataset().n_rows == 0);
REQUIRE(t.NumDescendants() == 0);
REQUIRE(t.NumPoints() == 0);
}
/**
* Ensure that maxLeafSize is respected.
*/
BOOST_AUTO_TEST_CASE(MaxLeafSizeTest)
TEST_CASE("MaxLeafSizeTest", "[OctreeTest]")
{
arma::mat dataset(5, 15, arma::fill::randu);
Octree<> t1(dataset, 20);
Octree<> t2(std::move(dataset), 20);
BOOST_REQUIRE_EQUAL(t1.NumChildren(), 0);
BOOST_REQUIRE_EQUAL(t1.NumDescendants(), 15);
BOOST_REQUIRE_EQUAL(t1.NumPoints(), 15);
REQUIRE(t1.NumChildren() == 0);
REQUIRE(t1.NumDescendants() == 15);
REQUIRE(t1.NumPoints() == 15);
BOOST_REQUIRE_EQUAL(t2.NumChildren(), 0);
BOOST_REQUIRE_EQUAL(t2.NumDescendants(), 15);
BOOST_REQUIRE_EQUAL(t2.NumPoints(), 15);
REQUIRE(t2.NumChildren() == 0);
REQUIRE(t2.NumDescendants() == 15);
REQUIRE(t2.NumPoints() == 15);
}
/**
* Check that the mappings given are correct.
*/
BOOST_AUTO_TEST_CASE(MappingsTest)
TEST_CASE("MappingsTest", "[OctreeTest]")
{
// Test with both constructors.
arma::mat dataset(3, 5, arma::fill::randu);
@@ -118,17 +116,17 @@ BOOST_AUTO_TEST_CASE(MappingsTest)
for (size_t i = 0; i < oldFromNewCopy.size(); ++i)
{
BOOST_REQUIRE_SMALL(arma::norm(datacopy.col(oldFromNewCopy[i]) -
t1.Dataset().col(i)), 1e-3);
BOOST_REQUIRE_SMALL(arma::norm(datacopy.col(oldFromNewMove[i]) -
t2.Dataset().col(i)), 1e-3);
REQUIRE(arma::norm(datacopy.col(oldFromNewCopy[i]) -
t1.Dataset().col(i)) == Approx(0.0).margin(1e-3));
REQUIRE(arma::norm(datacopy.col(oldFromNewMove[i]) -
t2.Dataset().col(i)) == Approx(0.0).margin(1e-3));
}
}
/**
* Check that the reverse mappings are correct too.
*/
BOOST_AUTO_TEST_CASE(ReverseMappingsTest)
TEST_CASE("ReverseMappingsTest", "[OctreeTest]")
{
// Test with both constructors.
arma::mat dataset(3, 300, arma::fill::randu);
@@ -141,13 +139,14 @@ BOOST_AUTO_TEST_CASE(ReverseMappingsTest)
for (size_t i = 0; i < oldFromNewCopy.size(); ++i)
{
BOOST_REQUIRE_SMALL(arma::norm(datacopy.col(oldFromNewCopy[i]) -
t1.Dataset().col(i)), 1e-3);
BOOST_REQUIRE_SMALL(arma::norm(datacopy.col(oldFromNewMove[i]) -
t2.Dataset().col(i)), 1e-3);
REQUIRE(arma::norm(datacopy.col(oldFromNewCopy[i]) -
t1.Dataset().col(i)) == Approx(0.0).margin(1e-3));
REQUIRE(arma::norm(datacopy.col(oldFromNewMove[i]) -
t2.Dataset().col(i)) == Approx(0.0).margin(1e-3));
BOOST_REQUIRE_EQUAL(newFromOldCopy[oldFromNewCopy[i]], i);
BOOST_REQUIRE_EQUAL(newFromOldMove[oldFromNewMove[i]], i);
REQUIRE(newFromOldCopy[oldFromNewCopy[i]] == i);
REQUIRE(newFromOldMove[oldFromNewMove[i]] == i);
}
}
@@ -160,14 +159,14 @@ void CheckOverlap(TreeType& node)
// Check each combination of children.
for (size_t i = 0; i < node.NumChildren(); ++i)
for (size_t j = i + 1; j < node.NumChildren(); ++j)
BOOST_REQUIRE_EQUAL(node.Child(i).Bound().Overlap(node.Child(j).Bound()),
REQUIRE(node.Child(i).Bound().Overlap(node.Child(j).Bound()) ==
0.0); // We need exact equality here.
for (size_t i = 0; i < node.NumChildren(); ++i)
CheckOverlap(node.Child(i));
}
BOOST_AUTO_TEST_CASE(OverlapTest)
TEST_CASE("OverlapTest", "[OctreeTest]")
{
// Test with both constructors.
arma::mat dataset(3, 300, arma::fill::randu);
@@ -193,8 +192,8 @@ void CheckFurthestDistances(TreeType& node)
for (size_t i = 0; i < node.NumPoints(); ++i)
{
// Handle floating-point inaccuracies.
BOOST_REQUIRE_LE(metric::EuclideanDistance::Evaluate(
node.Dataset().col(node.Point(i)), center),
REQUIRE(metric::EuclideanDistance::Evaluate(
node.Dataset().col(node.Point(i)), center) <=
node.FurthestPointDistance() * (1 + 1e-5));
}
@@ -202,16 +201,16 @@ void CheckFurthestDistances(TreeType& node)
for (size_t i = 0; i < node.NumDescendants(); ++i)
{
// Handle floating-point inaccuracies.
BOOST_REQUIRE_LE(metric::EuclideanDistance::Evaluate(
REQUIRE(metric::EuclideanDistance::Evaluate(
node.Dataset().col(node.Descendant(i)),
center), node.FurthestDescendantDistance() * (1 + 1e-5));
center) <= node.FurthestDescendantDistance() * (1 + 1e-5));
}
for (size_t i = 0; i < node.NumChildren(); ++i)
CheckFurthestDistances(node.Child(i));
}
BOOST_AUTO_TEST_CASE(FurthestDistanceTest)
TEST_CASE("FurthestDistanceTest", "[OctreeTest]")
{
// Test with both constructors.
arma::mat dataset(3, 500, arma::fill::randu);
@@ -231,12 +230,12 @@ BOOST_AUTO_TEST_CASE(FurthestDistanceTest)
template<typename TreeType>
void CheckNumChildren(TreeType& node)
{
BOOST_REQUIRE_LE(node.NumChildren(), std::pow(2, node.Dataset().n_rows));
REQUIRE(node.NumChildren() <= std::pow(2, node.Dataset().n_rows));
for (size_t i = 0; i < node.NumChildren(); ++i)
CheckNumChildren(node.Child(i));
}
BOOST_AUTO_TEST_CASE(MaxNumChildrenTest)
TEST_CASE("MaxNumChildrenTest", "[OctreeTest]")
{
for (size_t d = 1; d < 10; ++d)
{
@@ -253,37 +252,39 @@ BOOST_AUTO_TEST_CASE(MaxNumChildrenTest)
template<typename TreeType>
void CheckSameNode(TreeType& node1, TreeType& node2)
{
BOOST_REQUIRE_EQUAL(node1.NumChildren(), node2.NumChildren());
BOOST_REQUIRE_NE(&node1.Dataset(), &node2.Dataset());
REQUIRE(node1.NumChildren() == node2.NumChildren());
REQUIRE(&node1.Dataset() != &node2.Dataset());
// Make sure the children actually got copied.
for (size_t i = 0; i < node1.NumChildren(); ++i)
BOOST_REQUIRE_NE(&node1.Child(i), &node2.Child(i));
REQUIRE(&node1.Child(i) != &node2.Child(i));
// Check that all the points are the same.
BOOST_REQUIRE_EQUAL(node1.NumPoints(), node2.NumPoints());
BOOST_REQUIRE_EQUAL(node1.NumDescendants(), node2.NumDescendants());
REQUIRE(node1.NumPoints() == node2.NumPoints());
REQUIRE(node1.NumDescendants() == node2.NumDescendants());
for (size_t i = 0; i < node1.NumPoints(); ++i)
BOOST_REQUIRE_EQUAL(node1.Point(i), node2.Point(i));
REQUIRE(node1.Point(i) == node2.Point(i));
for (size_t i = 0; i < node1.NumDescendants(); ++i)
BOOST_REQUIRE_EQUAL(node1.Descendant(i), node2.Descendant(i));
REQUIRE(node1.Descendant(i) == node2.Descendant(i));
// Check that the bound is the same.
BOOST_REQUIRE_EQUAL(node1.Bound().Dim(), node2.Bound().Dim());
REQUIRE(node1.Bound().Dim() == node2.Bound().Dim());
for (size_t d = 0; d < node1.Bound().Dim(); ++d)
{
BOOST_REQUIRE_CLOSE(node1.Bound()[d].Lo(), node2.Bound()[d].Lo(), 1e-5);
BOOST_REQUIRE_CLOSE(node1.Bound()[d].Hi(), node2.Bound()[d].Hi(), 1e-5);
REQUIRE(node1.Bound()[d].Lo() ==
Approx(node2.Bound()[d].Lo()).epsilon(1e-7));
REQUIRE(node1.Bound()[d].Hi() ==
Approx(node2.Bound()[d].Hi()).epsilon(1e-7));
}
// Check that the furthest point and descendant distance are the same.
BOOST_REQUIRE_CLOSE(node1.FurthestPointDistance(),
node2.FurthestPointDistance(), 1e-5);
BOOST_REQUIRE_CLOSE(node1.FurthestDescendantDistance(),
node2.FurthestDescendantDistance(), 1e-5);
REQUIRE(node1.FurthestPointDistance() ==
Approx(node2.FurthestPointDistance()).epsilon(1e-7));
REQUIRE(node1.FurthestDescendantDistance() ==
Approx(node2.FurthestDescendantDistance()).epsilon(1e-7));
}
BOOST_AUTO_TEST_CASE(CopyConstructorTest)
TEST_CASE("CopyConstructorTest", "[OctreeTest]")
{
// Use a small random dataset.
arma::mat dataset(3, 100, arma::fill::randu);
@@ -297,7 +298,7 @@ BOOST_AUTO_TEST_CASE(CopyConstructorTest)
/**
* Test the move constructor.
*/
BOOST_AUTO_TEST_CASE(MoveConstructorTest)
TEST_CASE("OcTreeTestMoveConstructorTest", "[OctreeTest]")
{
// Use a small random dataset.
arma::mat dataset(3, 100, arma::fill::randu);
@@ -309,14 +310,14 @@ BOOST_AUTO_TEST_CASE(MoveConstructorTest)
Octree<> t2(std::move(t));
// Make sure the original tree has no data.
BOOST_REQUIRE_EQUAL(t.Dataset().n_rows, 0);
BOOST_REQUIRE_EQUAL(t.Dataset().n_cols, 0);
BOOST_REQUIRE_EQUAL(t.NumChildren(), 0);
BOOST_REQUIRE_EQUAL(t.NumPoints(), 0);
BOOST_REQUIRE_EQUAL(t.NumDescendants(), 0);
BOOST_REQUIRE_SMALL(t.FurthestPointDistance(), 1e-5);
BOOST_REQUIRE_SMALL(t.FurthestDescendantDistance(), 1e-5);
BOOST_REQUIRE_EQUAL(t.Bound().Dim(), 0);
REQUIRE(t.Dataset().n_rows == 0);
REQUIRE(t.Dataset().n_cols == 0);
REQUIRE(t.NumChildren() == 0);
REQUIRE(t.NumPoints() == 0);
REQUIRE(t.NumDescendants() == 0);
REQUIRE(t.FurthestPointDistance() == Approx(0.0).margin(1e-5));
REQUIRE(t.FurthestDescendantDistance() == Approx(0.0).margin(1e-5));
REQUIRE(t.Bound().Dim() == 0);
// Check that the new tree is the same as our copy.
CheckSameNode(tcopy, t2);
@@ -325,7 +326,7 @@ BOOST_AUTO_TEST_CASE(MoveConstructorTest)
/**
* Test serialization.
*/
BOOST_AUTO_TEST_CASE(SerializationTest)
TEST_CASE("OctreeSerializationTest", "[OctreeTest]")
{
// Use a small random dataset.
arma::mat dataset(3, 500, arma::fill::randu);
@@ -345,5 +346,3 @@ BOOST_AUTO_TEST_CASE(SerializationTest)
delete binaryTree;
delete textTree;
}
BOOST_AUTO_TEST_SUITE_END();
File diff suppressed because it is too large Load Diff
+225 -251
View File
@@ -16,35 +16,33 @@
#include <mlpack/core/tree/rectangle_tree.hpp>
#include <mlpack/methods/neighbor_search/neighbor_search.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
#include "test_catch_tools.hpp"
using namespace mlpack;
using namespace mlpack::neighbor;
using namespace mlpack::tree;
using namespace mlpack::metric;
BOOST_AUTO_TEST_SUITE(RectangleTreeTest);
// Test the traits on RectangleTrees.
BOOST_AUTO_TEST_CASE(RectangleTreeTraitsTest)
TEST_CASE("RectangleTreeTraitsTest", "[RectangleTreeTraitsTest]")
{
// Children may be overlapping.
bool b = TreeTraits<RTree<EuclideanDistance, EmptyStatistic,
arma::mat>>::HasOverlappingChildren;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
// Points are not contained in multiple levels.
b = TreeTraits<RTree<EuclideanDistance, EmptyStatistic,
arma::mat>>::HasSelfChildren;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
}
// Test to make sure the tree can be contains the correct number of points after
// it is constructed.
BOOST_AUTO_TEST_CASE(RectangleTreeConstructionCountTest)
TEST_CASE("RectangleTreeConstructionCountTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(3, 1000); // 1000 points in 3 dimensions.
@@ -55,8 +53,8 @@ BOOST_AUTO_TEST_CASE(RectangleTreeConstructionCountTest)
TreeType tree(dataset, 20, 6, 5, 2, 0);
TreeType tree2 = tree;
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), 1000);
BOOST_REQUIRE_EQUAL(tree2.NumDescendants(), 1000);
REQUIRE(tree.NumDescendants() == 1000);
REQUIRE(tree2.NumDescendants() == 1000);
}
/**
@@ -92,7 +90,7 @@ std::vector<arma::vec*> GetAllPointsInTree(const TreeType& tree)
// Test to ensure that none of the points in the tree are duplicates. This,
// combined with the above test to see how many points are in the tree, should
// ensure that we inserted all points.
BOOST_AUTO_TEST_CASE(RectangleTreeConstructionRepeatTest)
TEST_CASE("RectangleTreeConstructionRepeatTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -113,7 +111,7 @@ BOOST_AUTO_TEST_CASE(RectangleTreeConstructionRepeatTest)
for (size_t k = 0; k < v1.n_rows; ++k)
same &= (v1[k] == v2[k]);
BOOST_REQUIRE_NE(same, true);
REQUIRE(same != true);
}
}
@@ -134,7 +132,7 @@ void CheckContainment(const TreeType& tree)
if (tree.NumChildren() == 0)
{
for (size_t i = 0; i < tree.Count(); ++i)
BOOST_REQUIRE(tree.Bound().Contains(
REQUIRE(tree.Bound().Contains(
tree.Dataset().unsafe_col(tree.Point(i))));
}
else
@@ -151,7 +149,7 @@ void CheckContainment(const TreeType& tree)
std::numeric_limits<typename TreeType::ElemType>::max()) ||
tree.Bound()[j].Contains(tree.Child(i).Bound()[j]);
BOOST_REQUIRE(success);
REQUIRE(success);
}
CheckContainment(tree.Child(i));
@@ -178,8 +176,8 @@ void CheckExactContainment(const TreeType& tree)
if (tree.Dataset().col(tree.Point(j))[i] > max)
max = tree.Dataset().col(tree.Point(j))[i];
}
BOOST_REQUIRE_EQUAL(max, tree.Bound()[i].Hi());
BOOST_REQUIRE_EQUAL(min, tree.Bound()[i].Lo());
REQUIRE(max == tree.Bound()[i].Hi());
REQUIRE(min == tree.Bound()[i].Lo());
}
}
else
@@ -196,8 +194,8 @@ void CheckExactContainment(const TreeType& tree)
max = tree.Child(j).Bound()[i].Hi();
}
BOOST_REQUIRE_EQUAL(max, tree.Bound()[i].Hi());
BOOST_REQUIRE_EQUAL(min, tree.Bound()[i].Lo());
REQUIRE(max == tree.Bound()[i].Hi());
REQUIRE(min == tree.Bound()[i].Lo());
}
for (size_t i = 0; i < tree.NumChildren(); ++i)
@@ -213,14 +211,14 @@ void CheckHierarchy(const TreeType& tree)
{
for (size_t i = 0; i < tree.NumChildren(); ++i)
{
BOOST_REQUIRE_EQUAL(&tree, tree.Child(i).Parent());
REQUIRE(&tree == tree.Child(i).Parent());
CheckHierarchy(tree.Child(i));
}
}
// Test to see if the bounds of the tree are correct. (Cover all bounds and
// points beneath this node of the tree).
BOOST_AUTO_TEST_CASE(RectangleTreeContainmentTest)
TEST_CASE("RectangleTreeContainmentTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -249,23 +247,23 @@ void CheckFills(const TreeType& tree)
{
if (tree.IsLeaf())
{
BOOST_REQUIRE(tree.Count() >= tree.MinLeafSize() || tree.Parent() == NULL);
BOOST_REQUIRE(tree.Count() <= tree.MaxLeafSize());
REQUIRE((tree.Count() >= tree.MinLeafSize() || tree.Parent() == NULL));
REQUIRE(tree.Count() <= tree.MaxLeafSize());
}
else
{
for (size_t i = 0; i < tree.NumChildren(); ++i)
{
BOOST_REQUIRE(tree.NumChildren() >= tree.MinNumChildren() ||
tree.Parent() == NULL);
BOOST_REQUIRE(tree.NumChildren() <= tree.MaxNumChildren());
REQUIRE((tree.NumChildren() >= tree.MinNumChildren() ||
tree.Parent() == NULL));
REQUIRE(tree.NumChildren() <= tree.MaxNumChildren());
CheckFills(tree.Child(i));
}
}
}
// Test to ensure that the minimum and maximum fills are satisfied.
BOOST_AUTO_TEST_CASE(CheckMinAndMaxFills)
TEST_CASE("CheckMinAndMaxFills", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -339,7 +337,7 @@ size_t CheckNumDescendants(const TreeType& tree)
{
if (tree.IsLeaf())
{
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), tree.Count());
REQUIRE(tree.NumDescendants() == tree.Count());
return tree.Count();
}
@@ -348,14 +346,14 @@ size_t CheckNumDescendants(const TreeType& tree)
for (size_t i = 0; i < tree.NumChildren(); ++i)
numDescendants += CheckNumDescendants(tree.Child(i));
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), numDescendants);
REQUIRE(tree.NumDescendants() == numDescendants);
return numDescendants;
}
// A test to ensure that all leaf nodes are stored on the same level of the
// tree.
BOOST_AUTO_TEST_CASE(TreeBalance)
TEST_CASE("TreeBalance", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -365,15 +363,15 @@ BOOST_AUTO_TEST_CASE(TreeBalance)
TreeType tree(dataset, 20, 6, 5, 2, 0);
BOOST_REQUIRE_EQUAL(GetMinLevel(tree), GetMaxLevel(tree));
BOOST_REQUIRE_EQUAL(tree.TreeDepth(), GetMinLevel(tree));
REQUIRE(GetMinLevel(tree) == GetMaxLevel(tree));
REQUIRE(tree.TreeDepth() == GetMinLevel(tree));
}
// A test to see if point deletion is working correctly. We build a tree, then
// delete numIter points and test that the query gives correct results. It is
// remotely possible that this test will give a false negative if it should
// happen that two points are the same distance from a third point.
BOOST_AUTO_TEST_CASE(PointDeletion)
TEST_CASE("PointDeletion", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -404,14 +402,14 @@ BOOST_AUTO_TEST_CASE(PointDeletion)
for (size_t k = 0; k < v1.n_rows; ++k)
same &= (v1[k] == v2[k]);
BOOST_REQUIRE(!same);
REQUIRE(!same);
}
}
for (size_t i = 0; i < allPoints.size(); ++i)
delete allPoints[i];
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), 1000 - numIter);
REQUIRE(tree.NumDescendants() == 1000 - numIter);
CheckContainment(tree);
CheckExactContainment(tree);
@@ -439,8 +437,8 @@ BOOST_AUTO_TEST_CASE(PointDeletion)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
}
}
@@ -450,7 +448,7 @@ BOOST_AUTO_TEST_CASE(PointDeletion)
// negative if it should happen that two points are the same distance from a
// third point. Note that this is extremely inefficient. You should not use
// dynamic insertion until a better solution for resizing matrices is available.
BOOST_AUTO_TEST_CASE(PointDynamicAdd)
TEST_CASE("PointDynamicAdd", "[RectangleTreeTraitsTest]")
{
const int numIter = 50;
arma::mat dataset;
@@ -488,14 +486,14 @@ BOOST_AUTO_TEST_CASE(PointDynamicAdd)
for (size_t k = 0; k < v1.n_rows; ++k)
same &= (v1[k] == v2[k]);
BOOST_REQUIRE(!same);
REQUIRE(!same);
}
}
for (size_t i = 0; i < allPoints.size(); ++i)
delete allPoints[i];
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), 1000 + numIter);
REQUIRE(tree.NumDescendants() == 1000 + numIter);
CheckContainment(tree);
CheckExactContainment(tree);
CheckNumDescendants(tree);
@@ -520,14 +518,14 @@ BOOST_AUTO_TEST_CASE(PointDynamicAdd)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
}
}
// A test to ensure that the SingleTreeTraverser is working correctly by
// comparing its results to the results of a naive search.
BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest)
TEST_CASE("SingleTreeTraverserTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -540,7 +538,7 @@ BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest)
arma::mat> TreeType;
TreeType rTree(dataset, 20, 6, 5, 2, 0);
BOOST_REQUIRE_EQUAL(rTree.NumDescendants(), 1000);
REQUIRE(rTree.NumDescendants() == 1000);
CheckContainment(rTree);
CheckExactContainment(rTree);
@@ -560,14 +558,14 @@ BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
}
}
// A test to ensure that the SingleTreeTraverser is working correctly by
// comparing its results to the results of a naive search.
BOOST_AUTO_TEST_CASE(XTreeTraverserTest)
TEST_CASE("XTreeTraverserTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
@@ -583,7 +581,7 @@ BOOST_AUTO_TEST_CASE(XTreeTraverserTest)
arma::mat> TreeType;
TreeType xTree(dataset, 20, 6, 5, 2, 0);
BOOST_REQUIRE_EQUAL(xTree.NumDescendants(), numP);
REQUIRE(xTree.NumDescendants() == numP);
CheckContainment(xTree);
CheckExactContainment(xTree);
@@ -603,12 +601,12 @@ BOOST_AUTO_TEST_CASE(XTreeTraverserTest)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
}
}
BOOST_AUTO_TEST_CASE(HilbertRTreeTraverserTest)
TEST_CASE("HilbertRTreeTraverserTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
@@ -624,7 +622,7 @@ BOOST_AUTO_TEST_CASE(HilbertRTreeTraverserTest)
NeighborSearchStat<NearestNeighborSort>, arma::mat> TreeType;
TreeType hilbertRTree(dataset, 20, 6, 5, 2, 0);
BOOST_REQUIRE_EQUAL(hilbertRTree.NumDescendants(), numP);
REQUIRE(hilbertRTree.NumDescendants() == numP);
CheckContainment(hilbertRTree);
CheckExactContainment(hilbertRTree);
@@ -644,8 +642,8 @@ BOOST_AUTO_TEST_CASE(HilbertRTreeTraverserTest)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
}
}
@@ -655,25 +653,30 @@ void CheckHilbertOrdering(const TreeType& tree)
if (tree.IsLeaf())
{
for (size_t i = 0; i < tree.NumPoints() - 1; ++i)
BOOST_REQUIRE_LE(tree.AuxiliaryInfo().HilbertValue().ComparePoints(
{
REQUIRE(tree.AuxiliaryInfo().HilbertValue().ComparePoints(
tree.Dataset().col(tree.Point(i)),
tree.Dataset().col(tree.Point(i + 1))),
tree.Dataset().col(tree.Point(i + 1))) <=
0);
}
BOOST_REQUIRE_EQUAL(tree.AuxiliaryInfo().HilbertValue().CompareWith(
tree.Dataset().col(tree.Point(tree.NumPoints() - 1))),
REQUIRE(tree.AuxiliaryInfo().HilbertValue().CompareWith(
tree.Dataset().col(tree.Point(tree.NumPoints() - 1))) ==
0);
}
else
{
for (size_t i = 0; i < tree.NumChildren() - 1; ++i)
BOOST_REQUIRE_LE(tree.AuxiliaryInfo().HilbertValue().CompareValues(
{
REQUIRE(tree.AuxiliaryInfo().HilbertValue().CompareValues(
tree.Child(i).AuxiliaryInfo().HilbertValue(),
tree.Child(i + 1).AuxiliaryInfo().HilbertValue()),
tree.Child(i + 1).AuxiliaryInfo().HilbertValue()) <=
0);
}
BOOST_REQUIRE_EQUAL(tree.AuxiliaryInfo().HilbertValue().CompareWith(
tree.Child(tree.NumChildren() - 1).AuxiliaryInfo().HilbertValue()),
REQUIRE(tree.AuxiliaryInfo().HilbertValue().CompareWith(
tree.Child(tree.NumChildren() - 1).AuxiliaryInfo().HilbertValue()) ==
0);
for (size_t i = 0; i < tree.NumChildren(); ++i)
@@ -681,7 +684,7 @@ void CheckHilbertOrdering(const TreeType& tree)
}
}
BOOST_AUTO_TEST_CASE(HilbertRTreeOrderingTest)
TEST_CASE("HilbertRTreeOrderingTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -712,7 +715,7 @@ void CheckDiscreteHilbertValueSync(const TreeType& tree)
const int equal = HilbertValue::CompareValues(
value.LocalHilbertValues()->col(i), pointValue);
BOOST_REQUIRE_EQUAL(equal, 0);
REQUIRE(equal == 0);
}
}
else
@@ -722,7 +725,7 @@ void CheckDiscreteHilbertValueSync(const TreeType& tree)
}
}
BOOST_AUTO_TEST_CASE(DiscreteHilbertValueSyncTest)
TEST_CASE("DiscreteHilbertValueSyncTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -734,7 +737,7 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueSyncTest)
CheckDiscreteHilbertValueSync(hilbertRTree);
}
BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
TEST_CASE("DiscreteHilbertValueTest", "[RectangleTreeTraitsTest]")
{
arma::vec point01(1);
arma::vec point02(1);
@@ -742,56 +745,47 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
point01[0] = -DBL_MAX;
point02[0] = DBL_MAX;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point01,
point02), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point01, point02) == -1);
point01[0] = -DBL_MAX;
point02[0] = -100;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point01,
point02), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point01, point02) == -1);
point01[0] = -100;
point02[0] = -1;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point01,
point02), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point01, point02) == -1);
point01[0] = -1;
point02[0] = -std::numeric_limits<double>::min();
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point01,
point02), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point01, point02) == -1);
point01[0] = -std::numeric_limits<double>::min();
point02[0] = 0;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point01,
point02), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point01, point02) == -1);
point01[0] = 0;
point02[0] = std::numeric_limits<double>::min();
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point01,
point02), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point01, point02) == -1);
point01[0] = std::numeric_limits<double>::min();
point02[0] = 1;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point01,
point02), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point01, point02) == -1);
point01[0] = 1;
point02[0] = 100;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point01,
point02), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point01, point02) == -1);
point01[0] = 100;
point02[0] = DBL_MAX;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point01,
point02), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point01, point02) == -1);
arma::vec point1(2);
arma::vec point2(2);
@@ -802,8 +796,7 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
point2[0] = 0;
point2[1] = 0;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point1,
point2), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point1, point2) == -1);
point1[0] = -1;
point1[1] = -1;
@@ -811,8 +804,7 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
point2[0] = 1;
point2[1] = -1;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point1,
point2), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point1, point2) == -1);
point1[0] = -1;
point1[1] = -1;
@@ -820,8 +812,7 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
point2[0] = -1;
point2[1] = 1;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point1,
point2), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point1, point2) == -1);
point1[0] = -DBL_MAX + 1;
point1[1] = -DBL_MAX + 1;
@@ -829,8 +820,7 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
point2[0] = -1;
point2[1] = -1;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point1,
point2), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point1, point2) == -1);
point1[0] = DBL_MAX * 0.75;
point1[1] = DBL_MAX * 0.75;
@@ -838,8 +828,7 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
point2[0] = DBL_MAX * 0.25;
point2[1] = DBL_MAX * 0.25;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point1,
point2), 1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point1, point2) == 1);
arma::vec point3(4);
arma::vec point4(4);
@@ -854,8 +843,7 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
point4[2] = 1.0;
point4[3] = 1.0;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point3,
point4), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point3, point4) == -1);
point3[0] = -DBL_MAX;
point3[1] = DBL_MAX;
@@ -867,8 +855,7 @@ BOOST_AUTO_TEST_CASE(DiscreteHilbertValueTest)
point4[2] = DBL_MAX;
point4[3] = DBL_MAX;
BOOST_REQUIRE_EQUAL(DiscreteHilbertValue<double>::ComparePoints(point3,
point4), -1);
REQUIRE(DiscreteHilbertValue<double>::ComparePoints(point3, point4) == -1);
}
template<typename TreeType>
@@ -881,7 +868,7 @@ void CheckHilbertValue(const TreeType& tree)
if (tree.IsLeaf())
{
BOOST_REQUIRE_EQUAL(value.OwnsLocalHilbertValues(), true);
REQUIRE(value.OwnsLocalHilbertValues() == true);
return;
}
@@ -889,26 +876,26 @@ void CheckHilbertValue(const TreeType& tree)
{
const HilbertValue& childValue =
tree.Child(i).AuxiliaryInfo().HilbertValue();
BOOST_REQUIRE_EQUAL(value.ValueToInsert(), childValue.ValueToInsert());
REQUIRE(value.ValueToInsert() == childValue.ValueToInsert());
}
const HilbertValue& childValue =
tree.Child(tree.NumChildren() - 1).AuxiliaryInfo().HilbertValue();
BOOST_REQUIRE_EQUAL(value.LocalHilbertValues(),
REQUIRE(value.LocalHilbertValues() ==
childValue.LocalHilbertValues());
if (!tree.Parent())
BOOST_REQUIRE_EQUAL(value.OwnsValueToInsert(), true);
REQUIRE(value.OwnsValueToInsert() == true);
else
BOOST_REQUIRE_EQUAL(value.OwnsValueToInsert(), false);
REQUIRE(value.OwnsValueToInsert() == false);
BOOST_REQUIRE_EQUAL(value.OwnsLocalHilbertValues(), false);
REQUIRE(value.OwnsLocalHilbertValues() == false);
for (size_t i = 0; i < tree.NumChildren(); ++i)
CheckHilbertValue(tree.Child(i));
}
BOOST_AUTO_TEST_CASE(HilbertRTeeCopyConstructorTest)
TEST_CASE("HilbertRTeeCopyConstructorTest", "[RectangleTreeTraitsTest]")
{
typedef HilbertRTree<EuclideanDistance,
NeighborSearchStat<NearestNeighborSort>, arma::mat> TreeType;
@@ -928,7 +915,7 @@ BOOST_AUTO_TEST_CASE(HilbertRTeeCopyConstructorTest)
CheckNumDescendants(copy);
}
BOOST_AUTO_TEST_CASE(HilbertRTeeMoveConstructorTest)
TEST_CASE("HilbertRTeeMoveConstructorTest", "[RectangleTreeTraitsTest]")
{
typedef HilbertRTree<EuclideanDistance,
NeighborSearchStat<NearestNeighborSort>, arma::mat> TreeType;
@@ -971,14 +958,14 @@ void CheckOverlap(const TreeType& tree)
if (!success)
break;
}
BOOST_REQUIRE_EQUAL(success, true);
REQUIRE(success == true);
for (size_t i = 0; i < tree.NumChildren(); ++i)
CheckOverlap(tree.Child(i));
}
BOOST_AUTO_TEST_CASE(RPlusTreeOverlapTest)
TEST_CASE("RPlusTreeOverlapTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -991,15 +978,15 @@ BOOST_AUTO_TEST_CASE(RPlusTreeOverlapTest)
// Children can not be overlapping.
bool b = TreeTraits<TreeType>::HasOverlappingChildren;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
// Ensure that all leaf nodes are at the same level.
BOOST_REQUIRE_EQUAL(GetMinLevel(rPlusTree), GetMaxLevel(rPlusTree));
BOOST_REQUIRE_EQUAL(rPlusTree.TreeDepth(), GetMinLevel(rPlusTree));
REQUIRE(GetMinLevel(rPlusTree) == GetMaxLevel(rPlusTree));
REQUIRE(rPlusTree.TreeDepth() == GetMinLevel(rPlusTree));
}
BOOST_AUTO_TEST_CASE(RPlusTreeTraverserTest)
TEST_CASE("RPlusTreeTraverserTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
@@ -1015,7 +1002,7 @@ BOOST_AUTO_TEST_CASE(RPlusTreeTraverserTest)
arma::mat > TreeType;
TreeType rPlusTree(dataset, 20, 6, 5, 2, 0);
BOOST_REQUIRE_EQUAL(rPlusTree.NumDescendants(), numP);
REQUIRE(rPlusTree.NumDescendants() == numP);
CheckContainment(rPlusTree);
CheckExactContainment(rPlusTree);
@@ -1036,8 +1023,8 @@ BOOST_AUTO_TEST_CASE(RPlusTreeTraverserTest)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
}
}
@@ -1052,9 +1039,9 @@ void CheckRPlusPlusTreeBound(const TreeType& tree)
// Ensure that the maximum bounding rectangle contains all children.
for (size_t k = 0; k < tree.Bound().Dim(); ++k)
{
BOOST_REQUIRE_LE(tree.Bound()[k].Hi(),
REQUIRE(tree.Bound()[k].Hi() <=
tree.AuxiliaryInfo().OuterBound()[k].Hi());
BOOST_REQUIRE_LE(tree.AuxiliaryInfo().OuterBound()[k].Lo(),
REQUIRE(tree.AuxiliaryInfo().OuterBound()[k].Lo() <=
tree.Bound()[k].Lo());
}
@@ -1062,7 +1049,7 @@ void CheckRPlusPlusTreeBound(const TreeType& tree)
{
// Ensure that the maximum bounding rectangle contains all points.
for (size_t i = 0; i < tree.Count(); ++i)
BOOST_REQUIRE_EQUAL(true,
REQUIRE(true ==
tree.Bound().Contains(tree.Dataset().col(tree.Point(i))));
return;
@@ -1089,13 +1076,13 @@ void CheckRPlusPlusTreeBound(const TreeType& tree)
if (!success)
break;
}
BOOST_REQUIRE_EQUAL(success, true);
REQUIRE(success == true);
for (size_t i = 0; i < tree.NumChildren(); ++i)
CheckRPlusPlusTreeBound(tree.Child(i));
}
BOOST_AUTO_TEST_CASE(RPlusPlusTreeBoundTest)
TEST_CASE("RPlusPlusTreeBoundTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -1109,10 +1096,10 @@ BOOST_AUTO_TEST_CASE(RPlusPlusTreeBoundTest)
// Children can not be overlapping.
bool b = TreeTraits<TreeType>::HasOverlappingChildren;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
BOOST_REQUIRE_EQUAL(GetMinLevel(rPlusPlusTree), GetMaxLevel(rPlusPlusTree));
BOOST_REQUIRE_EQUAL(rPlusPlusTree.TreeDepth(), GetMinLevel(rPlusPlusTree));
REQUIRE(GetMinLevel(rPlusPlusTree) == GetMaxLevel(rPlusPlusTree));
REQUIRE(rPlusPlusTree.TreeDepth() == GetMinLevel(rPlusPlusTree));
// Check the MinimalSplitsNumberSweep.
typedef RectangleTree<EuclideanDistance,
@@ -1125,11 +1112,11 @@ BOOST_AUTO_TEST_CASE(RPlusPlusTreeBoundTest)
CheckRPlusPlusTreeBound(rPlusPlusTree2);
BOOST_REQUIRE_EQUAL(GetMinLevel(rPlusPlusTree2), GetMaxLevel(rPlusPlusTree2));
BOOST_REQUIRE_EQUAL(rPlusPlusTree2.TreeDepth(), GetMinLevel(rPlusPlusTree2));
REQUIRE(GetMinLevel(rPlusPlusTree2) == GetMaxLevel(rPlusPlusTree2));
REQUIRE(rPlusPlusTree2.TreeDepth() == GetMinLevel(rPlusPlusTree2));
}
BOOST_AUTO_TEST_CASE(RPlusPlusTreeTraverserTest)
TEST_CASE("RPlusPlusTreeTraverserTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset;
@@ -1145,7 +1132,7 @@ BOOST_AUTO_TEST_CASE(RPlusPlusTreeTraverserTest)
NeighborSearchStat<NearestNeighborSort>, arma::mat > TreeType;
TreeType rPlusPlusTree(dataset, 20, 6, 5, 2, 0);
BOOST_REQUIRE_EQUAL(rPlusPlusTree.NumDescendants(), numP);
REQUIRE(rPlusPlusTree.NumDescendants() == numP);
CheckContainment(rPlusPlusTree);
CheckExactContainment(rPlusPlusTree);
@@ -1167,15 +1154,15 @@ BOOST_AUTO_TEST_CASE(RPlusPlusTreeTraverserTest)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
}
}
// Test the tree splitting. We set MaxLeafSize and MaxNumChildren rather low
// to allow us to test by hand without adding hundreds of points.
BOOST_AUTO_TEST_CASE(RTreeSplitTest)
TEST_CASE("RTreeSplitTest", "[RectangleTreeTraitsTest]")
{
arma::mat data = arma::trans(arma::mat("0.0 0.0;"
"0.0 1.0;"
@@ -1194,9 +1181,9 @@ BOOST_AUTO_TEST_CASE(RTreeSplitTest)
// There's technically no reason they have to be in a certain order, so we
// use firstChild etc. to arbitrarily name them.
BOOST_REQUIRE_EQUAL(rTree.NumChildren(), 2);
BOOST_REQUIRE_EQUAL(rTree.NumDescendants(), 10);
BOOST_REQUIRE_EQUAL(rTree.TreeDepth(), 3);
REQUIRE(rTree.NumChildren() == 2);
REQUIRE(rTree.NumDescendants() == 10);
REQUIRE(rTree.TreeDepth() == 3);
int firstChild = 0, secondChild = 1;
if (rTree.Child(firstChild).NumChildren() == 2)
@@ -1205,34 +1192,37 @@ BOOST_AUTO_TEST_CASE(RTreeSplitTest)
secondChild = 0;
}
BOOST_REQUIRE_SMALL(rTree.Child(firstChild).Bound()[0].Lo(), 1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(firstChild).Bound()[0].Hi(), 0.1,
1e-15);
BOOST_REQUIRE_SMALL(rTree.Child(firstChild).Bound()[1].Lo(), 1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(firstChild).Bound()[1].Hi(), 1.0,
1e-15);
REQUIRE(rTree.Child(firstChild).Bound()[0].Lo() ==
Approx(0.0).margin(1e-15));
BOOST_REQUIRE_CLOSE(rTree.Child(secondChild).Bound()[0].Lo(), 0.3,
1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(secondChild).Bound()[0].Hi(), 1.0,
1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(secondChild).Bound()[1].Lo(), 0.1,
1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(secondChild).Bound()[1].Hi(), 0.9,
1e-15);
REQUIRE(rTree.Child(firstChild).Bound()[0].Hi() ==
Approx(0.1).epsilon(1e-17));
REQUIRE(rTree.Child(firstChild).Bound()[1].Lo() ==
Approx(0.0).margin(1e-15));
REQUIRE(rTree.Child(firstChild).Bound()[1].Hi() ==
Approx(1.0).epsilon(1e-17));
BOOST_REQUIRE_EQUAL(rTree.Child(firstChild).NumChildren(), 1);
BOOST_REQUIRE_SMALL(
rTree.Child(firstChild).Child(0).Bound()[0].Lo(), 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(firstChild).Child(0).Bound()[0].Hi(), 0.1,
1e-15);
BOOST_REQUIRE_SMALL(
rTree.Child(firstChild).Child(0).Bound()[1].Lo(), 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(firstChild).Child(0).Bound()[1].Hi(), 1.0,
1e-15);
BOOST_REQUIRE_EQUAL(rTree.Child(firstChild).Child(0).Count(), 3);
REQUIRE(rTree.Child(secondChild).Bound()[0].Lo() ==
Approx(0.3).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Bound()[0].Hi() ==
Approx(1.0).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Bound()[1].Lo() ==
Approx(0.1).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Bound()[1].Hi() ==
Approx(0.9).epsilon(1e-17));
REQUIRE(rTree.Child(firstChild).NumChildren() == 1);
REQUIRE(rTree.Child(firstChild).Child(0).Bound()[0].Lo() ==
Approx(0.0).margin(1e-15));
REQUIRE(rTree.Child(firstChild).Child(0).Bound()[0].Hi() ==
Approx(0.1).epsilon(1e-17));
REQUIRE(rTree.Child(firstChild).Child(0).Bound()[1].Lo() ==
Approx(0.0).margin(1e-15));
REQUIRE(rTree.Child(firstChild).Child(0).Bound()[1].Hi() ==
Approx(1.0).epsilon(1e-17));
REQUIRE(rTree.Child(firstChild).Child(0).Count() == 3);
int firstPrime = 0, secondPrime = 1;
if (rTree.Child(secondChild).Child(firstPrime).Count() == 3)
@@ -1241,41 +1231,33 @@ BOOST_AUTO_TEST_CASE(RTreeSplitTest)
secondPrime = 0;
}
BOOST_REQUIRE_EQUAL(rTree.Child(secondChild).NumChildren(), 2);
BOOST_REQUIRE_EQUAL(
rTree.Child(secondChild).Child(firstPrime).Count(), 4);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(firstPrime).Bound()[0].Lo(),
0.3, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(firstPrime).Bound()[0].Hi(),
0.7, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(firstPrime).Bound()[1].Lo(),
0.3, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(firstPrime).Bound()[1].Hi(),
0.7, 1e-15);
REQUIRE(rTree.Child(secondChild).NumChildren() == 2);
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Count() == 4);
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Bound()[0].Lo() ==
Approx(0.3).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Bound()[0].Hi() ==
Approx(0.7).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Bound()[1].Lo() ==
Approx(0.3).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Bound()[1].Hi() ==
Approx(0.7).epsilon(1e-17));
BOOST_REQUIRE_EQUAL(
rTree.Child(secondChild).Child(secondPrime).Count(), 3);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(secondPrime).Bound()[0].Lo(),
0.9, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(secondPrime).Bound()[0].Hi(),
1.0, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(secondPrime).Bound()[1].Lo(),
0.1, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(secondPrime).Bound()[1].Hi(),
0.9, 1e-15);
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Count() == 3);
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Bound()[0].Lo() ==
Approx(0.9).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Bound()[0].Hi() ==
Approx(1.0).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Bound()[1].Lo() ==
Approx(0.1).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Bound()[1].Hi() ==
Approx(0.9).epsilon(1e-17));
}
// Test the tree splitting. We set MaxLeafSize and MaxNumChildren rather low
// to allow us to test by hand without adding hundreds of points.
BOOST_AUTO_TEST_CASE(RStarTreeSplitTest)
TEST_CASE("RStarTreeSplitTest", "[RectangleTreeTraitsTest]")
{
arma::mat data = arma::trans(arma::mat("0.0 0.0;"
"0.0 1.0;"
@@ -1295,9 +1277,9 @@ BOOST_AUTO_TEST_CASE(RStarTreeSplitTest)
// There's technically no reason they have to be in a certain order, so we
// use firstChild etc. to arbitrarily name them.
BOOST_REQUIRE_EQUAL(rTree.NumChildren(), 2);
BOOST_REQUIRE_EQUAL(rTree.NumDescendants(), 10);
BOOST_REQUIRE_EQUAL(rTree.TreeDepth(), 3);
REQUIRE(rTree.NumChildren() == 2);
REQUIRE(rTree.NumDescendants() == 10);
REQUIRE(rTree.TreeDepth() == 3);
int firstChild = 0, secondChild = 1;
if (rTree.Child(firstChild).NumChildren() == 2)
@@ -1306,32 +1288,35 @@ BOOST_AUTO_TEST_CASE(RStarTreeSplitTest)
secondChild = 0;
}
BOOST_REQUIRE_SMALL(rTree.Child(firstChild).Bound()[0].Lo(), 1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(firstChild).Bound()[0].Hi(), 0.1,
1e-15);
BOOST_REQUIRE_SMALL(rTree.Child(firstChild).Bound()[1].Lo(), 1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(firstChild).Bound()[1].Hi(), 1.0,
1e-15);
REQUIRE(rTree.Child(firstChild).Bound()[0].Lo() ==
Approx(0.0).margin(1e-15));
REQUIRE(rTree.Child(firstChild).Bound()[0].Hi() ==
Approx(0.1).epsilon(1e-17));
REQUIRE(rTree.Child(firstChild).Bound()[1].Lo() ==
Approx(0.0).margin(1e-15));
REQUIRE(rTree.Child(firstChild).Bound()[1].Hi() ==
Approx(1.0).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Bound()[0].Lo() ==
Approx(0.3).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Bound()[0].Hi() ==
Approx(1.0).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Bound()[1].Lo() ==
Approx(0.1).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Bound()[1].Hi() ==
Approx(0.9).epsilon(1e-17));
REQUIRE(rTree.Child(firstChild).NumChildren() == 1);
BOOST_REQUIRE_CLOSE(rTree.Child(secondChild).Bound()[0].Lo(), 0.3,
1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(secondChild).Bound()[0].Hi(), 1.0,
1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(secondChild).Bound()[1].Lo(), 0.1,
1e-15);
BOOST_REQUIRE_CLOSE(rTree.Child(secondChild).Bound()[1].Hi(), 0.9,
1e-15);
BOOST_REQUIRE_EQUAL(rTree.Child(firstChild).NumChildren(), 1);
BOOST_REQUIRE_SMALL(
rTree.Child(firstChild).Child(0).Bound()[0].Lo(), 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(firstChild).Child(0).Bound()[0].Hi(), 0.1, 1e-15);
BOOST_REQUIRE_SMALL(
rTree.Child(firstChild).Child(0).Bound()[1].Lo(), 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(firstChild).Child(0).Bound()[1].Hi(), 1.0, 1e-15);
BOOST_REQUIRE_EQUAL(rTree.Child(firstChild).Child(0).Count(), 3);
REQUIRE(rTree.Child(firstChild).Child(0).Bound()[0].Lo() ==
Approx(0.0).margin(1e-15));
REQUIRE(rTree.Child(firstChild).Child(0).Bound()[0].Hi() ==
Approx(0.1).epsilon(1e-17));
REQUIRE(rTree.Child(firstChild).Child(0).Bound()[1].Lo() ==
Approx(0.0).margin(1e-15));
REQUIRE(rTree.Child(firstChild).Child(0).Bound()[1].Hi() ==
Approx(1.0).epsilon(1e-17));
REQUIRE(rTree.Child(firstChild).Child(0).Count() == 3);
int firstPrime = 0, secondPrime = 1;
if (rTree.Child(secondChild).Child(firstPrime).Count() == 3)
@@ -1340,48 +1325,37 @@ BOOST_AUTO_TEST_CASE(RStarTreeSplitTest)
secondPrime = 0;
}
BOOST_REQUIRE_EQUAL(rTree.Child(secondChild).NumChildren(), 2);
BOOST_REQUIRE_EQUAL(
rTree.Child(secondChild).Child(firstPrime).Count(), 4);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(firstPrime).Bound()[0].Lo(),
0.3, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(firstPrime).Bound()[0].Hi(),
0.7, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(firstPrime).Bound()[1].Lo(),
0.3, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(firstPrime).Bound()[1].Hi(),
0.7, 1e-15);
BOOST_REQUIRE_EQUAL(
rTree.Child(secondChild).Child(secondPrime).Count(), 3);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(secondPrime).Bound()[0].Lo(),
0.9, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(secondPrime).Bound()[0].Hi(),
1.0, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(secondPrime).Bound()[1].Lo(),
0.1, 1e-15);
BOOST_REQUIRE_CLOSE(
rTree.Child(secondChild).Child(secondPrime).Bound()[1].Hi(),
0.9, 1e-15);
REQUIRE(rTree.Child(secondChild).NumChildren() == 2);
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Count() == 4);
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Bound()[0].Lo() ==
Approx(0.3).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Bound()[0].Hi() ==
Approx(0.7).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Bound()[1].Lo() ==
Approx(0.3).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Bound()[1].Lo() ==
Approx(0.3).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(firstPrime).Bound()[1].Hi() ==
Approx(0.7).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Count() == 3);
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Bound()[0].Lo() ==
Approx(0.9).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Bound()[0].Hi() ==
Approx(1.0).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Bound()[1].Lo() ==
Approx(0.1).epsilon(1e-17));
REQUIRE(rTree.Child(secondChild).Child(secondPrime).Bound()[1].Hi() ==
Approx(0.9).epsilon(1e-17));
}
BOOST_AUTO_TEST_CASE(RectangleTreeMoveDatasetTest)
TEST_CASE("RectangleTreeMoveDatasetTest", "[RectangleTreeTraitsTest]")
{
arma::mat dataset = arma::randu<arma::mat>(3, 1000);
typedef RTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
TreeType tree(std::move(dataset));
BOOST_REQUIRE_EQUAL(dataset.n_elem, 0);
BOOST_REQUIRE_EQUAL(tree.Dataset().n_rows, 3);
BOOST_REQUIRE_EQUAL(tree.Dataset().n_cols, 1000);
REQUIRE(dataset.n_elem == 0);
REQUIRE(tree.Dataset().n_rows == 3);
REQUIRE(tree.Dataset().n_cols == 1000);
}
BOOST_AUTO_TEST_SUITE_END();
+4 -8
View File
@@ -13,9 +13,7 @@
#include <mlpack/core.hpp>
#include <mlpack/core/util/sfinae_utility.hpp>
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(SFINAETest);
#include "catch.hpp"
class A
{
@@ -97,7 +95,7 @@ HAS_ANY_METHOD_FORM(Model, HasModel);
* Test at compile time the presence of methods of the specified forms with the
* stated number of additional arguments.
*/
BOOST_AUTO_TEST_CASE(HasMethodFormWithNAdditionalArgsTest)
TEST_CASE("HasMethodFormWithNAdditionalArgsTest", "[SFINAETest]")
{
static_assert(!HasM<A, MForm1>::WithNAdditionalArgs<0>::value,
"value should be false");
@@ -145,7 +143,7 @@ BOOST_AUTO_TEST_CASE(HasMethodFormWithNAdditionalArgsTest)
/*
* Test at compile time the presence of methods of the specified forms.
*/
BOOST_AUTO_TEST_CASE(HasMethodFormTest)
TEST_CASE("HasMethodFormTest", "[SFINAETest]")
{
static_assert(HasM<A, MForm1>::value, "value should be true");
@@ -168,7 +166,7 @@ BOOST_AUTO_TEST_CASE(HasMethodFormTest)
* Test at compile time, for the presence/absence of a specific member
* function in a class.
*/
BOOST_AUTO_TEST_CASE(HasMethodNameTest)
TEST_CASE("HasMethodNameTest", "[SFINAETest]")
{
static_assert(!HasModel<WithOutFunctionModel>::value,
"value should be false");
@@ -176,5 +174,3 @@ BOOST_AUTO_TEST_CASE(HasMethodNameTest)
static_assert(HasModel<WithFunctionModelB>::value, "value should be true");
static_assert(HasModel<WithInheritedModelA>::value, "value should be true");
}
BOOST_AUTO_TEST_SUITE_END();
+45 -50
View File
@@ -16,8 +16,7 @@
#include <mlpack/methods/neighbor_search/sort_policies/nearest_neighbor_sort.hpp>
#include <mlpack/methods/neighbor_search/sort_policies/furthest_neighbor_sort.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
using namespace mlpack;
using namespace mlpack::neighbor;
@@ -25,47 +24,45 @@ using namespace mlpack::bound;
using namespace mlpack::tree;
using namespace mlpack::metric;
BOOST_AUTO_TEST_SUITE(SortPolicyTest);
// Tests for NearestNeighborSort
/**
* Ensure the best distance for nearest neighbors is 0.
*/
BOOST_AUTO_TEST_CASE(NnsBestDistance)
TEST_CASE("NnsBestDistance", "[SortPolicyTest]")
{
BOOST_REQUIRE(NearestNeighborSort::BestDistance() == 0);
REQUIRE(NearestNeighborSort::BestDistance() == 0);
}
/**
* Ensure the worst distance for nearest neighbors is DBL_MAX.
*/
BOOST_AUTO_TEST_CASE(NnsWorstDistance)
TEST_CASE("NnsWorstDistance", "[SortPolicyTest]")
{
BOOST_REQUIRE(NearestNeighborSort::WorstDistance() == DBL_MAX);
REQUIRE(NearestNeighborSort::WorstDistance() == DBL_MAX);
}
/**
* Make sure the comparison works for values strictly less than the reference.
*/
BOOST_AUTO_TEST_CASE(NnsIsBetterStrict)
TEST_CASE("NnsIsBetterStrict", "[SortPolicyTest]")
{
BOOST_REQUIRE(NearestNeighborSort::IsBetter(5.0, 6.0) == true);
REQUIRE(NearestNeighborSort::IsBetter(5.0, 6.0) == true);
}
/**
* Warn in case the comparison is not strict.
*/
BOOST_AUTO_TEST_CASE(NnsIsBetterNotStrict)
TEST_CASE("NnsIsBetterNotStrict", "[SortPolicyTest]")
{
BOOST_WARN(NearestNeighborSort::IsBetter(6.0, 6.0) == true);
CHECK(NearestNeighborSort::IsBetter(6.0, 6.0) == true);
}
/**
* Very simple sanity check to ensure that bounds are working alright. We will
* use a one-dimensional bound for simplicity.
*/
BOOST_AUTO_TEST_CASE(NnsNodeToNodeDistance)
TEST_CASE("NnsNodeToNodeDistance", "[SortPolicyTest]")
{
// Well, there's no easy way to make HRectBounds the way we want, so we have
// to make them and then expand the region to include new points.
@@ -89,8 +86,8 @@ BOOST_AUTO_TEST_CASE(NnsNodeToNodeDistance)
nodeTwo.Bound() |= utility;
// This should use the L2 distance.
BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne,
&nodeTwo), 4.0, 1e-5);
REQUIRE(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne, &nodeTwo) ==
Approx(4.0).epsilon(1e-7));
// And another just to be sure, from the other side.
nodeTwo.Bound().Clear();
@@ -100,8 +97,8 @@ BOOST_AUTO_TEST_CASE(NnsNodeToNodeDistance)
nodeTwo.Bound() |= utility;
// Again, the distance is the L2 distance.
BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne,
&nodeTwo), 1.0, 1e-5);
REQUIRE(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne, &nodeTwo) ==
Approx(1.0).epsilon(1e-7));
// Now, when the bounds overlap.
nodeTwo.Bound().Clear();
@@ -110,15 +107,15 @@ BOOST_AUTO_TEST_CASE(NnsNodeToNodeDistance)
utility[0] = 0.5;
nodeTwo.Bound() |= utility;
BOOST_REQUIRE_SMALL(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne,
&nodeTwo), 1e-5);
REQUIRE(NearestNeighborSort::BestNodeToNodeDistance(&nodeOne, &nodeTwo) ==
Approx(0.0).margin(1e-5));
}
/**
* Another very simple sanity check for the point-to-node case, again in one
* dimension.
*/
BOOST_AUTO_TEST_CASE(NnsPointToNodeDistance)
TEST_CASE("NnsPointToNodeDistance", "[SortPolicyTest]")
{
// Well, there's no easy way to make HRectBounds the way we want, so we have
// to make them and then expand the region to include new points.
@@ -137,20 +134,20 @@ BOOST_AUTO_TEST_CASE(NnsPointToNodeDistance)
point[0] = -0.5;
// The distance is the L2 distance.
BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestPointToNodeDistance(point,
&node), 0.5, 1e-5);
REQUIRE(NearestNeighborSort::BestPointToNodeDistance(point, &node) ==
Approx(0.5).epsilon(1e-7));
// Now from the other side of the bound.
point[0] = 1.5;
BOOST_REQUIRE_CLOSE(NearestNeighborSort::BestPointToNodeDistance(point,
&node), 0.5, 1e-5);
REQUIRE(NearestNeighborSort::BestPointToNodeDistance(point, &node) ==
Approx(0.5).epsilon(1e-7));
// And now when the point is inside the bound.
point[0] = 0.5;
BOOST_REQUIRE_SMALL(NearestNeighborSort::BestPointToNodeDistance(point,
&node), 1e-5);
REQUIRE(NearestNeighborSort::BestPointToNodeDistance(point, &node) ==
Approx(0.0).margin(1e-5));
}
// Tests for FurthestNeighborSort
@@ -158,40 +155,40 @@ BOOST_AUTO_TEST_CASE(NnsPointToNodeDistance)
/**
* Ensure the best distance for furthest neighbors is DBL_MAX.
*/
BOOST_AUTO_TEST_CASE(FnsBestDistance)
TEST_CASE("FnsBestDistance", "[SortPolicyTest]")
{
BOOST_REQUIRE(FurthestNeighborSort::BestDistance() == DBL_MAX);
REQUIRE(FurthestNeighborSort::BestDistance() == DBL_MAX);
}
/**
* Ensure the worst distance for furthest neighbors is 0.
*/
BOOST_AUTO_TEST_CASE(FnsWorstDistance)
TEST_CASE("FnsWorstDistance", "[SortPolicyTest]")
{
BOOST_REQUIRE(FurthestNeighborSort::WorstDistance() == 0);
REQUIRE(FurthestNeighborSort::WorstDistance() == 0);
}
/**
* Make sure the comparison works for values strictly less than the reference.
*/
BOOST_AUTO_TEST_CASE(FnsIsBetterStrict)
TEST_CASE("FnsIsBetterStrict", "[SortPolicyTest]")
{
BOOST_REQUIRE(FurthestNeighborSort::IsBetter(5.0, 4.0) == true);
REQUIRE(FurthestNeighborSort::IsBetter(5.0, 4.0) == true);
}
/**
* Warn in case the comparison is not strict.
*/
BOOST_AUTO_TEST_CASE(FnsIsBetterNotStrict)
TEST_CASE("FnsIsBetterNotStrict", "[SortPolicyTest]")
{
BOOST_WARN(FurthestNeighborSort::IsBetter(6.0, 6.0) == true);
CHECK(FurthestNeighborSort::IsBetter(6.0, 6.0) == true);
}
/**
* Very simple sanity check to ensure that bounds are working alright. We will
* use a one-dimensional bound for simplicity.
*/
BOOST_AUTO_TEST_CASE(FnsNodeToNodeDistance)
TEST_CASE("FnsNodeToNodeDistance", "[SortPolicyTest]")
{
// Well, there's no easy way to make HRectBounds the way we want, so we have
// to make them and then expand the region to include new points.
@@ -214,8 +211,8 @@ BOOST_AUTO_TEST_CASE(FnsNodeToNodeDistance)
nodeTwo.Bound() |= utility;
// This should use the L2 distance.
BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestNodeToNodeDistance(&nodeOne,
&nodeTwo), 6.0, 1e-5);
REQUIRE(FurthestNeighborSort::BestNodeToNodeDistance(&nodeOne, &nodeTwo) ==
Approx(6.0).epsilon(1e-7));
// And another just to be sure, from the other side.
nodeTwo.Bound().Clear();
@@ -225,8 +222,8 @@ BOOST_AUTO_TEST_CASE(FnsNodeToNodeDistance)
nodeTwo.Bound() |= utility;
// Again, the distance is the L2 distance.
BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestNodeToNodeDistance(&nodeOne,
&nodeTwo), 3.0, 1e-5);
REQUIRE(FurthestNeighborSort::BestNodeToNodeDistance(&nodeOne, &nodeTwo) ==
Approx(3.0).epsilon(1e-7));
// Now, when the bounds overlap.
nodeTwo.Bound().Clear();
@@ -235,15 +232,15 @@ BOOST_AUTO_TEST_CASE(FnsNodeToNodeDistance)
utility[0] = 0.5;
nodeTwo.Bound() |= utility;
BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestNodeToNodeDistance(&nodeOne,
&nodeTwo), 1.5, 1e-5);
REQUIRE(FurthestNeighborSort::BestNodeToNodeDistance(&nodeOne, &nodeTwo) ==
Approx(1.5).epsilon(1e-7));
}
/**
* Another very simple sanity check for the point-to-node case, again in one
* dimension.
*/
BOOST_AUTO_TEST_CASE(FnsPointToNodeDistance)
TEST_CASE("FnsPointToNodeDistance", "[SortPolicyTest]")
{
// Well, there's no easy way to make HRectBounds the way we want, so we have
// to make them and then expand the region to include new points.
@@ -262,20 +259,18 @@ BOOST_AUTO_TEST_CASE(FnsPointToNodeDistance)
point[0] = -0.5;
// The distance is the L2 distance.
BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestPointToNodeDistance(point,
&node), 1.5, 1e-5);
REQUIRE(FurthestNeighborSort::BestPointToNodeDistance(point, &node) ==
Approx(1.5).epsilon(1e-7));
// Now from the other side of the bound.
point[0] = 1.5;
BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestPointToNodeDistance(point,
&node), 1.5, 1e-5);
REQUIRE(FurthestNeighborSort::BestPointToNodeDistance(point, &node) ==
Approx(1.5).epsilon(1e-7));
// And now when the point is inside the bound.
point[0] = 0.5;
BOOST_REQUIRE_CLOSE(FurthestNeighborSort::BestPointToNodeDistance(point,
&node), 0.5, 1e-5);
REQUIRE(FurthestNeighborSort::BestPointToNodeDistance(point, &node) ==
Approx(0.5).epsilon(1e-7));
}
BOOST_AUTO_TEST_SUITE_END();
+42 -47
View File
@@ -13,21 +13,19 @@
#include <mlpack/core.hpp>
#include <mlpack/core/tree/spill_tree.hpp>
#include <boost/test/unit_test.hpp>
#include "catch.hpp"
#include <stack>
using namespace mlpack;
using namespace mlpack::tree;
using namespace mlpack::metric;
BOOST_AUTO_TEST_SUITE(SpillTreeTest);
/**
* Test to make sure the tree contains the correct number of points after
* it is constructed. Also, it checks some invariants in the relation between
* parent and child nodes.
*/
BOOST_AUTO_TEST_CASE(SpillTreeConstructionCountTest)
TEST_CASE("SpillTreeConstructionCountTest", "[SpillTreeTest]")
{
arma::mat dataset;
dataset.randu(3, 1000); // 1000 points in 3 dimensions.
@@ -38,8 +36,8 @@ BOOST_AUTO_TEST_CASE(SpillTreeConstructionCountTest)
TreeType tree1(dataset, 0);
TreeType tree2 = tree1;
BOOST_REQUIRE_EQUAL(tree1.NumDescendants(), 1000);
BOOST_REQUIRE_EQUAL(tree2.NumDescendants(), 1000);
REQUIRE(tree1.NumDescendants() == 1000);
REQUIRE(tree2.NumDescendants() == 1000);
// When overlapping buffer is greater than 0, it is possible to have repeated
// points. So, let's check node by node, that the number of descendants
@@ -68,18 +66,18 @@ BOOST_AUTO_TEST_CASE(SpillTreeConstructionCountTest)
}
if (node->IsLeaf())
BOOST_REQUIRE_EQUAL(node->NumPoints(), node->NumDescendants());
REQUIRE(node->NumPoints() == node->NumDescendants());
else
BOOST_REQUIRE_EQUAL(node->NumPoints(), 0);
REQUIRE(node->NumPoints() == 0);
BOOST_REQUIRE_EQUAL(node->NumDescendants(), numDesc);
REQUIRE(node->NumDescendants() == numDesc);
}
}
/**
* Test to check that parents and children are set correctly.
*/
BOOST_AUTO_TEST_CASE(SpillTreeConstructionParentTest)
TEST_CASE("SpillTreeConstructionParentTest", "[SpillTreeTest]")
{
arma::mat dataset;
dataset.randu(3, 1000); // 1000 points in 3 dimensions.
@@ -98,13 +96,13 @@ BOOST_AUTO_TEST_CASE(SpillTreeConstructionParentTest)
if (node->Left())
{
nodes.push(node->Left());
BOOST_REQUIRE_EQUAL(node, node->Left()->Parent());
REQUIRE(node == node->Left()->Parent());
}
if (node->Right())
{
nodes.push(node->Right());
BOOST_REQUIRE_EQUAL(node, node->Right()->Parent());
REQUIRE(node == node->Right()->Parent());
}
}
}
@@ -146,8 +144,8 @@ void SpillTreeHyperplaneTestAux()
for (size_t i = 0; i < numDesc; ++i)
{
size_t descIndex = node->Left()->Descendant(i);
BOOST_REQUIRE_LE(
node->Hyperplane().Project(node->Dataset().col(descIndex)),
REQUIRE(
node->Hyperplane().Project(node->Dataset().col(descIndex)) <
tau);
}
}
@@ -159,9 +157,8 @@ void SpillTreeHyperplaneTestAux()
for (size_t i = 0; i < numDesc; ++i)
{
size_t descIndex = node->Right()->Descendant(i);
BOOST_REQUIRE_GT(
node->Hyperplane().Project(node->Dataset().col(descIndex)),
-tau);
REQUIRE(node->Hyperplane().Project(node->Dataset().col(descIndex))
> -tau);
}
}
}
@@ -176,7 +173,7 @@ void SpillTreeHyperplaneTestAux()
for (size_t i = 0; i < numDesc; ++i)
{
size_t descIndex = node->Left()->Descendant(i);
BOOST_REQUIRE(
REQUIRE(
node->Hyperplane().Left(node->Dataset().col(descIndex)));
}
}
@@ -188,7 +185,7 @@ void SpillTreeHyperplaneTestAux()
for (size_t i = 0; i < numDesc; ++i)
{
size_t descIndex = node->Right()->Descendant(i);
BOOST_REQUIRE(
REQUIRE(
node->Hyperplane().Right(node->Dataset().col(descIndex)));
}
}
@@ -208,7 +205,7 @@ void SpillTreeHyperplaneTestAux()
* left by the node's splitting hyperplane, and the same for points in the
* right child.
*/
BOOST_AUTO_TEST_CASE(SpillTreeHyperplaneTest)
TEST_CASE("SpillTreeHyperplaneTest", "[SpillTreeTest]")
{
typedef SPTree<EuclideanDistance, EmptyStatistic, arma::mat> SpillType1;
typedef NonOrtSPTree<EuclideanDistance, EmptyStatistic, arma::mat> SpillType2;
@@ -225,7 +222,7 @@ BOOST_AUTO_TEST_CASE(SpillTreeHyperplaneTest)
/**
* Simple test for the move constructor.
*/
BOOST_AUTO_TEST_CASE(SpillTreeMoveConstructorTest)
TEST_CASE("SpillTreeMoveConstructorTest", "[SpillTreeTest]")
{
arma::mat dataset = arma::randu<arma::mat>(3, 1000);
typedef SPTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
@@ -238,29 +235,29 @@ BOOST_AUTO_TEST_CASE(SpillTreeMoveConstructorTest)
TreeType newTree(std::move(tree));
BOOST_REQUIRE(tree.Left() == NULL);
BOOST_REQUIRE(tree.Right() == NULL);
BOOST_REQUIRE_EQUAL(tree.NumDescendants(), 0);
REQUIRE(tree.Left() == NULL);
REQUIRE(tree.Right() == NULL);
REQUIRE(tree.NumDescendants() == 0);
BOOST_REQUIRE_EQUAL(newTree.Left(), left);
BOOST_REQUIRE_EQUAL(newTree.Right(), right);
BOOST_REQUIRE_EQUAL(newTree.NumDescendants(), numDesc);
REQUIRE(newTree.Left() == left);
REQUIRE(newTree.Right() == right);
REQUIRE(newTree.NumDescendants() == numDesc);
if (left)
{
BOOST_REQUIRE(newTree.Left() != NULL);
BOOST_REQUIRE_EQUAL(newTree.Left()->Parent(), &newTree);
REQUIRE(newTree.Left() != NULL);
REQUIRE(newTree.Left()->Parent() == &newTree);
}
if (right)
{
BOOST_REQUIRE(newTree.Right() != NULL);
BOOST_REQUIRE_EQUAL(newTree.Right()->Parent(), &newTree);
REQUIRE(newTree.Right() != NULL);
REQUIRE(newTree.Right()->Parent() == &newTree);
}
}
/**
* Simple test for the copy constructor.
*/
BOOST_AUTO_TEST_CASE(SpillTreeCopyConstructorTest)
TEST_CASE("SpillTreeCopyConstructorTest", "[SpillTreeTest]")
{
arma::mat dataset = arma::randu<arma::mat>(3, 1000);
typedef SPTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
@@ -276,36 +273,34 @@ BOOST_AUTO_TEST_CASE(SpillTreeCopyConstructorTest)
delete tree;
BOOST_REQUIRE_EQUAL(newTree.Dataset().n_rows, 3);
BOOST_REQUIRE_EQUAL(newTree.Dataset().n_cols, 1000);
BOOST_REQUIRE_EQUAL(newTree.NumDescendants(), numDesc);
REQUIRE(newTree.Dataset().n_rows == 3);
REQUIRE(newTree.Dataset().n_cols == 1000);
REQUIRE(newTree.NumDescendants() == numDesc);
if (left)
{
BOOST_REQUIRE(newTree.Left() != left);
BOOST_REQUIRE(newTree.Left() != NULL);
BOOST_REQUIRE_EQUAL(newTree.Left()->Parent(), &newTree);
REQUIRE(newTree.Left() != left);
REQUIRE(newTree.Left() != NULL);
REQUIRE(newTree.Left()->Parent() == &newTree);
}
if (right)
{
BOOST_REQUIRE(newTree.Right() != right);
BOOST_REQUIRE(newTree.Right() != NULL);
BOOST_REQUIRE_EQUAL(newTree.Right()->Parent(), &newTree);
REQUIRE(newTree.Right() != right);
REQUIRE(newTree.Right() != NULL);
REQUIRE(newTree.Right()->Parent() == &newTree);
}
}
/**
* Simple test for the constructor that takes a rvalue reference to the dataset.
*/
BOOST_AUTO_TEST_CASE(SpillTreeMoveDatasetTest)
TEST_CASE("SpillTreeMoveDatasetTest", "[SpillTreeTest]")
{
arma::mat dataset = arma::randu<arma::mat>(3, 1000);
typedef SPTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
TreeType tree(std::move(dataset));
BOOST_REQUIRE_EQUAL(dataset.n_elem, 0);
BOOST_REQUIRE_EQUAL(tree.Dataset().n_rows, 3);
BOOST_REQUIRE_EQUAL(tree.Dataset().n_cols, 1000);
REQUIRE(dataset.n_elem == 0);
REQUIRE(tree.Dataset().n_rows == 3);
REQUIRE(tree.Dataset().n_cols == 1000);
}
BOOST_AUTO_TEST_SUITE_END();
+71 -75
View File
@@ -20,15 +20,14 @@
#include <mlpack/core/data/string_encoding_policies/tf_idf_encoding_policy.hpp>
#include <boost/test/unit_test.hpp>
#include <memory>
#include "test_tools.hpp"
#include "serialization.hpp"
#include "test_catch_tools.hpp"
#include "catch.hpp"
#include "serialization_catch.hpp"
using namespace mlpack;
using namespace mlpack::data;
using namespace std;
BOOST_AUTO_TEST_SUITE(StringEncodingTest);
//! Common input for some tests.
static vector<string> stringEncodingInput = {
"mlpack is an intuitive, fast, and flexible C++ machine learning library "
@@ -64,21 +63,21 @@ void CheckVectors(const vector<vector<ValueType>>& a,
const vector<vector<ValueType>>& b,
const ValueType tolerance = 1e-5)
{
BOOST_REQUIRE_EQUAL(a.size(), b.size());
REQUIRE(a.size() == b.size());
for (size_t i = 0; i < a.size(); ++i)
{
BOOST_REQUIRE_EQUAL(a[i].size(), b[i].size());
REQUIRE(a[i].size() == b[i].size());
for (size_t j = 0; j < a[i].size(); ++j)
BOOST_REQUIRE_CLOSE(a[i][j], b[i][j], tolerance);
REQUIRE(a[i][j] == Approx(b[i][j]).epsilon(tolerance / 100));
}
}
/**
* Test the dictionary encoding algorithm.
*/
BOOST_AUTO_TEST_CASE(DictionaryEncodingTest)
TEST_CASE("DictionaryEncodingTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
@@ -97,7 +96,7 @@ BOOST_AUTO_TEST_CASE(DictionaryEncodingTest)
{
keysCount[keyValue.second]++;
BOOST_REQUIRE_EQUAL(keysCount[keyValue.second], 1);
REQUIRE(keysCount[keyValue.second] == 1);
}
arma::mat expected = {
@@ -115,7 +114,7 @@ BOOST_AUTO_TEST_CASE(DictionaryEncodingTest)
/**
* Test the dictionary encoding algorithm with unicode characters.
*/
BOOST_AUTO_TEST_CASE(UnicodeDictionaryEncodingTest)
TEST_CASE("UnicodeDictionaryEncodingTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
@@ -134,7 +133,7 @@ BOOST_AUTO_TEST_CASE(UnicodeDictionaryEncodingTest)
{
keysCount[keyValue.second]++;
BOOST_REQUIRE_EQUAL(keysCount[keyValue.second], 1);
REQUIRE(keysCount[keyValue.second] == 1);
}
arma::mat expected = {
@@ -149,7 +148,7 @@ BOOST_AUTO_TEST_CASE(UnicodeDictionaryEncodingTest)
/**
* Test the one pass modification of the dictionary encoding algorithm.
*/
BOOST_AUTO_TEST_CASE(OnePassDictionaryEncodingTest)
TEST_CASE("OnePassDictionaryEncodingTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
@@ -169,7 +168,7 @@ BOOST_AUTO_TEST_CASE(OnePassDictionaryEncodingTest)
{
keysCount[keyValue.second]++;
BOOST_REQUIRE_EQUAL(keysCount[keyValue.second], 1);
REQUIRE(keysCount[keyValue.second] == 1);
}
vector<vector<size_t>> expected = {
@@ -179,14 +178,14 @@ BOOST_AUTO_TEST_CASE(OnePassDictionaryEncodingTest)
{ 36, 37, 14, 38, 39, 8, 40, 1, 41, 42, 43, 44, 6, 45, 13 }
};
BOOST_REQUIRE(output == expected);
REQUIRE(output == expected);
}
/**
* Test the SplitByAnyOf tokenizer.
*/
BOOST_AUTO_TEST_CASE(SplitByAnyOfTokenizerTest)
TEST_CASE("SplitByAnyOfTokenizerTest", "[StringEncodingTest]")
{
std::vector<boost::string_view> tokens;
boost::string_view line(stringEncodingInput[0]);
@@ -204,16 +203,16 @@ BOOST_AUTO_TEST_CASE(SplitByAnyOfTokenizerTest)
"bindings", "to", "other", "languages"
};
BOOST_REQUIRE_EQUAL(tokens.size(), expected.size());
REQUIRE(tokens.size() == expected.size());
for (size_t i = 0; i < tokens.size(); ++i)
BOOST_REQUIRE_EQUAL(tokens[i], expected[i]);
REQUIRE(tokens[i] == expected[i]);
}
/**
* Test the SplitByAnyOf tokenizer in case of unicode characters.
*/
BOOST_AUTO_TEST_CASE(SplitByAnyOfTokenizerUnicodeTest)
TEST_CASE("SplitByAnyOfTokenizerUnicodeTest", "[StringEncodingTest]")
{
vector<string> expectedUtf8Tokens = {
"\xF0\x9F\x84\xBC\xF0\x9F\x84\xBB\xF0\x9F\x84\xBF\xF0\x9F\x84\xB0"
@@ -236,16 +235,16 @@ BOOST_AUTO_TEST_CASE(SplitByAnyOfTokenizerUnicodeTest)
token = tokenizer(line);
}
BOOST_REQUIRE_EQUAL(tokens.size(), expectedUtf8Tokens.size());
REQUIRE(tokens.size() == expectedUtf8Tokens.size());
for (size_t i = 0; i < tokens.size(); ++i)
BOOST_REQUIRE_EQUAL(tokens[i], expectedUtf8Tokens[i]);
REQUIRE(tokens[i] == expectedUtf8Tokens[i]);
}
/**
* Test the CharExtract tokenizer.
*/
BOOST_AUTO_TEST_CASE(DictionaryEncodingIndividualCharactersTest)
TEST_CASE("DictionaryEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -270,7 +269,7 @@ BOOST_AUTO_TEST_CASE(DictionaryEncodingIndividualCharactersTest)
* Test the one pass modification of the dictionary encoding algorithm
* in case of individual character encoding.
*/
BOOST_AUTO_TEST_CASE(OnePassDictionaryEncodingIndividualCharactersTest)
TEST_CASE("OnePassDictionaryEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
std::vector<string> input = {
"GACCA",
@@ -289,13 +288,13 @@ BOOST_AUTO_TEST_CASE(OnePassDictionaryEncodingIndividualCharactersTest)
{ 1, 2, 4 }
};
BOOST_REQUIRE(output == expected);
REQUIRE(output == expected);
}
/**
* Test the functionality of copy constructor.
*/
BOOST_AUTO_TEST_CASE(StringEncodingCopyTest)
TEST_CASE("StringEncodingCopyTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
arma::sp_mat output;
@@ -318,12 +317,12 @@ BOOST_AUTO_TEST_CASE(StringEncodingCopyTest)
const DictionaryType& copiedDictionary = encoderCopy.Dictionary();
BOOST_REQUIRE_EQUAL(naiveDictionary.size(), copiedDictionary.Size());
REQUIRE(naiveDictionary.size() == copiedDictionary.Size());
for (const pair<string, size_t>& keyValue : naiveDictionary)
{
BOOST_REQUIRE(copiedDictionary.HasToken(keyValue.first));
BOOST_REQUIRE_EQUAL(copiedDictionary.Value(keyValue.first),
REQUIRE(copiedDictionary.HasToken(keyValue.first));
REQUIRE(copiedDictionary.Value(keyValue.first) ==
keyValue.second);
}
}
@@ -331,7 +330,7 @@ BOOST_AUTO_TEST_CASE(StringEncodingCopyTest)
/**
* Test the move assignment operator.
*/
BOOST_AUTO_TEST_CASE(StringEncodingMoveTest)
TEST_CASE("StringEncodingMoveTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
arma::sp_mat output;
@@ -354,12 +353,12 @@ BOOST_AUTO_TEST_CASE(StringEncodingMoveTest)
const DictionaryType& copiedDictionary = encoderCopy.Dictionary();
BOOST_REQUIRE_EQUAL(naiveDictionary.size(), copiedDictionary.Size());
REQUIRE(naiveDictionary.size() == copiedDictionary.Size());
for (const pair<string, size_t>& keyValue : naiveDictionary)
{
BOOST_REQUIRE(copiedDictionary.HasToken(keyValue.first));
BOOST_REQUIRE_EQUAL(copiedDictionary.Value(keyValue.first),
REQUIRE(copiedDictionary.HasToken(keyValue.first));
REQUIRE(copiedDictionary.Value(keyValue.first) ==
keyValue.second);
}
}
@@ -377,16 +376,16 @@ void CheckDictionaries(const StringEncodingDictionary<TokenType>& expected,
const MapType& mapping = obtained.Mapping();
const MapType& expectedMapping = expected.Mapping();
BOOST_REQUIRE_EQUAL(mapping.size(), expectedMapping.size());
REQUIRE(mapping.size() == expectedMapping.size());
for (auto& keyVal : expectedMapping)
{
BOOST_REQUIRE_EQUAL(mapping.at(keyVal.first), keyVal.second);
REQUIRE(mapping.at(keyVal.first) == keyVal.second);
}
for (auto& keyVal : mapping)
{
BOOST_REQUIRE_EQUAL(expectedMapping.at(keyVal.first), keyVal.second);
REQUIRE(expectedMapping.at(keyVal.first) == keyVal.second);
}
}
@@ -413,14 +412,14 @@ void CheckDictionaries(
const MapType& expectedMapping = expected.Mapping();
const MapType& mapping = obtained.Mapping();
BOOST_REQUIRE_EQUAL(tokens.size(), expectedTokens.size());
BOOST_REQUIRE_EQUAL(mapping.size(), expectedMapping.size());
BOOST_REQUIRE_EQUAL(mapping.size(), tokens.size());
REQUIRE(tokens.size() == expectedTokens.size());
REQUIRE(mapping.size() == expectedMapping.size());
REQUIRE(mapping.size() == tokens.size());
for (size_t i = 0; i < tokens.size(); ++i)
{
BOOST_REQUIRE_EQUAL(tokens[i], expectedTokens[i]);
BOOST_REQUIRE_EQUAL(expectedMapping.at(tokens[i]), mapping.at(tokens[i]));
REQUIRE(tokens[i] == expectedTokens[i]);
REQUIRE(expectedMapping.at(tokens[i]) == mapping.at(tokens[i]));
}
}
@@ -438,11 +437,11 @@ void CheckDictionaries(const StringEncodingDictionary<int>& expected,
const MapType& expectedMapping = expected.Mapping();
const MapType& mapping = obtained.Mapping();
BOOST_REQUIRE_EQUAL(expected.Size(), obtained.Size());
REQUIRE(expected.Size() == obtained.Size());
for (size_t i = 0; i < mapping.size(); ++i)
{
BOOST_REQUIRE_EQUAL(mapping[i], expectedMapping[i]);
REQUIRE(mapping[i] == expectedMapping[i]);
}
}
@@ -450,7 +449,7 @@ void CheckDictionaries(const StringEncodingDictionary<int>& expected,
* Serialization test for the general template of the StringEncodingDictionary
* class.
*/
BOOST_AUTO_TEST_CASE(StringEncodingDictionarySerialization)
TEST_CASE("StringEncodingDictionarySerialization", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<string>;
@@ -485,7 +484,7 @@ BOOST_AUTO_TEST_CASE(StringEncodingDictionarySerialization)
* Serialization test for the dictionary encoding algorithm with
* the SplitByAnyOf tokenizer.
*/
BOOST_AUTO_TEST_CASE(SplitByAnyOfDictionaryEncodingSerialization)
TEST_CASE("SplitByAnyOfDictionaryEncodingSerialization", "[StringEncodingTest]")
{
using EncoderType = DictionaryEncoding<SplitByAnyOf::TokenType>;
@@ -515,7 +514,7 @@ BOOST_AUTO_TEST_CASE(SplitByAnyOfDictionaryEncodingSerialization)
* Serialization test for the dictionary encoding algorithm with
* the CharExtract tokenizer.
*/
BOOST_AUTO_TEST_CASE(CharExtractDictionaryEncodingSerialization)
TEST_CASE("CharExtractDictionaryEncodingSerialization", "[StringEncodingTest]")
{
using EncoderType = DictionaryEncoding<CharExtract::TokenType>;
@@ -544,7 +543,7 @@ BOOST_AUTO_TEST_CASE(CharExtractDictionaryEncodingSerialization)
/**
* Test the Bag of Words encoding algorithm.
*/
BOOST_AUTO_TEST_CASE(BagOfWordsEncodingTest)
TEST_CASE("BagOfWordsEncodingTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
@@ -563,7 +562,7 @@ BOOST_AUTO_TEST_CASE(BagOfWordsEncodingTest)
{
keysCount[keyValue.second]++;
BOOST_REQUIRE_EQUAL(keysCount[keyValue.second], 1);
REQUIRE(keysCount[keyValue.second] == 1);
}
/* The expected values were obtained by the following Python script:
@@ -619,7 +618,7 @@ BOOST_AUTO_TEST_CASE(BagOfWordsEncodingTest)
/**
* Test the Bag of Words encoding algorithm. The output is saved into a vector.
*/
BOOST_AUTO_TEST_CASE(VectorBagOfWordsEncodingTest)
TEST_CASE("VectorBagOfWordsEncodingTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
@@ -639,7 +638,7 @@ BOOST_AUTO_TEST_CASE(VectorBagOfWordsEncodingTest)
{
keysCount[keyValue.second]++;
BOOST_REQUIRE_EQUAL(keysCount[keyValue.second], 1);
REQUIRE(keysCount[keyValue.second] == 1);
}
/* The expected values were obtained by the same script as in
@@ -653,13 +652,13 @@ BOOST_AUTO_TEST_CASE(VectorBagOfWordsEncodingTest)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
BOOST_REQUIRE(output == expected);
REQUIRE(output == expected);
}
/**
* Test the Bag of Words algorithm for individual characters.
*/
BOOST_AUTO_TEST_CASE(BagOfWordsEncodingIndividualCharactersTest)
TEST_CASE("BagOfWordsEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -685,7 +684,7 @@ BOOST_AUTO_TEST_CASE(BagOfWordsEncodingIndividualCharactersTest)
* Test the Bag of Words encoding algorithm in case of individual
* characters encoding. The output type is vector<vector<size_t>>.
*/
BOOST_AUTO_TEST_CASE(VectorBagOfWordsEncodingIndividualCharactersTest)
TEST_CASE("VectorBagOfWordsEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
std::vector<string> input = {
"GACCA",
@@ -704,7 +703,7 @@ BOOST_AUTO_TEST_CASE(VectorBagOfWordsEncodingIndividualCharactersTest)
{ 1, 1, 0, 1, 0 }
};
BOOST_REQUIRE(output == expected);
REQUIRE(output == expected);
}
/**
@@ -712,7 +711,7 @@ BOOST_AUTO_TEST_CASE(VectorBagOfWordsEncodingIndividualCharactersTest)
* and the smooth inverse document frequency type. These parameters are
* the default ones.
*/
BOOST_AUTO_TEST_CASE(RawCountSmoothIdfEncodingTest)
TEST_CASE("RawCountSmoothIdfEncodingTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
@@ -730,7 +729,7 @@ BOOST_AUTO_TEST_CASE(RawCountSmoothIdfEncodingTest)
{
keysCount[keyValue.second]++;
BOOST_REQUIRE_EQUAL(keysCount[keyValue.second], 1);
REQUIRE(keysCount[keyValue.second] == 1);
}
/* The expected values were obtained by the following Python script:
@@ -814,7 +813,7 @@ BOOST_AUTO_TEST_CASE(RawCountSmoothIdfEncodingTest)
* and the smooth inverse document frequency type. These parameters are
* the default ones. The output type is vector<vector<double>>.
*/
BOOST_AUTO_TEST_CASE(VectorRawCountSmoothIdfEncodingTest)
TEST_CASE("VectorRawCountSmoothIdfEncodingTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
@@ -834,7 +833,7 @@ BOOST_AUTO_TEST_CASE(VectorRawCountSmoothIdfEncodingTest)
{
keysCount[keyValue.second]++;
BOOST_REQUIRE_EQUAL(keysCount[keyValue.second], 1);
REQUIRE(keysCount[keyValue.second] == 1);
}
/* The expected values were obtained by the same script as in
@@ -862,7 +861,7 @@ BOOST_AUTO_TEST_CASE(VectorRawCountSmoothIdfEncodingTest)
* raw count term frequency type and the smooth inverse document frequency type.
* These parameters are the default ones.
*/
BOOST_AUTO_TEST_CASE(RawCountSmoothIdfEncodingIndividualCharactersTest)
TEST_CASE("RawCountSmoothIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -943,7 +942,7 @@ BOOST_AUTO_TEST_CASE(RawCountSmoothIdfEncodingIndividualCharactersTest)
* These parameters are the default ones. The output type is
* vector<vector<double>>.
*/
BOOST_AUTO_TEST_CASE(VectorRawCountSmoothIdfEncodingIndividualCharactersTest)
TEST_CASE("VectorRawCountSmoothIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
std::vector<string> input = {
"GACCA",
@@ -971,7 +970,7 @@ BOOST_AUTO_TEST_CASE(VectorRawCountSmoothIdfEncodingIndividualCharactersTest)
* Test the Tf-Idf encoding algorithm with the raw count term frequency type
* and the non-smooth inverse document frequency type.
*/
BOOST_AUTO_TEST_CASE(TfIdfRawCountEncodingTest)
TEST_CASE("TfIdfRawCountEncodingTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
@@ -991,7 +990,7 @@ BOOST_AUTO_TEST_CASE(TfIdfRawCountEncodingTest)
{
keysCount[keyValue.second]++;
BOOST_REQUIRE_EQUAL(keysCount[keyValue.second], 1);
REQUIRE(keysCount[keyValue.second] == 1);
}
/* The expected values were obtained by almost the same script as in
@@ -1021,7 +1020,7 @@ BOOST_AUTO_TEST_CASE(TfIdfRawCountEncodingTest)
* and the non-smooth inverse document frequency type. The output type is
* vector<vector<double>>.
*/
BOOST_AUTO_TEST_CASE(VectorTfIdfRawCountEncodingTest)
TEST_CASE("VectorTfIdfRawCountEncodingTest", "[StringEncodingTest]")
{
using DictionaryType = StringEncodingDictionary<boost::string_view>;
@@ -1040,7 +1039,7 @@ BOOST_AUTO_TEST_CASE(VectorTfIdfRawCountEncodingTest)
{
keysCount[keyValue.second]++;
BOOST_REQUIRE_EQUAL(keysCount[keyValue.second], 1);
REQUIRE(keysCount[keyValue.second] == 1);
}
/* The expected values were obtained by almost the same script as in
@@ -1069,7 +1068,7 @@ BOOST_AUTO_TEST_CASE(VectorTfIdfRawCountEncodingTest)
* raw count term frequency type and the non-smooth inverse document frequency
* type.
*/
BOOST_AUTO_TEST_CASE(RawCountTfIdfEncodingIndividualCharactersTest)
TEST_CASE("RawCountTfIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -1100,7 +1099,7 @@ BOOST_AUTO_TEST_CASE(RawCountTfIdfEncodingIndividualCharactersTest)
* raw count term frequency type and the non-smooth inverse document frequency
* type. The output type is vector<vector<double>>.
*/
BOOST_AUTO_TEST_CASE(VectorRawCountTfIdfEncodingIndividualCharactersTest)
TEST_CASE("VectorRawCountTfIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
std::vector<string> input = {
"GACCA",
@@ -1130,7 +1129,7 @@ BOOST_AUTO_TEST_CASE(VectorRawCountTfIdfEncodingIndividualCharactersTest)
* Test the Tf-Idf encoding algorithm for individual characters with the
* binary term frequency type and the smooth inverse document frequency type.
*/
BOOST_AUTO_TEST_CASE(BinarySmoothIdfEncodingIndividualCharactersTest)
TEST_CASE("BinarySmoothIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -1161,7 +1160,7 @@ BOOST_AUTO_TEST_CASE(BinarySmoothIdfEncodingIndividualCharactersTest)
* binary term frequency type and the smooth inverse document frequency type.
* The output type is vector<vector<double>>.
*/
BOOST_AUTO_TEST_CASE(VectorBinarySmoothIdfEncodingIndividualCharactersTest)
TEST_CASE("VectorBinarySmoothIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
std::vector<string> input = {
"GACCA",
@@ -1192,7 +1191,7 @@ BOOST_AUTO_TEST_CASE(VectorBinarySmoothIdfEncodingIndividualCharactersTest)
* binary term frequency type and the non-smooth inverse document frequency
* type.
*/
BOOST_AUTO_TEST_CASE(BinaryTfIdfEncodingIndividualCharactersTest)
TEST_CASE("BinaryTfIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -1223,7 +1222,7 @@ BOOST_AUTO_TEST_CASE(BinaryTfIdfEncodingIndividualCharactersTest)
* sublinear term frequency type and the smooth inverse document frequency
* type.
*/
BOOST_AUTO_TEST_CASE(SublinearSmoothIdfEncodingIndividualCharactersTest)
TEST_CASE("SublinearSmoothIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -1255,7 +1254,7 @@ BOOST_AUTO_TEST_CASE(SublinearSmoothIdfEncodingIndividualCharactersTest)
* sublinear term frequency type and the non-smooth inverse document frequency
* type.
*/
BOOST_AUTO_TEST_CASE(SublinearTfIdfEncodingIndividualCharactersTest)
TEST_CASE("SublinearTfIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -1287,7 +1286,7 @@ BOOST_AUTO_TEST_CASE(SublinearTfIdfEncodingIndividualCharactersTest)
* standard term frequency type and the smooth inverse document frequency
* type.
*/
BOOST_AUTO_TEST_CASE(TermFrequencySmoothIdfEncodingIndividualCharactersTest)
TEST_CASE("TermFrequencySmoothIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -1368,7 +1367,7 @@ BOOST_AUTO_TEST_CASE(TermFrequencySmoothIdfEncodingIndividualCharactersTest)
* standard term frequency type and the non-smooth inverse document frequency
* type.
*/
BOOST_AUTO_TEST_CASE(TermFrequencyTfIdfEncodingIndividualCharactersTest)
TEST_CASE("TermFrequencyTfIdfEncodingIndividualCharactersTest", "[StringEncodingTest]")
{
vector<string> input = {
"GACCA",
@@ -1399,7 +1398,7 @@ BOOST_AUTO_TEST_CASE(TermFrequencyTfIdfEncodingIndividualCharactersTest)
* Serialization test for the Tf-Idf encoding algorithm with
* the SplitByAnyOf tokenizer.
*/
BOOST_AUTO_TEST_CASE(SplitByAnyOfTfIdfEncodingSerialization)
TEST_CASE("SplitByAnyOfTfIdfEncodingSerialization", "[StringEncodingTest]")
{
using EncoderType = TfIdfEncoding<SplitByAnyOf::TokenType>;
@@ -1424,6 +1423,3 @@ BOOST_AUTO_TEST_CASE(SplitByAnyOfTfIdfEncodingSerialization)
CheckMatrices(output, xmlOutput, textOutput, binaryOutput);
}
BOOST_AUTO_TEST_SUITE_END();
+22 -26
View File
@@ -13,18 +13,16 @@
#include <mlpack/methods/reinforcement_learning/replay/sumtree.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
#include "test_catch_tools.hpp"
using namespace mlpack;
using namespace mlpack::rl;
BOOST_AUTO_TEST_SUITE(SumTreeTest);
/**
* Test that we set the element.
*/
BOOST_AUTO_TEST_CASE(SetElement)
TEST_CASE("SetElement", "[SumTreeTest]")
{
SumTree<double> sumtree(4);
sumtree.Set(0, 1.0);
@@ -32,16 +30,16 @@ BOOST_AUTO_TEST_CASE(SetElement)
sumtree.Set(2, 0.6);
sumtree.Set(3, 0.4);
BOOST_CHECK_CLOSE(sumtree.Sum(), 2.8, 1e-8);
BOOST_CHECK_CLOSE(sumtree.Sum(0, 1), 1.0, 1e-8);
BOOST_CHECK_CLOSE(sumtree.Sum(0, 3), 2.4, 1e-8);
BOOST_CHECK_CLOSE(sumtree.Sum(1, 4), 1.8, 1e-8);
CHECK(sumtree.Sum() == Approx(2.8).epsilon(1e-10));
CHECK(sumtree.Sum(0, 1) == Approx(1.0).epsilon(1e-10));
CHECK(sumtree.Sum(0, 3) == Approx(2.4).epsilon(1e-10));
CHECK(sumtree.Sum(1, 4) == Approx(1.8).epsilon(1e-10));
}
/**
* Test that we get the element.
*/
BOOST_AUTO_TEST_CASE(GetElement)
TEST_CASE("GetElement", "[SumTreeTest]")
{
SumTree<double> sumtree(4);
sumtree.Set(0, 1.0);
@@ -49,17 +47,17 @@ BOOST_AUTO_TEST_CASE(GetElement)
sumtree.Set(2, 0.6);
sumtree.Set(3, 0.4);
BOOST_CHECK_CLOSE(sumtree.Get(0), 1.0, 1e-8);
BOOST_CHECK_CLOSE(sumtree.Get(1), 0.8, 1e-8);
BOOST_CHECK_CLOSE(sumtree.Get(2), 0.6, 1e-8);
BOOST_CHECK_CLOSE(sumtree.Get(3), 0.4, 1e-8);
CHECK(sumtree.Get(0) == Approx(1.0).epsilon(1e-10));
CHECK(sumtree.Get(1) == Approx(0.8).epsilon(1e-10));
CHECK(sumtree.Get(2) == Approx(0.6).epsilon(1e-10));
CHECK(sumtree.Get(3) == Approx(0.4).epsilon(1e-10));
}
/**
* Test that we find the highest index in the array such that
* Sum(arr[0] + arr[1] + arr[2] ... + arr[i]) <= mass.
*/
BOOST_AUTO_TEST_CASE(FindPrefixSum)
TEST_CASE("FindPrefixSum", "[SumTreeTest]")
{
SumTree<double> sumtree(4);
sumtree.Set(0, 1.0);
@@ -67,17 +65,17 @@ BOOST_AUTO_TEST_CASE(FindPrefixSum)
sumtree.Set(2, 0.6);
sumtree.Set(3, 0.4);
BOOST_CHECK_EQUAL(sumtree.FindPrefixSum(0), 0);
BOOST_CHECK_EQUAL(sumtree.FindPrefixSum(1), 1);
BOOST_CHECK_EQUAL(sumtree.FindPrefixSum(2.8), 3);
BOOST_CHECK_EQUAL(sumtree.FindPrefixSum(3.0), 3);
CHECK(sumtree.FindPrefixSum(0) <= 0.0);
CHECK(sumtree.FindPrefixSum(1) <= 1.0);
CHECK(sumtree.FindPrefixSum(2.8) <= 3.0);
CHECK(sumtree.FindPrefixSum(3.0) <= 3.0);
}
/**
* Test that we find the highest index in the array such that
* sum(arr[0] + arr[1] + arr[2] ... + arr[i]) <= mass.
*/
BOOST_AUTO_TEST_CASE(BatchUpdate)
TEST_CASE("BatchUpdate", "[SumTreeTest]")
{
SumTree<double> sumtree(4);
arma::ucolvec indices = {0, 1, 2, 3};
@@ -85,10 +83,8 @@ BOOST_AUTO_TEST_CASE(BatchUpdate)
sumtree.BatchUpdate(indices, data);
BOOST_CHECK_EQUAL(sumtree.FindPrefixSum(0), 0);
BOOST_CHECK_EQUAL(sumtree.FindPrefixSum(1), 1);
BOOST_CHECK_EQUAL(sumtree.FindPrefixSum(2.8), 3);
BOOST_CHECK_EQUAL(sumtree.FindPrefixSum(3.0), 3);
CHECK(sumtree.FindPrefixSum(0) <= 0);
CHECK(sumtree.FindPrefixSum(1) <= 1);
CHECK(sumtree.FindPrefixSum(2.8) <= 3);
CHECK(sumtree.FindPrefixSum(3.0) <= 3);
}
BOOST_AUTO_TEST_SUITE_END();
File diff suppressed because it is too large Load Diff
+20 -24
View File
@@ -19,82 +19,78 @@
#include <mlpack/core/tree/cover_tree.hpp>
#include <mlpack/core/tree/rectangle_tree.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
#include "test_catch_tools.hpp"
using namespace mlpack;
using namespace mlpack::tree;
using namespace mlpack::metric;
BOOST_AUTO_TEST_SUITE(TreeTraitsTest);
// Be careful! When writing new tests, always get the boolean value of each
// trait and store it in a temporary, because the Boost unit test macros do
// weird things and will cause bizarre problems.
// Test the defaults.
BOOST_AUTO_TEST_CASE(DefaultsTraitsTest)
TEST_CASE("DefaultsTraitsTest", "[TreeTraitsTestt]")
{
// An irrelevant non-tree type class is used here so that the default
// implementation of TreeTraits is chosen.
bool b = TreeTraits<int>::HasOverlappingChildren;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
b = TreeTraits<int>::HasSelfChildren;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
b = TreeTraits<int>::FirstPointIsCentroid;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
b = TreeTraits<int>::RearrangesDataset;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
b = TreeTraits<int>::BinaryTree;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
}
// Test the binary space tree traits.
BOOST_AUTO_TEST_CASE(BinarySpaceTreeTraitsTest)
TEST_CASE("BinarySpaceTreeTraitsTest", "[TreeTraitsTestt]")
{
typedef BinarySpaceTree<LMetric<2, false>> TreeType;
// Children are non-overlapping.
bool b = TreeTraits<TreeType>::HasOverlappingChildren;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
// Points are not contained at multiple levels.
b = TreeTraits<TreeType>::HasSelfChildren;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
// The first point is not the centroid.
b = TreeTraits<TreeType>::FirstPointIsCentroid;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
// The dataset gets rearranged at build time.
b = TreeTraits<TreeType>::RearrangesDataset;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
// It is a binary tree.
b = TreeTraits<TreeType>::BinaryTree;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
}
// Test the cover tree traits.
BOOST_AUTO_TEST_CASE(CoverTreeTraitsTest)
TEST_CASE("CoverTreeTraitsTest", "[TreeTraitsTestt]")
{
// Children may be overlapping.
bool b = TreeTraits<CoverTree<>>::HasOverlappingChildren;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
// The cover tree has self-children.
b = TreeTraits<CoverTree<>>::HasSelfChildren;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
// The first point is the center of the node.
b = TreeTraits<CoverTree<>>::FirstPointIsCentroid;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
b = TreeTraits<CoverTree<>>::RearrangesDataset;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
b = TreeTraits<CoverTree<>>::BinaryTree;
BOOST_REQUIRE_EQUAL(b, false); // Not necessarily binary.
REQUIRE(b == false); // Not necessarily binary.
}
BOOST_AUTO_TEST_SUITE_END();
+27 -31
View File
@@ -14,7 +14,7 @@
#include <mlpack/methods/neighbor_search/neighbor_search.hpp>
#include <mlpack/core/tree/binary_space_tree.hpp>
#include <boost/test/unit_test.hpp>
#include "catch.hpp"
using namespace mlpack;
using namespace mlpack::math;
@@ -23,9 +23,7 @@ using namespace mlpack::metric;
using namespace mlpack::bound;
using namespace mlpack::neighbor;
BOOST_AUTO_TEST_SUITE(UBTreeTest);
BOOST_AUTO_TEST_CASE(AddressTest)
TEST_CASE("AddressTest", "[UBTreeTest]")
{
typedef double ElemType;
typedef typename std::conditional<sizeof(ElemType) * CHAR_BIT <= 32,
@@ -45,7 +43,7 @@ BOOST_AUTO_TEST_CASE(AddressTest)
addr::AddressToPoint(point, address);
for (size_t k = 0; k < dataset.n_rows; ++k)
BOOST_REQUIRE_CLOSE(dataset(k, i), point[k], 1e-13);
REQUIRE(dataset(k, i) == Approx(point[k]).epsilon(1e-15));
}
}
@@ -89,13 +87,13 @@ void CheckSplit(const TreeType& tree)
}
// Addresses in the left node should be less than addresses in the right node.
BOOST_REQUIRE_LE(addr::CompareAddresses(hi, lo), 0);
REQUIRE(addr::CompareAddresses(hi, lo) <= 0);
CheckSplit(*tree.Left());
CheckSplit(*tree.Right());
}
BOOST_AUTO_TEST_CASE(UBTreeSplitTest)
TEST_CASE("UBTreeSplitTest", "[UBTreeTest]")
{
typedef UBTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
arma::mat dataset(8, 1000);
@@ -115,7 +113,7 @@ void CheckBound(const TreeType& tree)
arma::Col<ElemType> point = tree.Dataset().col(tree.Descendant(i));
// Check that the point is contained in the bound.
BOOST_REQUIRE_EQUAL(true, tree.Bound().Contains(point));
REQUIRE(true == tree.Bound().Contains(point));
const arma::Mat<ElemType>& loBound = tree.Bound().LoBound();
const arma::Mat<ElemType>& hiBound = tree.Bound().HiBound();
@@ -138,7 +136,7 @@ void CheckBound(const TreeType& tree)
break;
}
BOOST_REQUIRE_EQUAL(success, true);
REQUIRE(success == true);
}
if (!tree.IsLeaf())
@@ -148,7 +146,7 @@ void CheckBound(const TreeType& tree)
}
}
BOOST_AUTO_TEST_CASE(UBTreeBoundTest)
TEST_CASE("UBTreeBoundTest", "[UBTreeTest]")
{
typedef UBTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
arma::mat dataset(8, 1000);
@@ -190,16 +188,16 @@ void CheckDistance(TreeType& tree, TreeType* node = NULL)
minDist = dist;
}
BOOST_REQUIRE_LE(tree.Bound().MinDistance(point), minDist *
REQUIRE(tree.Bound().MinDistance(point) <= minDist *
(1.0 + 10 * std::numeric_limits<ElemType>::epsilon()));
BOOST_REQUIRE_LE(maxDist, tree.Bound().MaxDistance(point) *
REQUIRE(maxDist <= tree.Bound().MaxDistance(point) *
(1.0 + 10 * std::numeric_limits<ElemType>::epsilon()));
math::RangeType<ElemType> r = tree.Bound().RangeDistance(point);
BOOST_REQUIRE_LE(r.Lo(), minDist *
REQUIRE(r.Lo() <= minDist *
(1.0 + 10 * std::numeric_limits<ElemType>::epsilon()));
BOOST_REQUIRE_LE(maxDist, r.Hi() *
REQUIRE(maxDist <= r.Hi() *
(1.0 + 10 * std::numeric_limits<ElemType>::epsilon()));
}
@@ -228,16 +226,16 @@ void CheckDistance(TreeType& tree, TreeType* node = NULL)
minDist = dist;
}
BOOST_REQUIRE_LE(tree.Bound().MinDistance(node->Bound()), minDist *
REQUIRE(tree.Bound().MinDistance(node->Bound()) <= minDist *
(1.0 + 10 * std::numeric_limits<ElemType>::epsilon()));
BOOST_REQUIRE_LE(maxDist, tree.Bound().MaxDistance(node->Bound()) *
REQUIRE(maxDist <= tree.Bound().MaxDistance(node->Bound()) *
(1.0 + 10 * std::numeric_limits<ElemType>::epsilon()));
math::RangeType<ElemType> r = tree.Bound().RangeDistance(node->Bound());
BOOST_REQUIRE_LE(r.Lo(), minDist *
REQUIRE(r.Lo() <= minDist *
(1.0 + 10 * std::numeric_limits<ElemType>::epsilon()));
BOOST_REQUIRE_LE(maxDist, r.Hi() *
REQUIRE(maxDist <= r.Hi() *
(1.0 + 10 * std::numeric_limits<ElemType>::epsilon()));
}
if (!node->IsLeaf())
@@ -248,7 +246,7 @@ void CheckDistance(TreeType& tree, TreeType* node = NULL)
}
}
BOOST_AUTO_TEST_CASE(UBTreeDistanceTest)
TEST_CASE("UBTreeDistanceTest", "[UBTreeTest]")
{
typedef UBTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
arma::mat dataset(8, 200);
@@ -260,7 +258,7 @@ BOOST_AUTO_TEST_CASE(UBTreeDistanceTest)
}
BOOST_AUTO_TEST_CASE(UBTreeTest)
TEST_CASE("UBTreeTest", "[UBTreeTest]")
{
typedef UBTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
@@ -289,21 +287,21 @@ BOOST_AUTO_TEST_CASE(UBTreeTest)
const arma::mat& treeset = root.Dataset();
// Ensure the size of the tree is correct.
BOOST_REQUIRE_EQUAL(root.NumDescendants(), size);
REQUIRE(root.NumDescendants() == size);
// Check the forward and backward mappings for correctness.
for (size_t i = 0; i < size; ++i)
{
for (size_t j = 0; j < dimensions; ++j)
{
BOOST_REQUIRE_EQUAL(treeset(j, i), dataset(j, newToOld[i]));
BOOST_REQUIRE_EQUAL(treeset(j, oldToNew[i]), dataset(j, i));
REQUIRE(treeset(j, i) == dataset(j, newToOld[i]));
REQUIRE(treeset(j, oldToNew[i]) == dataset(j, i));
}
}
}
}
BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest)
TEST_CASE("SingleUBTreeTraverserTest", "[UBTreeTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -325,12 +323,12 @@ BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
}
}
BOOST_AUTO_TEST_CASE(DualTreeTraverserTest)
TEST_CASE("DualUBTreeTraverserTest", "[UBTreeTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -352,9 +350,7 @@ BOOST_AUTO_TEST_CASE(DualTreeTraverserTest)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
}
}
BOOST_AUTO_TEST_SUITE_END();
+58 -63
View File
@@ -14,8 +14,8 @@
#include <mlpack/methods/neighbor_search/neighbor_search.hpp>
#include <mlpack/core/tree/binary_space_tree.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "catch.hpp"
#include "test_catch_tools.hpp"
using namespace mlpack;
using namespace mlpack::math;
@@ -24,112 +24,109 @@ using namespace mlpack::neighbor;
using namespace mlpack::metric;
using namespace mlpack::bound;
BOOST_AUTO_TEST_SUITE(VantagePointTreeTest);
BOOST_AUTO_TEST_CASE(VPTreeTraitsTest)
TEST_CASE("VPTreeTraitsTest", "[VantagePointTreeTest]")
{
typedef VPTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
bool b = TreeTraits<TreeType>::HasOverlappingChildren;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
b = TreeTraits<TreeType>::FirstPointIsCentroid;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
b = TreeTraits<TreeType>::HasSelfChildren;
BOOST_REQUIRE_EQUAL(b, false);
REQUIRE(b == false);
b = TreeTraits<TreeType>::RearrangesDataset;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
b = TreeTraits<TreeType>::BinaryTree;
BOOST_REQUIRE_EQUAL(b, true);
REQUIRE(b == true);
}
BOOST_AUTO_TEST_CASE(HollowBallBoundTest)
TEST_CASE("HollowBallBoundTest", "[VantagePointTreeTest]")
{
HollowBallBound<EuclideanDistance> b(2, 4, arma::vec("1.0 2.0 3.0 4.0 5.0"));
BOOST_REQUIRE_EQUAL(b.Contains(arma::vec("1.0 2.0 3.0 7.0 5.0")), true);
REQUIRE(b.Contains(arma::vec("1.0 2.0 3.0 7.0 5.0")) == true);
BOOST_REQUIRE_EQUAL(b.Contains(arma::vec("1.0 2.0 3.0 9.0 5.0")), false);
REQUIRE(b.Contains(arma::vec("1.0 2.0 3.0 9.0 5.0")) == false);
BOOST_REQUIRE_EQUAL(b.Contains(arma::vec("1.0 2.0 3.0 5.0 5.0")), false);
REQUIRE(b.Contains(arma::vec("1.0 2.0 3.0 5.0 5.0")) == false);
HollowBallBound<EuclideanDistance> b2(0.5, 1,
arma::vec("1.0 2.0 3.0 7.0 5.0"));
BOOST_REQUIRE_EQUAL(b.Contains(b2), true);
REQUIRE(b.Contains(b2) == true);
b2 = HollowBallBound<EuclideanDistance>(2.5, 3.5,
arma::vec("1.0 2.0 3.0 4.5 5.0"));
BOOST_REQUIRE_EQUAL(b.Contains(b2), true);
REQUIRE(b.Contains(b2) == true);
b2 = HollowBallBound<EuclideanDistance>(2.0, 3.5,
arma::vec("1.0 2.0 3.0 4.5 5.0"));
BOOST_REQUIRE_EQUAL(b.Contains(b2), false);
REQUIRE(b.Contains(b2) == false);
BOOST_REQUIRE_CLOSE(b.MinDistance(arma::vec("1.0 2.0 8.0 4.0 5.0")), 1.0,
1e-5);
BOOST_REQUIRE_CLOSE(b.MinDistance(arma::vec("1.0 2.0 4.0 4.0 5.0")), 1.0,
1e-5);
BOOST_REQUIRE_CLOSE(b.MinDistance(arma::vec("1.0 2.0 3.0 4.0 5.0")), 2.0,
1e-5);
BOOST_REQUIRE_CLOSE(b.MinDistance(arma::vec("1.0 2.0 5.0 4.0 5.0")), 0.0,
1e-5);
BOOST_REQUIRE_CLOSE(b.MinDistance(arma::vec("5.0 2.0 3.0 4.0 5.0")), 0.0,
1e-5);
BOOST_REQUIRE_CLOSE(b.MinDistance(arma::vec("3.0 2.0 3.0 4.0 5.0")), 0.0,
1e-5);
BOOST_REQUIRE_CLOSE(b.MaxDistance(arma::vec("1.0 2.0 4.0 4.0 5.0")), 5.0,
1e-5);
BOOST_REQUIRE_CLOSE(b.MaxDistance(arma::vec("1.0 2.0 8.0 4.0 5.0")), 9.0,
1e-5);
BOOST_REQUIRE_CLOSE(b.MaxDistance(arma::vec("1.0 2.0 3.0 4.0 5.0")), 4.0,
1e-5);
REQUIRE(b.MinDistance(arma::vec("1.0 2.0 8.0 4.0 5.0")) ==
Approx(1.0).epsilon(1e-7));
REQUIRE(b.MinDistance(arma::vec("1.0 2.0 4.0 4.0 5.0")) ==
Approx(1.0).epsilon(1e-7));
REQUIRE(b.MinDistance(arma::vec("1.0 2.0 3.0 4.0 5.0")) ==
Approx(2.0).epsilon(1e-7));
REQUIRE(b.MinDistance(arma::vec("1.0 2.0 5.0 4.0 5.0")) ==
Approx(0.0).epsilon(1e-7));
REQUIRE(b.MinDistance(arma::vec("5.0 2.0 3.0 4.0 5.0")) ==
Approx(0.0).epsilon(1e-7));
REQUIRE(b.MinDistance(arma::vec("3.0 2.0 3.0 4.0 5.0")) ==
Approx(0.0).epsilon(1e-7));
REQUIRE(b.MaxDistance(arma::vec("1.0 2.0 4.0 4.0 5.0")) ==
Approx(5.0).epsilon(1e-7));
REQUIRE(b.MaxDistance(arma::vec("1.0 2.0 8.0 4.0 5.0")) ==
Approx(9.0).epsilon(1e-7));
REQUIRE(b.MaxDistance(arma::vec("1.0 2.0 3.0 4.0 5.0")) ==
Approx(4.0).epsilon(1e-7));
b2 = HollowBallBound<EuclideanDistance>(3, 4,
arma::vec("1.0 2.0 3.0 5.0 5.0"));
BOOST_REQUIRE_CLOSE(b.MinDistance(b2), 0.0, 1e-5);
REQUIRE(b.MinDistance(b2) == Approx(0.0).epsilon(1e-7));
b2 = HollowBallBound<EuclideanDistance>(1, 2,
arma::vec("1.0 2.0 3.0 4.0 5.0"));
BOOST_REQUIRE_CLOSE(b.MinDistance(b2), 0.0, 1e-5);
REQUIRE(b.MinDistance(b2) == Approx(0.0).epsilon(1e-7));
b2 = HollowBallBound<EuclideanDistance>(0.5, 1.0,
arma::vec("1.0 2.5 3.0 4.0 5.0"));
BOOST_REQUIRE_CLOSE(b.MinDistance(b2), 0.5, 1e-5);
REQUIRE(b.MinDistance(b2) == Approx(0.5).epsilon(1e-7));
b2 = HollowBallBound<EuclideanDistance>(0.5, 1.0,
arma::vec("1.0 8.0 3.0 4.0 5.0"));
BOOST_REQUIRE_CLOSE(b.MinDistance(b2), 1.0, 1e-5);
REQUIRE(b.MinDistance(b2) == Approx(1.0).epsilon(1e-7));
b2 = HollowBallBound<EuclideanDistance>(0.5, 2.0,
arma::vec("1.0 8.0 3.0 4.0 5.0"));
BOOST_REQUIRE_CLOSE(b.MinDistance(b2), 0.0, 1e-5);
REQUIRE(b.MinDistance(b2) == Approx(0.0).epsilon(1e-7));
b2 = HollowBallBound<EuclideanDistance>(0.5, 2.0,
arma::vec("1.0 8.0 3.0 4.0 5.0"));
BOOST_REQUIRE_CLOSE(b.MaxDistance(b2), 12.0, 1e-5);
REQUIRE(b.MaxDistance(b2) == Approx(12.0).epsilon(1e-7));
b2 = HollowBallBound<EuclideanDistance>(0.5, 2.0,
arma::vec("1.0 3.0 3.0 4.0 5.0"));
BOOST_REQUIRE_CLOSE(b.MaxDistance(b2), 7.0, 1e-5);
REQUIRE(b.MaxDistance(b2) == Approx(7.0).epsilon(1e-7));
HollowBallBound<EuclideanDistance> b1 = b;
b2 = HollowBallBound<EuclideanDistance>(1.0, 2.0,
arma::vec("1.0 2.5 3.0 4.0 5.0"));
b1 |= b2;
BOOST_REQUIRE_CLOSE(b1.InnerRadius(), 0.5, 1e-5);
REQUIRE(b1.InnerRadius() == Approx(0.5).epsilon(1e-7));
b1 = b;
b2 = HollowBallBound<EuclideanDistance>(0.5, 2.0,
arma::vec("1.0 3.0 3.0 4.0 5.0"));
b1 |= b2;
BOOST_REQUIRE_CLOSE(b1.InnerRadius(), 0.0, 1e-5);
REQUIRE(b1.InnerRadius() == Approx(0.0).epsilon(1e-7));
b1 = b;
b2 = HollowBallBound<EuclideanDistance>(0.5, 4.0,
arma::vec("1.0 3.0 3.0 4.0 5.0"));
b1 |= b2;
BOOST_REQUIRE_CLOSE(b1.OuterRadius(), 5.0, 1e-5);
REQUIRE(b1.OuterRadius() == Approx(5.0).epsilon(1e-7));
}
template<typename TreeType>
@@ -147,10 +144,10 @@ void CheckBound(TreeType& tree)
tree.Bound().HollowCenter(),
tree.Dataset().col(tree.Point(i)));
BOOST_REQUIRE_LE(tree.Bound().InnerRadius(), hollowDist *
REQUIRE(tree.Bound().InnerRadius() <= hollowDist *
(1.0 + 10.0 * std::numeric_limits<ElemType>::epsilon()));
BOOST_REQUIRE_LE(dist, tree.Bound().OuterRadius() *
REQUIRE(dist <= tree.Bound().OuterRadius() *
(1.0 + 10.0 * std::numeric_limits<ElemType>::epsilon()));
}
}
@@ -165,10 +162,10 @@ void CheckBound(TreeType& tree)
tree.Bound().HollowCenter(),
tree.Dataset().col(tree.Descendant(i)));
BOOST_REQUIRE_LE(tree.Bound().InnerRadius(), hollowDist *
REQUIRE(tree.Bound().InnerRadius() <= hollowDist *
(1.0 + 10.0 * std::numeric_limits<ElemType>::epsilon()));
BOOST_REQUIRE_LE(dist, tree.Bound().OuterRadius() *
REQUIRE(dist <= tree.Bound().OuterRadius() *
(1.0 + 10.0 * std::numeric_limits<ElemType>::epsilon()));
}
@@ -177,7 +174,7 @@ void CheckBound(TreeType& tree)
}
}
BOOST_AUTO_TEST_CASE(VPTreeBoundTest)
TEST_CASE("VPTreeBoundTest", "[VantagePointTreeTest]")
{
typedef VPTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
@@ -188,7 +185,7 @@ BOOST_AUTO_TEST_CASE(VPTreeBoundTest)
CheckBound(tree);
}
BOOST_AUTO_TEST_CASE(VPTreeTest)
TEST_CASE("VPTreeTest", "[VantagePointTreeTest]")
{
typedef VPTree<EuclideanDistance, EmptyStatistic, arma::mat> TreeType;
@@ -217,21 +214,21 @@ BOOST_AUTO_TEST_CASE(VPTreeTest)
const arma::mat& treeset = root.Dataset();
// Ensure the size of the tree is correct.
BOOST_REQUIRE_EQUAL(root.NumDescendants(), size);
REQUIRE(root.NumDescendants() == size);
// Check the forward and backward mappings for correctness.
for (size_t i = 0; i < size; ++i)
{
for (size_t j = 0; j < dimensions; ++j)
{
BOOST_REQUIRE_EQUAL(treeset(j, i), dataset(j, newToOld[i]));
BOOST_REQUIRE_EQUAL(treeset(j, oldToNew[i]), dataset(j, i));
REQUIRE(treeset(j, i) == dataset(j, newToOld[i]));
REQUIRE(treeset(j, oldToNew[i]) == dataset(j, i));
}
}
}
}
BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest)
TEST_CASE("SingleVPTreeTraverserTest", "[VantagePointTreeTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -253,12 +250,12 @@ BOOST_AUTO_TEST_CASE(SingleTreeTraverserTest)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
}
}
BOOST_AUTO_TEST_CASE(DualTreeTraverserTest)
TEST_CASE("DualVPTreeTraverserTest", "[VantagePointTreeTest]")
{
arma::mat dataset;
dataset.randu(8, 1000); // 1000 points in 8 dimensions.
@@ -280,9 +277,7 @@ BOOST_AUTO_TEST_CASE(DualTreeTraverserTest)
for (size_t i = 0; i < neighbors1.size(); ++i)
{
BOOST_REQUIRE_EQUAL(neighbors1[i], neighbors2[i]);
BOOST_REQUIRE_EQUAL(distances1[i], distances2[i]);
REQUIRE(neighbors1[i] == neighbors2[i]);
REQUIRE(distances1[i] == distances2[i]);
}
}
BOOST_AUTO_TEST_SUITE_END();