diff --git a/HISTORY.md b/HISTORY.md index a941b58491..67d39452d2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -11,6 +11,11 @@ * Additional functionality for the ARFF loader (#2486); use case sensitive categories (#2516). + * Add `bayesian_linear_regression` binding for the command-line, Python, + Julia, and Go. Also called "Bayesian Ridge", this is equivalent to a + version of linear regression where the regularization parameter is + automatically tuned (#2030). + ### mlpack 3.3.2 ###### 2020-06-18 * Added Noisy DQN to q_networks (#2446). diff --git a/doc/guide/sample_ml_app.hpp b/doc/guide/sample_ml_app.hpp index 28ae6ad737..6a1b1aa30a 100644 --- a/doc/guide/sample_ml_app.hpp +++ b/doc/guide/sample_ml_app.hpp @@ -94,7 +94,7 @@ copy "mlpack/tests/data/german.csv" and paste into a new "data" folder in your p mat dataset; bool loaded = mlpack::data::Load("data/german.csv", dataset); if (!loaded) - return -1; + return -1; @endcode Then we need to extract the labels from the last dimension of the dataset and remove the @@ -121,7 +121,7 @@ const size_t numTrees = 10; RandomForest rf; rf = RandomForest(dataset, labels, - numClasses, numTrees, minimumLeafSize); + numClasses, numTrees, minimumLeafSize); @endcode Now that the training is completed, we quickly compute the training accuracy: @@ -143,7 +143,7 @@ to assess the quality of the trained model. @code const size_t k = 10; KFoldCV, Accuracy> cv(k, - dataset, labels, numClasses); + dataset, labels, numClasses); double cvAcc = cv.Evaluate(numTrees, minimumLeafSize); cout << "\nKFoldCV Accuracy: " << cvAcc; @endcode @@ -188,12 +188,16 @@ Finally, the ultimate goal is to classify a new sample using the previously trai Random Forest classifier provides both predictions and probabilities, we obtain both. @code -mat sample("2 12 2 13 1 2 2 1 3 24 3 1 1 1 1 1 0 1 0 1 0 0 0"); +// Create a test sample containing only one point. Because Armadillo is +// column-major, this matrix has one column (one point) and the number of rows +// is equal to the dimensionality of the point (23). +mat sample("2; 12; 2; 13; 1; 2; 2; 1; 3; 24; 3; 1; 1; 1; 1; 1; 0; 1; 0; 1;" + " 0; 0; 0"); mat probabilities; rf.Classify(sample, predictions, probabilities); u64 result = predictions.at(0); cout << "\nClassification result: " << result << " , Probabilities: " << - probabilities.at(0) << "/" << probabilities.at(1); + probabilities.at(0) << "/" << probabilities.at(1); @endcode @section sample_app_conclussion Final thoughts diff --git a/src/mlpack/core/metrics/CMakeLists.txt b/src/mlpack/core/metrics/CMakeLists.txt index 5296f6124f..843ac642d2 100644 --- a/src/mlpack/core/metrics/CMakeLists.txt +++ b/src/mlpack/core/metrics/CMakeLists.txt @@ -1,6 +1,8 @@ # Define the files we need to compile. # Anything not in this list will not be compiled into mlpack. set(SOURCES + bleu.hpp + bleu_impl.hpp ip_metric.hpp ip_metric_impl.hpp iou_metric.hpp diff --git a/src/mlpack/core/metrics/bleu.hpp b/src/mlpack/core/metrics/bleu.hpp new file mode 100644 index 0000000000..97f8d3614e --- /dev/null +++ b/src/mlpack/core/metrics/bleu.hpp @@ -0,0 +1,169 @@ +/** + * @file core/metrics/bleu.hpp + * @author Mrityunjay Tripathi + * + * Definition of BLEU class. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_CORE_METRICS_BLEU_HPP +#define MLPACK_CORE_METRICS_BLEU_HPP + +#include + +namespace mlpack { +namespace metric { + +/** + * BLEU, or the Bilingual Evaluation Understudy, is an algorithm for evaluating + * the quality of text which has been machine translated from one natural + * language to another. It can also be used to evaluate text generated for a + * suite of natural language processing tasks. + * + * The BLEU score is calculated using the following formula: + * + * \f{eqnarray*}{ + * \text{B} &=& bp \cdot \exp \left(\sum_{n=1}^{N} w \log p_n \right) \\ + * \text{where,} \\ + * bp &=& \text{brevity penalty} = + * \begin{cases} + * 1 & \text{if ratio} > 1 \\ + * \exp \left(1-\frac{1}{ratio}\right) & \text{otherwise} + * \end{cases} \\ + * p_n &=& \text{modified precision for n-gram,} \\ + * w &=& \frac {1}{maxOrder}, \\ + * ratio &=& \text{translation to reference length ratio,} \\ + * maxOrder &=& \text{maximum length of tokens in n-grams.} + * \f} + * + * The value of BLEU Score lies in between 0 and 1. + * + * @tparam ElemType Type of the quantities in BLEU, e.g. (long double, + * double, float). + * @tparam PrecisionType Container type for precision for corresponding order. + * e.g. (std::vector, std::vector, or any such boost or + * armadillo container). + */ +template +> +class BLEU +{ + public: + /** + * Create an instance of BLEU class. + * + * @param maxOrder The maximum length of tokens in n-grams. + */ + BLEU(const size_t maxOrder = 4); + + /** + * Computes the BLEU Score. + * + * @tparam ReferenceCorpusType Type of reference corpus. + * @tparam TranslationCorpusType Type of translation corpus. + * @param referenceCorpus It is an array of various references or documents. + * So, the \f$ referenceCorpus = \{reference_1, reference_2, \ldots \} \f$ + * and each reference is an array of paragraphs. So, + * \f$ reference_i = \{paragraph_1, paragraph_2, \ldots \} \f$ + * and then each paragraph is an array of tokenized words/string. Like, + * \f$ paragraph_i = \{word_1, word_2, \ldots \} \f$. + * For ex. + * ``` + * refCorpus = {{{"this", "is", "paragraph", "1", "from", "document", "1"}, + * {"this", "is", "paragraph", "2", "from", "document", "1"}}, + * + * {{"this", "is", "paragraph", "1", "from", "document", "2"}, + * {"this", "is", "paragraph", "2", "from", "document", "2"}}} + * ``` + * @param translationCorpus It is an array of paragraphs which has been + * machine translated or generated for any natural language processing task. + * Like, \f$ translationCorpus = \{paragraph_1, paragraph_2, \ldots \} \f$. + * And then, each paragraph is an array of words. The ith paragraph from the + * corpus is \f$ paragraph_i = \{word_1, word_2, \ldots \} \f$. + * For ex. + * ``` + * transCorpus = {{"this", "is", "generated", "paragraph", "1"}, + * {"this", "is", "generated", "paragraph", "2"}} + * ``` + * @param smooth Whether or not to apply Lin et al. 2004 smoothing. + * @return The Evaluate method returns the BLEU Score. This method also + * calculates other BLEU metrics (brevity penalty, translation length, reference + * length, ratio and precisions) which can be accessed by their corresponding + * accessor methods. + */ + template + ElemType Evaluate(const ReferenceCorpusType& referenceCorpus, + const TranslationCorpusType& translationCorpus, + const bool smooth = false); + + //! Serialize the metric. + template + void serialize(Archive& ar, const unsigned int /* version */); + + //! Get the value of maximum length of tokens in n-grams. + size_t MaxOrder() const { return maxOrder; } + //! Modify the value of maximum length of tokens in n-grams. + size_t& MaxOrder() { return maxOrder; } + + //! Get the BLEU Score. + ElemType BLEUScore() const { return bleuScore; } + + //! Get the brevity penalty. + ElemType BrevityPenalty() const { return brevityPenalty; } + + //! Get the value of translation length. + size_t TranslationLength() const { return translationLength; } + + //! Get the value of reference length. + size_t ReferenceLength() const { return referenceLength; } + + //! Get the ratio of translation to reference length ratio. + ElemType Ratio() const { return ratio; } + + //! Get the precisions for corresponding order. + PrecisionType const& Precisions() const { return precisions; } + + private: + /** + * Extracts all the n-grams. + * + * @tparam WordVector Type of the tokenized vector. + * @param segment Tokenized sequence represented in form of vector. + */ + template + std::map GetNGrams(const WordVector& segment); + + //! Locally-stored value of maximum length of tokens in n-grams. + size_t maxOrder; + + //! Locally-stored BLEU score. + ElemType bleuScore; + + //! Locally-stored brevity penalty. It is a penalty for short machine + //! translation. + ElemType brevityPenalty; + + //! Locally-stored translation length. + size_t translationLength; + + //! Locally-stored reference length. + size_t referenceLength; + + //! Locally-stored translation to reference length ratio. + ElemType ratio; + + //! Locally stored precision for corresponding order. + PrecisionType precisions; +}; + +} // namespace metric +} // namespace mlpack + +// Include implementation. +#include "bleu_impl.hpp" + +#endif diff --git a/src/mlpack/core/metrics/bleu_impl.hpp b/src/mlpack/core/metrics/bleu_impl.hpp new file mode 100644 index 0000000000..ac7389cf29 --- /dev/null +++ b/src/mlpack/core/metrics/bleu_impl.hpp @@ -0,0 +1,200 @@ +/** + * @file core/metrics/bleu_impl.hpp + * @author Mrityunjay Tripathi + * + * Implementation of BLEU class. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_CORE_METRICS_BLEU_IMPL_HPP +#define MLPACK_CORE_METRICS_BLEU_IMPL_HPP + +// In case it hasn't been included. +#include "bleu.hpp" + +namespace mlpack { +namespace metric { + +template +BLEU::BLEU(const size_t maxOrder) : + maxOrder(maxOrder), + translationLength(0), + referenceLength(0) +{ + // Nothing to do here. +} + +template +template +std::map BLEU::GetNGrams( + const WordVector& segment) +{ + std::map ngramsCount; + for (size_t order = 1; order < maxOrder + 1; ++order) + { + for (size_t i = 0; i + order < segment.size() + 1; ++i) + { + WordVector seq = WordVector(segment.cbegin() + i, + segment.cbegin() + i + order); + ngramsCount[seq]++; + } + } + return ngramsCount; +} + +template +template +ElemType BLEU::Evaluate( + const ReferenceCorpusType& referenceCorpus, + const TranslationCorpusType& translationCorpus, + const bool smooth) +{ + // WordVector is a string container type. + // Also, TranslationCorpusType is an array of such containers. + typedef typename TranslationCorpusType::value_type WordVector; + + // matchesByOrder: It catches how many times sequence of a particular order + // is encountered in both reference corpus and translation corpus. + std::vector matchesByOrder(maxOrder, 0); + + // possibleMatchesByOrder: It tracks how many possible matches can be in the + // translation corpus. + std::vector possibleMatchesByOrder(maxOrder, 0); + + // referenceLength: It is the sum of minimum length of the paragraph from + // various documents. + // translationLength: It is the sum of length of each paragraphs. + referenceLength = 0, translationLength = 0; + + auto refIt = referenceCorpus.cbegin(); + auto trIt = translationCorpus.cbegin(); + for (; refIt != referenceCorpus.cend() && trIt != translationCorpus.cend(); + ++refIt, ++trIt) + { + size_t min = std::numeric_limits::max(); + for (const auto& t : *refIt) + { + if (min > t.size()) + { + min = t.size(); + } + } + + if (min == std::numeric_limits::max()) + min = 0; + + referenceLength += min; + translationLength += trIt->size(); + + // mergedRefNGramCounts: It accumulates all the similar n-grams from + // various references or documents, so that there is no repetition of + // any key (sequence of order n). + std::map mergedRefNGramCounts; + for (const auto& t : *refIt) + { + // ngram: It holds the n-grams of each document/reference. + const std::map ngrams = GetNGrams(t); + for (auto it = ngrams.cbegin(); it != ngrams.cend(); ++it) + { + mergedRefNGramCounts[it->first] = std::max(it->second, + mergedRefNGramCounts[it->first]); + } + } + // translationNGramCounts: It extracts the n-grams of the generated text + // sequence. + const std::map translationNGramCounts + = GetNGrams(*trIt); + + // overlap: It holds those keys (sequence of order n) which are common to + // reference corpus and translation corpus. + std::map overlap; + for (auto it = translationNGramCounts.cbegin(); + it != translationNGramCounts.cend(); + ++it) + { + auto mergedIt = mergedRefNGramCounts.find(it->first); + if (mergedIt != mergedRefNGramCounts.end()) + { + // If the key (sequence of order n) is present in both translation + // corpus as well as reference corpus, then the minimum number of + // counts it has occurred in any is considered. + overlap[it->first] = std::min(mergedIt->second, it->second); + } + } + + for (auto it = overlap.cbegin(); it != overlap.cend(); ++it) + { + matchesByOrder[it->first.size() - 1] += it->second; + } + + for (size_t order = 1; order < maxOrder + 1; ++order) + { + if (order < trIt->size() + 1) + possibleMatchesByOrder[order - 1] += trIt->size() - order + 1; + } + } + + precisions = PrecisionType(maxOrder, 0.0); + + if (smooth) + { + for (size_t i = 0; i < maxOrder; ++i) + { + precisions[i] + = (matchesByOrder[i] + 1.0) / (possibleMatchesByOrder[i] + 1.0); + } + } + else + { + for (size_t i = 0; i < maxOrder; ++i) + { + if (possibleMatchesByOrder[i] > 0) + precisions[i] = ElemType(matchesByOrder[i]) / possibleMatchesByOrder[i]; + else + precisions[i] = 0.0; + } + } + + ElemType minPrecision = std::numeric_limits::max(); + for (size_t i = 0; i < maxOrder; ++i) + { + if (minPrecision > precisions[i]) + minPrecision = precisions[i]; + } + + ElemType geometricMean; + if (minPrecision > 0) + { + ElemType pLogSum = 0.0; + for (const auto& t : precisions) + { + pLogSum += (1.0 / maxOrder) * std::log(t); + } + geometricMean = std::exp(pLogSum); + } + else + geometricMean = 0.0; + + ratio = ElemType(translationLength) / referenceLength; + brevityPenalty = (ratio > 1.0) ? 1.0 : std::exp(1.0 - 1.0 / ratio); + bleuScore = geometricMean * brevityPenalty; + + return bleuScore; +} + +template +template +void BLEU::serialize( + Archive& ar, + const unsigned int /* version */) +{ + ar & BOOST_SERIALIZATION_NVP(maxOrder); +} + +} // namespace metric +} // namespace mlpack + +#endif diff --git a/src/mlpack/methods/CMakeLists.txt b/src/mlpack/methods/CMakeLists.txt index 83c96e68dd..d548d9c769 100644 --- a/src/mlpack/methods/CMakeLists.txt +++ b/src/mlpack/methods/CMakeLists.txt @@ -6,6 +6,7 @@ set(DIRS ann approx_kfn bias_svd + bayesian_linear_regression block_krylov_svd cf dbscan diff --git a/src/mlpack/methods/ann/ffn_impl.hpp b/src/mlpack/methods/ann/ffn_impl.hpp index 12194ec9c0..e11b624cc8 100644 --- a/src/mlpack/methods/ann/ffn_impl.hpp +++ b/src/mlpack/methods/ann/ffn_impl.hpp @@ -39,7 +39,7 @@ FFN::FFN( height(0), reset(false), numFunctions(0), - deterministic(true) + deterministic(false) { /* Nothing to do here. */ } @@ -60,7 +60,7 @@ void FFN::ResetData( numFunctions = responses.n_cols; this->predictors = std::move(predictors); this->responses = std::move(responses); - this->deterministic = true; + this->deterministic = false; ResetDeterministic(); if (!reset) @@ -158,12 +158,6 @@ void FFN::Forward( if (parameter.is_empty()) ResetParameters(); - if (!deterministic) - { - deterministic = true; - ResetDeterministic(); - } - Forward(inputs); results = boost::apply_visitor(outputParameterVisitor, network.back()); } diff --git a/src/mlpack/methods/ann/layer/lookup.hpp b/src/mlpack/methods/ann/layer/lookup.hpp index 93e70712ae..e704a5a1f7 100644 --- a/src/mlpack/methods/ann/layer/lookup.hpp +++ b/src/mlpack/methods/ann/layer/lookup.hpp @@ -17,11 +17,17 @@ #include namespace mlpack { -namespace ann /** Artificial Neural Network. */ { +namespace ann /* Artificial Neural Network. */ { /** - * Implementation of the Lookup class. The Lookup class is a particular - * convolution, where the width of the convolution is 1. + * The Lookup class stores word embeddings and retrieves them using tokens. The + * Lookup layer is always the first layer of the network. The input to the + * Lookup class is a matrix of shape (sequenceLength, batchSize). The matrix + * consists of tokens which are used to lookup the table (i.e. weights) to find + * the embeddings of those tokens. + * + * The input shape : (sequenceLength, batchSize). + * The output shape : (sequenceLength * embeddingSize, batchSize). * * @tparam InputDataType Type of the input data (arma::colvec, arma::mat, * arma::sp_mat or arma::cube). @@ -36,13 +42,12 @@ class Lookup { public: /** - * Create the Lookup object using the specified number of input and output - * units. + * Create the Lookup object using the specified vocabulary and embedding size. * - * @param inSize The number of input units. - * @param outSize The number of output units. + * @param vocabSize The size of the vocabulary. + * @param embeddingSize The length of each embedding vector. */ - Lookup(const size_t inSize = 0, const size_t outSize = 0); + Lookup(const size_t vocabSize = 0, const size_t embeddingSize = 0); /** * Ordinary feed forward pass of a neural network, evaluating the function @@ -68,7 +73,7 @@ class Lookup const arma::Mat& gy, arma::Mat& g); - /* + /** * Calculate the gradient using the output delta and the input activation. * * @param input The input parameter used for calculating the gradient. @@ -100,11 +105,11 @@ class Lookup //! Modify the gradient. OutputDataType& Gradient() { return gradient; } - //! Get the number of input units. - size_t InSize() const { return inSize; } + //! Get the size of the vocabulary. + size_t VocabSize() const { return vocabSize; } - //! Get the number of output units. - size_t OutSize() const { return outSize; } + //! Get the length of each embedding vector. + size_t EmbeddingSize() const { return embeddingSize; } /** * Serialize the layer @@ -113,11 +118,11 @@ class Lookup void serialize(Archive& ar, const unsigned int /* version */); private: - //! Locally-stored number of input units. - size_t inSize; + //! Locally-stored size of the vocabulary. + size_t vocabSize; - //! Locally-stored number of output units. - size_t outSize; + //! Locally-stored length of each embedding vector. + size_t embeddingSize; //! Locally-stored weight object. OutputDataType weights; diff --git a/src/mlpack/methods/ann/layer/lookup_impl.hpp b/src/mlpack/methods/ann/layer/lookup_impl.hpp index 2e94496d82..6afcb56218 100644 --- a/src/mlpack/methods/ann/layer/lookup_impl.hpp +++ b/src/mlpack/methods/ann/layer/lookup_impl.hpp @@ -21,12 +21,12 @@ namespace ann /** Artificial Neural Network. */ { template Lookup::Lookup( - const size_t inSize, - const size_t outSize) : - inSize(inSize), - outSize(outSize) + const size_t vocabSize, + const size_t embeddingSize) : + vocabSize(vocabSize), + embeddingSize(embeddingSize) { - weights.set_size(outSize, inSize); + weights.set_size(vocabSize, embeddingSize); } template @@ -34,17 +34,30 @@ template void Lookup::Forward( const arma::Mat& input, arma::Mat& output) { - output = weights.cols(arma::conv_to::from(input) - 1); + const size_t seqLength = input.n_rows; + const size_t batchSize = input.n_cols; + + output.set_size(seqLength * embeddingSize, batchSize); + + for (size_t i = 0; i < batchSize; ++i) + { + //! ith column of output is a vectorized form of a matrix of shape + //! (seqLength, embeddingSize) selected as a combination of rows from the + //! weights. The MultiheadAttention class requires this particular ordering + //! of matrix dimensions. + output.col(i) = arma::vectorise(weights.rows( + arma::conv_to::from(input.col(i)) - 1)); + } } template template void Lookup::Backward( const arma::Mat& /* input */, - const arma::Mat& gy, - arma::Mat& g) + const arma::Mat& /* gy */, + arma::Mat& /* g */) { - g = gy; + Log::Fatal << "Lookup cannot be used as an intermediate layer." << std::endl; } template @@ -54,8 +67,20 @@ void Lookup::Gradient( const arma::Mat& error, arma::Mat& gradient) { - gradient = arma::zeros >(weights.n_rows, weights.n_cols); - gradient.cols(arma::conv_to::from(input) - 1) = error; + const size_t seqLength = input.n_rows; + const size_t batchSize = input.n_cols; + + arma::Cube errorTemp(const_cast&>(error).memptr(), + seqLength, embeddingSize, batchSize, false, false); + + gradient.set_size(arma::size(weights)); + gradient.zeros(); + + for (size_t i = 0; i < batchSize; ++i) + { + gradient.rows(arma::conv_to::from(input.col(i)) - 1) + += errorTemp.slice(i); + } } template @@ -63,8 +88,13 @@ template void Lookup::serialize( Archive& ar, const unsigned int /* version */) { - ar & BOOST_SERIALIZATION_NVP(inSize); - ar & BOOST_SERIALIZATION_NVP(outSize); + ar & BOOST_SERIALIZATION_NVP(vocabSize); + ar & BOOST_SERIALIZATION_NVP(embeddingSize); + + // This is inefficient, but we have to allocate this memory so that + // WeightSetVisitor gets the right size. + if (Archive::is_loading::value) + weights.set_size(vocabSize, embeddingSize); } } // namespace ann diff --git a/src/mlpack/methods/ann/loss_functions/CMakeLists.txt b/src/mlpack/methods/ann/loss_functions/CMakeLists.txt index a4e2cc590c..5dbfe5a1c7 100644 --- a/src/mlpack/methods/ann/loss_functions/CMakeLists.txt +++ b/src/mlpack/methods/ann/loss_functions/CMakeLists.txt @@ -33,6 +33,8 @@ set(SOURCES reconstruction_loss_impl.hpp sigmoid_cross_entropy_error.hpp sigmoid_cross_entropy_error_impl.hpp + soft_margin_loss.hpp + soft_margin_loss_impl.hpp hinge_embedding_loss.hpp hinge_embedding_loss_impl.hpp empty_loss.hpp diff --git a/src/mlpack/methods/ann/loss_functions/soft_margin_loss.hpp b/src/mlpack/methods/ann/loss_functions/soft_margin_loss.hpp new file mode 100644 index 0000000000..6050875113 --- /dev/null +++ b/src/mlpack/methods/ann/loss_functions/soft_margin_loss.hpp @@ -0,0 +1,100 @@ +/** + * @file methods/ann/loss_functions/soft_margin_loss.hpp + * @author Anjishnu Mukherjee + * + * Definition of the Soft Margin Loss function. + * + * It is a criterion that optimizes a two-class classification logistic loss, + * between input x and target y, both having the same shape, with the target + * containing only the values 1 or -1. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_ANN_LOSS_FUNCTION_SOFT_MARGIN_LOSS_HPP +#define MLPACK_ANN_LOSS_FUNCTION_SOFT_MARGIN_LOSS_HPP + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * @tparam InputDataType Type of the input data (arma::colvec, arma::mat, + * arma::sp_mat or arma::cube). + * @tparam OutputDataType Type of the output data (arma::colvec, arma::mat, + * arma::sp_mat or arma::cube). + */ +template < + typename InputDataType = arma::mat, + typename OutputDataType = arma::mat +> +class SoftMarginLoss +{ + public: + /** + * Create the SoftMarginLoss object. + * + * @param reduction Specifies the reduction to apply to the output. If false, + * 'mean' reduction is used, where sum of the output will be + * divided by the number of elements in the output. If + * true, 'sum' reduction is used and the output will be + * summed. It is set to true by default. + */ + SoftMarginLoss(const bool reduction = true); + + /** + * Computes the Soft Margin Loss function. + * + * @param input Input data used for evaluating the specified function. + * @param target The target vector with same shape as input. + */ + template + typename InputType::elem_type Forward(const InputType& input, + const TargetType& target); + + /** + * Ordinary feed backward pass of a neural network. + * + * @param input The propagated input activation. + * @param target The target vector. + * @param output The calculated error. + */ + template + void Backward(const InputType& input, + const TargetType& target, + OutputType& output); + + //! Get the output parameter. + OutputDataType& OutputParameter() const { return outputParameter; } + //! Modify the output parameter. + OutputDataType& OutputParameter() { return outputParameter; } + + //! Get the type of reduction used. + bool Reduction() const { return reduction; } + //! Modify the type of reduction used. + bool& Reduction() { return reduction; } + + /** + * Serialize the layer. + */ + template + void serialize(Archive& ar, const unsigned int /* version */); + + private: + //! Locally-stored output parameter object. + OutputDataType outputParameter; + + //! The boolean value that tells if reduction is sum or mean. + bool reduction; +}; // class SoftMarginLoss + +} // namespace ann +} // namespace mlpack + +// include implementation. +#include "soft_margin_loss_impl.hpp" + +#endif diff --git a/src/mlpack/methods/ann/loss_functions/soft_margin_loss_impl.hpp b/src/mlpack/methods/ann/loss_functions/soft_margin_loss_impl.hpp new file mode 100644 index 0000000000..87fdb3f801 --- /dev/null +++ b/src/mlpack/methods/ann/loss_functions/soft_margin_loss_impl.hpp @@ -0,0 +1,72 @@ +/** + * @file methods/ann/loss_functions/soft_margin_loss_impl.hpp + * @author Anjishnu Mukherjee + * + * Implementation of the Soft Margin Loss function. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_METHODS_ANN_LOSS_FUNCTION_SOFT_MARGIN_LOSS_IMPL_HPP +#define MLPACK_METHODS_ANN_LOSS_FUNCTION_SOFT_MARGIN_LOSS_IMPL_HPP + +// In case it hasn't been included. +#include "soft_margin_loss.hpp" + +namespace mlpack { +namespace ann /** Artifical Neural Network. */ { + +template +SoftMarginLoss:: +SoftMarginLoss(const bool reduction) : reduction(reduction) +{ + // Nothing to do here. +} + +template +template +typename InputType::elem_type +SoftMarginLoss::Forward( + const InputType& input, const TargetType& target) +{ + InputType loss = arma::log(1 + arma::exp(-target % input)); + typename InputType::elem_type lossSum = arma::accu(loss); + + if (reduction) + return lossSum; + + return lossSum / input.n_elem; +} + +template +template +void SoftMarginLoss::Backward( + const InputType& input, + const TargetType& target, + OutputType& output) +{ + output.set_size(size(input)); + InputType temp = arma::exp(-target % input); + InputType numerator = -target % temp; + InputType denominator = 1 + temp; + output = numerator / denominator; + + if (!reduction) + output = output / input.n_elem; +} + +template +template +void SoftMarginLoss::serialize( + Archive& ar, + const unsigned int /* version */) +{ + ar & BOOST_SERIALIZATION_NVP(reduction); +} + +} // namespace ann +} // namespace mlpack + +#endif diff --git a/src/mlpack/methods/bayesian_linear_regression/CMakeLists.txt b/src/mlpack/methods/bayesian_linear_regression/CMakeLists.txt new file mode 100644 index 0000000000..5cdae4274d --- /dev/null +++ b/src/mlpack/methods/bayesian_linear_regression/CMakeLists.txt @@ -0,0 +1,21 @@ +# Define the files we need to compile +# Anything not in this list will not be compiled into the output library +set(SOURCES + bayesian_linear_regression.hpp + bayesian_linear_regression_impl.hpp + bayesian_linear_regression.cpp +) + +# add directory name to sources +set(DIR_SRCS) +foreach(file ${SOURCES}) + set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) +endforeach() +# append sources (with directory name) to list of all mlpack sources (used at the parent scope) +set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE) + +add_cli_executable(bayesian_linear_regression) +add_python_binding(bayesian_linear_regression) +add_julia_binding(bayesian_linear_regression) +add_go_binding(bayesian_linear_regression) +add_markdown_docs(bayesian_linear_regression "cli;python;julia;go" "regression") diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp new file mode 100644 index 0000000000..10a5f92bd5 --- /dev/null +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.cpp @@ -0,0 +1,188 @@ +/** + * @file methods/bayesian_linear_regression/bayesian_linear_regression.cpp + * @author Clement Mercier + * + * Implementation of Bayesian linear regression. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#include "bayesian_linear_regression.hpp" +#include +#include + +using namespace mlpack; +using namespace mlpack::regression; + +BayesianLinearRegression::BayesianLinearRegression(const bool centerData, + const bool scaleData, + const size_t nIterMax, + const double tol) : + centerData(centerData), + scaleData(scaleData), + nIterMax(nIterMax), + tol(tol), + responsesOffset(0.0), + alpha(0.0), + beta(0.0), + gamma(0.0) +{/* Nothing to do */} + +double BayesianLinearRegression::Train(const arma::mat& data, + const arma::rowvec& responses) +{ + Timer::Start("bayesian_linear_regression"); + + arma::mat phi; + arma::rowvec t; + arma::colvec eigVal; + arma::mat eigVec; + + // Preprocess the data. Center and scale. + responsesOffset = CenterScaleData(data, responses, phi, t); + + if (!arma::eig_sym(eigVal, eigVec, arma::symmatu(phi * phi.t()))) + { + Log::Fatal << "BayesianLinearRegression::Train(): Eigendecomposition " + << "of covariance failed!" << std::endl; + } + + // Compute this quantities once and for all. + const arma::mat eigVecInv = inv(eigVec); + const arma::colvec eigVecInvPhitT = eigVecInv * phi * t.t(); + + // Initialize the hyperparameters and begin with an infinitely broad prior. + alpha = 1e-6; + beta = 1 / (var(t, 1) * 0.1); + + unsigned short i = 0; + double deltaAlpha = 1.0, deltaBeta = 1.0, crit = 1.0; + + while ((crit > tol) && (i < nIterMax)) + { + deltaAlpha = -alpha; + deltaBeta = -beta; + + // Update the solution. + omega = eigVec * diagmat(1 / (eigVal + (alpha / beta))) * eigVecInvPhitT; + + // Update alpha. + gamma = sum(eigVal / (alpha / beta + eigVal)); + alpha = gamma / dot(omega, omega); + + // Update beta. + const arma::rowvec temp = t - omega.t() * phi; + beta = (data.n_cols - gamma) / dot(temp, temp); + + // Compute the stopping criterion. + deltaAlpha += alpha; + deltaBeta += beta; + crit = std::abs(deltaAlpha / alpha + deltaBeta / beta); + i++; + } + // Compute the covariance matrix for the uncertainties later. + matCovariance = eigVec * diagmat(1 / (beta * eigVal + alpha)) * eigVecInv; + + Timer::Stop("bayesian_linear_regression"); + + return RMSE(data, responses); +} + +void BayesianLinearRegression::Predict(const arma::mat& points, + arma::rowvec& predictions) const +{ + // Center and scale the points before applying the model. + arma::mat matX; + CenterScaleDataPred(points, matX); + predictions = omega.t() * matX + responsesOffset; +} + +void BayesianLinearRegression::Predict(const arma::mat& points, + arma::rowvec& predictions, + arma::rowvec& std) const +{ + // Center and scale the points before applying the model. + arma::mat matX; + CenterScaleDataPred(points, matX); + predictions = omega.t() * matX + responsesOffset; + // Compute the standard deviation for each point. + std = sqrt(Variance() + sum(matX % (matCovariance * matX), 0)); +} + +double BayesianLinearRegression::RMSE(const arma::mat& data, + const arma::rowvec& responses) const +{ + arma::rowvec predictions; + Predict(data, predictions); + return sqrt(mean(square(responses - predictions))); +} + +double BayesianLinearRegression::CenterScaleData(const arma::mat& data, + const arma::rowvec& responses, + arma::mat& dataProc, + arma::rowvec& responsesProc) +{ + if (!centerData && !scaleData) + { + dataProc = arma::mat(const_cast(data.memptr()), data.n_rows, + data.n_cols, false, true); + responsesProc = arma::rowvec(const_cast(responses.memptr()), + responses.n_elem, false, + true); + } + + else if (centerData && !scaleData) + { + dataOffset = mean(data, 1); + responsesOffset = mean(responses); + dataProc = data.each_col() - dataOffset; + responsesProc = responses - responsesOffset; + } + + else if (!centerData && scaleData) + { + dataScale = stddev(data, 0, 1); + dataProc = data.each_col() / dataScale; + responsesProc = arma::rowvec(const_cast(responses.memptr()), + responses.n_elem, false, + true); + } + + else + { + dataOffset = mean(data, 1); + dataScale = stddev(data, 0, 1); + responsesOffset = mean(responses); + dataProc = (data.each_col() - dataOffset).each_col() / dataScale; + responsesProc = responses - responsesOffset; + } + return responsesOffset; +} + +void BayesianLinearRegression::CenterScaleDataPred( + const arma::mat& data, + arma::mat& dataProc) const +{ + if (!centerData && !scaleData) + { + dataProc = arma::mat(const_cast(data.memptr()), data.n_rows, + data.n_cols, false, true); + } + + else if (centerData && !scaleData) + { + dataProc = data.each_col() - dataOffset; + } + + else if (!centerData && scaleData) + { + dataProc = data.each_col() / dataScale; + } + + else + { + dataProc = (data.each_col() - dataOffset).each_col() / dataScale; + } +} diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.hpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.hpp new file mode 100644 index 0000000000..415f63e595 --- /dev/null +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression.hpp @@ -0,0 +1,285 @@ +/** + * @file methods/bayesian_linear_regression/bayesian_linear_regression.hpp + * @author Clement Mercier + * + * Definition of the BayesianRidge class, which performs the + * bayesian linear regression. According to the armadillo standards, + * all the functions consider data in column-major format. +**/ + +#ifndef MLPACK_METHODS_BAYESIAN_LINEAR_REGRESSION_HPP +#define MLPACK_METHODS_BAYESIAN_LINEAR_REGRESSION_HPP + +#include + +namespace mlpack { +namespace regression { + +/** + * A Bayesian approach to the maximum likelihood estimation of the parameters + * \f$ \omega \f$ of the linear regression model. The Complexity is governed by + * the addition of a gaussian isotropic prior of precision \f$ \alpha \f$ over + * \f$ \omega \f$: + * + * \f[ + * p(\omega|\alpha) = \mathcal{N}(\omega|0, \alpha^{-1}I) + * \f] + * + * The optimization procedure calculates the posterior distribution of + * \f$ \omega \f$ knowing the data by maximizing an approximation of the log + * marginal likelihood derived from a type II maximum likelihood approximation. + * The determination of \f$ alpha \f$ and of the noise precision \f$ beta \f$ + * is part of the optimization process, leading to an automatic determination of + * w. The model being entirely based on probabilty distributions, uncertainties + * are available and easly computed for both the parameters and the predictions. + * + * The advantage over linear regression and ridge regression is that the + * regularization is determined from all the training data alone without any + * require to an hold out method. + * + * The code below is an implementation of the maximization of the evidence + * function described in the section 3.5.2 of the C.Bishop book, Pattern + * Recognition and Machine Learning. + * + * @code + * @article{MacKay91bayesianinterpolation, + * author = {David J.C. MacKay}, + * title = {Bayesian Interpolation}, + * journal = {NEURAL COMPUTATION}, + * year = {1991}, + * volume = {4}, + * pages = {415--447} + * } + * @endcode + * + * @code + * @book{Bishop:2006:PRM:1162264, + * author = {Bishop, Christopher M.}, + * title = {Pattern Recognition and Machine Learning (Information Science + * and Statistics)}, + * chapter = {3} + * year = {2006}, + * isbn = {0387310738}, + * publisher = {Springer-Verlag}, + * address = {Berlin, Heidelberg}, + * } + * @endcode + * + * Example of use: + * + * @code + * arma::mat xTrain; // Train data matrix. Column-major. + * arma::rowvec yTrain; // Train target values. + + * // Train the model. Regularization strength is optimally tunned with the + * // training data alone by applying the Train method. + * BayesianLinearRegression estimator(); // Instanciate the estimator with default option. + * estimator.Train(xTrain, yTrain); + + * // Prediction on test points. + * arma::mat xTest; // Test data matrix. Column-major. + * arma::rowvec predictions; + + * estimator.Predict(xTest, prediction); + + * arma::rowvec yTest; // Test target values. + * estimator.RMSE(xTest, yTest); // Evaluate using the RMSE score. + + * // Compute the standard deviations of the predictions. + * arma::rowvec stds; + * estimator.Predict(xTest, responses, stds) + * @endcode + */ +class BayesianLinearRegression +{ + public: + /** + * Set the parameters of Bayesian Ridge regression object. The + * regularization parameter is automatically set to its optimal value by + * maximization of the marginal likelihood. + * + * @param centerData Whether or not center the data according to the + * examples. + * @param scaleData Whether or not scale the data according to the + * standard deviation of each feature. + * @param nIterMax Maximum number of iterations for convergency. + * @param tol Level from which the solution is considered sufficientlly + * stable. + */ + BayesianLinearRegression(const bool centerData = true, + const bool scaleData = false, + const size_t nIterMax = 50, + const double tol = 1e-4); + + /** + * Run BayesianLinearRegression. The input matrix (like all mlpack matrices) should be + * column-major -- each column is an observation and each row is a dimension. + * + * @param data Column-major input data, dim(P, N). + * @param responses A vector of targets, dim(N). + * @return Root mean squared error. + */ + double Train(const arma::mat& data, + const arma::rowvec& responses); + + /** + * Predict \f$y_{i}\f$ for each data point in the given data matrix using the + * currently-trained Bayesian Ridge model. + * + * @param points The data points to apply the model. + * @param predictions y, Contains the predicted values on completion. + * @return Root mean squared error computed on the train set. + */ + void Predict(const arma::mat& points, + arma::rowvec& predictions) const; + + /** + * Predict \f$y_{i}\f$ and the standard deviation of the predictive posterior + * distribution for each data point in the given data matrix, using the + * currently-trained Bayesian Ridge estimator. + * + * @param points The data point to apply the model. + * @param predictions Vector which will contain calculated values on completion. + * @param std Standard deviations of the predictions. + */ + void Predict(const arma::mat& points, + arma::rowvec& predictions, + arma::rowvec& std) const; + + /** + * Compute the Root Mean Square Error between the predictions returned by the + * model and the true responses. + * + * @param data Data points to predict + * @param responses A vector of targets. + * @return Root mean squared error. + **/ + double RMSE(const arma::mat& data, + const arma::rowvec& responses) const; + + /** + * Get the solution vector. + * + * @return omega Solution vector. + */ + const arma::colvec& Omega() const { return omega; } + + /** + * Get the precision (or inverse variance) of the gaussian prior. Train() + * must be called before. + * + * @return \f$ \alpha \f$ + */ + double Alpha() const { return alpha; } + + /** + * Get the precision (or inverse variance) beta of the model. Train() must be + * called before. + * + * @return \f$ \beta \f$ + */ + double Beta() const { return beta; } + + /** + * Get the estimated variance. Train() must be called before. + * + * @return 1.0 / \f$ \beta \f$ + */ + double Variance() const { return 1.0 / Beta(); } + + /** + * Get the mean vector computed on the features over the training points. + * + * @return responsesOffset + */ + const arma::colvec& DataOffset() const { return dataOffset; } + + /** + * Get the vector of standard deviations computed on the features over the + * training points. + * + * @return dataOffset + */ + const arma::colvec& DataScale() const { return dataScale; } + + /** + * Get the mean value of the train responses. + * + * @return responsesOffset + */ + double ResponsesOffset() const { return responsesOffset; } + + /** + * Serialize the BayesianLinearRegression model. + **/ + template + void serialize(Archive& ar, const unsigned int /* version */); + + private: + //! Center the data if true. + bool centerData; + + //! Scale the data by standard deviations if true. + bool scaleData; + + //! Maximum number of iterations for convergency. + size_t nIterMax; + + //! Level from which the solution is considered sufficientlly stable. + double tol; + + //! Mean vector computed over the points. + arma::colvec dataOffset; + + //! Std vector computed over the points. + arma::colvec dataScale; + + //! Mean of the response vector computed over the points. + double responsesOffset; + + //! Precision of the prior pdf (gaussian). + double alpha; + + //! Noise inverse variance. + double beta; + + //! Effective number of parameters. + double gamma; + + //! Solution vector + arma::colvec omega; + + //! Covariance matrix of the solution vector omega. + arma::mat matCovariance; + + /** + * Center and scale the data accordind to centerData and scaleData. + * Allows future modifications of new points. + * + * @param data Design matrix in column-major format, dim(P, N). + * @param responses A vector of targets. + * @param dataProc Data processed, dim(P, N). + * @param responsesProc Responses processed, dim(N). + * @return reponsesOffset Mean of responses. + */ + double CenterScaleData(const arma::mat& data, + const arma::rowvec& responses, + arma::mat& dataProc, + arma::rowvec& responsesProc); + + /** + * Center and scale the points before prediction. + * + * @param data Design matrix in column-major format, dim(P, N). + * @param dataProc Data processed, dim(P, N). + */ + void CenterScaleDataPred(const arma::mat& data, + arma::mat& dataProc) const; +}; +} // namespace regression +} // namespace mlpack + +// Include implementation of serialize. +#include "bayesian_linear_regression_impl.hpp" + +#endif diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_impl.hpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_impl.hpp new file mode 100644 index 0000000000..9c4cb20f09 --- /dev/null +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_impl.hpp @@ -0,0 +1,44 @@ +/** + * @file methods/bayesian_linear_regression/bayesian_linear_regression_impl.hpp + * @author Clement Mercier + * + * Implementation of templated BayesianLinearRegression functions. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_METHODS_BAYESIAN_LINEAR_REGRESSION_IMPL_HPP +#define MLPACK_METHODS_BAYESIAN_LINEAR_REGRESSION_IMPL_HPP + +#include "bayesian_linear_regression.hpp" + +namespace mlpack { +namespace regression { + +/** + * Serialize the Bayesian linear regression model. + */ +template +void BayesianLinearRegression::serialize(Archive& ar, + const unsigned int /* version */) +{ + ar & BOOST_SERIALIZATION_NVP(centerData); + ar & BOOST_SERIALIZATION_NVP(scaleData); + ar & BOOST_SERIALIZATION_NVP(nIterMax); + ar & BOOST_SERIALIZATION_NVP(tol); + ar & BOOST_SERIALIZATION_NVP(dataOffset); + ar & BOOST_SERIALIZATION_NVP(dataScale); + ar & BOOST_SERIALIZATION_NVP(responsesOffset); + ar & BOOST_SERIALIZATION_NVP(alpha); + ar & BOOST_SERIALIZATION_NVP(beta); + ar & BOOST_SERIALIZATION_NVP(gamma); + ar & BOOST_SERIALIZATION_NVP(omega); + ar & BOOST_SERIALIZATION_NVP(matCovariance); +} + +} // namespace regression +} // namespace mlpack + +#endif diff --git a/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp new file mode 100644 index 0000000000..86fc946fe2 --- /dev/null +++ b/src/mlpack/methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp @@ -0,0 +1,199 @@ +/** + * @file methods/bayesian_linear_regression/bayesian_linear_regression_main.cpp + * @author Clement Mercier + * + * Executable for BayesianLinearRegression. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#include +#include +#include + +#include "bayesian_linear_regression.hpp" + +using namespace arma; +using namespace std; +using namespace mlpack; +using namespace mlpack::regression; +using namespace mlpack::util; + +PROGRAM_INFO("BayesianLinearRegression", + // Short description. + "An implementation of the bayesian linear regression.", + // Long description. + "An implementation of the bayesian linear regression." + "\n" + "This model is a probabilistic view and implementation of the linear " + "regression. The final solution is obtained by computing a posterior " + "distribution from gaussian likelihood and a zero mean gaussian isotropic " + " prior distribution on the solution. " + "\n" + "Optimization is AUTOMATIC and does not require cross validation. " + "The optimization is performed by maximization of the evidence function. " + "Parameters are tuned during the maximization of the marginal likelihood. " + "This procedure includes the Ockham's razor that penalizes over complex " + "solutions. " + "\n\n" + "This program is able to train a Bayesian linear regression model or load " + "a model from file, output regression predictions for a test set, and save " + "the trained model to a file." + "\n\n" + "To train a BayesianLinearRegression model, the " + + PRINT_PARAM_STRING("input") + " and " + PRINT_PARAM_STRING("responses") + + "parameters must be given. The " + PRINT_PARAM_STRING("center") + + "and " + PRINT_PARAM_STRING("scale") + " parameters control the " + "centering and the normalizing options. A trained model can be saved with " + "the " + PRINT_PARAM_STRING("output_model") + ". If no training is desired " + "at all, a model can be passed via the " + + PRINT_PARAM_STRING("input_model") + " parameter." + "\n\n" + "The program can also provide predictions for test data using either the " + "trained model or the given input model. Test points can be specified " + "with the " + PRINT_PARAM_STRING("test") + " parameter. Predicted " + "responses to the test points can be saved with the " + + PRINT_PARAM_STRING("predictions") + " output parameter. The " + "corresponding standard deviation can be save by precising the " + + PRINT_PARAM_STRING("stds") + " parameter." + "\n\n" + "For example, the following command trains a model on the data " + + PRINT_DATASET("data") + " and responses " + PRINT_DATASET("responses") + + "with center set to true and scale set to false (so, Bayesian " + "linear regression is being solved, and then the model is saved to " + + PRINT_MODEL("bayesian_linear_regression_model") + ":" + "\n\n" + + PRINT_CALL("bayesian_linear_regression", "input", "data", "responses", + "responses", "center", 1, "scale", 0, "output_model", + "bayesian_linear_regression_model") + + "\n\n" + "The following command uses the " + + PRINT_MODEL("bayesian_linear_regression_model") + " to provide predicted " + + " responses for the data " + PRINT_DATASET("test") + " and save those " + + " responses to " + PRINT_DATASET("test_predictions") + ": " + "\n\n" + + PRINT_CALL("bayesian_linear_regression", "input_model", + "bayesian_linear_regression_model", "test", "test", + "predictions", "test_predictions") + + "\n\n" + "Because the estimator computes a predictive distribution instead of " + "simple point estimate, the " + PRINT_PARAM_STRING("stds") + " parameter " + "allows to save the prediction uncertainties: " + "\n\n" + + PRINT_CALL("bayesian_linear_regression", "input_model", + "bayesian_linear_regression_model", "test", "test", + "predictions", "test_predictions", "stds", "stds"), + SEE_ALSO("Bayesian Interpolation", + "https://authors.library.caltech.edu/13792/1/MACnc92a.pdf"), + SEE_ALSO("Bayesian Linear Regression, Section 3.3", + "MLA Bishop, Christopher M. Pattern Recognition and Machine " + "Learning. New York :Springer, 2006, section 3.3."), + SEE_ALSO("mlpack::regression::BayesianLinearRegression C++ class " + "documentation", + "@doxygen/classmlpack_1_1regression_1_1BayesianLinearRegression.html")); + +PARAM_MATRIX_IN("input", "Matrix of covariates (X).", "i"); + +PARAM_ROW_IN("responses", "Matrix of responses/observations (y).", "r"); + +PARAM_MODEL_IN(BayesianLinearRegression, "input_model", "Trained " + "BayesianLinearRegression model to use.", "m"); + +PARAM_MODEL_OUT(BayesianLinearRegression, "output_model", "Output " + "BayesianLinearRegression model.", "M"); + +PARAM_MATRIX_IN("test", "Matrix containing points to regress on (test " + "points).", "t"); + +PARAM_MATRIX_OUT("predictions", "If --test_file is specified, this " + "file is where the predicted responses will be saved.", "o"); + +PARAM_MATRIX_OUT("stds", "If specified, this is where the standard deviations " + "of the predictive distribution will be saved.", "u"); + +PARAM_FLAG("center", "Center the data and fit the intercept if enabled.", "c"); + +PARAM_FLAG("scale", "Scale each feature by their standard deviations if " + "enabled.", "s"); + +static void mlpackMain() +{ + bool center = IO::GetParam("center"); + bool scale = IO::GetParam("scale"); + + // Check parameters -- make sure everything given makes sense. + RequireOnlyOnePassed({"input", "input_model"}, true); + if (IO::HasParam("input")) + { + RequireOnlyOnePassed({"responses"}, true, "if input data is specified, " + "responses must also be specified"); + } + ReportIgnoredParam({{"input", false }}, "responses"); + + RequireAtLeastOnePassed({"predictions", "output_model", "stds"}, false, + "no results will be saved"); + + // Ignore out_predictions unless test is specified. + ReportIgnoredParam({{"test", false}}, "predictions"); + + BayesianLinearRegression* bayesLinReg; + if (IO::HasParam("input")) + { + Log::Info << "input detected " << std::endl; + // Initialize the object. + bayesLinReg = new BayesianLinearRegression(center, scale); + + // Load covariates. We can avoid LARS transposing our data by choosing to + // not transpose this data (that's why we used PARAM_TMATRIX_IN). + mat matX = std::move(IO::GetParam("input")); + + // Load responses. The responses should be a one-dimensional vector, and it + // seems more likely that these will be stored with one response per line + // (one per row). So we should not transpose upon loading. + arma::rowvec responses = std::move( + IO::GetParam("responses")); + + if (responses.n_elem != matX.n_cols) + { + delete bayesLinReg; + Log::Fatal << "Number of responses must be equal to number of rows of X!" + << endl; + } + + arma::rowvec predictionsTrain; + // The Train method is ready to take data in column-major format. + bayesLinReg->Train(matX, responses); + } + else // We must have --input_model_file. + { + bayesLinReg = IO::GetParam("input_model"); + } + + if (IO::HasParam("test")) + { + Log::Info << "Regressing on test points." << endl; + // Load test points. + mat testPoints = std::move(IO::GetParam("test")); + arma::rowvec predictions; + + if (IO::HasParam("stds")) + { + arma::rowvec std; + bayesLinReg->Predict(testPoints, predictions, std); + + // Save the standard deviation of the test points (one per line). + IO::GetParam("stds") = std::move(std); + } + else + { + bayesLinReg->Predict(testPoints, predictions); + } + + // Save test predictions (one per line). + IO::GetParam("predictions") = std::move(predictions); + } + + IO::GetParam("output_model") = bayesLinReg; +} diff --git a/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp b/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp index 9d22940457..6a160a48ac 100644 --- a/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp @@ -38,13 +38,17 @@ using namespace mlpack::ann; * } * @endcode * + * @tparam OutputLayerType The output layer type of the network. + * @tparam InitType The initialization type used for the network. * @tparam CompleteNetworkType The type of network used for full dueling dqn. * @tparam FeatureNetworkType The type of network used for feature network. * @tparam AdvantageNetworkType The type of network used for advantage network. * @tparam ValueNetworkType The type of network used for value network. */ template < - typename CompleteNetworkType = FFN, GaussianInitialization>, + typename OutputLayerType = EmptyLoss<>, + typename InitType = GaussianInitialization, + typename CompleteNetworkType = FFN, typename FeatureNetworkType = Sequential<>, typename AdvantageNetworkType = Sequential<>, typename ValueNetworkType = Sequential<> @@ -75,13 +79,17 @@ class DuelingDQN * @param h2 Number of neurons in hiddenlayer-2. * @param outputDim Number of neurons in output layer. * @param isNoisy Specifies whether the network needs to be of type noisy. + * @param init Specifies the initialization rule for the network. + * @param outputLayer Specifies the output layer type for network. */ DuelingDQN(const int inputDim, const int h1, const int h2, const int outputDim, - const bool isNoisy = false): - completeNetwork(EmptyLoss<>(), GaussianInitialization(0, 0.001)), + const bool isNoisy = false, + InitType init = InitType(), + OutputLayerType outputLayer = OutputLayerType()): + completeNetwork(outputLayer, init), isNoisy(isNoisy) { featureNetwork = new Sequential<>(); @@ -125,13 +133,21 @@ class DuelingDQN this->ResetParameters(); } - DuelingDQN(FeatureNetworkType featureNetwork, - AdvantageNetworkType advantageNetwork, - ValueNetworkType valueNetwork, + /** + * Construct an instance of DuelingDQN class from a pre-constructed network. + * + * @param featureNetwork The feature network to be used by DuelingDQN class. + * @param advantageNetwork The advantage network to be used by DuelingDQN class. + * @param valueNetwork The value network to be used by DuelingDQN class. + * @param isNoisy Specifies whether the network needs to be of type noisy. + */ + DuelingDQN(FeatureNetworkType& featureNetwork, + AdvantageNetworkType& advantageNetwork, + ValueNetworkType& valueNetwork, const bool isNoisy = false): - featureNetwork(std::move(featureNetwork)), - advantageNetwork(std::move(advantageNetwork)), - valueNetwork(std::move(valueNetwork)), + featureNetwork(featureNetwork), + advantageNetwork(advantageNetwork), + valueNetwork(valueNetwork), isNoisy(isNoisy) { concat = new Concat<>(true); diff --git a/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp b/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp index 211df0649d..818e004a4d 100644 --- a/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp @@ -24,10 +24,15 @@ namespace rl { using namespace mlpack::ann; /** + * @tparam OutputLayerType The output layer type of the network. + * @tparam InitType The initialization type used for the network. * @tparam NetworkType The type of network used for simple dqn. */ -template , - GaussianInitialization>> +template< + typename OutputLayerType = MeanSquaredError<>, + typename InitType = GaussianInitialization, + typename NetworkType = FFN +> class SimpleDQN { public: @@ -45,13 +50,17 @@ class SimpleDQN * @param h2 Number of neurons in hiddenlayer-2. * @param outputDim Number of neurons in output layer. * @param isNoisy Specifies whether the network needs to be of type noisy. + * @param init Specifies the initialization rule for the network. + * @param outputLayer Specifies the output layer type for network. */ SimpleDQN(const int inputDim, const int h1, const int h2, const int outputDim, - const bool isNoisy = false): - network(MeanSquaredError<>(), GaussianInitialization(0, 0.001)), + const bool isNoisy = false, + InitType init = InitType(), + OutputLayerType outputLayer = OutputLayerType()): + network(outputLayer, init), isNoisy(isNoisy) { network.Add(new Linear<>(inputDim, h1)); @@ -72,8 +81,14 @@ class SimpleDQN } } - SimpleDQN(NetworkType network, const bool isNoisy = false): - network(std::move(network)), + /** + * Construct an instance of SimpleDQN class from a pre-constructed network. + * + * @param network The network to be used by SimpleDQN class. + * @param isNoisy Specifies whether the network needs to be of type noisy. + */ + SimpleDQN(NetworkType& network, const bool isNoisy = false): + network(network), isNoisy(isNoisy) { /* Nothing to do here. */ } diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index 38110b841e..918b33666d 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -1,19 +1,10 @@ # mlpack test executable. add_executable(mlpack_test - akfn_test.cpp - aknn_test.cpp - ann_dist_test.cpp - ann_layer_test.cpp - ann_regularizer_test.cpp - ann_test_tools.hpp - ann_visitor_test.cpp arma_extend_test.cpp - armadillo_svd_test.cpp async_learning_test.cpp augmented_rnns_tasks_test.cpp - bias_svd_test.cpp binarize_test.cpp - block_krylov_svd_test.cpp + bayesian_linear_regression_test.cpp callback_test.cpp cf_test.cpp cli_binding_test.cpp @@ -22,8 +13,6 @@ add_executable(mlpack_test cv_test.cpp dbscan_test.cpp dcgan_test.cpp - decision_stump_test.cpp - decision_tree_test.cpp det_test.cpp distribution_test.cpp drusilla_select_test.cpp @@ -43,9 +32,7 @@ add_executable(mlpack_test kernel_pca_test.cpp kernel_test.cpp kernel_traits_test.cpp - kfn_test.cpp kmeans_test.cpp - knn_test.cpp krann_search_test.cpp ksinit_test.cpp lars_test.cpp @@ -53,7 +40,6 @@ add_executable(mlpack_test lin_alg_test.cpp linear_svm_test.cpp lmnn_test.cpp - load_save_test.cpp local_coordinate_coding_test.cpp log_test.cpp logistic_regression_test.cpp @@ -77,16 +63,13 @@ add_executable(mlpack_test python_binding_test.cpp q_learning_test.cpp qdafn_test.cpp - quic_svd_test.cpp radical_test.cpp random_forest_test.cpp random_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 reward_clipping_test.cpp rl_components_test.cpp scaling_test.cpp @@ -101,9 +84,6 @@ add_executable(mlpack_test split_data_test.cpp string_encoding_test.cpp sumtree_test.cpp - svd_batch_test.cpp - svd_incremental_test.cpp - svdplusplus_test.cpp termination_policy_test.cpp test_function_tools.hpp test_tools.hpp @@ -114,11 +94,9 @@ add_executable(mlpack_test union_find_test.cpp vantage_point_tree_test.cpp wgan_test.cpp - main_tests/approx_kfn_test.cpp + main_tests/bayesian_linear_regression_test.cpp main_tests/cf_test.cpp main_tests/dbscan_test.cpp - main_tests/decision_stump_test.cpp - main_tests/decision_tree_test.cpp main_tests/det_test.cpp main_tests/emst_test.cpp main_tests/fastmks_test.cpp @@ -133,9 +111,7 @@ add_executable(mlpack_test main_tests/hoeffding_tree_test.cpp main_tests/kde_test.cpp main_tests/kernel_pca_test.cpp - main_tests/kfn_test.cpp main_tests/kmeans_test.cpp - main_tests/knn_test.cpp main_tests/krann_test.cpp main_tests/linear_svm_test.cpp main_tests/lmnn_test.cpp @@ -162,17 +138,43 @@ add_executable(mlpack_test add_executable(mlpack_catch_test activation_functions_test.cpp adaboost_test.cpp + akfn_test.cpp + aknn_test.cpp + ann_dist_test.cpp + ann_layer_test.cpp + ann_regularizer_test.cpp + ann_test_tools.hpp + ann_visitor_test.cpp + armadillo_svd_test.cpp + bias_svd_test.cpp + block_krylov_svd_test.cpp convolutional_network_test.cpp convolution_test.cpp + decision_stump_test.cpp + decision_tree_test.cpp image_load_test.cpp + kfn_test.cpp + knn_test.cpp linear_regression_test.cpp + load_save_test.cpp main.cpp serialization_catch.cpp serialization_catch.hpp softmax_regression_test.cpp + quic_svd_test.cpp + randomized_svd_test.cpp + regularized_svd_test.cpp + svd_batch_test.cpp + svd_incremental_test.cpp + svdplusplus_test.cpp test_catch_tools.hpp main_tests/adaboost_test.cpp + main_tests/approx_kfn_test.cpp + main_tests/decision_stump_test.cpp + main_tests/decision_tree_test.cpp main_tests/image_converter_test.cpp + main_tests/kfn_test.cpp + main_tests/knn_test.cpp main_tests/linear_regression_test.cpp main_tests/softmax_regression_test.cpp main_tests/test_helper.hpp @@ -223,10 +225,7 @@ add_custom_command(TARGET mlpack_test # The list of long running parallel tests set(parallel_tests - "ANNLayerTest;" "AsyncLearningTest;" - "SVDIncrementalTest;" - "SVDBatchTest;" "LocalCoordinateCodingTest;" "FeedForwardNetworkTest;" "RecurrentNetworkTest;" diff --git a/src/mlpack/tests/akfn_test.cpp b/src/mlpack/tests/akfn_test.cpp index 48d3022939..162817656c 100644 --- a/src/mlpack/tests/akfn_test.cpp +++ b/src/mlpack/tests/akfn_test.cpp @@ -11,8 +11,8 @@ #include #include #include -#include -#include "test_tools.hpp" +#include "test_catch_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::neighbor; @@ -20,20 +20,18 @@ using namespace mlpack::tree; using namespace mlpack::metric; using namespace mlpack::bound; -BOOST_AUTO_TEST_SUITE(AKFNTest); - /** * Test the dual-tree furthest-neighbors method with different values for * epsilon. This uses both a query and reference dataset. * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(ApproxVsExact1) +TEST_CASE("AKFNApproxVsExact1", "[AKFNTest]") { arma::mat dataset; if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KFN exact(dataset); arma::Mat neighborsExact; @@ -81,12 +79,12 @@ BOOST_AUTO_TEST_CASE(ApproxVsExact1) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(ApproxVsExact2) +TEST_CASE("AKFNApproxVsExact2", "[AKFNTest]") { arma::mat dataset; if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KFN exact(dataset); arma::Mat neighborsExact; @@ -108,12 +106,12 @@ BOOST_AUTO_TEST_CASE(ApproxVsExact2) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(SingleTreeVsExact) +TEST_CASE("AKFNSingleTreeVsExact", "[AKFNTest]") { arma::mat dataset; if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KFN exact(dataset); arma::Mat neighborsExact; @@ -135,7 +133,7 @@ BOOST_AUTO_TEST_CASE(SingleTreeVsExact) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) +TEST_CASE("AKFNSingleCoverTreeTest", "[AKFNTest]") { arma::mat dataset; dataset.randu(75, 1000); // 75 dimensional, 1000 points. @@ -165,7 +163,7 @@ BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(DualCoverTreeTest) +TEST_CASE("AKFNDualCoverTreeTest", "[AKFNTest]") { arma::mat dataset; data::Load("test_data_3_1000.csv", dataset); @@ -195,7 +193,7 @@ BOOST_AUTO_TEST_CASE(DualCoverTreeTest) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(SingleBallTreeTest) +TEST_CASE("AKFNSingleBallTreeTest", "[AKFNTest]") { arma::mat dataset; dataset.randu(75, 1000); // 75 dimensional, 1000 points. @@ -222,7 +220,7 @@ BOOST_AUTO_TEST_CASE(SingleBallTreeTest) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(DualBallTreeTest) +TEST_CASE("AKFNDualBallTreeTest", "[AKFNTest]") { arma::mat dataset; data::Load("test_data_3_1000.csv", dataset); @@ -242,4 +240,3 @@ BOOST_AUTO_TEST_CASE(DualBallTreeTest) REQUIRE_RELATIVE_ERR(distancesBallTree(i), distancesExact(i), 0.05); } -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/aknn_test.cpp b/src/mlpack/tests/aknn_test.cpp index c9a584883e..e77721ceac 100644 --- a/src/mlpack/tests/aknn_test.cpp +++ b/src/mlpack/tests/aknn_test.cpp @@ -14,8 +14,8 @@ #include #include #include -#include -#include "test_tools.hpp" +#include "test_catch_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::neighbor; @@ -23,20 +23,18 @@ using namespace mlpack::tree; using namespace mlpack::metric; using namespace mlpack::bound; -BOOST_AUTO_TEST_SUITE(AKNNTest); - /** * Test the dual-tree nearest-neighbors method with different values for * epsilon. This uses both a query and reference dataset. * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(ApproxVsExact1) +TEST_CASE("AKNNApproxVsExact1", "[AKNNTest]") { arma::mat dataset; if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KNN exact(dataset); arma::Mat neighborsExact; @@ -84,12 +82,12 @@ BOOST_AUTO_TEST_CASE(ApproxVsExact1) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(ApproxVsExact2) +TEST_CASE("AKNNApproxVsExact2", "[AKNNTest]") { arma::mat dataset; if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KNN exact(dataset); arma::Mat neighborsExact; @@ -111,12 +109,12 @@ BOOST_AUTO_TEST_CASE(ApproxVsExact2) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(SingleTreeApproxVsExact) +TEST_CASE("AKNNSingleTreeApproxVsExact", "[AKNNTest]") { arma::mat dataset; if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KNN exact(dataset); arma::Mat neighborsExact; @@ -138,7 +136,7 @@ BOOST_AUTO_TEST_CASE(SingleTreeApproxVsExact) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) +TEST_CASE("AKNNSingleCoverTreeTest", "[AKNNTest]") { arma::mat dataset; dataset.randu(75, 1000); // 75 dimensional, 1000 points. @@ -168,7 +166,7 @@ BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(DualCoverTreeTest) +TEST_CASE("AKNNDualCoverTreeTest", "[AKNNTest]") { arma::mat dataset; data::Load("test_data_3_1000.csv", dataset); @@ -195,7 +193,7 @@ BOOST_AUTO_TEST_CASE(DualCoverTreeTest) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(SingleBallTreeTest) +TEST_CASE("AKNNSingleBallTreeTest", "[AKNNTest]") { arma::mat dataset; dataset.randu(50, 300); // 50 dimensional, 300 points. @@ -222,7 +220,7 @@ BOOST_AUTO_TEST_CASE(SingleBallTreeTest) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(DualBallTreeTest) +TEST_CASE("AKNNDualBallTreeTest", "[AKNNTest]") { arma::mat dataset; data::Load("test_data_3_1000.csv", dataset); @@ -249,7 +247,7 @@ BOOST_AUTO_TEST_CASE(DualBallTreeTest) * * Errors are produced if the results are not according to relative error. */ -BOOST_AUTO_TEST_CASE(SingleSpillTreeTest) +TEST_CASE("AKNNSingleSpillTreeTest", "[AKNNTest]") { arma::mat dataset; dataset.randu(50, 300); // 50 dimensional, 300 points. @@ -286,7 +284,7 @@ BOOST_AUTO_TEST_CASE(SingleSpillTreeTest) /** * Make sure sparse nearest neighbors works with kd trees. */ -BOOST_AUTO_TEST_CASE(SparseKNNKDTreeTest) +TEST_CASE("AKNNSparseKNNKDTreeTest", "[AKNNTest]") { // The dimensionality of these datasets must be high so that the probability // of a completely empty point is very low. In this case, with dimensionality @@ -321,7 +319,7 @@ BOOST_AUTO_TEST_CASE(SparseKNNKDTreeTest) * Ensure that we can build an NSModel and get correct * results. */ -BOOST_AUTO_TEST_CASE(KNNModelTest) +TEST_CASE("AKNNModelTest", "[AKNNTest]") { typedef NSModel KNNModel; @@ -385,12 +383,12 @@ BOOST_AUTO_TEST_CASE(KNNModelTest) models[i].Search(std::move(queryCopy), 3, neighborsApprox, distancesApprox); - BOOST_REQUIRE_EQUAL(neighborsApprox.n_rows, neighborsExact.n_rows); - BOOST_REQUIRE_EQUAL(neighborsApprox.n_cols, neighborsExact.n_cols); - BOOST_REQUIRE_EQUAL(neighborsApprox.n_elem, neighborsExact.n_elem); - BOOST_REQUIRE_EQUAL(distancesApprox.n_rows, distancesExact.n_rows); - BOOST_REQUIRE_EQUAL(distancesApprox.n_cols, distancesExact.n_cols); - BOOST_REQUIRE_EQUAL(distancesApprox.n_elem, distancesExact.n_elem); + REQUIRE(neighborsApprox.n_rows == neighborsExact.n_rows); + REQUIRE(neighborsApprox.n_cols == neighborsExact.n_cols); + REQUIRE(neighborsApprox.n_elem == neighborsExact.n_elem); + REQUIRE(distancesApprox.n_rows == distancesExact.n_rows); + REQUIRE(distancesApprox.n_cols == distancesExact.n_cols); + REQUIRE(distancesApprox.n_elem == distancesExact.n_elem); for (size_t k = 0; k < distancesApprox.n_elem; ++k) REQUIRE_RELATIVE_ERR(distancesApprox[k], distancesExact[k], 0.05); } @@ -401,7 +399,7 @@ BOOST_AUTO_TEST_CASE(KNNModelTest) * Ensure that we can build an NSModel and get correct * results, in the case where the reference set is the same as the query set. */ -BOOST_AUTO_TEST_CASE(KNNModelMonochromaticTest) +TEST_CASE("AKNNModelMonochromaticTest", "[AKNNTest]") { typedef NSModel KNNModel; @@ -460,16 +458,14 @@ BOOST_AUTO_TEST_CASE(KNNModelMonochromaticTest) models[i].Search(3, neighborsApprox, distancesApprox); - BOOST_REQUIRE_EQUAL(neighborsApprox.n_rows, neighborsExact.n_rows); - BOOST_REQUIRE_EQUAL(neighborsApprox.n_cols, neighborsExact.n_cols); - BOOST_REQUIRE_EQUAL(neighborsApprox.n_elem, neighborsExact.n_elem); - BOOST_REQUIRE_EQUAL(distancesApprox.n_rows, distancesExact.n_rows); - BOOST_REQUIRE_EQUAL(distancesApprox.n_cols, distancesExact.n_cols); - BOOST_REQUIRE_EQUAL(distancesApprox.n_elem, distancesExact.n_elem); + REQUIRE(neighborsApprox.n_rows == neighborsExact.n_rows); + REQUIRE(neighborsApprox.n_cols == neighborsExact.n_cols); + REQUIRE(neighborsApprox.n_elem == neighborsExact.n_elem); + REQUIRE(distancesApprox.n_rows == distancesExact.n_rows); + REQUIRE(distancesApprox.n_cols == distancesExact.n_cols); + REQUIRE(distancesApprox.n_elem == distancesExact.n_elem); for (size_t k = 0; k < distancesApprox.n_elem; ++k) REQUIRE_RELATIVE_ERR(distancesApprox[k], distancesExact[k], 0.05); } } } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/ann_dist_test.cpp b/src/mlpack/tests/ann_dist_test.cpp index 702414759a..ea1d8605a1 100644 --- a/src/mlpack/tests/ann_dist_test.cpp +++ b/src/mlpack/tests/ann_dist_test.cpp @@ -16,20 +16,18 @@ #include #include -#include -#include "test_tools.hpp" +#include "catch.hpp" +#include "test_catch_tools.hpp" #include using namespace mlpack; using namespace mlpack::ann; -BOOST_AUTO_TEST_SUITE(ANNDistTest); - /** * Simple bernoulli distribution module test. */ -BOOST_AUTO_TEST_CASE(SimpleBernoulliDistributionTest) +TEST_CASE("SimpleBernoulliDistributionTest", "[ANNDistTest]") { arma::mat param = arma::mat("1 1 0"); BernoulliDistribution<> module(param, false); @@ -43,7 +41,7 @@ BOOST_AUTO_TEST_CASE(SimpleBernoulliDistributionTest) /** * Jacobian bernoulli distribution module test when we don't apply logistic. */ -BOOST_AUTO_TEST_CASE(JacobianBernoulliDistributionTest) +TEST_CASE("JacobianBernoulliDistributionTest", "[ANNDistTest]") { for (size_t i = 0; i < 5; ++i) { @@ -78,15 +76,14 @@ BOOST_AUTO_TEST_CASE(JacobianBernoulliDistributionTest) } module.LogProbBackward(target, jacobianB); - BOOST_REQUIRE_LE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))), - 1e-5); + REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 1e-5); } } /** * Jacobian bernoulli distribution module test when we apply logistic. */ -BOOST_AUTO_TEST_CASE(JacobianBernoulliDistributionLogisticTest) +TEST_CASE("JacobianBernoulliDistributionLogisticTest", "[ANNDistTest]") { for (size_t i = 0; i < 5; ++i) { @@ -124,15 +121,14 @@ BOOST_AUTO_TEST_CASE(JacobianBernoulliDistributionLogisticTest) } module.LogProbBackward(target, jacobianB); - BOOST_REQUIRE_LE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))), - 3e-5); + REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 3e-5); } } /** * Normal Distribution module test. */ -BOOST_AUTO_TEST_CASE(NormalDistributionTest) +TEST_CASE("NormalDistributionTest", "[ANNDistTest]") { arma::vec mu = {1.1, 1.2, 1.5, 1.7}; arma::vec sigma = {0.1, 0.11, 0.5, 0.23}; @@ -145,29 +141,29 @@ BOOST_AUTO_TEST_CASE(NormalDistributionTest) normalDist.LogProbability(x, prob); // Testing output of log probability for some random mu, sigma and x. - BOOST_REQUIRE_CLOSE(prob[0], 1.2586464, 1e-3); - BOOST_REQUIRE_CLOSE(prob[1], 0.8751131, 1e-3); - BOOST_REQUIRE_CLOSE(prob[2], -0.30579138, 1e-3); - BOOST_REQUIRE_CLOSE(prob[3], -5.498411, 1e-3); + REQUIRE(prob[0] == Approx(1.2586464).epsilon(1e-5)); + REQUIRE(prob[1] == Approx(0.8751131).epsilon(1e-5)); + REQUIRE(prob[2] == Approx(-0.30579138).epsilon(1e-5)); + REQUIRE(prob[3] == Approx(-5.498411).epsilon(1e-5)); arma::vec dmu, dsigma; normalDist.ProbBackward(x, dmu, dsigma); // Testing output of dmu and dsigma for some random mu, sigma and x. - BOOST_REQUIRE_CLOSE(dmu[0], -17.603287, 1e-3); - BOOST_REQUIRE_CLOSE(dsigma[0], -26.40487, 1e-3); - BOOST_REQUIRE_CLOSE(dmu[1], -19.827663, 1e-3); - BOOST_REQUIRE_CLOSE(dsigma[1], -3.7852707, 1e-3); - BOOST_REQUIRE_CLOSE(dmu[2], 0.5892323, 1e-3); - BOOST_REQUIRE_CLOSE(dsigma[2], -1.2373875, 1e-3); - BOOST_REQUIRE_CLOSE(dmu[3], 0.061901994, 1e-3); - BOOST_REQUIRE_CLOSE(dsigma[3], 0.19751444, 1e-3); + REQUIRE(dmu[0] == Approx(-17.603287).epsilon(1e-5)); + REQUIRE(dsigma[0] == Approx(-26.40487).epsilon(1e-5)); + REQUIRE(dmu[1] == Approx(-19.827663).epsilon(1e-5)); + REQUIRE(dsigma[1] == Approx(-3.7852707).epsilon(1e-5)); + REQUIRE(dmu[2] == Approx(0.5892323).epsilon(1e-5)); + REQUIRE(dsigma[2] == Approx(-1.2373875).epsilon(1e-5)); + REQUIRE(dmu[3] == Approx(0.061901994).epsilon(1e-5)); + REQUIRE(dsigma[3] == Approx(0.19751444).epsilon(1e-5)); } /** * Jacobian Normal Distribution module test for mean. */ -BOOST_AUTO_TEST_CASE(JacobianNormalDistributionMeanTest) +TEST_CASE("JacobianNormalDistributionMeanTest", "[ANNDistTest]") { for (size_t i = 0; i < 5; i++) { @@ -226,15 +222,14 @@ BOOST_AUTO_TEST_CASE(JacobianNormalDistributionMeanTest) jacobianB.col(k) = deltaMu % deriv; } - BOOST_REQUIRE_LE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))), - 5e-3); + REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 5e-3); } } /** * Jacobian Normal Distribution module test for standard deviation. */ -BOOST_AUTO_TEST_CASE(JacobianNormalDistributionStandardDeviationTest) +TEST_CASE("JacobianNormalDistributionStandardDeviationTest", "[ANNDistTest]") { for (size_t i = 0; i < 5; i++) { @@ -293,10 +288,6 @@ BOOST_AUTO_TEST_CASE(JacobianNormalDistributionStandardDeviationTest) jacobianB.col(k) = deltaSigma % deriv; } - BOOST_REQUIRE_LE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))), - 5e-3); + REQUIRE(arma::max(arma::max(arma::abs(jacobianA - jacobianB))) <= 5e-3); } } - - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 8cd06e56f5..29e16273b8 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -15,26 +15,26 @@ #include #include #include +#include #include #include #include +#include #include #include -#include -#include "test_tools.hpp" +#include "test_catch_tools.hpp" +#include "catch.hpp" #include "ann_test_tools.hpp" -#include "serialization.hpp" +#include "serialization_catch.hpp" using namespace mlpack; using namespace mlpack::ann; -BOOST_AUTO_TEST_SUITE(ANNLayerTest); - /** * Simple add module test. */ -BOOST_AUTO_TEST_CASE(SimpleAddLayerTest) +TEST_CASE("SimpleAddLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; Add<> module(10); @@ -43,27 +43,27 @@ BOOST_AUTO_TEST_CASE(SimpleAddLayerTest) // Test the Forward function. input = arma::zeros(10, 1); module.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(module.Parameters()), arma::accu(output)); + REQUIRE(arma::accu(module.Parameters()) == arma::accu(output)); // Test the Backward function. module.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(output), arma::accu(delta)); + REQUIRE(arma::accu(output) == arma::accu(delta)); // Test the forward function. input = arma::ones(10, 1); module.Forward(input, output); - BOOST_REQUIRE_CLOSE(10 + arma::accu(module.Parameters()), - arma::accu(output), 1e-3); + REQUIRE(10 + arma::accu(module.Parameters()) == + Approx(arma::accu(output)).epsilon(1e-5)); // Test the backward function. module.Backward(input, output, delta); - BOOST_REQUIRE_CLOSE(arma::accu(output), arma::accu(delta), 1e-3); + REQUIRE(arma::accu(output) == Approx(arma::accu(delta)).epsilon(1e-5)); } /** * Jacobian add module test. */ -BOOST_AUTO_TEST_CASE(JacobianAddLayerTest) +TEST_CASE("JacobianAddLayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -75,14 +75,14 @@ BOOST_AUTO_TEST_CASE(JacobianAddLayerTest) module.Parameters().randu(); double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } /** * Add layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientAddLayerTest) +TEST_CASE("GradientAddLayerTest", "[ANNLayerTest]") { // Add function gradient instantiation. struct GradientFunction @@ -119,26 +119,26 @@ BOOST_AUTO_TEST_CASE(GradientAddLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Test that the function that can access the outSize parameter of * the Add layer works. */ -BOOST_AUTO_TEST_CASE(AddLayerParametersTest) +TEST_CASE("AddLayerParametersTest", "[ANNLayerTest]") { // Parameter : outSize. Add<> layer(7); // Make sure we can get the parameter successfully. - BOOST_REQUIRE_EQUAL(layer.OutputSize(), 7); + REQUIRE(layer.OutputSize() == 7); } /** * Simple constant module test. */ -BOOST_AUTO_TEST_CASE(SimpleConstantLayerTest) +TEST_CASE("SimpleConstantLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; Constant<> module(10, 3.0); @@ -146,26 +146,26 @@ BOOST_AUTO_TEST_CASE(SimpleConstantLayerTest) // Test the Forward function. input = arma::zeros(10, 1); module.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 30.0); + REQUIRE(arma::accu(output) == 30.0); // Test the Backward function. module.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(arma::accu(delta) == 0); // Test the forward function. input = arma::ones(10, 1); module.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 30.0); + REQUIRE(arma::accu(output) == 30.0); // Test the backward function. module.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(arma::accu(delta) == 0); } /** * Jacobian constant module test. */ -BOOST_AUTO_TEST_CASE(JacobianConstantLayerTest) +TEST_CASE("JacobianConstantLayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -176,7 +176,7 @@ BOOST_AUTO_TEST_CASE(JacobianConstantLayerTest) Constant<> module(elements, 1.0); double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } @@ -184,19 +184,19 @@ BOOST_AUTO_TEST_CASE(JacobianConstantLayerTest) * Test that the function that can access the outSize parameter of the * Constant layer works. */ -BOOST_AUTO_TEST_CASE(ConstantLayerParametersTest) +TEST_CASE("ConstantLayerParametersTest", "[ANNLayerTest]") { // Parameter : outSize. Constant<> layer(7); // Make sure we can get the parameter successfully. - BOOST_REQUIRE_EQUAL(layer.OutSize(), 7); + REQUIRE(layer.OutSize() == 7); } /** * Simple dropout module test. */ -BOOST_AUTO_TEST_CASE(SimpleDropoutLayerTest) +TEST_CASE("SimpleDropoutLayerTest", "[ANNLayerTest]") { // Initialize the probability of setting a value to zero. const double p = 0.2; @@ -211,19 +211,17 @@ BOOST_AUTO_TEST_CASE(SimpleDropoutLayerTest) // Test the Forward function. arma::mat output; module.Forward(input, output); - BOOST_REQUIRE_LE( - arma::as_scalar(arma::abs(arma::mean(output) - (1 - p))), 0.05); + REQUIRE(arma::as_scalar(arma::abs(arma::mean(output) - (1 - p))) <= 0.05); // Test the Backward function. arma::mat delta; module.Backward(input, input, delta); - BOOST_REQUIRE_LE( - arma::as_scalar(arma::abs(arma::mean(delta) - (1 - p))), 0.05); + REQUIRE(arma::as_scalar(arma::abs(arma::mean(delta) - (1 - p))) <= 0.05); // Test the Forward function. module.Deterministic() = true; module.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(input), arma::accu(output)); + REQUIRE(arma::accu(input) == arma::accu(output)); } /** @@ -231,7 +229,7 @@ BOOST_AUTO_TEST_CASE(SimpleDropoutLayerTest) * validate that the layer is producing approximately the correct number of * ones. */ -BOOST_AUTO_TEST_CASE(DropoutProbabilityTest) +TEST_CASE("DropoutProbabilityTest", "[ANNLayerTest]") { arma::mat input = arma::ones(1500, 1); const size_t iterations = 10; @@ -257,14 +255,14 @@ BOOST_AUTO_TEST_CASE(DropoutProbabilityTest) iterations; const double error = fabs(nonzeroCount - expected) / expected; - BOOST_REQUIRE_LE(error, 0.15); + REQUIRE(error <= 0.15); } } /* * Perform dropout with probability 1 - p where p = 0, means no dropout. */ -BOOST_AUTO_TEST_CASE(NoDropoutTest) +TEST_CASE("NoDropoutTest", "[ANNLayerTest]") { arma::mat input = arma::ones(1500, 1); Dropout<> module(0); @@ -273,14 +271,14 @@ BOOST_AUTO_TEST_CASE(NoDropoutTest) arma::mat output; module.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), arma::accu(input)); + REQUIRE(arma::accu(output) == arma::accu(input)); } /* * Perform test to check whether mean and variance remain nearly same * after AlphaDropout. */ -BOOST_AUTO_TEST_CASE(SimpleAlphaDropoutLayerTest) +TEST_CASE("SimpleAlphaDropoutLayerTest", "[ANNLayerTest]") { // Initialize the probability of setting a value to alphaDash. const double p = 0.2; @@ -296,23 +294,22 @@ BOOST_AUTO_TEST_CASE(SimpleAlphaDropoutLayerTest) arma::mat output; module.Forward(input, output); // Check whether mean remains nearly same. - BOOST_REQUIRE_LE( - arma::as_scalar(arma::abs(arma::mean(input) - arma::mean(output))), 0.1); + REQUIRE(arma::as_scalar(arma::abs(arma::mean(input) - arma::mean(output))) <= + 0.1); // Check whether variance remains nearly same. - BOOST_REQUIRE_LE( - arma::as_scalar(arma::abs(arma::var(input) - arma::var(output))), 0.1); + REQUIRE(arma::as_scalar(arma::abs(arma::var(input) - arma::var(output))) <= + 0.1); // Test the Backward function when training phase. arma::mat delta; module.Backward(input, input, delta); - BOOST_REQUIRE_LE( - arma::as_scalar(arma::abs(arma::mean(delta) - 0)), 0.05); + REQUIRE(arma::as_scalar(arma::abs(arma::mean(delta) - 0)) <= 0.05); // Test the Forward function when testing phase. module.Deterministic() = true; module.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(input), arma::accu(output)); + REQUIRE(arma::accu(input) == arma::accu(output)); } /** @@ -320,7 +317,7 @@ BOOST_AUTO_TEST_CASE(SimpleAlphaDropoutLayerTest) * and validate that the layer is producing approximately the correct number * of ones. */ -BOOST_AUTO_TEST_CASE(AlphaDropoutProbabilityTest) +TEST_CASE("AlphaDropoutProbabilityTest", "[ANNLayerTest]") { arma::mat input = arma::ones(1500, 1); const size_t iterations = 10; @@ -348,7 +345,7 @@ BOOST_AUTO_TEST_CASE(AlphaDropoutProbabilityTest) const double error = fabs(nonzeroCount - expected) / expected; - BOOST_REQUIRE_LE(error, 0.15); + REQUIRE(error <= 0.15); } } @@ -356,7 +353,7 @@ BOOST_AUTO_TEST_CASE(AlphaDropoutProbabilityTest) * Perform AlphaDropout with probability 1 - p where p = 0, * means no AlphaDropout. */ -BOOST_AUTO_TEST_CASE(NoAlphaDropoutTest) +TEST_CASE("NoAlphaDropoutTest", "[ANNLayerTest]") { arma::mat input = arma::ones(1500, 1); AlphaDropout<> module(0); @@ -365,13 +362,13 @@ BOOST_AUTO_TEST_CASE(NoAlphaDropoutTest) arma::mat output; module.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), arma::accu(input)); + REQUIRE(arma::accu(output) == arma::accu(input)); } /** * Simple linear module test. */ -BOOST_AUTO_TEST_CASE(SimpleLinearLayerTest) +TEST_CASE("SimpleLinearLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; Linear<> module(10, 10); @@ -381,19 +378,19 @@ BOOST_AUTO_TEST_CASE(SimpleLinearLayerTest) // Test the Forward function. input = arma::zeros(10, 1); module.Forward(input, output); - BOOST_REQUIRE_CLOSE(arma::accu( - module.Parameters().submat(100, 0, module.Parameters().n_elem - 1, 0)), - arma::accu(output), 1e-3); + REQUIRE(arma::accu(module.Parameters().submat(100, + 0, module.Parameters().n_elem - 1, 0)) == + Approx(arma::accu(output)).epsilon(1e-5)); // Test the Backward function. module.Backward(input, input, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(arma::accu(delta) == 0); } /** * Jacobian linear module test. */ -BOOST_AUTO_TEST_CASE(JacobianLinearLayerTest) +TEST_CASE("JacobianLinearLayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -407,14 +404,14 @@ BOOST_AUTO_TEST_CASE(JacobianLinearLayerTest) module.Parameters().randu(); double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } /** * Linear layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientLinearLayerTest) +TEST_CASE("GradientLinearLayerTest", "[ANNLayerTest]") { // Linear function gradient instantiation. struct GradientFunction @@ -451,13 +448,13 @@ BOOST_AUTO_TEST_CASE(GradientLinearLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Simple noisy linear module test. */ -BOOST_AUTO_TEST_CASE(SimpleNoisyLinearLayerTest) +TEST_CASE("SimpleNoisyLinearLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; NoisyLinear<> module(10, 10); @@ -466,13 +463,13 @@ BOOST_AUTO_TEST_CASE(SimpleNoisyLinearLayerTest) // Test the Backward function. module.Backward(input, input, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(arma::accu(delta) == 0); } /** * Jacobian noisy linear module test. */ -BOOST_AUTO_TEST_CASE(JacobianNoisyLinearLayerTest) +TEST_CASE("JacobianNoisyLinearLayerTest", "[ANNLayerTest]") { const size_t inputElements = math::RandInt(2, 1000); const size_t outputElements = math::RandInt(2, 1000); @@ -484,13 +481,13 @@ BOOST_AUTO_TEST_CASE(JacobianNoisyLinearLayerTest) module.Parameters().randu(); double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } /** * Noisy Linear layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientNoisyLinearLayerTest) +TEST_CASE("GradientNoisyLinearLayerTest", "[ANNLayerTest]") { // Noisy linear function gradient instantiation. struct GradientFunction @@ -527,13 +524,13 @@ BOOST_AUTO_TEST_CASE(GradientNoisyLinearLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Simple linear no bias module test. */ -BOOST_AUTO_TEST_CASE(SimpleLinearNoBiasLayerTest) +TEST_CASE("SimpleLinearNoBiasLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; LinearNoBias<> module(10, 10); @@ -543,17 +540,17 @@ BOOST_AUTO_TEST_CASE(SimpleLinearNoBiasLayerTest) // Test the Forward function. input = arma::zeros(10, 1); module.Forward(input, output); - BOOST_REQUIRE_EQUAL(0, arma::accu(output)); + REQUIRE(0 == arma::accu(output)); // Test the Backward function. module.Backward(input, input, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(arma::accu(delta) == 0); } /** * Simple padding layer test. */ -BOOST_AUTO_TEST_CASE(SimplePaddingLayerTest) +TEST_CASE("SimplePaddingLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; Padding<> module(1, 2, 3, 4); @@ -561,9 +558,9 @@ BOOST_AUTO_TEST_CASE(SimplePaddingLayerTest) // Test the Forward function. input = arma::randu(10, 1); module.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(input), arma::accu(output)); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows + 3); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols + 7); + REQUIRE(arma::accu(input) == arma::accu(output)); + REQUIRE(output.n_rows == input.n_rows + 3); + REQUIRE(output.n_cols == input.n_cols + 7); // Test the Backward function. module.Backward(input, output, delta); @@ -573,7 +570,7 @@ BOOST_AUTO_TEST_CASE(SimplePaddingLayerTest) /** * Jacobian linear no bias module test. */ -BOOST_AUTO_TEST_CASE(JacobianLinearNoBiasLayerTest) +TEST_CASE("JacobianLinearNoBiasLayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -587,14 +584,14 @@ BOOST_AUTO_TEST_CASE(JacobianLinearNoBiasLayerTest) module.Parameters().randu(); double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } /** * LinearNoBias layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientLinearNoBiasLayerTest) +TEST_CASE("GradientLinearNoBiasLayerTest", "[ANNLayerTest]") { // LinearNoBias function gradient instantiation. struct GradientFunction @@ -631,13 +628,13 @@ BOOST_AUTO_TEST_CASE(GradientLinearNoBiasLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Jacobian negative log likelihood module test. */ -BOOST_AUTO_TEST_CASE(JacobianNegativeLogLikelihoodLayerTest) +TEST_CASE("JacobianNegativeLogLikelihoodLayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -651,14 +648,14 @@ BOOST_AUTO_TEST_CASE(JacobianNegativeLogLikelihoodLayerTest) target(0) = math::RandInt(1, inputElements - 1); double error = JacobianPerformanceTest(module, input, target); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } /** * Jacobian LeakyReLU module test. */ -BOOST_AUTO_TEST_CASE(JacobianLeakyReLULayerTest) +TEST_CASE("JacobianLeakyReLULayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -670,14 +667,14 @@ BOOST_AUTO_TEST_CASE(JacobianLeakyReLULayerTest) LeakyReLU<> module; double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } /** * Jacobian FlexibleReLU module test. */ -BOOST_AUTO_TEST_CASE(JacobianFlexibleReLULayerTest) +TEST_CASE("JacobianFlexibleReLULayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -689,14 +686,14 @@ BOOST_AUTO_TEST_CASE(JacobianFlexibleReLULayerTest) FlexibleReLU<> module; double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } /** * Flexible ReLU layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientFlexibleReLULayerTest) +TEST_CASE("GradientFlexibleReLULayerTest", "[ANNLayerTest]") { // Add function gradient instantiation. struct GradientFunction @@ -735,13 +732,13 @@ BOOST_AUTO_TEST_CASE(GradientFlexibleReLULayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Jacobian MultiplyConstant module test. */ -BOOST_AUTO_TEST_CASE(JacobianMultiplyConstantLayerTest) +TEST_CASE("JacobianMultiplyConstantLayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -753,14 +750,14 @@ BOOST_AUTO_TEST_CASE(JacobianMultiplyConstantLayerTest) MultiplyConstant<> module(3.0); double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } /** * Jacobian HardTanH module test. */ -BOOST_AUTO_TEST_CASE(JacobianHardTanHLayerTest) +TEST_CASE("JacobianHardTanHLayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -772,14 +769,14 @@ BOOST_AUTO_TEST_CASE(JacobianHardTanHLayerTest) HardTanH<> module; double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } /** * Simple select module test. */ -BOOST_AUTO_TEST_CASE(SimpleSelectLayerTest) +TEST_CASE("SimpleSelectLayerTest", "[ANNLayerTest]") { arma::mat outputA, outputB, input, delta; @@ -792,40 +789,40 @@ BOOST_AUTO_TEST_CASE(SimpleSelectLayerTest) // Test the Forward function. Select<> moduleA(3); moduleA.Forward(input, outputA); - BOOST_REQUIRE_EQUAL(30, arma::accu(outputA)); + REQUIRE(30 == arma::accu(outputA)); // Test the Forward function. Select<> moduleB(3, 5); moduleB.Forward(input, outputB); - BOOST_REQUIRE_EQUAL(15, arma::accu(outputB)); + REQUIRE(15 == arma::accu(outputB)); // Test the Backward function. moduleA.Backward(input, outputA, delta); - BOOST_REQUIRE_EQUAL(30, arma::accu(delta)); + REQUIRE(30 == arma::accu(delta)); // Test the Backward function. moduleB.Backward(input, outputA, delta); - BOOST_REQUIRE_EQUAL(15, arma::accu(delta)); + REQUIRE(15 == arma::accu(delta)); } /** * Test that the functions that can access the parameters of the * Select layer work. */ -BOOST_AUTO_TEST_CASE(SelectLayerParametersTest) +TEST_CASE("SelectLayerParametersTest", "[ANNLayerTest]") { // Parameter order : index, elements. Select<> layer(3, 5); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer.Index(), 3); - BOOST_REQUIRE_EQUAL(layer.NumElements(), 5); + REQUIRE(layer.Index() == 3); + REQUIRE(layer.NumElements() == 5); } /** * Simple join module test. */ -BOOST_AUTO_TEST_CASE(SimpleJoinLayerTest) +TEST_CASE("SimpleJoinLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; input = arma::ones(10, 5); @@ -833,23 +830,23 @@ BOOST_AUTO_TEST_CASE(SimpleJoinLayerTest) // Test the Forward function. Join<> module; module.Forward(input, output); - BOOST_REQUIRE_EQUAL(50, arma::accu(output)); + REQUIRE(50 == arma::accu(output)); bool b = output.n_rows == 1 || output.n_cols == 1; - BOOST_REQUIRE_EQUAL(b, true); + REQUIRE(b == true); // Test the Backward function. module.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(50, arma::accu(delta)); + REQUIRE(50 == arma::accu(delta)); b = delta.n_rows == input.n_rows && input.n_cols; - BOOST_REQUIRE_EQUAL(b, true); + REQUIRE(b == true); } /** * Simple add merge module test. */ -BOOST_AUTO_TEST_CASE(SimpleAddMergeLayerTest) +TEST_CASE("SimpleAddMergeLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; input = arma::ones(10, 1); @@ -868,18 +865,18 @@ BOOST_AUTO_TEST_CASE(SimpleAddMergeLayerTest) // Test the Forward function. module.Forward(input, output); - BOOST_REQUIRE_EQUAL(10 * numMergeModules, arma::accu(output)); + REQUIRE(10 * numMergeModules == arma::accu(output)); // Test the Backward function. module.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(output), arma::accu(delta)); + REQUIRE(arma::accu(output) == arma::accu(delta)); } } /** * Test the LSTM layer with a user defined rho parameter and without. */ -BOOST_AUTO_TEST_CASE(LSTMRrhoTest) +TEST_CASE("LSTMRrhoTest", "[ANNLayerTest]") { const size_t rho = 5; arma::cube input = arma::randu(1, 1, 5); @@ -916,7 +913,7 @@ BOOST_AUTO_TEST_CASE(LSTMRrhoTest) /** * LSTM layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientLSTMLayerTest) +TEST_CASE("GradientLSTMLayerTest", "[ANNLayerTest]") { // LSTM function gradient instantiation. struct GradientFunction @@ -954,37 +951,37 @@ BOOST_AUTO_TEST_CASE(GradientLSTMLayerTest) arma::cube input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Test that the functions that can modify and access the parameters of the * LSTM layer work. */ -BOOST_AUTO_TEST_CASE(LSTMLayerParametersTest) +TEST_CASE("LSTMLayerParametersTest", "[ANNLayerTest]") { // Parameter order : inSize, outSize, rho. LSTM<> layer1(1, 2, 3); LSTM<> layer2(1, 2, 4); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer1.InSize(), 1); - BOOST_REQUIRE_EQUAL(layer1.OutSize(), 2); - BOOST_REQUIRE_EQUAL(layer1.Rho(), 3); + REQUIRE(layer1.InSize() == 1); + REQUIRE(layer1.OutSize() == 2); + REQUIRE(layer1.Rho() == 3); // Now modify the parameters to match the second layer. layer1.Rho() = 4; // Now ensure all the results are the same. - BOOST_REQUIRE_EQUAL(layer1.InSize(), layer2.InSize()); - BOOST_REQUIRE_EQUAL(layer2.OutSize(), layer2.OutSize()); - BOOST_REQUIRE_EQUAL(layer1.Rho(), layer2.Rho()); + REQUIRE(layer1.InSize() == layer2.InSize()); + REQUIRE(layer1.OutSize() == layer2.OutSize()); + REQUIRE(layer1.Rho() == layer2.Rho()); } /** * Test the FastLSTM layer with a user defined rho parameter and without. */ -BOOST_AUTO_TEST_CASE(FastLSTMRrhoTest) +TEST_CASE("FastLSTMRrhoTest", "[ANNLayerTest]") { const size_t rho = 5; arma::cube input = arma::randu(1, 1, 5); @@ -1021,7 +1018,7 @@ BOOST_AUTO_TEST_CASE(FastLSTMRrhoTest) /** * FastLSTM layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientFastLSTMLayerTest) +TEST_CASE("GradientFastLSTMLayerTest", "[ANNLayerTest]") { // Fast LSTM function gradient instantiation. struct GradientFunction @@ -1062,31 +1059,31 @@ BOOST_AUTO_TEST_CASE(GradientFastLSTMLayerTest) // The threshold should be << 0.1 but since the Fast LSTM layer uses an // approximation of the sigmoid function the estimated gradient is not // correct. - BOOST_REQUIRE_LE(CheckGradient(function), 0.2); + REQUIRE(CheckGradient(function) <= 0.2); } /** * Test that the functions that can modify and access the parameters of the * Fast LSTM layer work. */ -BOOST_AUTO_TEST_CASE(FastLSTMLayerParametersTest) +TEST_CASE("FastLSTMLayerParametersTest", "[ANNLayerTest]") { // Parameter order : inSize, outSize, rho. FastLSTM<> layer1(1, 2, 3); FastLSTM<> layer2(1, 2, 4); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer1.InSize(), 1); - BOOST_REQUIRE_EQUAL(layer1.OutSize(), 2); - BOOST_REQUIRE_EQUAL(layer1.Rho(), 3); + REQUIRE(layer1.InSize() == 1); + REQUIRE(layer1.OutSize() == 2); + REQUIRE(layer1.Rho() == 3); // Now modify the parameters to match the second layer. layer1.Rho() = 4; // Now ensure all the results are the same. - BOOST_REQUIRE_EQUAL(layer1.InSize(), layer2.InSize()); - BOOST_REQUIRE_EQUAL(layer2.OutSize(), layer2.OutSize()); - BOOST_REQUIRE_EQUAL(layer1.Rho(), layer2.Rho()); + REQUIRE(layer1.InSize() == layer2.InSize()); + REQUIRE(layer1.OutSize() == layer2.OutSize()); + REQUIRE(layer1.Rho() == layer2.Rho()); } /** @@ -1094,7 +1091,7 @@ BOOST_AUTO_TEST_CASE(FastLSTMLayerParametersTest) * state. Besides output, the overloaded function provides read access to cell * state of the LSTM layer. */ -BOOST_AUTO_TEST_CASE(ReadCellStateParamLSTMLayerTest) +TEST_CASE("ReadCellStateParamLSTMLayerTest", "[ANNLayerTest]") { const size_t rho = 5, inputSize = 3, outputSize = 2; @@ -1163,7 +1160,7 @@ BOOST_AUTO_TEST_CASE(ReadCellStateParamLSTMLayerTest) * state. Besides output, the overloaded function provides write access to cell * state of the LSTM layer. */ -BOOST_AUTO_TEST_CASE(WriteCellStateParamLSTMLayerTest) +TEST_CASE("WriteCellStateParamLSTMLayerTest", "[ANNLayerTest]") { const size_t rho = 5, inputSize = 3, outputSize = 2; @@ -1254,11 +1251,11 @@ BOOST_AUTO_TEST_CASE(WriteCellStateParamLSTMLayerTest) { arma::mat empty; // Should throw error. - BOOST_REQUIRE_THROW(lstm.Forward(stepData, // Input. - outLstm, // Output. - empty, // Cell state. - true), // Write into cell state. - std::runtime_error); + REQUIRE_THROWS_AS(lstm.Forward(stepData, // Input. + outLstm, // Output. + empty, // Cell state. + true), // Write into cell state. + std::runtime_error); } } @@ -1266,31 +1263,31 @@ BOOST_AUTO_TEST_CASE(WriteCellStateParamLSTMLayerTest) * Test that the functions that can modify and access the parameters of the * GRU layer work. */ -BOOST_AUTO_TEST_CASE(GRULayerParametersTest) +TEST_CASE("GRULayerParametersTest", "[ANNLayerTest]") { // Parameter order : inSize, outSize, rho. GRU<> layer1(1, 2, 3); GRU<> layer2(1, 2, 4); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer1.InSize(), 1); - BOOST_REQUIRE_EQUAL(layer1.OutSize(), 2); - BOOST_REQUIRE_EQUAL(layer1.Rho(), 3); + REQUIRE(layer1.InSize() == 1); + REQUIRE(layer1.OutSize() == 2); + REQUIRE(layer1.Rho() == 3); // Now modify the parameters to match the second layer. layer1.Rho() = 4; // Now ensure all the results are the same. - BOOST_REQUIRE_EQUAL(layer1.InSize(), layer2.InSize()); - BOOST_REQUIRE_EQUAL(layer2.OutSize(), layer2.OutSize()); - BOOST_REQUIRE_EQUAL(layer1.Rho(), layer2.Rho()); + REQUIRE(layer1.InSize() == layer2.InSize()); + REQUIRE(layer1.OutSize() == layer2.OutSize()); + REQUIRE(layer1.Rho() == layer2.Rho()); } /** * Check if the gradients computed by GRU cell are close enough to the * approximation of the gradients. */ -BOOST_AUTO_TEST_CASE(GradientGRULayerTest) +TEST_CASE("GradientGRULayerTest", "[ANNLayerTest]") { // GRU function gradient instantiation. struct GradientFunction @@ -1329,13 +1326,13 @@ BOOST_AUTO_TEST_CASE(GradientGRULayerTest) arma::cube input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * GRU layer manual forward test. */ -BOOST_AUTO_TEST_CASE(ForwardGRULayerTest) +TEST_CASE("ForwardGRULayerTest", "[ANNLayerTest]") { // This will make it easier to clean memory later. GRU<>* gruAlloc = new GRU<>(3, 3, 5); @@ -1361,7 +1358,7 @@ BOOST_AUTO_TEST_CASE(ForwardGRULayerTest) // For the first input the output should be equal to the output of // gate z_t as the previous output fed to the cell is all zeros. - BOOST_REQUIRE_LE(arma::as_scalar(arma::trans(output) * expectedOutput), 1e-2); + REQUIRE(arma::as_scalar(arma::trans(output) * expectedOutput) <= 1e-2); expectedOutput = output; @@ -1384,7 +1381,7 @@ BOOST_AUTO_TEST_CASE(ForwardGRULayerTest) // Expected output for the second input. expectedOutput = z_t % expectedOutput + (arma::ones(3, 1) - z_t) % o_t; - BOOST_REQUIRE_LE(arma::as_scalar(arma::trans(output) * expectedOutput), 1e-2); + REQUIRE(arma::as_scalar(arma::trans(output) * expectedOutput) <= 1e-2); LayerTypes<> layer(gruAlloc); boost::apply_visitor(DeleteVisitor(), layer); @@ -1393,7 +1390,7 @@ BOOST_AUTO_TEST_CASE(ForwardGRULayerTest) /** * Simple concat module test. */ -BOOST_AUTO_TEST_CASE(SimpleConcatLayerTest) +TEST_CASE("SimpleConcatLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta, error; @@ -1419,18 +1416,19 @@ BOOST_AUTO_TEST_CASE(SimpleConcatLayerTest) const double sumModuleB = arma::accu( moduleB->Parameters().submat( 100, 0, moduleB->Parameters().n_elem - 1, 0)); - BOOST_REQUIRE_CLOSE(sumModuleA + sumModuleB, arma::accu(output.col(0)), 1e-3); + REQUIRE(sumModuleA + sumModuleB == + Approx(arma::accu(output.col(0))).epsilon(1e-5)); // Test the Backward function. error = arma::zeros(20, 1); module.Backward(input, error, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(arma::accu(delta) == 0); } /** * Test to check Concat layer along different axes. */ -BOOST_AUTO_TEST_CASE(ConcatAlongAxisTest) +TEST_CASE("ConcatAlongAxisTest", "[ANNLayerTest]") { arma::mat output, input, error, outputA, outputB; size_t inputWidth = 4, inputHeight = 4, inputChannel = 2; @@ -1516,20 +1514,20 @@ BOOST_AUTO_TEST_CASE(ConcatAlongAxisTest) * Test that the function that can access the axis parameter of the * Concat layer works. */ -BOOST_AUTO_TEST_CASE(ConcatLayerParametersTest) +TEST_CASE("ConcatLayerParametersTest", "[ANNLayerTest]") { // Parameter order : inputSize{width, height, channels}, axis, model, run. arma::Row inputSize{128, 128, 3}; Concat<> layer(inputSize, 2, false, true); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer.ConcatAxis(), 2); + REQUIRE(layer.ConcatAxis() == 2); } /** * Concat layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientConcatLayerTest) +TEST_CASE("GradientConcatLayerTest", "[ANNLayerTest]") { // Concat function gradient instantiation. struct GradientFunction @@ -1571,13 +1569,13 @@ BOOST_AUTO_TEST_CASE(GradientConcatLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Simple concatenate module test. */ -BOOST_AUTO_TEST_CASE(SimpleConcatenateLayerTest) +TEST_CASE("SimpleConcatenateLayerTest", "[ANNLayerTest]") { arma::mat input = arma::ones(5, 1); arma::mat output, delta; @@ -1588,17 +1586,17 @@ BOOST_AUTO_TEST_CASE(SimpleConcatenateLayerTest) // Test the Forward function. module.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 7.5); + REQUIRE(arma::accu(output) == 7.5); // Test the Backward function. module.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 5); + REQUIRE(arma::accu(delta) == 5); } /** * Concatenate layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientConcatenateLayerTest) +TEST_CASE("GradientConcatenateLayerTest", "[ANNLayerTest]") { // Concatenate function gradient instantiation. struct GradientFunction @@ -1642,68 +1640,123 @@ BOOST_AUTO_TEST_CASE(GradientConcatenateLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Simple lookup module test. */ -BOOST_AUTO_TEST_CASE(SimpleLookupLayerTest) +TEST_CASE("SimpleLookupLayerTest", "[ANNLayerTest]") { - arma::mat output, input, delta, gradient; - Lookup<> module(10, 5); + const size_t vocabSize = 10; + const size_t embeddingSize = 2; + const size_t seqLength = 3; + const size_t batchSize = 4; + + arma::mat output, input, gy, g, gradient; + + Lookup<> module(vocabSize, embeddingSize); module.Parameters().randu(); // Test the Forward function. - input = arma::zeros(2, 1); - input(0) = 1; - input(1) = 3; + input = arma::zeros(seqLength, batchSize); + for (size_t i = 0; i < input.n_elem; ++i) + { + int token = math::RandInt(1, vocabSize); + input(i) = token; + } module.Forward(input, output); + for (size_t i = 0; i < batchSize; ++i) + { + // The Lookup module uses index - 1 for the cols. + const double outputSum = arma::accu(module.Parameters().rows( + arma::conv_to::from(input.col(i)) - 1)); - // The Lookup module uses index - 1 for the cols. - const double outputSum = arma::accu(module.Parameters().col(0)) + - arma::accu(module.Parameters().col(2)); - - BOOST_REQUIRE_CLOSE(outputSum, arma::accu(output), 1e-3); - - // Test the Backward function. - module.Backward(input, input, delta); - BOOST_REQUIRE_EQUAL(arma::accu(input), arma::accu(input)); + REQUIRE(std::fabs(outputSum - arma::accu(output.col(i))) <= 1e-5); + } // Test the Gradient function. - arma::mat error = arma::ones(2, 5); - error = error.t(); - error.col(1) *= 0.5; - + arma::mat error = 0.01 * arma::randu(embeddingSize * seqLength, batchSize); module.Gradient(input, error, gradient); - // The Lookup module uses index - 1 for the cols. - const double gradientSum = arma::accu(gradient.col(0)) + - arma::accu(gradient.col(2)); + REQUIRE(std::fabs(arma::accu(error) - arma::accu(gradient)) <= 1e-07); +} - BOOST_REQUIRE_CLOSE(gradientSum, arma::accu(error), 1e-3); - BOOST_REQUIRE_CLOSE(arma::accu(gradient), arma::accu(error), 1e-3); +/** + * Lookup layer numerical gradient test. + */ +TEST_CASE("GradientLookupLayerTest", "[ANNLayerTest]") +{ + // Lookup function gradient instantiation. + struct GradientFunction + { + GradientFunction() + { + input.set_size(seqLength, batchSize); + for (size_t i = 0; i < input.n_elem; ++i) + { + input(i) = math::RandInt(1, vocabSize); + } + target = arma::zeros(vocabSize, batchSize); + for (size_t i = 0; i < batchSize; ++i) + { + const size_t targetWord = math::RandInt(1, vocabSize); + target(targetWord, i) = 1; + } + + model = new FFN, GlorotInitialization>(); + model->Predictors() = input; + model->Responses() = target; + model->Add >(vocabSize, embeddingSize); + model->Add >(embeddingSize * seqLength, vocabSize); + model->Add >(); + } + + ~GradientFunction() + { + delete model; + } + + double Gradient(arma::mat& gradient) const + { + double error = model->Evaluate(model->Parameters(), 0, batchSize); + model->Gradient(model->Parameters(), 0, gradient, batchSize); + return error; + } + + arma::mat& Parameters() { return model->Parameters(); } + + FFN, GlorotInitialization>* model; + arma::mat input, target; + + const size_t seqLength = 10; + const size_t embeddingSize = 8; + const size_t vocabSize = 20; + const size_t batchSize = 4; + } function; + + REQUIRE(CheckGradient(function) <= 1e-6); } /** * Test that the functions that can access the parameters of the * Lookup layer work. */ -BOOST_AUTO_TEST_CASE(LookupLayerParametersTest) +TEST_CASE("LookupLayerParametersTest", "[ANNLayerTest]") { - // Parameter order : inSize, outSize. - Lookup<> layer(5, 7); + // Parameter order : vocabSize, embedingSize. + Lookup<> layer(100, 8); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer.InSize(), 5); - BOOST_REQUIRE_EQUAL(layer.OutSize(), 7); + REQUIRE(layer.VocabSize() == 100); + REQUIRE(layer.EmbeddingSize() == 8); } /** * Simple LogSoftMax module test. */ -BOOST_AUTO_TEST_CASE(SimpleLogSoftmaxLayerTest) +TEST_CASE("SimpleLogSoftmaxLayerTest", "[ANNLayerTest]") { arma::mat output, input, error, delta; LogSoftMax<> module; @@ -1711,22 +1764,22 @@ BOOST_AUTO_TEST_CASE(SimpleLogSoftmaxLayerTest) // Test the Forward function. input = arma::mat("0.5; 0.5"); module.Forward(input, output); - BOOST_REQUIRE_SMALL(arma::accu(arma::abs( - arma::mat("-0.6931; -0.6931") - output)), 1e-3); + REQUIRE(arma::accu(arma::abs(arma::mat("-0.6931; -0.6931") - output)) == + Approx(0.0).margin(1e-3)); // Test the Backward function. error = arma::zeros(input.n_rows, input.n_cols); // Assume LogSoftmax layer is always associated with NLL output layer. error(1, 0) = -1; module.Backward(input, error, delta); - BOOST_REQUIRE_SMALL(arma::accu(arma::abs( - arma::mat("1.6487; 0.6487") - delta)), 1e-3); + REQUIRE(arma::accu(arma::abs(arma::mat("1.6487; 0.6487") - delta)) == + Approx(0.0).margin(1e-3)); } /** * Simple Softmax module test. */ -BOOST_AUTO_TEST_CASE(SimpleSoftmaxLayerTest) +TEST_CASE("SimpleSoftmaxLayerTest", "[ANNLayerTest]") { arma::mat input, output, gy, g; Softmax<> module; @@ -1734,21 +1787,21 @@ BOOST_AUTO_TEST_CASE(SimpleSoftmaxLayerTest) // Test the forward function. input = arma::mat("1.7; 3.6"); module.Forward(input, output); - BOOST_REQUIRE_SMALL(arma::accu(arma::abs( - arma::mat("0.130108; 0.869892") - output)), 1e-4); + REQUIRE(arma::accu(arma::abs(arma::mat("0.130108; 0.869892") - output)) == + Approx(0.0).margin(1e-4)); // Test the backward function. gy = arma::zeros(input.n_rows, input.n_cols); gy(0) = 1; module.Backward(output, gy, g); - BOOST_REQUIRE_SMALL(arma::accu(arma::abs( - arma::mat("0.11318; -0.11318") - g)), 1e-04); + REQUIRE(arma::accu(arma::abs(arma::mat("0.11318; -0.11318") - g)) == + Approx(0.0).margin(1e-04)); } /** * Softmax layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientSoftmaxTest) +TEST_CASE("GradientSoftmaxTest", "[ANNLayerTest]") { // Softmax function gradient instantiation. struct GradientFunction @@ -1785,13 +1838,13 @@ BOOST_AUTO_TEST_CASE(GradientSoftmaxTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /* * Simple test for the BilinearInterpolation layer */ -BOOST_AUTO_TEST_CASE(SimpleBilinearInterpolationLayerTest) +TEST_CASE("SimpleBilinearInterpolationLayerTest", "[ANNLayerTest]") { // Tested output against tensorflow.image.resize_bilinear() arma::mat input, output, unzoomedOutput, expectedOutput; @@ -1826,18 +1879,18 @@ BOOST_AUTO_TEST_CASE(SimpleBilinearInterpolationLayerTest) * Test that the functions that can modify and access the parameters of the * Bilinear Interpolation layer work. */ -BOOST_AUTO_TEST_CASE(BilinearInterpolationLayerParametersTest) +TEST_CASE("BilinearInterpolationLayerParametersTest", "[ANNLayerTest]") { // Parameter order : inRowSize, inColSize, outRowSize, outColSize, depth. BilinearInterpolation<> layer1(1, 2, 3, 4, 5); BilinearInterpolation<> layer2(2, 3, 4, 5, 6); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer1.InRowSize(), 1); - BOOST_REQUIRE_EQUAL(layer1.InColSize(), 2); - BOOST_REQUIRE_EQUAL(layer1.OutRowSize(), 3); - BOOST_REQUIRE_EQUAL(layer1.OutColSize(), 4); - BOOST_REQUIRE_EQUAL(layer1.InDepth(), 5); + REQUIRE(layer1.InRowSize() == 1); + REQUIRE(layer1.InColSize() == 2); + REQUIRE(layer1.OutRowSize() == 3); + REQUIRE(layer1.OutColSize() == 4); + REQUIRE(layer1.InDepth() == 5); // Now modify the parameters to match the second layer. layer1.InRowSize() = 2; @@ -1847,11 +1900,11 @@ BOOST_AUTO_TEST_CASE(BilinearInterpolationLayerParametersTest) layer1.InDepth() = 6; // Now ensure all results are the same. - BOOST_REQUIRE_EQUAL(layer1.InRowSize(), layer2.InRowSize()); - BOOST_REQUIRE_EQUAL(layer1.InColSize(), layer2.InColSize()); - BOOST_REQUIRE_EQUAL(layer1.OutRowSize(), layer2.OutRowSize()); - BOOST_REQUIRE_EQUAL(layer1.OutColSize(), layer2.OutColSize()); - BOOST_REQUIRE_EQUAL(layer1.InDepth(), layer2.InDepth()); + REQUIRE(layer1.InRowSize() == layer2.InRowSize()); + REQUIRE(layer1.InColSize() == layer2.InColSize()); + REQUIRE(layer1.OutRowSize() == layer2.OutRowSize()); + REQUIRE(layer1.OutColSize() == layer2.OutColSize()); + REQUIRE(layer1.InDepth() == layer2.InDepth()); } /** @@ -1859,7 +1912,7 @@ BOOST_AUTO_TEST_CASE(BilinearInterpolationLayerParametersTest) * the values from another implementation. * Link to the implementation - http://cthorey.github.io./backpropagation/ */ -BOOST_AUTO_TEST_CASE(BatchNormTest) +TEST_CASE("BatchNormTest", "[ANNLayerTest]") { arma::mat input, output; input << 5.1 << 3.5 << 1.4 << arma::endr @@ -1949,7 +2002,7 @@ BOOST_AUTO_TEST_CASE(BatchNormTest) /** * BatchNorm layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientBatchNormTest) +TEST_CASE("GradientBatchNormTest", "[ANNLayerTest]") { bool pass = false; for (size_t trial = 0; trial < 10; trial++) @@ -1999,21 +2052,21 @@ BOOST_AUTO_TEST_CASE(GradientBatchNormTest) } } - BOOST_REQUIRE(pass); + REQUIRE(pass); } /** * Test that the functions that can access the parameters of the * Batch Norm layer work. */ -BOOST_AUTO_TEST_CASE(BatchNormLayerParametersTest) +TEST_CASE("BatchNormLayerParametersTest", "[ANNLayerTest]") { // Parameter order : size, eps. BatchNorm<> layer(7, 1e-3); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer.InputSize(), 7); - BOOST_REQUIRE_EQUAL(layer.Epsilon(), 1e-3); + REQUIRE(layer.InputSize() == 7); + REQUIRE(layer.Epsilon() == 1e-3); arma::mat runningMean(7, 1, arma::fill::randn); arma::mat runningVariance(7, 1, arma::fill::randn); @@ -2027,7 +2080,7 @@ BOOST_AUTO_TEST_CASE(BatchNormLayerParametersTest) /** * VirtualBatchNorm layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientVirtualBatchNormTest) +TEST_CASE("GradientVirtualBatchNormTest", "[ANNLayerTest]") { // Add function gradient instantiation. struct GradientFunction @@ -2067,14 +2120,14 @@ BOOST_AUTO_TEST_CASE(GradientVirtualBatchNormTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Test that the functions that can modify and access the parameters of the * Virtual Batch Norm layer work. */ -BOOST_AUTO_TEST_CASE(VirtualBatchNormLayerParametersTest) +TEST_CASE("VirtualBatchNormLayerParametersTest", "[ANNLayerTest]") { arma::mat input = arma::randn(5, 256); arma::mat referenceBatch = arma::mat(input.memptr(), input.n_rows, 16); @@ -2083,14 +2136,14 @@ BOOST_AUTO_TEST_CASE(VirtualBatchNormLayerParametersTest) VirtualBatchNorm<> layer(referenceBatch, 5, 1e-3); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer.InSize(), 5); - BOOST_REQUIRE_EQUAL(layer.Epsilon(), 1e-3); + REQUIRE(layer.InSize() == 5); + REQUIRE(layer.Epsilon() == 1e-3); } /** * MiniBatchDiscrimination layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(MiniBatchDiscriminationTest) +TEST_CASE("MiniBatchDiscriminationTest", "[ANNLayerTest]") { // Add function gradient instantiation. struct GradientFunction @@ -2127,13 +2180,13 @@ BOOST_AUTO_TEST_CASE(MiniBatchDiscriminationTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Simple Transposed Convolution layer test. */ -BOOST_AUTO_TEST_CASE(SimpleTransposedConvolutionLayerTest) +TEST_CASE("SimpleTransposedConvolutionLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; @@ -2146,12 +2199,12 @@ BOOST_AUTO_TEST_CASE(SimpleTransposedConvolutionLayerTest) module1.Reset(); module1.Forward(input, output); // Value calculated using tensorflow.nn.conv2d_transpose() - BOOST_REQUIRE_EQUAL(arma::accu(output), 360.0); + REQUIRE(arma::accu(output) == 360.0); // Test the backward function. module1.Backward(input, output, delta); // Value calculated using tensorflow.nn.conv2d() - BOOST_REQUIRE_EQUAL(arma::accu(delta), 720.0); + REQUIRE(arma::accu(delta) == 720.0); TransposedConvolution<> module2(1, 1, 4, 4, 1, 1, 1, 1, 5, 5, 6, 6); // Test the forward function. @@ -2166,12 +2219,12 @@ BOOST_AUTO_TEST_CASE(SimpleTransposedConvolutionLayerTest) module2.Reset(); module2.Forward(input, output); // Value calculated using torch.nn.functional.conv_transpose2d() - BOOST_REQUIRE_EQUAL(arma::accu(output), 1512.0); + REQUIRE(arma::accu(output) == 1512.0); // Test the backward function. module2.Backward(input, output, delta); // Value calculated using torch.nn.functional.conv2d() - BOOST_REQUIRE_EQUAL(arma::accu(delta), 6504.0); + REQUIRE(arma::accu(delta) == 6504.0); TransposedConvolution<> module3(1, 1, 3, 3, 1, 1, 1, 1, 5, 5, 5, 5); // Test the forward function. @@ -2184,12 +2237,12 @@ BOOST_AUTO_TEST_CASE(SimpleTransposedConvolutionLayerTest) module3.Reset(); module3.Forward(input, output); // Value calculated using torch.nn.functional.conv_transpose2d() - BOOST_REQUIRE_EQUAL(arma::accu(output), 2370.0); + REQUIRE(arma::accu(output) == 2370.0); // Test the backward function. module3.Backward(input, output, delta); // Value calculated using torch.nn.functional.conv2d() - BOOST_REQUIRE_EQUAL(arma::accu(delta), 19154.0); + REQUIRE(arma::accu(delta) == 19154.0); TransposedConvolution<> module4(1, 1, 3, 3, 1, 1, 0, 0, 5, 5, 7, 7); // Test the forward function. @@ -2202,12 +2255,12 @@ BOOST_AUTO_TEST_CASE(SimpleTransposedConvolutionLayerTest) module4.Reset(); module4.Forward(input, output); // Value calculated using torch.nn.functional.conv_transpose2d() - BOOST_REQUIRE_EQUAL(arma::accu(output), 6000.0); + REQUIRE(arma::accu(output) == 6000.0); // Test the backward function. module4.Backward(input, output, delta); // Value calculated using torch.nn.functional.conv2d() - BOOST_REQUIRE_EQUAL(arma::accu(delta), 86208.0); + REQUIRE(arma::accu(delta) == 86208.0); TransposedConvolution<> module5(1, 1, 3, 3, 2, 2, 0, 0, 2, 2, 5, 5); // Test the forward function. @@ -2220,12 +2273,12 @@ BOOST_AUTO_TEST_CASE(SimpleTransposedConvolutionLayerTest) module5.Reset(); module5.Forward(input, output); // Value calculated using torch.nn.functional.conv_transpose2d() - BOOST_REQUIRE_EQUAL(arma::accu(output), 120.0); + REQUIRE(arma::accu(output) == 120.0); // Test the backward function. module5.Backward(input, output, delta); // Value calculated using torch.nn.functional.conv2d() - BOOST_REQUIRE_EQUAL(arma::accu(delta), 960.0); + REQUIRE(arma::accu(delta) == 960.0); TransposedConvolution<> module6(1, 1, 3, 3, 2, 2, 1, 1, 3, 3, 5, 5); // Test the forward function. @@ -2238,12 +2291,12 @@ BOOST_AUTO_TEST_CASE(SimpleTransposedConvolutionLayerTest) module6.Reset(); module6.Forward(input, output); // Value calculated using torch.nn.functional.conv_transpose2d() - BOOST_REQUIRE_EQUAL(arma::accu(output), 410.0); + REQUIRE(arma::accu(output) == 410.0); // Test the backward function. module6.Backward(input, output, delta); // Value calculated using torch.nn.functional.conv2d() - BOOST_REQUIRE_EQUAL(arma::accu(delta), 4444.0); + REQUIRE(arma::accu(delta) == 4444.0); TransposedConvolution<> module7(1, 1, 3, 3, 2, 2, 1, 1, 3, 3, 6, 6); // Test the forward function. @@ -2256,17 +2309,17 @@ BOOST_AUTO_TEST_CASE(SimpleTransposedConvolutionLayerTest) module7.Reset(); module7.Forward(input, output); // Value calculated using torch.nn.functional.conv_transpose2d() - BOOST_REQUIRE_EQUAL(arma::accu(output), 606.0); + REQUIRE(arma::accu(output) == 606.0); module7.Backward(input, output, delta); // Value calculated using torch.nn.functional.conv2d() - BOOST_REQUIRE_EQUAL(arma::accu(delta), 7732.0); + REQUIRE(arma::accu(delta) == 7732.0); } /** * Transposed Convolution layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientTransposedConvolutionLayerTest) +TEST_CASE("GradientTransposedConvolutionLayerTest", "[ANNLayerTest]") { // Add function gradient instantiation. // To make this test robust, check it five times. @@ -2312,13 +2365,13 @@ BOOST_AUTO_TEST_CASE(GradientTransposedConvolutionLayerTest) break; } } - BOOST_REQUIRE_EQUAL(pass, true); + REQUIRE(pass == true); } /** * Simple MultiplyMerge module test. */ -BOOST_AUTO_TEST_CASE(SimpleMultiplyMergeLayerTest) +TEST_CASE("SimpleMultiplyMergeLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; input = arma::ones(10, 1); @@ -2337,18 +2390,18 @@ BOOST_AUTO_TEST_CASE(SimpleMultiplyMergeLayerTest) // Test the Forward function. module.Forward(input, output); - BOOST_REQUIRE_EQUAL(10, arma::accu(output)); + REQUIRE(10 == arma::accu(output)); // Test the Backward function. module.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(output), arma::accu(delta)); + REQUIRE(arma::accu(output) == arma::accu(delta)); } } /** * Simple Atrous Convolution layer test. */ -BOOST_AUTO_TEST_CASE(SimpleAtrousConvolutionLayerTest) +TEST_CASE("SimpleAtrousConvolutionLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta; @@ -2361,11 +2414,11 @@ BOOST_AUTO_TEST_CASE(SimpleAtrousConvolutionLayerTest) module1.Reset(); module1.Forward(input, output); // Value calculated using tensorflow.nn.atrous_conv2d() - BOOST_REQUIRE_EQUAL(arma::accu(output), 792.0); + REQUIRE(arma::accu(output) == 792.0); // Test the Backward function. module1.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 2376); + REQUIRE(arma::accu(delta) == 2376); AtrousConvolution<> module2(1, 1, 3, 3, 2, 2, 0, 0, 7, 7, 2, 2); // Test the forward function. @@ -2377,17 +2430,17 @@ BOOST_AUTO_TEST_CASE(SimpleAtrousConvolutionLayerTest) module2.Reset(); module2.Forward(input, output); // Value calculated using tensorflow.nn.conv2d() - BOOST_REQUIRE_EQUAL(arma::accu(output), 264.0); + REQUIRE(arma::accu(output) == 264.0); // Test the backward function. module2.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 792.0); + REQUIRE(arma::accu(delta) == 792.0); } /** * Atrous Convolution layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientAtrousConvolutionLayerTest) +TEST_CASE("GradientAtrousConvolutionLayerTest", "[ANNLayerTest]") { // Add function gradient instantiation. struct GradientFunction @@ -2425,14 +2478,14 @@ BOOST_AUTO_TEST_CASE(GradientAtrousConvolutionLayerTest) // TODO: this tolerance seems far higher than necessary. The implementation // should be checked. - BOOST_REQUIRE_LE(CheckGradient(function), 0.2); + REQUIRE(CheckGradient(function) <= 0.2); } /** * Test the functions to access and modify the parameters of the * AtrousConvolution layer. */ -BOOST_AUTO_TEST_CASE(AtrousConvolutionLayerParametersTest) +TEST_CASE("AtrousConvolutionLayerParametersTest", "[ANNLayerTest]") { // Parameter order for the constructor: inSize, outSize, kW, kH, dW, dH, padW, // padH, inputWidth, inputHeight, dilationW, dilationH, paddingType ("none"). @@ -2442,18 +2495,18 @@ BOOST_AUTO_TEST_CASE(AtrousConvolutionLayerParametersTest) std::make_tuple(10, 11), 12, 13, 14, 15); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer1.InputWidth(), 11); - BOOST_REQUIRE_EQUAL(layer1.InputHeight(), 12); - BOOST_REQUIRE_EQUAL(layer1.KernelWidth(), 3); - BOOST_REQUIRE_EQUAL(layer1.KernelHeight(), 4); - BOOST_REQUIRE_EQUAL(layer1.StrideWidth(), 5); - BOOST_REQUIRE_EQUAL(layer1.StrideHeight(), 6); - BOOST_REQUIRE_EQUAL(layer1.Padding().PadHTop(), 9); - BOOST_REQUIRE_EQUAL(layer1.Padding().PadHBottom(), 10); - BOOST_REQUIRE_EQUAL(layer1.Padding().PadWLeft(), 7); - BOOST_REQUIRE_EQUAL(layer1.Padding().PadWRight(), 8); - BOOST_REQUIRE_EQUAL(layer1.DilationWidth(), 13); - BOOST_REQUIRE_EQUAL(layer1.DilationHeight(), 14); + REQUIRE(layer1.InputWidth() == 11); + REQUIRE(layer1.InputHeight() == 12); + REQUIRE(layer1.KernelWidth() == 3); + REQUIRE(layer1.KernelHeight() == 4); + REQUIRE(layer1.StrideWidth() == 5); + REQUIRE(layer1.StrideHeight() == 6); + REQUIRE(layer1.Padding().PadHTop() == 9); + REQUIRE(layer1.Padding().PadHBottom() == 10); + REQUIRE(layer1.Padding().PadWLeft() == 7); + REQUIRE(layer1.Padding().PadWRight() == 8); + REQUIRE(layer1.DilationWidth() == 13); + REQUIRE(layer1.DilationHeight() == 14); // Now modify the parameters to match the second layer. layer1.InputWidth() = 12; @@ -2470,28 +2523,28 @@ BOOST_AUTO_TEST_CASE(AtrousConvolutionLayerParametersTest) layer1.DilationHeight() = 15; // Now ensure all results are the same. - BOOST_REQUIRE_EQUAL(layer1.InputWidth(), layer2.InputWidth()); - BOOST_REQUIRE_EQUAL(layer1.InputHeight(), layer2.InputHeight()); - BOOST_REQUIRE_EQUAL(layer1.KernelWidth(), layer2.KernelWidth()); - BOOST_REQUIRE_EQUAL(layer1.KernelHeight(), layer2.KernelHeight()); - BOOST_REQUIRE_EQUAL(layer1.StrideWidth(), layer2.StrideWidth()); - BOOST_REQUIRE_EQUAL(layer1.StrideHeight(), layer2.StrideHeight()); - BOOST_REQUIRE_EQUAL(layer1.Padding().PadHTop(), layer2.Padding().PadHTop()); - BOOST_REQUIRE_EQUAL(layer1.Padding().PadHBottom(), + REQUIRE(layer1.InputWidth() == layer2.InputWidth()); + REQUIRE(layer1.InputHeight() == layer2.InputHeight()); + REQUIRE(layer1.KernelWidth() == layer2.KernelWidth()); + REQUIRE(layer1.KernelHeight() == layer2.KernelHeight()); + REQUIRE(layer1.StrideWidth() == layer2.StrideWidth()); + REQUIRE(layer1.StrideHeight() == layer2.StrideHeight()); + REQUIRE(layer1.Padding().PadHTop() == layer2.Padding().PadHTop()); + REQUIRE(layer1.Padding().PadHBottom() == layer2.Padding().PadHBottom()); - BOOST_REQUIRE_EQUAL(layer1.Padding().PadWLeft(), + REQUIRE(layer1.Padding().PadWLeft() == layer2.Padding().PadWLeft()); - BOOST_REQUIRE_EQUAL(layer1.Padding().PadWRight(), + REQUIRE(layer1.Padding().PadWRight() == layer2.Padding().PadWRight()); - BOOST_REQUIRE_EQUAL(layer1.DilationWidth(), layer2.DilationWidth()); - BOOST_REQUIRE_EQUAL(layer1.DilationHeight(), layer2.DilationHeight()); + REQUIRE(layer1.DilationWidth() == layer2.DilationWidth()); + REQUIRE(layer1.DilationHeight() == layer2.DilationHeight()); } /** * Test that the padding options are working correctly in Atrous Convolution * layer. */ -BOOST_AUTO_TEST_CASE(AtrousConvolutionLayerPaddingTest) +TEST_CASE("AtrousConvolutionLayerPaddingTest", "[ANNLayerTest]") { arma::mat output, input, delta; @@ -2506,9 +2559,9 @@ BOOST_AUTO_TEST_CASE(AtrousConvolutionLayerPaddingTest) module1.Reset(); module1.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 0); - BOOST_REQUIRE_EQUAL(output.n_rows, 9); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 0); + REQUIRE(output.n_rows == 9); + REQUIRE(output.n_cols == 1); // Test the Backward function. module1.Backward(input, output, delta); @@ -2524,9 +2577,9 @@ BOOST_AUTO_TEST_CASE(AtrousConvolutionLayerPaddingTest) module2.Reset(); module2.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 0); - BOOST_REQUIRE_EQUAL(output.n_rows, 49); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 0); + REQUIRE(output.n_rows == 49); + REQUIRE(output.n_cols == 1); // Test the backward function. module2.Backward(input, output, delta); @@ -2535,7 +2588,7 @@ BOOST_AUTO_TEST_CASE(AtrousConvolutionLayerPaddingTest) /** * Tests the LayerNorm layer. */ -BOOST_AUTO_TEST_CASE(LayerNormTest) +TEST_CASE("LayerNormTest", "[ANNLayerTest]") { arma::mat input, output; input << 5.1 << 3.5 << arma::endr @@ -2569,7 +2622,7 @@ BOOST_AUTO_TEST_CASE(LayerNormTest) /** * LayerNorm layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientLayerNormTest) +TEST_CASE("GradientLayerNormTest", "[ANNLayerTest]") { // Add function gradient instantiation. struct GradientFunction @@ -2608,28 +2661,28 @@ BOOST_AUTO_TEST_CASE(GradientLayerNormTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Test that the functions that can access the parameters of the * Layer Norm layer work. */ -BOOST_AUTO_TEST_CASE(LayerNormLayerParametersTest) +TEST_CASE("LayerNormLayerParametersTest", "[ANNLayerTest]") { // Parameter order : size, eps. LayerNorm<> layer(5, 1e-3); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer.InSize(), 5); - BOOST_REQUIRE_EQUAL(layer.Epsilon(), 1e-3); + REQUIRE(layer.InSize() == 5); + REQUIRE(layer.Epsilon() == 1e-3); } /** * Test if the AddMerge layer is able to forward the * Forward/Backward/Gradient calls. */ -BOOST_AUTO_TEST_CASE(AddMergeRunTest) +TEST_CASE("AddMergeRunTest", "[ANNLayerTest]") { arma::mat output, input, delta, error; @@ -2653,15 +2706,15 @@ BOOST_AUTO_TEST_CASE(AddMergeRunTest) // Clean up before we break, delete linear; - BOOST_REQUIRE_CLOSE(parameterSum, arma::accu(output), 1e-3); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(parameterSum == Approx(arma::accu(output)).epsilon(1e-5)); + REQUIRE(arma::accu(delta) == 0); } /** * Test if the MultiplyMerge layer is able to forward the * Forward/Backward/Gradient calls. */ -BOOST_AUTO_TEST_CASE(MultiplyMergeRunTest) +TEST_CASE("MultiplyMergeRunTest", "[ANNLayerTest]") { arma::mat output, input, delta, error; @@ -2685,14 +2738,14 @@ BOOST_AUTO_TEST_CASE(MultiplyMergeRunTest) // Clean up before we break, delete linear; - BOOST_REQUIRE_CLOSE(parameterSum, arma::accu(output), 1e-3); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(parameterSum == Approx(arma::accu(output)).epsilon(1e-5)); + REQUIRE(arma::accu(delta) == 0); } /** * Simple subview module test. */ -BOOST_AUTO_TEST_CASE(SimpleSubviewLayerTest) +TEST_CASE("SimpleSubviewLayerTest", "[ANNLayerTest]") { arma::mat output, input, delta, outputMat; Subview<> moduleRow(1, 10, 19); @@ -2700,26 +2753,26 @@ BOOST_AUTO_TEST_CASE(SimpleSubviewLayerTest) // Test the Forward function for a vector. input = arma::ones(20, 1); moduleRow.Forward(input, output); - BOOST_REQUIRE_EQUAL(output.n_rows, 10); + REQUIRE(output.n_rows == 10); Subview<> moduleMat(4, 3, 6, 0, 2); // Test the Forward function for a matrix. input = arma::ones(20, 8); moduleMat.Forward(input, outputMat); - BOOST_REQUIRE_EQUAL(outputMat.n_rows, 12); - BOOST_REQUIRE_EQUAL(outputMat.n_cols, 2); + REQUIRE(outputMat.n_rows == 12); + REQUIRE(outputMat.n_cols == 2); // Test the Backward function. moduleMat.Backward(input, input, delta); - BOOST_REQUIRE_EQUAL(accu(delta), 160); - BOOST_REQUIRE_EQUAL(delta.n_rows, 20); + REQUIRE(accu(delta) == 160); + REQUIRE(delta.n_rows == 20); } /** * Subview index test. */ -BOOST_AUTO_TEST_CASE(SubviewIndexTest) +TEST_CASE("SubviewIndexTest", "[ANNLayerTest]") { arma::mat outputEnd, outputMid, outputStart, input, delta; input = arma::linspace(1, 20, 20); @@ -2749,7 +2802,7 @@ BOOST_AUTO_TEST_CASE(SubviewIndexTest) /** * Subview batch test. */ -BOOST_AUTO_TEST_CASE(SubviewBatchTest) +TEST_CASE("SubviewBatchTest", "[ANNLayerTest]") { arma::mat output, input, outputCol, outputMat, outputDef; @@ -2782,18 +2835,18 @@ BOOST_AUTO_TEST_CASE(SubviewBatchTest) * Test that the functions that can modify and access the parameters of the * Subview layer work. */ -BOOST_AUTO_TEST_CASE(SubviewLayerParametersTest) +TEST_CASE("SubviewLayerParametersTest", "[ANNLayerTest]") { // Parameter order : inSize, beginRow, endRow, beginCol, endCol. Subview<> layer1(1, 2, 3, 4, 5); Subview<> layer2(1, 3, 4, 5, 6); // Make sure we can get the parameters correctly. - BOOST_REQUIRE_EQUAL(layer1.InSize(), 1); - BOOST_REQUIRE_EQUAL(layer1.BeginRow(), 2); - BOOST_REQUIRE_EQUAL(layer1.EndRow(), 3); - BOOST_REQUIRE_EQUAL(layer1.BeginCol(), 4); - BOOST_REQUIRE_EQUAL(layer1.EndCol(), 5); + REQUIRE(layer1.InSize() == 1); + REQUIRE(layer1.BeginRow() == 2); + REQUIRE(layer1.EndRow() == 3); + REQUIRE(layer1.BeginCol() == 4); + REQUIRE(layer1.EndCol() == 5); // Now modify the parameters to match the second layer. layer1.BeginRow() = 3; @@ -2802,17 +2855,17 @@ BOOST_AUTO_TEST_CASE(SubviewLayerParametersTest) layer1.EndCol() = 6; // Now ensure all results are the same. - BOOST_REQUIRE_EQUAL(layer1.InSize(), layer2.InSize()); - BOOST_REQUIRE_EQUAL(layer1.BeginRow(), layer2.BeginRow()); - BOOST_REQUIRE_EQUAL(layer1.EndRow(), layer2.EndRow()); - BOOST_REQUIRE_EQUAL(layer1.BeginCol(), layer2.BeginCol()); - BOOST_REQUIRE_EQUAL(layer1.EndCol(), layer2.EndCol()); + REQUIRE(layer1.InSize() == layer2.InSize()); + REQUIRE(layer1.BeginRow() == layer2.BeginRow()); + REQUIRE(layer1.EndRow() == layer2.EndRow()); + REQUIRE(layer1.BeginCol() == layer2.BeginCol()); + REQUIRE(layer1.EndCol() == layer2.EndCol()); } /* * Simple Reparametrization module test. */ -BOOST_AUTO_TEST_CASE(SimpleReparametrizationLayerTest) +TEST_CASE("SimpleReparametrizationLayerTest", "[ANNLayerTest]") { arma::mat input, output, delta; Reparametrization<> module(5); @@ -2823,18 +2876,18 @@ BOOST_AUTO_TEST_CASE(SimpleReparametrizationLayerTest) input = join_cols(arma::ones(5, 1) * -15, arma::zeros(5, 1)); module.Forward(input, output); - BOOST_REQUIRE_LE(arma::accu(output), 1e-5); + REQUIRE(arma::accu(output) <= 1e-5); // Test the Backward function. arma::mat gy = arma::zeros(5, 1); module.Backward(input, gy, delta); - BOOST_REQUIRE(arma::accu(delta) != 0); // klBackward will be added. + REQUIRE(arma::accu(delta) != 0); // klBackward will be added. } /** * Reparametrization module stochastic boolean test. */ -BOOST_AUTO_TEST_CASE(ReparametrizationLayerStochasticTest) +TEST_CASE("ReparametrizationLayerStochasticTest", "[ANNLayerTest]") { arma::mat input, outputA, outputB; Reparametrization<> module(5, false); @@ -2852,7 +2905,7 @@ BOOST_AUTO_TEST_CASE(ReparametrizationLayerStochasticTest) /** * Reparametrization module includeKl boolean test. */ -BOOST_AUTO_TEST_CASE(ReparametrizationLayerIncludeKlTest) +TEST_CASE("ReparametrizationLayerIncludeKlTest", "[ANNLayerTest]") { arma::mat input, output, gy, delta; Reparametrization<> module(5, true, false); @@ -2866,13 +2919,13 @@ BOOST_AUTO_TEST_CASE(ReparametrizationLayerIncludeKlTest) gy = arma::zeros(output.n_rows, output.n_cols); module.Backward(output, gy, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(arma::accu(delta) == 0); } /** * Jacobian Reparametrization module test. */ -BOOST_AUTO_TEST_CASE(JacobianReparametrizationLayerTest) +TEST_CASE("JacobianReparametrizationLayerTest", "[ANNLayerTest]") { for (size_t i = 0; i < 5; ++i) { @@ -2884,14 +2937,14 @@ BOOST_AUTO_TEST_CASE(JacobianReparametrizationLayerTest) Reparametrization<> module(inputElementsHalf, false, false); double error = JacobianTest(module, input); - BOOST_REQUIRE_LE(error, 1e-5); + REQUIRE(error <= 1e-5); } } /** * Reparametrization layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientReparametrizationLayerTest) +TEST_CASE("GradientReparametrizationLayerTest", "[ANNLayerTest]") { // Linear function gradient instantiation. struct GradientFunction @@ -2929,13 +2982,13 @@ BOOST_AUTO_TEST_CASE(GradientReparametrizationLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Reparametrization layer beta numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientReparametrizationLayerBetaTest) +TEST_CASE("GradientReparametrizationLayerBetaTest", "[ANNLayerTest]") { // Linear function gradient instantiation. struct GradientFunction @@ -2974,29 +3027,29 @@ BOOST_AUTO_TEST_CASE(GradientReparametrizationLayerBetaTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Test that the functions that can access the parameters of the * Reparametrization layer work. */ -BOOST_AUTO_TEST_CASE(ReparametrizationLayerParametersTest) +TEST_CASE("ReparametrizationLayerParametersTest", "[ANNLayerTest]") { // Parameter order : latentSize, stochastic, includeKL, beta. Reparametrization<> layer(5, false, false, 2); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer.OutputSize(), 5); - BOOST_REQUIRE_EQUAL(layer.Stochastic(), false); - BOOST_REQUIRE_EQUAL(layer.IncludeKL(), false); - BOOST_REQUIRE_EQUAL(layer.Beta(), 2); + REQUIRE(layer.OutputSize() == 5); + REQUIRE(layer.Stochastic() == false); + REQUIRE(layer.IncludeKL() == false); + REQUIRE(layer.Beta() == 2); } /** * Simple residual module test. */ -BOOST_AUTO_TEST_CASE(SimpleResidualLayerTest) +TEST_CASE("SimpleResidualLayerTest", "[ANNLayerTest]") { arma::mat outputA, outputB, input, deltaA, deltaB; @@ -3040,7 +3093,7 @@ BOOST_AUTO_TEST_CASE(SimpleResidualLayerTest) /** * Simple Highway module test. */ -BOOST_AUTO_TEST_CASE(SimpleHighwayLayerTest) +TEST_CASE("SimpleHighwayLayerTest", "[ANNLayerTest]") { arma::mat outputA, outputB, input, deltaA, deltaB; Sequential<>* sequential = new Sequential<>(true); @@ -3079,19 +3132,19 @@ BOOST_AUTO_TEST_CASE(SimpleHighwayLayerTest) * Test that the function that can access the inSize parameter of the * Highway layer works. */ -BOOST_AUTO_TEST_CASE(HighwayLayerParametersTest) +TEST_CASE("HighwayLayerParametersTest", "[ANNLayerTest]") { // Parameter order : inSize, model. Highway<> layer(1, true); // Make sure we can get the parameter successfully. - BOOST_REQUIRE_EQUAL(layer.InSize(), 1); + REQUIRE(layer.InSize() == 1); } /** * Sequential layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientHighwayLayerTest) +TEST_CASE("GradientHighwayLayerTest", "[ANNLayerTest]") { // Linear function gradient instantiation. struct GradientFunction @@ -3137,13 +3190,13 @@ BOOST_AUTO_TEST_CASE(GradientHighwayLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Sequential layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientSequentialLayerTest) +TEST_CASE("GradientSequentialLayerTest", "[ANNLayerTest]") { // Linear function gradient instantiation. struct GradientFunction @@ -3188,13 +3241,13 @@ BOOST_AUTO_TEST_CASE(GradientSequentialLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * WeightNorm layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientWeightNormLayerTest) +TEST_CASE("GradientWeightNormLayerTest", "[ANNLayerTest]") { // Linear function gradient instantiation. struct GradientFunction @@ -3235,14 +3288,14 @@ BOOST_AUTO_TEST_CASE(GradientWeightNormLayerTest) arma::mat input, target; } function; - BOOST_REQUIRE_LE(CheckGradient(function), 1e-4); + REQUIRE(CheckGradient(function) <= 1e-4); } /** * Test if the WeightNorm layer is able to forward the * Forward/Backward/Gradient calls. */ -BOOST_AUTO_TEST_CASE(WeightNormRunTest) +TEST_CASE("WeightNormRunTest", "[ANNLayerTest]") { arma::mat output, input, delta, error; @@ -3261,8 +3314,8 @@ BOOST_AUTO_TEST_CASE(WeightNormRunTest) // Test the Backward function. module.Backward(input, input, delta); - BOOST_REQUIRE_EQUAL(0, arma::accu(output)); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0); + REQUIRE(0 == arma::accu(output)); + REQUIRE(arma::accu(delta) == 0); } // General ANN serialization test. @@ -3306,7 +3359,7 @@ void ANNLayerSerializationTest(LayerType& layer) /** * Simple serialization test for batch normalization layer. */ -BOOST_AUTO_TEST_CASE(BatchNormSerializationTest) +TEST_CASE("BatchNormSerializationTest", "[ANNLayerTest]") { BatchNorm<> layer(10); ANNLayerSerializationTest(layer); @@ -3315,7 +3368,7 @@ BOOST_AUTO_TEST_CASE(BatchNormSerializationTest) /** * Simple serialization test for layer normalization layer. */ -BOOST_AUTO_TEST_CASE(LayerNormSerializationTest) +TEST_CASE("LayerNormSerializationTest", "[ANNLayerTest]") { LayerNorm<> layer(10); ANNLayerSerializationTest(layer); @@ -3325,7 +3378,7 @@ BOOST_AUTO_TEST_CASE(LayerNormSerializationTest) * Test that the functions that can modify and access the parameters of the * Convolution layer work. */ -BOOST_AUTO_TEST_CASE(ConvolutionLayerParametersTest) +TEST_CASE("ConvolutionLayerParametersTest", "[ANNLayerTest]") { // Parameter order: inSize, outSize, kW, kH, dW, dH, padW, padH, inputWidth, // inputHeight, paddingType. @@ -3335,16 +3388,16 @@ BOOST_AUTO_TEST_CASE(ConvolutionLayerParametersTest) std::tuple(10, 11), 12, 13, "none"); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer1.InputWidth(), 11); - BOOST_REQUIRE_EQUAL(layer1.InputHeight(), 12); - BOOST_REQUIRE_EQUAL(layer1.KernelWidth(), 3); - BOOST_REQUIRE_EQUAL(layer1.KernelHeight(), 4); - BOOST_REQUIRE_EQUAL(layer1.StrideWidth(), 5); - BOOST_REQUIRE_EQUAL(layer1.StrideHeight(), 6); - BOOST_REQUIRE_EQUAL(layer1.PadWLeft(), 7); - BOOST_REQUIRE_EQUAL(layer1.PadWRight(), 8); - BOOST_REQUIRE_EQUAL(layer1.PadHTop(), 9); - BOOST_REQUIRE_EQUAL(layer1.PadHBottom(), 10); + REQUIRE(layer1.InputWidth() == 11); + REQUIRE(layer1.InputHeight() == 12); + REQUIRE(layer1.KernelWidth() == 3); + REQUIRE(layer1.KernelHeight() == 4); + REQUIRE(layer1.StrideWidth() == 5); + REQUIRE(layer1.StrideHeight() == 6); + REQUIRE(layer1.PadWLeft() == 7); + REQUIRE(layer1.PadWRight() == 8); + REQUIRE(layer1.PadHTop() == 9); + REQUIRE(layer1.PadHBottom() == 10); // Now modify the parameters to match the second layer. layer1.InputWidth() = 12; @@ -3359,22 +3412,22 @@ BOOST_AUTO_TEST_CASE(ConvolutionLayerParametersTest) layer1.PadHBottom() = 11; // Now ensure all results are the same. - BOOST_REQUIRE_EQUAL(layer1.InputWidth(), layer2.InputWidth()); - BOOST_REQUIRE_EQUAL(layer1.InputHeight(), layer2.InputHeight()); - BOOST_REQUIRE_EQUAL(layer1.KernelWidth(), layer2.KernelWidth()); - BOOST_REQUIRE_EQUAL(layer1.KernelHeight(), layer2.KernelHeight()); - BOOST_REQUIRE_EQUAL(layer1.StrideWidth(), layer2.StrideWidth()); - BOOST_REQUIRE_EQUAL(layer1.StrideHeight(), layer2.StrideHeight()); - BOOST_REQUIRE_EQUAL(layer1.PadWLeft(), layer2.PadWLeft()); - BOOST_REQUIRE_EQUAL(layer1.PadWRight(), layer2.PadWRight()); - BOOST_REQUIRE_EQUAL(layer1.PadHTop(), layer2.PadHTop()); - BOOST_REQUIRE_EQUAL(layer1.PadHBottom(), layer2.PadHBottom()); + REQUIRE(layer1.InputWidth() == layer2.InputWidth()); + REQUIRE(layer1.InputHeight() == layer2.InputHeight()); + REQUIRE(layer1.KernelWidth() == layer2.KernelWidth()); + REQUIRE(layer1.KernelHeight() == layer2.KernelHeight()); + REQUIRE(layer1.StrideWidth() == layer2.StrideWidth()); + REQUIRE(layer1.StrideHeight() == layer2.StrideHeight()); + REQUIRE(layer1.PadWLeft() == layer2.PadWLeft()); + REQUIRE(layer1.PadWRight() == layer2.PadWRight()); + REQUIRE(layer1.PadHTop() == layer2.PadHTop()); + REQUIRE(layer1.PadHBottom() == layer2.PadHBottom()); } /** * Test that the padding options are working correctly in Convolution layer. */ -BOOST_AUTO_TEST_CASE(ConvolutionLayerPaddingTest) +TEST_CASE("ConvolutionLayerPaddingTest", "[ANNLayerTest]") { arma::mat output, input, delta; @@ -3388,9 +3441,9 @@ BOOST_AUTO_TEST_CASE(ConvolutionLayerPaddingTest) module1.Reset(); module1.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 0); - BOOST_REQUIRE_EQUAL(output.n_rows, 25); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 0); + REQUIRE(output.n_rows == 25); + REQUIRE(output.n_cols == 1); // Test the Backward function. module1.Backward(input, output, delta); @@ -3405,9 +3458,9 @@ BOOST_AUTO_TEST_CASE(ConvolutionLayerPaddingTest) module2.Reset(); module2.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 0); - BOOST_REQUIRE_EQUAL(output.n_rows, 49); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 0); + REQUIRE(output.n_rows == 49); + REQUIRE(output.n_cols == 1); // Test the backward function. module2.Backward(input, output, delta); @@ -3416,7 +3469,7 @@ BOOST_AUTO_TEST_CASE(ConvolutionLayerPaddingTest) /** * Test that the padding options in Transposed Convolution layer. */ -BOOST_AUTO_TEST_CASE(TransposedConvolutionLayerPaddingTest) +TEST_CASE("TransposedConvolutionLayerPaddingTest", "[ANNLayerTest]") { arma::mat output, input, delta; @@ -3428,11 +3481,11 @@ BOOST_AUTO_TEST_CASE(TransposedConvolutionLayerPaddingTest) module1.Reset(); module1.Forward(input, output); // Value calculated using tensorflow.nn.conv2d_transpose(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 0.0); + REQUIRE(arma::accu(output) == 0.0); // Test the Backward Function. module1.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0); + REQUIRE(arma::accu(delta) == 0.0); // Test Valid for non zero padding. TransposedConvolution<> module2(1, 1, 3, 3, 2, 2, @@ -3448,11 +3501,11 @@ BOOST_AUTO_TEST_CASE(TransposedConvolutionLayerPaddingTest) module2.Reset(); module2.Forward(input, output); // Value calculated using torch.nn.functional.conv_transpose2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 120.0); + REQUIRE(arma::accu(output) == 120.0); // Test the Backward Function. module2.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 960.0); + REQUIRE(arma::accu(delta) == 960.0); // Test for same padding type. TransposedConvolution<> module3(1, 1, 3, 3, 2, 2, 0, 0, 3, 3, 3, 3, "SAME"); @@ -3461,13 +3514,13 @@ BOOST_AUTO_TEST_CASE(TransposedConvolutionLayerPaddingTest) module3.Parameters() = arma::mat(9 + 1, 1, arma::fill::zeros); module3.Reset(); module3.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 0); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(arma::accu(output) == 0); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); // Test the Backward Function. module3.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0); + REQUIRE(arma::accu(delta) == 0.0); // Output shape should equal input. TransposedConvolution<> module4(1, 1, 3, 3, 1, 1, @@ -3478,13 +3531,13 @@ BOOST_AUTO_TEST_CASE(TransposedConvolutionLayerPaddingTest) module4.Parameters() = arma::mat(9 + 1, 1, arma::fill::zeros); module4.Reset(); module4.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 0); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(arma::accu(output) == 0); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); // Test the Backward Function. module4.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0); + REQUIRE(arma::accu(delta) == 0.0); TransposedConvolution<> module5(1, 1, 3, 3, 2, 2, 0, 0, 2, 2, 2, 2, "SAME"); // Test the forward function. @@ -3492,13 +3545,13 @@ BOOST_AUTO_TEST_CASE(TransposedConvolutionLayerPaddingTest) module5.Parameters() = arma::mat(25 + 1, 1, arma::fill::zeros); module5.Reset(); module5.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 0); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(arma::accu(output) == 0); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); // Test the Backward Function. module5.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0); + REQUIRE(arma::accu(delta) == 0.0); TransposedConvolution<> module6(1, 1, 4, 4, 1, 1, 1, 1, 5, 5, 5, 5, "SAME"); // Test the forward function. @@ -3506,19 +3559,19 @@ BOOST_AUTO_TEST_CASE(TransposedConvolutionLayerPaddingTest) module6.Parameters() = arma::mat(16 + 1, 1, arma::fill::zeros); module6.Reset(); module6.Forward(input, output); - BOOST_REQUIRE_EQUAL(arma::accu(output), 0); - BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); - BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + REQUIRE(arma::accu(output) == 0); + REQUIRE(output.n_rows == input.n_rows); + REQUIRE(output.n_cols == input.n_cols); // Test the Backward Function. module6.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0); + REQUIRE(arma::accu(delta) == 0.0); } /** * Simple test for Max Pooling layer. */ -BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) +TEST_CASE("MaxPoolingTestCase", "[ANNLayerTest]") { // For rectangular input to pooling layers. arma::mat input = arma::mat(12, 1); @@ -3540,9 +3593,9 @@ BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) module1.InputWidth() = 4; module1.Forward(input, output); // Calculated using torch.nn.MaxPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 28); - BOOST_REQUIRE_EQUAL(output.n_elem, 4); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 28); + REQUIRE(output.n_elem == 4); + REQUIRE(output.n_cols == 1); // For Square input. input = arma::mat(9, 1); @@ -3559,9 +3612,9 @@ BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) module2.InputWidth() = 3; module2.Forward(input, output); // Calculated using torch.nn.MaxPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 12.0); - BOOST_REQUIRE_EQUAL(output.n_elem, 2); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 12.0); + REQUIRE(output.n_elem == 2); + REQUIRE(output.n_cols == 1); // For Square input. input = arma::mat(16, 1); @@ -3578,9 +3631,9 @@ BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) module3.InputWidth() = 4; module3.Forward(input, output); // Calculated using torch.nn.MaxPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 30.0); - BOOST_REQUIRE_EQUAL(output.n_elem, 9); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 30.0); + REQUIRE(output.n_elem == 9); + REQUIRE(output.n_cols == 1); // For Rectangular input. input = arma::mat(6, 1); @@ -3595,73 +3648,73 @@ BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) module4.InputWidth() = 3; module4.Forward(input, output); // Calculated using torch.nn.MaxPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 3); - BOOST_REQUIRE_EQUAL(output.n_elem, 4); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 3); + REQUIRE(output.n_elem == 4); + REQUIRE(output.n_cols == 1); } /** * Test that the functions that can modify and access the parameters of the * Glimpse layer work. */ -BOOST_AUTO_TEST_CASE(GlimpseLayerParametersTest) +TEST_CASE("GlimpseLayerParametersTest", "[ANNLayerTest]") { // Parameter order : inSize, size, depth, scale, inputWidth, inputHeight. Glimpse<> layer1(1, 2, 3, 4, 5, 6); Glimpse<> layer2(1, 2, 3, 4, 6, 7); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer1.InputHeight(), 6); - BOOST_REQUIRE_EQUAL(layer1.InputWidth(), 5); - BOOST_REQUIRE_EQUAL(layer1.Scale(), 4); - BOOST_REQUIRE_EQUAL(layer1.Depth(), 3); - BOOST_REQUIRE_EQUAL(layer1.GlimpseSize(), 2); - BOOST_REQUIRE_EQUAL(layer1.InSize(), 1); + REQUIRE(layer1.InputHeight() == 6); + REQUIRE(layer1.InputWidth() == 5); + REQUIRE(layer1.Scale() == 4); + REQUIRE(layer1.Depth() == 3); + REQUIRE(layer1.GlimpseSize() == 2); + REQUIRE(layer1.InSize() == 1); // Now modify the parameters to match the second layer. layer1.InputHeight() = 7; layer1.InputWidth() = 6; // Now ensure that all the results are the same. - BOOST_REQUIRE_EQUAL(layer1.InputHeight(), layer2.InputHeight()); - BOOST_REQUIRE_EQUAL(layer1.InputWidth(), layer2.InputWidth()); - BOOST_REQUIRE_EQUAL(layer1.Scale(), layer2.Scale()); - BOOST_REQUIRE_EQUAL(layer1.Depth(), layer2.Depth()); - BOOST_REQUIRE_EQUAL(layer1.GlimpseSize(), layer2.GlimpseSize()); - BOOST_REQUIRE_EQUAL(layer1.InSize(), layer2.InSize()); + REQUIRE(layer1.InputHeight() == layer2.InputHeight()); + REQUIRE(layer1.InputWidth() == layer2.InputWidth()); + REQUIRE(layer1.Scale() == layer2.Scale()); + REQUIRE(layer1.Depth() == layer2.Depth()); + REQUIRE(layer1.GlimpseSize() == layer2.GlimpseSize()); + REQUIRE(layer1.InSize() == layer2.InSize()); } /** * Test that the function that can access the stdev parameter of the * Reinforce Normal layer works. */ -BOOST_AUTO_TEST_CASE(ReinforceNormalLayerParametersTest) +TEST_CASE("ReinforceNormalLayerParametersTest", "[ANNLayerTest]") { // Parameter : stdev. ReinforceNormal<> layer(4.0); // Make sure we can get the parameter successfully. - BOOST_REQUIRE_EQUAL(layer.StandardDeviation(), 4.0); + REQUIRE(layer.StandardDeviation() == 4.0); } /** * Test that the function that can access the parameters of the * VR Class Reward layer works. */ -BOOST_AUTO_TEST_CASE(VRClassRewardLayerParametersTest) +TEST_CASE("VRClassRewardLayerParametersTest", "[ANNLayerTest]") { // Parameter order : scale, sizeAverage. VRClassReward<> layer(2, false); // Make sure we can get the parameters successfully. - BOOST_REQUIRE_EQUAL(layer.Scale(), 2); - BOOST_REQUIRE_EQUAL(layer.SizeAverage(), false); + REQUIRE(layer.Scale() == 2); + REQUIRE(layer.SizeAverage() == false); } /** * Simple test for Adaptive pooling for Max Pooling layer. */ -BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) +TEST_CASE("AdaptiveMaxPoolingTestCase", "[ANNLayerTest]") { // For rectangular input. arma::mat input = arma::mat(12, 1); @@ -3684,12 +3737,12 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) module1.InputWidth() = 4; module1.Forward(input, output); // Calculated using torch.nn.AdaptiveMaxPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 28); - BOOST_REQUIRE_EQUAL(output.n_elem, 4); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 28); + REQUIRE(output.n_elem == 4); + REQUIRE(output.n_cols == 1); // Test the Backward Function. module1.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 28.0); + REQUIRE(arma::accu(delta) == 28.0); // For Square input. input = arma::mat(9, 1); @@ -3706,12 +3759,12 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) module2.InputWidth() = 3; module2.Forward(input, output); // Calculated using torch.nn.AdaptiveMaxPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 15.0); - BOOST_REQUIRE_EQUAL(output.n_elem, 2); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 15.0); + REQUIRE(output.n_elem == 2); + REQUIRE(output.n_cols == 1); // Test the Backward Function. module2.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 15.0); + REQUIRE(arma::accu(delta) == 15.0); // For Square input. input = arma::mat(16, 1); @@ -3728,12 +3781,12 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) module3.InputWidth() = 4; module3.Forward(input, output); // Calculated using torch.nn.AdaptiveMaxPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 30.0); - BOOST_REQUIRE_EQUAL(output.n_elem, 9); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 30.0); + REQUIRE(output.n_elem == 9); + REQUIRE(output.n_cols == 1); // Test the Backward Function. module3.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 30.0); + REQUIRE(arma::accu(delta) == 30.0); // For Rectangular input. input = arma::mat(20, 1); @@ -3748,18 +3801,18 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) module4.InputWidth() = 5; module4.Forward(input, output); // Calculated using torch.nn.AdaptiveMaxPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 2); - BOOST_REQUIRE_EQUAL(output.n_elem, 4); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 2); + REQUIRE(output.n_elem == 4); + REQUIRE(output.n_cols == 1); // Test the Backward Function. module4.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 2.0); + REQUIRE(arma::accu(delta) == 2.0); } /** * Simple test for Adaptive pooling for Mean Pooling layer. */ -BOOST_AUTO_TEST_CASE(AdaptiveMeanPoolingTestCase) +TEST_CASE("AdaptiveMeanPoolingTestCase", "[ANNLayerTest]") { // For rectangular input. arma::mat input = arma::mat(12, 1); @@ -3782,12 +3835,12 @@ BOOST_AUTO_TEST_CASE(AdaptiveMeanPoolingTestCase) module1.InputWidth() = 4; module1.Forward(input, output); // Calculated using torch.nn.AdaptiveAvgPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 19.75); - BOOST_REQUIRE_EQUAL(output.n_elem, 4); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 19.75); + REQUIRE(output.n_elem == 4); + REQUIRE(output.n_cols == 1); // Test the Backward Function. module1.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 7.0); + REQUIRE(arma::accu(delta) == 7.0); // For Square input. input = arma::mat(9, 1); @@ -3804,12 +3857,12 @@ BOOST_AUTO_TEST_CASE(AdaptiveMeanPoolingTestCase) module2.InputWidth() = 3; module2.Forward(input, output); // Calculated using torch.nn.AdaptiveAvgPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 4.5); - BOOST_REQUIRE_EQUAL(output.n_elem, 2); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 4.5); + REQUIRE(output.n_elem == 2); + REQUIRE(output.n_cols == 1); // Test the Backward Function. module2.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0); + REQUIRE(arma::accu(delta) == 0.0); // For Square input. input = arma::mat(16, 1); @@ -3826,12 +3879,12 @@ BOOST_AUTO_TEST_CASE(AdaptiveMeanPoolingTestCase) module3.InputWidth() = 4; module3.Forward(input, output); // Calculated using torch.nn.AdaptiveAvgPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 10.5); - BOOST_REQUIRE_EQUAL(output.n_elem, 9); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 10.5); + REQUIRE(output.n_elem == 9); + REQUIRE(output.n_cols == 1); // Test the Backward Function. module3.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 10.5); + REQUIRE(arma::accu(delta) == 10.5); // For Rectangular input. input = arma::mat(24, 1); @@ -3846,29 +3899,29 @@ BOOST_AUTO_TEST_CASE(AdaptiveMeanPoolingTestCase) module4.InputWidth() = 6; module4.Forward(input, output); // Calculated using torch.nn.AdaptiveAvgPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 2.25); - BOOST_REQUIRE_EQUAL(output.n_elem, 9); - BOOST_REQUIRE_EQUAL(output.n_cols, 1); + REQUIRE(arma::accu(output) == 2.25); + REQUIRE(output.n_elem == 9); + REQUIRE(output.n_cols == 1); // Test the Backward Function. module4.Backward(input, output, delta); - BOOST_REQUIRE_EQUAL(arma::accu(delta), 1.5); + REQUIRE(arma::accu(delta) == 1.5); } -BOOST_AUTO_TEST_CASE(TransposedConvolutionalLayerOptionalParameterTest) +TEST_CASE("TransposedConvolutionalLayerOptionalParameterTest", "[ANNLayerTest]") { Sequential<>* decoder = new Sequential<>(); // Check if we can create an object without specifying output. - BOOST_REQUIRE_NO_THROW(decoder->Add>(24, 16, + REQUIRE_NOTHROW(decoder->Add>(24, 16, 5, 5, 1, 1, 0, 0, 10, 10)); - BOOST_REQUIRE_NO_THROW(decoder->Add>(16, 1, + REQUIRE_NOTHROW(decoder->Add>(16, 1, 15, 15, 1, 1, 1, 1, 14, 14)); - delete decoder; + delete decoder; } -BOOST_AUTO_TEST_CASE(BatchNormWithMinBatchesTest) +TEST_CASE("BatchNormWithMinBatchesTest", "[ANNLayerTest]") { arma::mat input, output, result, runningMean, runningVar, delta; @@ -3903,7 +3956,7 @@ BOOST_AUTO_TEST_CASE(BatchNormWithMinBatchesTest) // Check backward function. module1.Backward(input, output, delta); - BOOST_REQUIRE_CLOSE(arma::accu(delta), 0.0102676, 1e-3); + REQUIRE(arma::accu(delta) == Approx(0.0102676).epsilon(1e-5)); // Check values for running mean and running variance. // Calculated using torch.nn.BatchNorm2d(). @@ -4024,7 +4077,7 @@ BOOST_AUTO_TEST_CASE(BatchNormWithMinBatchesTest) /** * Batch Normalization layer numerical gradient test. */ -BOOST_AUTO_TEST_CASE(GradientBatchNormWithMiniBatchesTest) +TEST_CASE("GradientBatchNormWithMiniBatchesTest", "[ANNLayerTest]") { // Add function gradient instantiation. // To make this test robust, check it ten times. @@ -4075,7 +4128,61 @@ BOOST_AUTO_TEST_CASE(GradientBatchNormWithMiniBatchesTest) } } - BOOST_REQUIRE(pass); + REQUIRE(pass); } -BOOST_AUTO_TEST_SUITE_END(); +TEST_CASE("ConvolutionLayerTestCase", "[ANNLayerTest]") +{ + arma::mat input, output; + + // The input test matrix is of the form 3 x 2 x 4 x 1 where + // number of images are 3 and number of feature maps are 2. + input = arma::mat(8, 3); + input << 1 << 446 << 42 << arma::endr + << 2 << 16 << 63 << arma::endr + << 3 << 13 << 63 << arma::endr + << 4 << 21 << 21 << arma::endr + << 1 << 13 << 11 << arma::endr + << 32 << 45 << 42 << arma::endr + << 22 << 16 << 63 << arma::endr + << 32 << 13 << 42 << arma::endr; + + Convolution<> layer(2, 4, 1, 1, 1, 1, 0, 0, 4, 1); + layer.Reset(); + + // Set weights to 1.0 and bias to 0.0. + layer.Parameters().zeros(); + arma::mat weight(2 * 4, 1); + weight.fill(1.0); + layer.Parameters().submat(arma::span(0, 2 * 4 - 1), arma::span()) = weight; + layer.Forward(input, output); + + // Value calculated using torch.nn.Conv2d(). + REQUIRE(arma::accu(output) == 4108); + + // Set bias to one. + layer.Parameters().fill(1.0); + layer.Forward(input, output); + + // Value calculated using torch.nn.Conv2d(). + REQUIRE(arma::accu(output) == 4156); +} + +TEST_CASE("BatchNormDeterministicTest", "[ANNLayerTest]") +{ + FFN<> module; + module.Add>(2, 1e-5, false); + module.Add>(); + + arma::mat input(4, 3), output; + module.ResetParameters(); + + // The model should switch to Deterministic mode for predicting. + module.Predict(input, output); + REQUIRE(boost::get*>(module.Model()[0])->Deterministic() == true); + + output.ones(); + module.Train(input, output); + // The model should switch to training mode for predicting. + REQUIRE(boost::get*>(module.Model()[0])->Deterministic() == 0); +} diff --git a/src/mlpack/tests/ann_regularizer_test.cpp b/src/mlpack/tests/ann_regularizer_test.cpp index a852e94d0c..2252852ee8 100644 --- a/src/mlpack/tests/ann_regularizer_test.cpp +++ b/src/mlpack/tests/ann_regularizer_test.cpp @@ -16,16 +16,14 @@ #include #include -#include +#include "catch.hpp" #include "ann_test_tools.hpp" -#include "serialization.hpp" +#include "serialization_catch.hpp" using namespace mlpack; using namespace mlpack::ann; -BOOST_AUTO_TEST_SUITE(ANNRegularizerTest); - -BOOST_AUTO_TEST_CASE(GradientL1RegularizerTest) +TEST_CASE("GradientL1RegularizerTest", "[ANNRegularizerTest]") { // Add function gradient instantiation. struct GradientFunction @@ -51,10 +49,10 @@ BOOST_AUTO_TEST_CASE(GradientL1RegularizerTest) L1Regularizer reg; } function; - BOOST_REQUIRE_LE(CheckRegularizerGradient(function), 1e-4); + REQUIRE(CheckRegularizerGradient(function) <= 1e-4); } -BOOST_AUTO_TEST_CASE(GradientL2RegularizerTest) +TEST_CASE("GradientL2RegularizerTest", "[ANNRegularizerTest]") { // Add function gradient instantiation. struct GradientFunction @@ -80,10 +78,10 @@ BOOST_AUTO_TEST_CASE(GradientL2RegularizerTest) L2Regularizer reg; } function; - BOOST_REQUIRE_LE(CheckRegularizerGradient(function), 1e-4); + REQUIRE(CheckRegularizerGradient(function) <= 1e-4); } -BOOST_AUTO_TEST_CASE(GradientOrthogonalRegularizerTest) +TEST_CASE("GradientOrthogonalRegularizerTest", "[ANNRegularizerTest]") { // Add function gradient instantiation. struct GradientFunction @@ -111,7 +109,5 @@ BOOST_AUTO_TEST_CASE(GradientOrthogonalRegularizerTest) OrthogonalRegularizer reg; } function; - BOOST_REQUIRE_LE(CheckRegularizerGradient(function), 1e-4); + REQUIRE(CheckRegularizerGradient(function) <= 1e-4); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/ann_visitor_test.cpp b/src/mlpack/tests/ann_visitor_test.cpp index 13b3e60657..1b01308ff3 100644 --- a/src/mlpack/tests/ann_visitor_test.cpp +++ b/src/mlpack/tests/ann_visitor_test.cpp @@ -15,18 +15,16 @@ #include #include -#include -#include "test_tools.hpp" +#include "catch.hpp" +#include "test_catch_tools.hpp" using namespace mlpack; using namespace mlpack::ann; -BOOST_AUTO_TEST_SUITE(ANNVisitorTest); - /** * Test that the BiasSetVisitor works properly. */ -BOOST_AUTO_TEST_CASE(BiasSetVisitorTest) +TEST_CASE("BiasSetVisitorTest", "[ANNVisitorTest]") { LayerTypes<> linear = new Linear<>(10, 10); @@ -43,16 +41,14 @@ BOOST_AUTO_TEST_CASE(BiasSetVisitorTest) size_t biasSize = boost::apply_visitor(BiasSetVisitor(weight, 0), linear); - BOOST_REQUIRE_EQUAL(biasSize, 10); + REQUIRE(biasSize == 10); arma::mat input(10, 1), output; input.randu(); boost::apply_visitor(ForwardVisitor(input, output), linear); - BOOST_REQUIRE_EQUAL(arma::accu(output), 55); + REQUIRE(arma::accu(output) == 55); boost::apply_visitor(DeleteVisitor(), linear); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/armadillo_svd_test.cpp b/src/mlpack/tests/armadillo_svd_test.cpp index 367c7e955e..96820f9148 100644 --- a/src/mlpack/tests/armadillo_svd_test.cpp +++ b/src/mlpack/tests/armadillo_svd_test.cpp @@ -1,10 +1,17 @@ +/** + * @file tests/armadillo_svd_test.cpp + * + * Test armadillo SVD. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ #include #include -#include -#include "test_tools.hpp" - -BOOST_AUTO_TEST_SUITE(ArmadilloSVDTest); +#include "catch.hpp" using namespace std; using namespace mlpack; @@ -13,13 +20,8 @@ using namespace arma; /** * Test armadillo SVD for normal factorization - * - * mlpack is free software; you may redistribute it and/or modify it under the - * terms of the 3-clause BSD license. You should have received a copy of the - * 3-clause BSD license along with mlpack. If not, see - * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -BOOST_AUTO_TEST_CASE(ArmadilloSVDNormalFactorizationTest) +TEST_CASE("ArmadilloSVDNormalFactorizationTest", "[ArmadilloSVDTest]") { mat test = randu(20, 20); @@ -27,18 +29,18 @@ BOOST_AUTO_TEST_CASE(ArmadilloSVDNormalFactorizationTest) arma::mat W, H, sigma; double result = svd.Apply(test, W, sigma, H); - BOOST_REQUIRE_LT(result, 0.01); + REQUIRE(result < 0.01); test = randu(50, 50); result = svd.Apply(test, W, sigma, H); - BOOST_REQUIRE_LT(result, 0.01); + REQUIRE(result < 0.01); } /** * Test armadillo SVD for low rank matrix factorization */ -BOOST_AUTO_TEST_CASE(ArmadilloSVDLowRankFactorizationTest) +TEST_CASE("ArmadilloSVDLowRankFactorizationTest", "[ArmadilloSVDTest]") { mat W_t = randu(30, 3); mat H_t = randu(3, 40); @@ -50,8 +52,5 @@ BOOST_AUTO_TEST_CASE(ArmadilloSVDLowRankFactorizationTest) arma::mat W, H; double result = svd.Apply(test, 3, W, H); - BOOST_REQUIRE_LT(result, 0.01); + REQUIRE(result < 0.01); } - - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/bayesian_linear_regression_test.cpp b/src/mlpack/tests/bayesian_linear_regression_test.cpp new file mode 100644 index 0000000000..d0c34509b9 --- /dev/null +++ b/src/mlpack/tests/bayesian_linear_regression_test.cpp @@ -0,0 +1,194 @@ +/** + * @file tests/bayesian_linear_regression_test.cpp + * @author Clement Mercier + * + * Test for BayesianLinearRegression. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#include +#include +#include + +#include + +using namespace mlpack::regression; +using namespace mlpack::data; + +BOOST_AUTO_TEST_SUITE(BayesianLinearRegressionTest); + +void GenerateProblem(arma::mat& matX, + arma::rowvec& y, + size_t nPoints, + size_t nDims, + float sigma = 0.0) +{ + matX = arma::randn(nDims, nPoints); + arma::colvec omega = arma::randn(nDims); + // Compute y and add noise. + y = omega.t() * matX + arma::randn(nPoints).t() * sigma; +} + +// Ensure that predictions are close enough to the target +// for a free noise dataset. +BOOST_AUTO_TEST_CASE(BayesianLinearRegressionRegressionTest) +{ + arma::mat matX; + arma::rowvec y, predictions; + + GenerateProblem(matX, y, 200, 10); + + // Instanciate and train the estimator. + BayesianLinearRegression estimator(true); + estimator.Train(matX, y); + estimator.Predict(matX, predictions); + + // Check the predictions are close enough to the targets in a free noise case. + for (size_t i = 0; i < y.size(); i++) + BOOST_REQUIRE_CLOSE(predictions[i], y[i], 1e-6); + + // Check that the estimated variance is zero. + BOOST_REQUIRE_SMALL(estimator.Variance(), 1e-6); +} + +// Verify centerData and scaleData equal false do not affect the solution. +BOOST_AUTO_TEST_CASE(TestCenter0ScaleData0) +{ + arma::mat matX; + arma::rowvec y; + size_t nDims = 30, nPoints = 100; + + GenerateProblem(matX, y, nPoints, nDims, 0.5); + + BayesianLinearRegression estimator(false, false); + + estimator.Train(matX, y); + + // Check dataOffset is empty. + BOOST_REQUIRE(estimator.DataOffset().n_elem == 0); + + // To be neutral responseOffset must be 0. + BOOST_REQUIRE(estimator.ResponsesOffset() == 0); + + // Check dataScale is empty. + BOOST_REQUIRE(estimator.DataScale().n_elem == 0); +} + +// Verify that centering and normalization are correct. +BOOST_AUTO_TEST_CASE(TestCenterDataTrueScaleDataTrue) +{ + arma::mat matX; + arma::rowvec y; + size_t nDims = 5, nPoints = 100; + GenerateProblem(matX, y, nPoints, nDims, 0.5); + + BayesianLinearRegression estimator(true, true); + estimator.Train(matX, y); + + arma::colvec xMean = arma::mean(matX, 1); + arma::colvec xStd = arma::stddev(matX, 0, 1); + double yMean = arma::mean(y); + + BOOST_REQUIRE_SMALL((double) abs(sum(estimator.DataOffset() - xMean)), 1e-6); + BOOST_REQUIRE_SMALL((double) abs(sum(estimator.DataScale() - xStd)), 1e-6); + BOOST_REQUIRE_CLOSE(estimator.ResponsesOffset(), yMean, 1e-6); +} + +// Make sure a model with center ans scale option set is different than a model +// without it set. +BOOST_AUTO_TEST_CASE(OptionsMakeModelDifferent) +{ + arma::mat matX; + arma::rowvec y; + size_t nDims = 10, nPoints = 100; + GenerateProblem(matX, y, nPoints, nDims, 0.5); + + BayesianLinearRegression blr(false, false), blrC(true, false), + blrCS(true, true); + + blr.Train(matX, y); + blrC.Train(matX, y); + blrCS.Train(matX, y); + + for (size_t i = 0; i < nDims; ++i) + BOOST_REQUIRE((blr.Omega()(i) != blrC.Omega()(i)) && + (blr.Omega()(i) != blrCS.Omega()(i)) && + (blrC.Omega()(i) != blrCS.Omega()(i))); +} + +// Check that Train() does not fail with two colinear vectors. +BOOST_AUTO_TEST_CASE(SingularMatix) +{ + arma::mat matX; + arma::rowvec y; + + GenerateProblem(matX, y, 200, 10); + // Now the first and the second rows are indentical. + matX.row(1) = matX.row(0); + + BayesianLinearRegression estimator; + estimator.Train(matX, y); +} + +// Check that std are well computed/coherent. At least higher than the +// estimated predictive variance. +BOOST_AUTO_TEST_CASE(PredictiveUncertainties) +{ + arma::mat matX; + arma::rowvec y; + + GenerateProblem(matX, y, 100, 10, 1); + + BayesianLinearRegression estimator(true, true); + estimator.Train(matX, y); + + arma::rowvec responses, std; + estimator.Predict(matX, responses, std); + const double estStd = sqrt(estimator.Variance()); + + for (size_t i = 0; i < matX.n_cols; i++) + BOOST_REQUIRE_GT(std[i], estStd); + + // Check that the estimated variance is close to 1. + BOOST_REQUIRE_CLOSE(estStd, 1, 30); +} + +// Check the solution is equal to the classical ridge. +BOOST_AUTO_TEST_CASE(EqualtoRidge) +{ + arma::mat matX; + arma::rowvec y, blrPred, ridgePred; + + size_t trial = 0; + for ( ; trial < 3; ++trial) + { + GenerateProblem(matX, y, 100, 10, 1); + + BayesianLinearRegression blr(false, false); + blr.Train(matX, y); + + LinearRegression ridge(matX, y, blr.Alpha() / blr.Beta(), false); + + blr.Predict(matX, blrPred); + ridge.Predict(matX, ridgePred); + + // If the predictions seem far off, just try again. + if (arma::norm(blrPred - ridgePred) > 1e-5) + continue; + + // Check the predictions are close enough between ridge and our blr. + for (size_t i = 0; i < y.size(); ++i) + BOOST_REQUIRE_CLOSE(blrPred[i], ridgePred[i], 1); + + // Exit once a test case has completed. + break; + } + + BOOST_REQUIRE_LT(trial, 3); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/bias_svd_test.cpp b/src/mlpack/tests/bias_svd_test.cpp index 9164b64bdf..bb9f3936f3 100644 --- a/src/mlpack/tests/bias_svd_test.cpp +++ b/src/mlpack/tests/bias_svd_test.cpp @@ -15,15 +15,12 @@ #include -#include -#include "test_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::svd; -BOOST_AUTO_TEST_SUITE(BiasSVDTest); - -BOOST_AUTO_TEST_CASE(BiasSVDFunctionRandomEvaluate) +TEST_CASE("BiasSVDFunctionRandomEvaluate", "[BiasSVDTest]") { // Define useful constants. const size_t numUsers = 100; @@ -69,11 +66,11 @@ BOOST_AUTO_TEST_CASE(BiasSVDFunctionRandomEvaluate) } // Compare calculated cost and value obtained using Evaluate(). - BOOST_REQUIRE_CLOSE(cost, biasSVDFunc.Evaluate(parameters), 1e-5); + REQUIRE(cost == Approx(biasSVDFunc.Evaluate(parameters)).epsilon(1e-7)); } } -BOOST_AUTO_TEST_CASE(BiasSVDFunctionRegularizationEvaluate) +TEST_CASE("BiasSVDFunctionRegularizationEvaluate", "[BiasSVDTest]") { // Define useful constants. const size_t numUsers = 100; @@ -123,14 +120,14 @@ BOOST_AUTO_TEST_CASE(BiasSVDFunctionRegularizationEvaluate) // Cost with regularization should be close to the sum of cost without // regularization and the regularization terms. - BOOST_REQUIRE_CLOSE(biasSVDFuncNoReg.Evaluate(parameters) + smallRegTerm, - biasSVDFuncSmallReg.Evaluate(parameters), 1e-5); - BOOST_REQUIRE_CLOSE(biasSVDFuncNoReg.Evaluate(parameters) + bigRegTerm, - biasSVDFuncBigReg.Evaluate(parameters), 1e-5); + REQUIRE(biasSVDFuncNoReg.Evaluate(parameters) + smallRegTerm == + Approx(biasSVDFuncSmallReg.Evaluate(parameters)).epsilon(1e-7)); + REQUIRE(biasSVDFuncNoReg.Evaluate(parameters) + bigRegTerm == + Approx(biasSVDFuncBigReg.Evaluate(parameters)).epsilon(1e-7)); } } -BOOST_AUTO_TEST_CASE(BiasSVDFunctionGradient) +TEST_CASE("BiasSVDFunctionGradient", "[BiasSVDTest]") { // Define useful constants. const size_t numUsers = 50; @@ -189,19 +186,19 @@ BOOST_AUTO_TEST_CASE(BiasSVDFunctionGradient) // Compare numerical and backpropagation gradient values. if (std::abs(gradient1(i, j)) <= 1e-6) - BOOST_REQUIRE_SMALL(numGradient1, 1e-5); + REQUIRE(numGradient1 == Approx(0.0).margin(1e-5)); else - BOOST_REQUIRE_CLOSE(numGradient1, gradient1(i, j), 0.02); + REQUIRE(numGradient1 == Approx(gradient1(i, j)).epsilon(0.0002)); if (std::abs(gradient2(i, j)) <= 1e-6) - BOOST_REQUIRE_SMALL(numGradient2, 1e-5); + REQUIRE(numGradient2 == Approx(0.0).margin(1e-5)); else - BOOST_REQUIRE_CLOSE(numGradient2, gradient2(i, j), 0.02); + REQUIRE(numGradient2 == Approx(gradient2(i, j)).epsilon(0.0002)); } } } -BOOST_AUTO_TEST_CASE(BiasSVDOutputSizeTest) +TEST_CASE("BiasSVDOutputSizeTest", "[BiasSVDTest]") { // Define useful constants. const size_t numUsers = 100; @@ -230,15 +227,15 @@ BOOST_AUTO_TEST_CASE(BiasSVDOutputSizeTest) biasSVD.Apply(data, rank, itemLatent, userLatent, itemBias, userBias); // Check the size of outputs. - BOOST_REQUIRE_EQUAL(itemLatent.n_rows, numItems); - BOOST_REQUIRE_EQUAL(itemLatent.n_cols, rank); - BOOST_REQUIRE_EQUAL(userLatent.n_rows, rank); - BOOST_REQUIRE_EQUAL(userLatent.n_cols, numUsers); - BOOST_REQUIRE_EQUAL(itemBias.n_elem, numItems); - BOOST_REQUIRE_EQUAL(userBias.n_elem, numUsers); + REQUIRE(itemLatent.n_rows == numItems); + REQUIRE(itemLatent.n_cols == rank); + REQUIRE(userLatent.n_rows == rank); + REQUIRE(userLatent.n_cols == numUsers); + REQUIRE(itemBias.n_elem == numItems); + REQUIRE(userBias.n_elem == numUsers); } -BOOST_AUTO_TEST_CASE(BiasSVDFunctionOptimize) +TEST_CASE("BiasSVDFunctionOptimize", "[BiasSVDTest]") { // Define useful constants. const size_t numUsers = 50; @@ -299,7 +296,7 @@ BOOST_AUTO_TEST_CASE(BiasSVDFunctionOptimize) arma::norm(data, "frob"); // Relative error should be small. - BOOST_REQUIRE_SMALL(relativeError, 1e-2); + REQUIRE(relativeError == Approx(0.0).margin(1e-2)); } // The test is only compiled if the user has specified OpenMP to be @@ -307,7 +304,7 @@ BOOST_AUTO_TEST_CASE(BiasSVDFunctionOptimize) #ifdef HAS_OPENMP // Test Bias SVD with parallel SGD. -BOOST_AUTO_TEST_CASE(BiasSVDFunctionParallelOptimize) +TEST_CASE("BiasSVDFunctionParallelOptimize", "[BiasSVDTest]") { // Define useful constants. const size_t numUsers = 50; @@ -374,9 +371,7 @@ BOOST_AUTO_TEST_CASE(BiasSVDFunctionParallelOptimize) arma::norm(data, "frob"); // Relative error should be small. - BOOST_REQUIRE_SMALL(relativeError, 1e-2); + REQUIRE(relativeError == Approx(0.0).margin(1e-2)); } #endif - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/block_krylov_svd_test.cpp b/src/mlpack/tests/block_krylov_svd_test.cpp index 2ef1bf1116..3c24b9d1b5 100644 --- a/src/mlpack/tests/block_krylov_svd_test.cpp +++ b/src/mlpack/tests/block_krylov_svd_test.cpp @@ -13,10 +13,7 @@ #include #include -#include -#include "test_tools.hpp" - -BOOST_AUTO_TEST_SUITE(BlockKrylovSVDTest); +#include "catch.hpp" using namespace mlpack; @@ -48,7 +45,8 @@ void CreateNoisyLowRankMatrix(arma::mat& data, * The reconstruction and sigular value error of the obtained SVD should be * small. */ -BOOST_AUTO_TEST_CASE(RandomizedBlockKrylovSVDReconstructionError) +TEST_CASE("RandomizedBlockKrylovSVDReconstructionError", + "[BlockKrylovSVDTest]") { arma::mat U = arma::randn(3, 20); arma::mat V = arma::randn(10, 3); @@ -78,20 +76,20 @@ BOOST_AUTO_TEST_CASE(RandomizedBlockKrylovSVDReconstructionError) // The sigular value error should be small. double error = arma::norm(s2 - s3, "frob") / arma::norm(s2, "frob"); - BOOST_REQUIRE_SMALL(error, 1e-5); + REQUIRE(error == Approx(0.0).margin(1e-5)); arma::mat reconstruct = U2 * arma::diagmat(s2) * V2.t(); // The relative reconstruction error should be small. error = arma::norm(centeredData - reconstruct, "frob") / arma::norm(centeredData, "frob"); - BOOST_REQUIRE_SMALL(error, 1e-5); + REQUIRE(error == Approx(0.0).margin(1e-7)); } /* * Check if the method can handle noisy matrices. */ -BOOST_AUTO_TEST_CASE(RandomizedBlockKrylovSVDNoisyLowRankTest) +TEST_CASE("RandomizedBlockKrylovSVDNoisyLowRankTest", "[BlockKrylovSVDTest]") { arma::mat data; CreateNoisyLowRankMatrix(data, 200, 1000, 5, 0.5); @@ -106,7 +104,5 @@ BOOST_AUTO_TEST_CASE(RandomizedBlockKrylovSVDNoisyLowRankTest) svd::RandomizedBlockKrylovSVD rSVDB(data, U2, s2, V2, 10, rank, 20); double error = arma::max(arma::abs(s1.subvec(0, rank) - s2.subvec(0, rank))); - BOOST_REQUIRE_SMALL(error, 1e-2); + REQUIRE(error == Approx(0.0).margin(1e-4)); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/decision_stump_test.cpp b/src/mlpack/tests/decision_stump_test.cpp index 58418ff416..d2fe36cc08 100644 --- a/src/mlpack/tests/decision_stump_test.cpp +++ b/src/mlpack/tests/decision_stump_test.cpp @@ -12,22 +12,19 @@ #include #include -#include -#include "test_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::decision_stump; using namespace arma; using namespace mlpack::distribution; -BOOST_AUTO_TEST_SUITE(DecisionStumpTest); - /** * This tests handles the case wherein only one class exists in the input * labels. It checks whether the only class supplied was the only class * predicted. */ -BOOST_AUTO_TEST_CASE(OneClass) +TEST_CASE("OneClass", "[DecisionStumpTest]") { const size_t numClasses = 2; const size_t inpBucketSize = 6; @@ -50,7 +47,7 @@ BOOST_AUTO_TEST_CASE(OneClass) ds.Classify(testingData, predictedLabels); for (size_t i = 0; i < predictedLabels.size(); ++i) - BOOST_CHECK_EQUAL(predictedLabels(i), 1); + REQUIRE(predictedLabels(i) == 1); } /** @@ -58,7 +55,7 @@ BOOST_AUTO_TEST_CASE(OneClass) * correct value of the splitting column value. This test is for an * inpBucketSize of 4 and the correct value of the splitting dimension is 0. */ -BOOST_AUTO_TEST_CASE(CorrectDimensionChosen) +TEST_CASE("CorrectDimensionChosen", "[DecisionStumpTest]") { const size_t numClasses = 2; const size_t inpBucketSize = 4; @@ -84,7 +81,7 @@ BOOST_AUTO_TEST_CASE(CorrectDimensionChosen) // Only need to check the value of the splitting column, no need of // classification. - BOOST_CHECK_EQUAL(ds.SplitDimension(), 0); + REQUIRE(ds.SplitDimension() == 0); } /** @@ -93,7 +90,7 @@ BOOST_AUTO_TEST_CASE(CorrectDimensionChosen) * if testinput > 0 - class 1 * An almost perfect split on zero. */ -BOOST_AUTO_TEST_CASE(PerfectSplitOnZero) +TEST_CASE("PerfectSplitOnZero", "[DecisionStumpTest]") { const size_t numClasses = 2; const size_t inpBucketSize = 2; @@ -113,18 +110,18 @@ BOOST_AUTO_TEST_CASE(PerfectSplitOnZero) Row predictedLabels; ds.Classify(testingData, predictedLabels); - BOOST_CHECK_EQUAL(predictedLabels(0, 0), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 1), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 2), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 3), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 4), 1); + REQUIRE(predictedLabels(0, 0) == 0); + REQUIRE(predictedLabels(0, 1) == 1); + REQUIRE(predictedLabels(0, 2) == 0); + REQUIRE(predictedLabels(0, 3) == 0); + REQUIRE(predictedLabels(0, 4) == 1); } /** * This tests the binning function for the case when a dataset with cardinality * of input < inpBucketSize is provided. */ -BOOST_AUTO_TEST_CASE(BinningTesting) +TEST_CASE("BinningTesting", "[DecisionStumpTest]") { const size_t numClasses = 2; const size_t inpBucketSize = 10; @@ -144,7 +141,7 @@ BOOST_AUTO_TEST_CASE(BinningTesting) Row predictedLabels; ds.Classify(testingData, predictedLabels); - BOOST_CHECK_EQUAL(predictedLabels(0, 0), 0); + REQUIRE(predictedLabels(0, 0) == 0); } /** @@ -152,7 +149,7 @@ BOOST_AUTO_TEST_CASE(BinningTesting) * provided. It tests for a perfect split due to the non-overlapping nature of * the input classes. */ -BOOST_AUTO_TEST_CASE(PerfectMultiClassSplit) +TEST_CASE("PerfectMultiClassSplit", "[DecisionStumpTest]") { const size_t numClasses = 4; const size_t inpBucketSize = 3; @@ -174,10 +171,10 @@ BOOST_AUTO_TEST_CASE(PerfectMultiClassSplit) Row predictedLabels; ds.Classify(testingData, predictedLabels); - BOOST_CHECK_EQUAL(predictedLabels(0, 0), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 1), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 2), 2); - BOOST_CHECK_EQUAL(predictedLabels(0, 3), 3); + REQUIRE(predictedLabels(0, 0) == 0); + REQUIRE(predictedLabels(0, 1) == 1); + REQUIRE(predictedLabels(0, 2) == 2); + REQUIRE(predictedLabels(0, 3) == 3); } /** @@ -186,7 +183,7 @@ BOOST_AUTO_TEST_CASE(PerfectMultiClassSplit) * with a reasonable amount of error due to the overlapping nature of input * classes. */ -BOOST_AUTO_TEST_CASE(MultiClassSplit) +TEST_CASE("MultiClassSplit", "[DecisionStumpTest]") { const size_t numClasses = 3; const size_t inpBucketSize = 3; @@ -209,21 +206,21 @@ BOOST_AUTO_TEST_CASE(MultiClassSplit) Row predictedLabels; ds.Classify(testingData, predictedLabels); - BOOST_CHECK_EQUAL(predictedLabels(0, 0), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 1), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 2), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 3), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 4), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 5), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 6), 2); - BOOST_CHECK_EQUAL(predictedLabels(0, 7), 2); + REQUIRE(predictedLabels(0, 0) == 0); + REQUIRE(predictedLabels(0, 1) == 0); + REQUIRE(predictedLabels(0, 2) == 1); + REQUIRE(predictedLabels(0, 3) == 1); + REQUIRE(predictedLabels(0, 4) == 1); + REQUIRE(predictedLabels(0, 5) == 1); + REQUIRE(predictedLabels(0, 6) == 2); + REQUIRE(predictedLabels(0, 7) == 2); } /** * This tests that the decision stump can learn a good split on a dataset with * four dimensions that have progressing levels of separation. */ -BOOST_AUTO_TEST_CASE(DimensionSelectionTest) +TEST_CASE("DimensionSelectionTest", "[DecisionStumpTest]") { const size_t numClasses = 2; const size_t inpBucketSize = 2500; @@ -299,16 +296,16 @@ BOOST_AUTO_TEST_CASE(DimensionSelectionTest) DecisionStump<> ds(dataset, labels, numClasses, inpBucketSize); // Make sure it split on the dimension that is most separable. - BOOST_CHECK_EQUAL(ds.SplitDimension(), 1); + REQUIRE(ds.SplitDimension() == 1); // Make sure every bin below -1 classifies as label 0, and every bin above 1 // classifies as label 1 (What happens in [-1, 1] isn't that big a deal.). for (size_t i = 0; i < ds.Split().n_elem; ++i) { if (ds.Split()[i] <= -3.0) - BOOST_CHECK_EQUAL(ds.BinLabels()[i], 0); + REQUIRE(ds.BinLabels()[i] == 0); else if (ds.Split()[i] >= 3.0) - BOOST_CHECK_EQUAL(ds.BinLabels()[i], 1); + REQUIRE(ds.BinLabels()[i] == 1); } } @@ -316,7 +313,7 @@ BOOST_AUTO_TEST_CASE(DimensionSelectionTest) * Ensure that the default constructor works and that it classifies things as 0 * always. */ -BOOST_AUTO_TEST_CASE(EmptyConstructorTest) +TEST_CASE("EmptyConstructorTest", "[DecisionStumpTest]") { DecisionStump<> d; @@ -326,7 +323,7 @@ BOOST_AUTO_TEST_CASE(EmptyConstructorTest) d.Classify(data, labels); for (size_t i = 0; i < 10; ++i) - BOOST_REQUIRE_EQUAL(labels[i], 0); + REQUIRE(labels[i] == 0); // Now train on another dataset and make sure something kind of makes sense. mat trainingData; @@ -347,21 +344,21 @@ BOOST_AUTO_TEST_CASE(EmptyConstructorTest) Row predictedLabels(testingData.n_cols); ds.Classify(testingData, predictedLabels); - BOOST_CHECK_EQUAL(predictedLabels(0, 0), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 1), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 2), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 3), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 4), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 5), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 6), 2); - BOOST_CHECK_EQUAL(predictedLabels(0, 7), 2); + REQUIRE(predictedLabels(0, 0) == 0); + REQUIRE(predictedLabels(0, 1) == 0); + REQUIRE(predictedLabels(0, 2) == 1); + REQUIRE(predictedLabels(0, 3) == 1); + REQUIRE(predictedLabels(0, 4) == 1); + REQUIRE(predictedLabels(0, 5) == 1); + REQUIRE(predictedLabels(0, 6) == 2); + REQUIRE(predictedLabels(0, 7) == 2); } /** * Ensure that a matrix holding ints can be trained. The bigger issue here is * just compilation. */ -BOOST_AUTO_TEST_CASE(IntTest) +TEST_CASE("IntTest", "[DecisionStumpTest]") { // Train on a dataset and make sure something kind of makes sense. imat trainingData; @@ -381,20 +378,20 @@ BOOST_AUTO_TEST_CASE(IntTest) arma::Row predictedLabels; ds.Classify(testingData, predictedLabels); - BOOST_CHECK_EQUAL(predictedLabels(0, 0), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 1), 0); - BOOST_CHECK_EQUAL(predictedLabels(0, 2), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 3), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 4), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 5), 1); - BOOST_CHECK_EQUAL(predictedLabels(0, 6), 2); - BOOST_CHECK_EQUAL(predictedLabels(0, 7), 2); + REQUIRE(predictedLabels(0, 0) == 0); + REQUIRE(predictedLabels(0, 1) == 0); + REQUIRE(predictedLabels(0, 2) == 1); + REQUIRE(predictedLabels(0, 3) == 1); + REQUIRE(predictedLabels(0, 4) == 1); + REQUIRE(predictedLabels(0, 5) == 1); + REQUIRE(predictedLabels(0, 6) == 2); + REQUIRE(predictedLabels(0, 7) == 2); } /** * Test that DecisionStump::Train() returns finite gain. */ -BOOST_AUTO_TEST_CASE(DecisionStumpTrainReturnEntropy) +TEST_CASE("DecisionStumpTrainReturnEntropy", "[DecisionStumpTest]") { const size_t numClasses = 2; const size_t inpBucketSize = 2; @@ -413,14 +410,12 @@ BOOST_AUTO_TEST_CASE(DecisionStumpTrainReturnEntropy) double gain = ds.Train(trainingData, labelsIn.row(0), numClasses, inpBucketSize); - BOOST_REQUIRE_EQUAL(std::isfinite(gain), true); + REQUIRE(std::isfinite(gain) == true); // Train decision stump with weights. DecisionStump<> wds; gain = wds.Train(trainingData, labelsIn.row(0), weights, numClasses, inpBucketSize); - BOOST_REQUIRE_EQUAL(std::isfinite(gain), true); + REQUIRE(std::isfinite(gain) == true); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index f96203cf2d..d1ae2225a1 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -16,8 +16,7 @@ #include #include -#include -#include "test_tools.hpp" +#include "catch.hpp" #include "serialization.hpp" #include "mock_categorical_data.hpp" @@ -25,12 +24,10 @@ using namespace mlpack; using namespace mlpack::tree; using namespace mlpack::distribution; -BOOST_AUTO_TEST_SUITE(DecisionTreeTest); - /** * Make sure the Gini gain is zero when the labels are perfect. */ -BOOST_AUTO_TEST_CASE(GiniGainPerfectTest) +TEST_CASE("GiniGainPerfectTest", "[DecisionTreeTest]") { arma::rowvec weights(10, arma::fill::ones); arma::Row labels; @@ -38,14 +35,17 @@ BOOST_AUTO_TEST_CASE(GiniGainPerfectTest) // Test that it's perfect regardless of number of classes. for (size_t c = 1; c < 10; ++c) - BOOST_REQUIRE_SMALL(GiniGain::Evaluate(labels, c, weights), 1e-5); + { + REQUIRE(GiniGain::Evaluate(labels, c, weights) == + Approx(0.0).margin(1e-5)); + } } /** * Make sure the Gini gain is -0.5 when the class split between two classes * is even. */ -BOOST_AUTO_TEST_CASE(GiniGainEvenSplitTest) +TEST_CASE("GiniGainEvenSplitTest", "[DecisionTreeTest]") { arma::rowvec weights = arma::ones(10); arma::Row labels(10); @@ -57,35 +57,41 @@ BOOST_AUTO_TEST_CASE(GiniGainEvenSplitTest) // Test that it's -0.5 regardless of the number of classes. for (size_t c = 2; c < 10; ++c) { - BOOST_REQUIRE_CLOSE( - GiniGain::Evaluate(labels, c, weights), -0.5, 1e-5); + REQUIRE(GiniGain::Evaluate(labels, c, weights) == + Approx(-0.5).epsilon(1e-7)); + double weightedGain = GiniGain::Evaluate(labels, c, weights); // The weighted gain should stay the same with unweight one - BOOST_REQUIRE_EQUAL( - GiniGain::Evaluate(labels, c, weights), weightedGain); + REQUIRE(GiniGain::Evaluate(labels, c, weights) == weightedGain); } } /** * The Gini gain of an empty vector is 0. */ -BOOST_AUTO_TEST_CASE(GiniGainEmptyTest) +TEST_CASE("GiniGainEmptyTest", "[DecisionTreeTest]") { arma::rowvec weights = arma::ones(10); // Test across some numbers of classes. arma::Row labels; for (size_t c = 1; c < 10; ++c) - BOOST_REQUIRE_SMALL(GiniGain::Evaluate(labels, c, weights), 1e-5); + { + REQUIRE(GiniGain::Evaluate(labels, c, weights) == + Approx(0.0).margin(1e-5)); + } for (size_t c = 1; c < 10; ++c) - BOOST_REQUIRE_SMALL(GiniGain::Evaluate(labels, c, weights), 1e-5); + { + REQUIRE(GiniGain::Evaluate(labels, c, weights) == + Approx(0.0).margin(1e-5)); + } } /** * The Gini gain is -(1 - 1/k) for k classes evenly split. */ -BOOST_AUTO_TEST_CASE(GiniGainEvenSplitManyClassTest) +TEST_CASE("GiniGainEvenSplitManyClassTest", "[DecisionTreeTest]") { // Try with many different classes. for (size_t c = 2; c < 30; ++c) @@ -99,17 +105,17 @@ BOOST_AUTO_TEST_CASE(GiniGainEvenSplitManyClassTest) } // Calculate Gini gain and make sure it is correct. - BOOST_REQUIRE_CLOSE(GiniGain::Evaluate(labels, c, weights), - -(1.0 - 1.0 / c), 1e-5); - BOOST_REQUIRE_CLOSE(GiniGain::Evaluate(labels, c, weights), - -(1.0 - 1.0 / c), 1e-5); + REQUIRE(GiniGain::Evaluate(labels, c, weights) == + Approx(-(1.0 - 1.0 / c)).epsilon(1e-7)); + REQUIRE(GiniGain::Evaluate(labels, c, weights) == + Approx(-(1.0 - 1.0 / c)).epsilon(1e-7)); } } /** * The Gini gain should not be sensitive to the number of points. */ -BOOST_AUTO_TEST_CASE(GiniGainManyPoints) +TEST_CASE("GiniGainManyPoints", "[DecisionTreeTest]") { for (size_t i = 1; i < 20; ++i) { @@ -121,11 +127,10 @@ BOOST_AUTO_TEST_CASE(GiniGainManyPoints) labels[j] = 0; for (size_t j = numPoints / 2; j < numPoints; ++j) labels[j] = 1; - - BOOST_REQUIRE_CLOSE(GiniGain::Evaluate(labels, 2, weights), -0.5, - 1e-5); - BOOST_REQUIRE_CLOSE(GiniGain::Evaluate(labels, 2, weights), -0.5, - 1e-5); + REQUIRE(GiniGain::Evaluate(labels, 2, weights) == + Approx(-0.5).epsilon(1e-7)); + REQUIRE(GiniGain::Evaluate(labels, 2, weights) == + Approx(-0.5).epsilon(1e-7)); } } @@ -133,7 +138,7 @@ BOOST_AUTO_TEST_CASE(GiniGainManyPoints) /** * To make sure the Gini gain can been cacluate proporately with weight. */ -BOOST_AUTO_TEST_CASE(GiniGainWithWeight) +TEST_CASE("GiniGainWithWeight", "[DecisionTreeTest]") { arma::Row labels(10); arma::rowvec weights(10); @@ -148,14 +153,14 @@ BOOST_AUTO_TEST_CASE(GiniGainWithWeight) weights[i] = 0.7; } - BOOST_REQUIRE_CLOSE( - GiniGain::Evaluate(labels, 2, weights), -0.42, 1e-5); + REQUIRE(GiniGain::Evaluate(labels, 2, weights) == + Approx(-0.42).epsilon(1e-7)); } /** * The information gain should be zero when the labels are perfect. */ -BOOST_AUTO_TEST_CASE(InformationGainPerfectTest) +TEST_CASE("InformationGainPerfectTest", "[DecisionTreeTest]") { arma::rowvec weights; arma::Row labels; @@ -164,15 +169,15 @@ BOOST_AUTO_TEST_CASE(InformationGainPerfectTest) // Test that it's perfect regardless of number of classes. for (size_t c = 1; c < 10; ++c) { - BOOST_REQUIRE_SMALL( - InformationGain::Evaluate(labels, c, weights), 1e-5); + REQUIRE(InformationGain::Evaluate(labels, c, weights) == + Approx(0.0).margin(1e-5)); } } /** * If we have an even split, the information gain should be -1. */ -BOOST_AUTO_TEST_CASE(InformationGainEvenSplitTest) +TEST_CASE("InformationGainEvenSplitTest", "[DecisionTreeTest]") { arma::Row labels(10); arma::rowvec weights(10); @@ -186,33 +191,33 @@ BOOST_AUTO_TEST_CASE(InformationGainEvenSplitTest) for (size_t c = 2; c < 10; ++c) { // Weighted and unweighted result should be the same. - BOOST_REQUIRE_CLOSE(InformationGain::Evaluate(labels, c, weights), - -1.0, 1e-5); - BOOST_REQUIRE_CLOSE(InformationGain::Evaluate(labels, c, weights), - -1.0, 1e-5); + REQUIRE(InformationGain::Evaluate(labels, c, weights) == + Approx(-1.0).epsilon(1e-7)); + REQUIRE(InformationGain::Evaluate(labels, c, weights) == + Approx(-1.0).epsilon(1e-7)); } } /** * The information gain of an empty vector is 0. */ -BOOST_AUTO_TEST_CASE(InformationGainEmptyTest) +TEST_CASE("InformationGainEmptyTest", "[DecisionTreeTest]") { arma::Row labels; arma::rowvec weights = arma::ones(10); for (size_t c = 1; c < 10; ++c) { - BOOST_REQUIRE_SMALL(InformationGain::Evaluate(labels, c, weights), - 1e-5); - BOOST_REQUIRE_SMALL(InformationGain::Evaluate(labels, c, weights), - 1e-5); + REQUIRE(InformationGain::Evaluate(labels, c, weights) == + Approx(0.0).margin(1e-5)); + REQUIRE(InformationGain::Evaluate(labels, c, weights) == + Approx(0.0).margin(1e-5)); } } /** * The information gain is log2(1/k) when splitting equal classes. */ -BOOST_AUTO_TEST_CASE(InformationGainEvenSplitManyClassTest) +TEST_CASE("InformationGainEvenSplitManyClassTest", "[DecisionTreeTest]") { arma::rowvec weights; // Try with many different numbers of classes. @@ -223,15 +228,15 @@ BOOST_AUTO_TEST_CASE(InformationGainEvenSplitManyClassTest) labels[i] = i; // Calculate information gain and make sure it is correct. - BOOST_REQUIRE_CLOSE(InformationGain::Evaluate(labels, c, weights), - std::log2(1.0 / c), 1e-5); + REQUIRE(InformationGain::Evaluate(labels, c, weights) == + Approx(std::log2(1.0 / c)).epsilon(1e-7)); } } /** * Test the information gain with weighted labels */ -BOOST_AUTO_TEST_CASE(InformationWithWeight) +TEST_CASE("InformationWithWeight", "[DecisionTreeTest]") { arma::Row labels(10); arma::rowvec weights("1 1 1 1 1 0 0 0 0 0"); @@ -242,15 +247,15 @@ BOOST_AUTO_TEST_CASE(InformationWithWeight) // Zero is not a good result as gain, but we just need to prove // cacluation works. - BOOST_REQUIRE_CLOSE( - InformationGain::Evaluate(labels, 2, weights), 0, 1e-5); + REQUIRE(InformationGain::Evaluate(labels, 2, weights) == + Approx(0).epsilon(1e-7)); } /** * The information gain should not be sensitive to the number of points. */ -BOOST_AUTO_TEST_CASE(InformationGainManyPoints) +TEST_CASE("InformationGainManyPoints", "[DecisionTreeTest]") { for (size_t i = 1; i < 20; ++i) { @@ -262,12 +267,13 @@ BOOST_AUTO_TEST_CASE(InformationGainManyPoints) for (size_t j = numPoints / 2; j < numPoints; ++j) labels[j] = 1; - BOOST_REQUIRE_CLOSE(InformationGain::Evaluate(labels, 2, weights), - -1.0, 1e-5); + REQUIRE(InformationGain::Evaluate(labels, 2, weights) == + Approx(-1.0).epsilon(1e-7)); + // It should make no difference between a weighted and unweighted // calculation. - BOOST_REQUIRE_CLOSE(InformationGain::Evaluate(labels, 2, weights), - -1.0, 1e-5); + REQUIRE(InformationGain::Evaluate(labels, 2, weights) == + Approx(-1.0).epsilon(1e-7)); } } @@ -275,7 +281,7 @@ BOOST_AUTO_TEST_CASE(InformationGainManyPoints) * Check that the BestBinaryNumericSplit will split on an obviously splittable * dimension. */ -BOOST_AUTO_TEST_CASE(BestBinaryNumericSplitSimpleSplitTest) +TEST_CASE("BestBinaryNumericSplitSimpleSplitTest", "[DecisionTreeTest]") { arma::vec values("0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0"); arma::Row labels("0 0 0 0 0 1 1 1 1 1 1"); @@ -295,26 +301,26 @@ BOOST_AUTO_TEST_CASE(BestBinaryNumericSplitSimpleSplitTest) labels, 2, weights, 3, 1e-7, classProbabilities, aux); // Make sure that a split was made. - BOOST_REQUIRE_GT(gain, bestGain); + REQUIRE(gain > bestGain); // Make sure weight works and is not different than the unweighted one. - BOOST_REQUIRE_EQUAL(gain, weightedGain); + REQUIRE(gain == weightedGain); // The split is perfect, so we should be able to accomplish a gain of 0. - BOOST_REQUIRE_SMALL(gain, 1e-5); + REQUIRE(gain == Approx(0.0).margin(1e-7)); // The class probabilities, for this split, hold the splitting point, which // should be between 4 and 5. - BOOST_REQUIRE_EQUAL(classProbabilities.n_elem, 1); - BOOST_REQUIRE_GT(classProbabilities[0], 0.4); - BOOST_REQUIRE_LT(classProbabilities[0], 0.5); + REQUIRE(classProbabilities.n_elem == 1); + REQUIRE(classProbabilities[0] > 0.4); + REQUIRE(classProbabilities[0] < 0.5); } /** * Check that the BestBinaryNumericSplit won't split if not enough points are * given. */ -BOOST_AUTO_TEST_CASE(BestBinaryNumericSplitMinSamplesTest) +TEST_CASE("BestBinaryNumericSplitMinSamplesTest", "[DecisionTreeTest]") { arma::vec values("0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0"); arma::Row labels("0 0 0 0 0 1 1 1 1 1 1"); @@ -334,16 +340,16 @@ BOOST_AUTO_TEST_CASE(BestBinaryNumericSplitMinSamplesTest) labels, 2, weights, 8, 1e-7, classProbabilities, aux); // Make sure that no split was made. - BOOST_REQUIRE_EQUAL(gain, DBL_MAX); - BOOST_REQUIRE_EQUAL(gain, weightedGain); - BOOST_REQUIRE_EQUAL(classProbabilities.n_elem, 0); + REQUIRE(gain == DBL_MAX); + REQUIRE(gain == weightedGain); + REQUIRE(classProbabilities.n_elem == 0); } /** * Check that the BestBinaryNumericSplit doesn't split a dimension that gives no * gain. */ -BOOST_AUTO_TEST_CASE(BestBinaryNumericSplitNoGainTest) +TEST_CASE("BestBinaryNumericSplitNoGainTest", "[DecisionTreeTest]") { arma::vec values(100); arma::Row labels(100); @@ -366,15 +372,15 @@ BOOST_AUTO_TEST_CASE(BestBinaryNumericSplitNoGainTest) aux); // Make sure there was no split. - BOOST_REQUIRE_EQUAL(gain, DBL_MAX); - BOOST_REQUIRE_EQUAL(classProbabilities.n_elem, 0); + REQUIRE(gain == DBL_MAX); + REQUIRE(classProbabilities.n_elem == 0); } /** * Check that the AllCategoricalSplit will split when the split is obviously * better. */ -BOOST_AUTO_TEST_CASE(AllCategoricalSplitSimpleSplitTest) +TEST_CASE("AllCategoricalSplitSimpleSplitTest", "[DecisionTreeTest]") { arma::vec values("0 0 0 1 1 1 2 2 2 3 3 3"); arma::Row labels("0 0 0 2 2 2 1 1 1 2 2 2"); @@ -394,23 +400,23 @@ BOOST_AUTO_TEST_CASE(AllCategoricalSplitSimpleSplitTest) labels, 3, weights, 3, 1e-7, classProbabilities, aux); // Make sure that a split was made. - BOOST_REQUIRE_GT(gain, bestGain); + REQUIRE(gain > bestGain); // Since the split is perfect, make sure the new gain is 0. - BOOST_REQUIRE_SMALL(gain, 1e-5); + REQUIRE(gain == Approx(0.0).margin(1e-7)); - BOOST_REQUIRE_EQUAL(gain, weightedGain); + REQUIRE(gain == weightedGain); // Make sure the class probabilities now hold the number of children. - BOOST_REQUIRE_EQUAL(classProbabilities.n_elem, 1); - BOOST_REQUIRE_EQUAL((size_t) classProbabilities[0], 4); + REQUIRE(classProbabilities.n_elem == 1); + REQUIRE((size_t) classProbabilities[0] == 4); } /** * Make sure that AllCategoricalSplit respects the minimum number of samples * required to split. */ -BOOST_AUTO_TEST_CASE(AllCategoricalSplitMinSamplesTest) +TEST_CASE("AllCategoricalSplitMinSamplesTest", "[DecisionTreeTest]") { arma::vec values("0 0 0 1 1 1 2 2 2 3 3 3"); arma::Row labels("0 0 0 2 2 2 1 1 1 2 2 2"); @@ -427,14 +433,14 @@ BOOST_AUTO_TEST_CASE(AllCategoricalSplitMinSamplesTest) aux); // Make sure it's not split. - BOOST_REQUIRE_EQUAL(gain, DBL_MAX); - BOOST_REQUIRE_EQUAL(classProbabilities.n_elem, 0); + REQUIRE(gain == DBL_MAX); + REQUIRE(classProbabilities.n_elem == 0); } /** * Check that no split is made when it doesn't get us anything. */ -BOOST_AUTO_TEST_CASE(AllCategoricalSplitNoGainTest) +TEST_CASE("AllCategoricalSplitNoGainTest", "[DecisionTreeTest]") { arma::vec values(300); arma::Row labels(300); @@ -463,16 +469,16 @@ BOOST_AUTO_TEST_CASE(AllCategoricalSplitNoGainTest) labels, 3, weights, 10, 1e-7, classProbabilities, aux); // Make sure that there was no split. - BOOST_REQUIRE_EQUAL(gain, DBL_MAX); - BOOST_REQUIRE_EQUAL(gain, weightedGain); - BOOST_REQUIRE_EQUAL(classProbabilities.n_elem, 0); + REQUIRE(gain == DBL_MAX); + REQUIRE(gain == weightedGain); + REQUIRE(classProbabilities.n_elem == 0); } /** * A basic construction of the decision tree---ensure that we can create the * tree and that it split at least once. */ -BOOST_AUTO_TEST_CASE(BasicConstructionTest) +TEST_CASE("BasicConstructionTest", "[DecisionTreeTest]") { arma::mat dataset(10, 100, arma::fill::randu); arma::Row labels(100); @@ -491,13 +497,13 @@ BOOST_AUTO_TEST_CASE(BasicConstructionTest) DecisionTree<> d(dataset, labels, 2, 10); // Now require that we have some children. - BOOST_REQUIRE_GT(d.NumChildren(), 0); + REQUIRE(d.NumChildren() > 0); } /** * Construct a tree with weighted labels. */ -BOOST_AUTO_TEST_CASE(BasicConstructionTestWithWeight) +TEST_CASE("BasicConstructionTestWithWeight", "[DecisionTreeTest]") { arma::mat dataset(10, 100, arma::fill::randu); arma::Row labels(100); @@ -519,15 +525,15 @@ BOOST_AUTO_TEST_CASE(BasicConstructionTestWithWeight) DecisionTree<> d(dataset, labels, 2, 10); // Now require that we have some children. - BOOST_REQUIRE_GT(wd.NumChildren(), 0); - BOOST_REQUIRE_EQUAL(wd.NumChildren(), d.NumChildren()); + REQUIRE(wd.NumChildren() > 0); + REQUIRE(wd.NumChildren() == d.NumChildren()); } /** * Construct the decision tree on numeric data only and see that we can fit it * exactly and achieve perfect performance on the training set. */ -BOOST_AUTO_TEST_CASE(PerfectTrainingSet) +TEST_CASE("PerfectTrainingSet", "[DecisionTreeTest]") { arma::mat dataset(10, 100, arma::fill::randu); arma::Row labels(100); @@ -551,14 +557,14 @@ BOOST_AUTO_TEST_CASE(PerfectTrainingSet) arma::vec probabilities; d.Classify(dataset.col(i), prediction, probabilities); - BOOST_REQUIRE_EQUAL(prediction, labels[i]); - BOOST_REQUIRE_EQUAL(probabilities.n_elem, 2); + REQUIRE(prediction == labels[i]); + REQUIRE(probabilities.n_elem == 2); for (size_t j = 0; j < 2; ++j) { if (labels[i] == j) - BOOST_REQUIRE_CLOSE(probabilities[j], 1.0, 1e-5); + REQUIRE(probabilities[j] == Approx(1.0).epsilon(1e-7)); else - BOOST_REQUIRE_SMALL(probabilities[j], 1e-5); + REQUIRE(probabilities[j] == Approx(0.0).margin(1e-5)); } } } @@ -566,7 +572,7 @@ BOOST_AUTO_TEST_CASE(PerfectTrainingSet) /** * Construct the decision tree with weighted labels */ -BOOST_AUTO_TEST_CASE(PerfectTrainingSetWithWeight) +TEST_CASE("PerfectTrainingSetWithWeight", "[DecisionTreeTest]") { // Completely random dataset with no structure. arma::mat dataset(10, 100, arma::fill::randu); @@ -594,14 +600,14 @@ BOOST_AUTO_TEST_CASE(PerfectTrainingSetWithWeight) arma::vec probabilities; d.Classify(dataset.col(i), prediction, probabilities); - BOOST_REQUIRE_EQUAL(prediction, labels[i]); - BOOST_REQUIRE_EQUAL(probabilities.n_elem, 2); + REQUIRE(prediction == labels[i]); + REQUIRE(probabilities.n_elem == 2); for (size_t j = 0; j < 2; ++j) { if (labels[i] == j) - BOOST_REQUIRE_CLOSE(probabilities[j], 1.0, 1e-5); + REQUIRE(probabilities[j] == Approx(1.0).epsilon(1e-7)); else - BOOST_REQUIRE_SMALL(probabilities[j], 1e-5); + REQUIRE(probabilities[j] == Approx(0.0).margin(1e-5)); } } } @@ -610,7 +616,7 @@ BOOST_AUTO_TEST_CASE(PerfectTrainingSetWithWeight) /** * Make sure class probabilities are computed correctly in the root node. */ -BOOST_AUTO_TEST_CASE(ClassProbabilityTest) +TEST_CASE("ClassProbabilityTest", "[DecisionTreeTest]") { arma::mat dataset(5, 100, arma::fill::randu); arma::Row labels(100); @@ -623,30 +629,30 @@ BOOST_AUTO_TEST_CASE(ClassProbabilityTest) // Create a decision tree that can't split. DecisionTree<> d(dataset, labels, 2, 1000); - BOOST_REQUIRE_EQUAL(d.NumChildren(), 0); + REQUIRE(d.NumChildren() == 0); // Estimate a point's probabilities. arma::vec probabilities; size_t prediction; d.Classify(dataset.col(0), prediction, probabilities); - BOOST_REQUIRE_EQUAL(probabilities.n_elem, 2); - BOOST_REQUIRE_CLOSE(probabilities[0], 0.5, 1e-5); - BOOST_REQUIRE_CLOSE(probabilities[1], 0.5, 1e-5); + REQUIRE(probabilities.n_elem == 2); + REQUIRE(probabilities[0] == Approx(0.5).epsilon(1e-7)); + REQUIRE(probabilities[1] == Approx(0.5).epsilon(1e-7)); } /** * Test that the decision tree generalizes reasonably. */ -BOOST_AUTO_TEST_CASE(SimpleGeneralizationTest) +TEST_CASE("SimpleGeneralizationTest", "[DecisionTreeTest]") { arma::mat inputData; if (!data::Load("vc2.csv", inputData)) - BOOST_FAIL("Cannot load test dataset vc2.csv!"); + FAIL("Cannot load test dataset vc2.csv!"); arma::Row 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"); // Initialize an all-ones weight matrix. arma::rowvec weights(labels.n_cols, arma::fill::ones); @@ -658,17 +664,17 @@ BOOST_AUTO_TEST_CASE(SimpleGeneralizationTest) // Load testing data. arma::mat testData; if (!data::Load("vc2_test.csv", testData)) - BOOST_FAIL("Cannot load test dataset vc2_test.csv!"); + FAIL("Cannot load test dataset vc2_test.csv!"); arma::Mat trueTestLabels; if (!data::Load("vc2_test_labels.txt", trueTestLabels)) - BOOST_FAIL("Cannot load labels for vc2_test_labels.txt"); + FAIL("Cannot load labels for vc2_test_labels.txt"); // Get the predicted test labels. arma::Row predictions; d.Classify(testData, predictions); - BOOST_REQUIRE_EQUAL(predictions.n_elem, testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); // Figure out the accuracy. double correct = 0.0; @@ -677,13 +683,13 @@ BOOST_AUTO_TEST_CASE(SimpleGeneralizationTest) ++correct; correct /= predictions.n_elem; - BOOST_REQUIRE_GT(correct, 0.75); + REQUIRE(correct > 0.75); // reset the prediction predictions.zeros(); wd.Classify(testData, predictions); - BOOST_REQUIRE_EQUAL(predictions.n_elem, testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); // Figure out the accuracy. double wdcorrect = 0.0; @@ -692,13 +698,13 @@ BOOST_AUTO_TEST_CASE(SimpleGeneralizationTest) ++wdcorrect; wdcorrect /= predictions.n_elem; - BOOST_REQUIRE_GT(wdcorrect, 0.75); + REQUIRE(wdcorrect > 0.75); } /** * Test that we can build a decision tree on a simple categorical dataset. */ -BOOST_AUTO_TEST_CASE(CategoricalBuildTest) +TEST_CASE("CategoricalBuildTest", "[DecisionTreeTest]") { arma::mat d; arma::Row l; @@ -718,7 +724,7 @@ BOOST_AUTO_TEST_CASE(CategoricalBuildTest) arma::Row predictions; tree.Classify(testData, predictions); - BOOST_REQUIRE_EQUAL(predictions.n_elem, testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); size_t correct = 0; for (size_t i = 0; i < testData.n_cols; ++i) if (testLabels[i] == predictions[i]) @@ -726,14 +732,14 @@ BOOST_AUTO_TEST_CASE(CategoricalBuildTest) // Make sure we got at least 70% accuracy. const double correctPct = double(correct) / double(testData.n_cols); - BOOST_REQUIRE_GT(correctPct, 0.70); + REQUIRE(correctPct > 0.70); } /** * Test that we can build a decision tree with weights on a simple categorical * dataset. */ -BOOST_AUTO_TEST_CASE(CategoricalBuildTestWithWeight) +TEST_CASE("CategoricalBuildTestWithWeight", "[DecisionTreeTest]") { arma::mat d; arma::Row l; @@ -756,7 +762,7 @@ BOOST_AUTO_TEST_CASE(CategoricalBuildTestWithWeight) arma::Row predictions; tree.Classify(testData, predictions); - BOOST_REQUIRE_EQUAL(predictions.n_elem, testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); size_t correct = 0; for (size_t i = 0; i < testData.n_cols; ++i) if (testLabels[i] == predictions[i]) @@ -764,13 +770,13 @@ BOOST_AUTO_TEST_CASE(CategoricalBuildTestWithWeight) // Make sure we got at least 70% accuracy. const double correctPct = double(correct) / double(testData.n_cols); - BOOST_REQUIRE_GT(correctPct, 0.70); + REQUIRE(correctPct > 0.70); } /** * Make sure that when we ask for a decision stump, we get one. */ -BOOST_AUTO_TEST_CASE(DecisionStumpTest) +TEST_CASE("DecisionStumpTest", "[DecisionTreeTest]") { // Use a random dataset. arma::mat dataset(10, 1000, arma::fill::randu); @@ -783,10 +789,10 @@ BOOST_AUTO_TEST_CASE(DecisionStumpTest) AllDimensionSelect, double, true> stump(dataset, labels, 3, 1); // Check that it has children. - BOOST_REQUIRE_EQUAL(stump.NumChildren(), 2); + REQUIRE(stump.NumChildren() == 2); // Check that its children doesn't have children. - BOOST_REQUIRE_EQUAL(stump.Child(0).NumChildren(), 0); - BOOST_REQUIRE_EQUAL(stump.Child(1).NumChildren(), 0); + REQUIRE(stump.Child(0).NumChildren() == 0); + REQUIRE(stump.Child(1).NumChildren() == 0); } /** @@ -794,7 +800,7 @@ BOOST_AUTO_TEST_CASE(DecisionStumpTest) * low-weighted data is random noise), and that the tree still builds correctly * enough to get good results. */ -BOOST_AUTO_TEST_CASE(WeightedDecisionTreeTest) +TEST_CASE("WeightedDecisionTreeTest", "[DecisionTreeTest]") { arma::mat dataset; arma::Row labels; @@ -830,7 +836,7 @@ BOOST_AUTO_TEST_CASE(WeightedDecisionTreeTest) arma::Row predictions; d.Classify(testData, predictions); - BOOST_REQUIRE_EQUAL(predictions.n_elem, testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); // Figure out the accuracy. double correct = 0.0; @@ -839,13 +845,13 @@ BOOST_AUTO_TEST_CASE(WeightedDecisionTreeTest) ++correct; correct /= predictions.n_elem; - BOOST_REQUIRE_GT(correct, 0.75); + REQUIRE(correct > 0.75); } /** * Test that we can build a decision tree on a simple categorical dataset using * weights, with low-weight noise added. */ -BOOST_AUTO_TEST_CASE(CategoricalWeightedBuildTest) +TEST_CASE("CategoricalWeightedBuildTest", "[DecisionTreeTest]") { arma::mat d; arma::Row l; @@ -887,7 +893,7 @@ BOOST_AUTO_TEST_CASE(CategoricalWeightedBuildTest) arma::Row predictions; tree.Classify(testData, predictions); - BOOST_REQUIRE_EQUAL(predictions.n_elem, testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); size_t correct = 0; for (size_t i = 0; i < testData.n_cols; ++i) if (testLabels[i] == predictions[i]) @@ -895,7 +901,7 @@ BOOST_AUTO_TEST_CASE(CategoricalWeightedBuildTest) // Make sure we got at least 70% accuracy. const double correctPct = double(correct) / double(testData.n_cols); - BOOST_REQUIRE_GT(correctPct, 0.70); + REQUIRE(correctPct > 0.70); } /** @@ -903,7 +909,7 @@ BOOST_AUTO_TEST_CASE(CategoricalWeightedBuildTest) * low-weighted data is random noise) with information gain, and that the tree * still builds correctly enough to get good results. */ -BOOST_AUTO_TEST_CASE(WeightedDecisionTreeInformationGainTest) +TEST_CASE("WeightedDecisionTreeInformationGainTest", "[DecisionTreeTest]") { arma::mat dataset; arma::Row labels; @@ -939,7 +945,7 @@ BOOST_AUTO_TEST_CASE(WeightedDecisionTreeInformationGainTest) arma::Row predictions; d.Classify(testData, predictions); - BOOST_REQUIRE_EQUAL(predictions.n_elem, testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); // Figure out the accuracy. double correct = 0.0; @@ -948,13 +954,13 @@ BOOST_AUTO_TEST_CASE(WeightedDecisionTreeInformationGainTest) ++correct; correct /= predictions.n_elem; - BOOST_REQUIRE_GT(correct, 0.75); + REQUIRE(correct > 0.75); } /** * Test that we can build a decision tree using information gain on a simple * categorical dataset using weights, with low-weight noise added. */ -BOOST_AUTO_TEST_CASE(CategoricalInformationGainWeightedBuildTest) +TEST_CASE("CategoricalInformationGainWeightedBuildTest", "[DecisionTreeTest]") { arma::mat d; arma::Row l; @@ -996,7 +1002,7 @@ BOOST_AUTO_TEST_CASE(CategoricalInformationGainWeightedBuildTest) arma::Row predictions; tree.Classify(testData, predictions); - BOOST_REQUIRE_EQUAL(predictions.n_elem, testData.n_cols); + REQUIRE(predictions.n_elem == testData.n_cols); size_t correct = 0; for (size_t i = 0; i < testData.n_cols; ++i) if (testLabels[i] == predictions[i]) @@ -1004,27 +1010,27 @@ BOOST_AUTO_TEST_CASE(CategoricalInformationGainWeightedBuildTest) // Make sure we got at least 70% accuracy. const double correctPct = double(correct) / double(testData.n_cols); - BOOST_REQUIRE_GT(correctPct, 0.70); + REQUIRE(correctPct > 0.70); } /** * Make sure that the random dimension selector only has one element. */ -BOOST_AUTO_TEST_CASE(RandomDimensionSelectTest) +TEST_CASE("RandomDimensionSelectTest", "[DecisionTreeTest]") { RandomDimensionSelect r; r.Dimensions() = 10; - BOOST_REQUIRE_LT(r.Begin(), 10); - BOOST_REQUIRE_EQUAL(r.Next(), r.End()); - BOOST_REQUIRE_EQUAL(r.Next(), r.End()); - BOOST_REQUIRE_EQUAL(r.Next(), r.End()); + REQUIRE(r.Begin() < 10); + REQUIRE(r.Next() == r.End()); + REQUIRE(r.Next() == r.End()); + REQUIRE(r.Next() == r.End()); } /** * Make sure that the random dimension selector selects different values. */ -BOOST_AUTO_TEST_CASE(RandomDimensionSelectRandomTest) +TEST_CASE("RandomDimensionSelectRandomTest", "[DecisionTreeTest]") { // We'll check that 4 values are not all the same. RandomDimensionSelect r1, r2, r3, r4; @@ -1033,33 +1039,33 @@ BOOST_AUTO_TEST_CASE(RandomDimensionSelectRandomTest) r3.Dimensions() = 100000; r4.Dimensions() = 100000; - BOOST_REQUIRE((r1.Begin() != r2.Begin()) || - (r1.Begin() != r3.Begin()) || - (r1.Begin() != r4.Begin())); + REQUIRE(((r1.Begin() != r2.Begin()) || + (r1.Begin() != r3.Begin()) || + (r1.Begin() != r4.Begin()))); } /** * Make sure that the multiple random dimension select only has the right number * of elements. */ -BOOST_AUTO_TEST_CASE(MultipleRandomDimensionSelectTest) +TEST_CASE("MultipleRandomDimensionSelectTest", "[DecisionTreeTest]") { MultipleRandomDimensionSelect r(5); r.Dimensions() = 10; // Make sure we get five elements. - BOOST_REQUIRE_LT(r.Begin(), 10); - BOOST_REQUIRE_LT(r.Next(), 10); - BOOST_REQUIRE_LT(r.Next(), 10); - BOOST_REQUIRE_LT(r.Next(), 10); - BOOST_REQUIRE_LT(r.Next(), 10); - BOOST_REQUIRE_EQUAL(r.Next(), r.End()); + REQUIRE(r.Begin() < 10); + REQUIRE(r.Next() < 10); + REQUIRE(r.Next() < 10); + REQUIRE(r.Next() < 10); + REQUIRE(r.Next() < 10); + REQUIRE(r.Next() == r.End()); } /** * Make sure we get every element from the distribution. */ -BOOST_AUTO_TEST_CASE(MultipleRandomDimensionAllSelectTest) +TEST_CASE("MultipleRandomDimensionAllSelectTest", "[DecisionTreeTest]") { MultipleRandomDimensionSelect r(3); r.Dimensions() = 3; @@ -1071,24 +1077,24 @@ BOOST_AUTO_TEST_CASE(MultipleRandomDimensionAllSelectTest) found[r.Next()] = true; found[r.Next()] = true; - BOOST_REQUIRE_EQUAL(found[0], true); - BOOST_REQUIRE_EQUAL(found[1], true); - BOOST_REQUIRE_EQUAL(found[2], true); + REQUIRE(found[0] == true); + REQUIRE(found[1] == true); + REQUIRE(found[2] == true); } /** * Make sure the right number of classes is returned for an empty tree (1). */ -BOOST_AUTO_TEST_CASE(NumClassesEmptyTreeTest) +TEST_CASE("NumClassesEmptyTreeTest", "[DecisionTreeTest]") { DecisionTree<> dt; - BOOST_REQUIRE_EQUAL(dt.NumClasses(), 1); + REQUIRE(dt.NumClasses() == 1); } /** * Make sure the right number of classes is returned for a nonempty tree. */ -BOOST_AUTO_TEST_CASE(NumClassesTest) +TEST_CASE("NumClassesTest", "[DecisionTreeTest]") { // Load a dataset to train with. arma::mat dataset; @@ -1098,13 +1104,13 @@ BOOST_AUTO_TEST_CASE(NumClassesTest) DecisionTree<> dt(dataset, labels, 3); - BOOST_REQUIRE_EQUAL(dt.NumClasses(), 3); + REQUIRE(dt.NumClasses() == 3); } /* * Test that we can pass const data into DecisionTree constructors. */ -BOOST_AUTO_TEST_CASE(ConstDataTest) +TEST_CASE("ConstDataTest", "[DecisionTreeTest]") { arma::mat data; arma::Row labels; @@ -1127,7 +1133,7 @@ BOOST_AUTO_TEST_CASE(ConstDataTest) * Construct the decision tree with splitting only if gain is more than * threshold. */ -BOOST_AUTO_TEST_CASE(RegularisedDecisionTree) +TEST_CASE("RegularisedDecisionTree", "[DecisionTreeTest]") { // Completely random dataset with no structure. arma::mat dataset(10, 1000, arma::fill::randu); @@ -1157,17 +1163,17 @@ BOOST_AUTO_TEST_CASE(RegularisedDecisionTree) if (prediction != predictionsregularised) count++; - BOOST_REQUIRE_EQUAL(probabilities.n_elem, 3); - BOOST_REQUIRE_EQUAL(probabilitiesRegularised.n_elem, 3); + REQUIRE(probabilities.n_elem == 3); + REQUIRE(probabilitiesRegularised.n_elem == 3); } - BOOST_REQUIRE_GT(count, 0); + REQUIRE(count > 0); } /** * Test that DecisionTree::Train() returns finite entropy on numeric dataset. */ -BOOST_AUTO_TEST_CASE(DecisionTreeNumericTrainReturnEntropy) +TEST_CASE("DecisionTreeNumericTrainReturnEntropy", "[DecisionTreeTest]") { arma::mat dataset(10, 1000, arma::fill::randu); arma::Row labels(1000); @@ -1181,20 +1187,20 @@ BOOST_AUTO_TEST_CASE(DecisionTreeNumericTrainReturnEntropy) DecisionTree<> d(3); double entropy = d.Train(dataset, labels, 3, 50); - BOOST_REQUIRE_EQUAL(std::isfinite(entropy), true); + REQUIRE(std::isfinite(entropy) == true); // Train a tree with weights on numeric dataset. DecisionTree<> wd(3); entropy = wd.Train(dataset, labels, 3, weights, 50); - BOOST_REQUIRE_EQUAL(std::isfinite(entropy), true); + REQUIRE(std::isfinite(entropy) == true); } /** * Test that DecisionTree::Train() returns finite entropy on categorical * dataset. */ -BOOST_AUTO_TEST_CASE(DecisionTreeCategoricalTrainReturnEntropy) +TEST_CASE("DecisionTreeCategoricalTrainReturnEntropy", "[DecisionTreeTest]") { arma::mat d; arma::Row l; @@ -1207,19 +1213,19 @@ BOOST_AUTO_TEST_CASE(DecisionTreeCategoricalTrainReturnEntropy) DecisionTree<> dtree(5); double entropy = dtree.Train(d, di, l, 5, 10); - BOOST_REQUIRE_EQUAL(std::isfinite(entropy), true); + REQUIRE(std::isfinite(entropy) == true); // Train a tree with weights on categorical dataset. DecisionTree<> wdtree(5); entropy = wdtree.Train(d, di, l, 5, weights, 10); - BOOST_REQUIRE_EQUAL(std::isfinite(entropy), true); + REQUIRE(std::isfinite(entropy) == true); } /** * Make sure different maximum depth values give different numbers of children. */ -BOOST_AUTO_TEST_CASE(DifferentMaximumDepthTest) +TEST_CASE("DifferentMaximumDepthTest", "[DecisionTreeTest]") { arma::mat dataset; arma::Row labels; @@ -1233,17 +1239,15 @@ BOOST_AUTO_TEST_CASE(DifferentMaximumDepthTest) DecisionTree<> d2(dataset, labels, 3, 10, 1e-7); // Now require that we have zero children. - BOOST_REQUIRE_EQUAL(d.NumChildren(), 0); + REQUIRE(d.NumChildren() == 0); // Now require that we have two children. - BOOST_REQUIRE_EQUAL(d1.NumChildren(), 2); - BOOST_REQUIRE_EQUAL(d1.Child(0).NumChildren(), 0); - BOOST_REQUIRE_EQUAL(d1.Child(1).NumChildren(), 0); + REQUIRE(d1.NumChildren() == 2); + REQUIRE(d1.Child(0).NumChildren() == 0); + REQUIRE(d1.Child(1).NumChildren() == 0); // Now require that we have two children. - BOOST_REQUIRE_EQUAL(d2.NumChildren(), 2); - BOOST_REQUIRE_EQUAL(d2.Child(0).NumChildren(), 2); - BOOST_REQUIRE_EQUAL(d2.Child(1).NumChildren(), 2); + REQUIRE(d2.NumChildren() == 2); + REQUIRE(d2.Child(0).NumChildren() == 2); + REQUIRE(d2.Child(1).NumChildren() == 2); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/kfn_test.cpp b/src/mlpack/tests/kfn_test.cpp index a9a9654ff1..f3fefadb7a 100644 --- a/src/mlpack/tests/kfn_test.cpp +++ b/src/mlpack/tests/kfn_test.cpp @@ -11,8 +11,8 @@ #include #include #include -#include -#include "test_tools.hpp" +#include "test_catch_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::neighbor; @@ -20,8 +20,6 @@ using namespace mlpack::tree; using namespace mlpack::metric; using namespace mlpack::bound; -BOOST_AUTO_TEST_SUITE(KFNTest); - /** * Simple furthest-neighbors test with small, synthetic dataset. This is an * exhaustive test, which checks that each method for performing the calculation @@ -30,7 +28,7 @@ BOOST_AUTO_TEST_SUITE(KFNTest); * is in one dimension for simplicity -- the correct functionality of distance * functions is not tested here. */ -BOOST_AUTO_TEST_CASE(ExhaustiveSyntheticTest) +TEST_CASE("KFNExhaustiveSyntheticTest", "[KFNTest]") { // Set up our data. arma::mat data(1, 11); @@ -82,246 +80,246 @@ BOOST_AUTO_TEST_CASE(ExhaustiveSyntheticTest) // readability. // Neighbors of point 0. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[0]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[0]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[0]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[0]), 0.27, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[0]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[0]), 0.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[0]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[0]), 0.40, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[0]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[0]), 0.85, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[0]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[0]), 0.95, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[0]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[0]), 1.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[0]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[0]), 1.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[0]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[0]), 2.05, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[0]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[0]), 5.00, 1e-5); + REQUIRE(neighbors(9, newFromOld[0]) == newFromOld[2]); + REQUIRE(distances(9, newFromOld[0]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[0]) == newFromOld[5]); + REQUIRE(distances(8, newFromOld[0]) == Approx(0.27).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[0]) == newFromOld[1]); + REQUIRE(distances(7, newFromOld[0]) == Approx(0.30).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[0]) == newFromOld[8]); + REQUIRE(distances(6, newFromOld[0]) == Approx(0.40).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[0]) == newFromOld[9]); + REQUIRE(distances(5, newFromOld[0]) == Approx(0.85).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[0]) == newFromOld[10]); + REQUIRE(distances(4, newFromOld[0]) == Approx(0.95).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[0]) == newFromOld[3]); + REQUIRE(distances(3, newFromOld[0]) == Approx(1.20).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[0]) == newFromOld[7]); + REQUIRE(distances(2, newFromOld[0]) == Approx(1.35).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[0]) == newFromOld[6]); + REQUIRE(distances(1, newFromOld[0]) == Approx(2.05).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[0]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[0]) == Approx(5.00).epsilon(1e-7)); // Neighbors of point 1. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[1]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[1]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[1]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[1]), 0.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[1]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[1]), 0.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[1]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[1]), 0.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[1]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[1]), 0.57, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[1]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[1]), 0.65, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[1]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[1]), 0.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[1]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[1]), 1.65, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[1]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[1]), 2.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[1]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[1]), 4.70, 1e-5); + REQUIRE(neighbors(9, newFromOld[1]) == newFromOld[8]); + REQUIRE(distances(9, newFromOld[1]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[1]) == newFromOld[2]); + REQUIRE(distances(8, newFromOld[1]) == Approx(0.20).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[1]) == newFromOld[0]); + REQUIRE(distances(7, newFromOld[1]) == Approx(0.30).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[1]) == newFromOld[9]); + REQUIRE(distances(6, newFromOld[1]) == Approx(0.55).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[1]) == newFromOld[5]); + REQUIRE(distances(5, newFromOld[1]) == Approx(0.57).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[1]) == newFromOld[10]); + REQUIRE(distances(4, newFromOld[1]) == Approx(0.65).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[1]) == newFromOld[3]); + REQUIRE(distances(3, newFromOld[1]) == Approx(0.90).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[1]) == newFromOld[7]); + REQUIRE(distances(2, newFromOld[1]) == Approx(1.65).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[1]) == newFromOld[6]); + REQUIRE(distances(1, newFromOld[1]) == Approx(2.35).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[1]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[1]) == Approx(4.70).epsilon(1e-7)); // Neighbors of point 2. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[2]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[2]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[2]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[2]), 0.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[2]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[2]), 0.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[2]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[2]), 0.37, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[2]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[2]), 0.75, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[2]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[2]), 0.85, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[2]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[2]), 1.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[2]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[2]), 1.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[2]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[2]), 2.15, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[2]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[2]), 4.90, 1e-5); + REQUIRE(neighbors(9, newFromOld[2]) == newFromOld[0]); + REQUIRE(distances(9, newFromOld[2]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[2]) == newFromOld[1]); + REQUIRE(distances(8, newFromOld[2]) == Approx(0.20).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[2]) == newFromOld[8]); + REQUIRE(distances(7, newFromOld[2]) == Approx(0.30).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[2]) == newFromOld[5]); + REQUIRE(distances(6, newFromOld[2]) == Approx(0.37).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[2]) == newFromOld[9]); + REQUIRE(distances(5, newFromOld[2]) == Approx(0.75).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[2]) == newFromOld[10]); + REQUIRE(distances(4, newFromOld[2]) == Approx(0.85).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[2]) == newFromOld[3]); + REQUIRE(distances(3, newFromOld[2]) == Approx(1.10).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[2]) == newFromOld[7]); + REQUIRE(distances(2, newFromOld[2]) == Approx(1.45).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[2]) == newFromOld[6]); + REQUIRE(distances(1, newFromOld[2]) == Approx(2.15).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[2]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[2]) == Approx(4.90).epsilon(1e-7)); // Neighbors of point 3. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[3]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[3]), 0.25, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[3]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[3]), 0.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[3]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[3]), 0.80, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[3]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[3]), 0.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[3]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[3]), 1.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[3]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[3]), 1.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[3]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[3]), 1.47, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[3]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[3]), 2.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[3]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[3]), 3.25, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[3]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[3]), 3.80, 1e-5); + REQUIRE(neighbors(9, newFromOld[3]) == newFromOld[10]); + REQUIRE(distances(9, newFromOld[3]) == Approx(0.25).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[3]) == newFromOld[9]); + REQUIRE(distances(8, newFromOld[3]) == Approx(0.35).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[3]) == newFromOld[8]); + REQUIRE(distances(7, newFromOld[3]) == Approx(0.80).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[3]) == newFromOld[1]); + REQUIRE(distances(6, newFromOld[3]) == Approx(0.90).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[3]) == newFromOld[2]); + REQUIRE(distances(5, newFromOld[3]) == Approx(1.10).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[3]) == newFromOld[0]); + REQUIRE(distances(4, newFromOld[3]) == Approx(1.20).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[3]) == newFromOld[5]); + REQUIRE(distances(3, newFromOld[3]) == Approx(1.47).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[3]) == newFromOld[7]); + REQUIRE(distances(2, newFromOld[3]) == Approx(2.55).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[3]) == newFromOld[6]); + REQUIRE(distances(1, newFromOld[3]) == Approx(3.25).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[3]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[3]) == Approx(3.80).epsilon(1e-7)); // Neighbors of point 4. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[4]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[4]), 3.80, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[4]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[4]), 4.05, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[4]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[4]), 4.15, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[4]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[4]), 4.60, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[4]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[4]), 4.70, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[4]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[4]), 4.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[4]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[4]), 5.00, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[4]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[4]), 5.27, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[4]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[4]), 6.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[4]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[4]), 7.05, 1e-5); + REQUIRE(neighbors(9, newFromOld[4]) == newFromOld[3]); + REQUIRE(distances(9, newFromOld[4]) == Approx(3.80).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[4]) == newFromOld[10]); + REQUIRE(distances(8, newFromOld[4]) == Approx(4.05).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[4]) == newFromOld[9]); + REQUIRE(distances(7, newFromOld[4]) == Approx(4.15).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[4]) == newFromOld[8]); + REQUIRE(distances(6, newFromOld[4]) == Approx(4.60).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[4]) == newFromOld[1]); + REQUIRE(distances(5, newFromOld[4]) == Approx(4.70).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[4]) == newFromOld[2]); + REQUIRE(distances(4, newFromOld[4]) == Approx(4.90).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[4]) == newFromOld[0]); + REQUIRE(distances(3, newFromOld[4]) == Approx(5.00).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[4]) == newFromOld[5]); + REQUIRE(distances(2, newFromOld[4]) == Approx(5.27).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[4]) == newFromOld[7]); + REQUIRE(distances(1, newFromOld[4]) == Approx(6.35).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[4]) == newFromOld[6]); + REQUIRE(distances(0, newFromOld[4]) == Approx(7.05).epsilon(1e-7)); // Neighbors of point 5. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[5]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[5]), 0.27, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[5]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[5]), 0.37, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[5]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[5]), 0.57, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[5]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[5]), 0.67, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[5]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[5]), 1.08, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[5]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[5]), 1.12, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[5]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[5]), 1.22, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[5]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[5]), 1.47, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[5]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[5]), 1.78, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[5]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[5]), 5.27, 1e-5); + REQUIRE(neighbors(9, newFromOld[5]) == newFromOld[0]); + REQUIRE(distances(9, newFromOld[5]) == Approx(0.27).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[5]) == newFromOld[2]); + REQUIRE(distances(8, newFromOld[5]) == Approx(0.37).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[5]) == newFromOld[1]); + REQUIRE(distances(7, newFromOld[5]) == Approx(0.57).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[5]) == newFromOld[8]); + REQUIRE(distances(6, newFromOld[5]) == Approx(0.67).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[5]) == newFromOld[7]); + REQUIRE(distances(5, newFromOld[5]) == Approx(1.08).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[5]) == newFromOld[9]); + REQUIRE(distances(4, newFromOld[5]) == Approx(1.12).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[5]) == newFromOld[10]); + REQUIRE(distances(3, newFromOld[5]) == Approx(1.22).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[5]) == newFromOld[3]); + REQUIRE(distances(2, newFromOld[5]) == Approx(1.47).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[5]) == newFromOld[6]); + REQUIRE(distances(1, newFromOld[5]) == Approx(1.78).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[5]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[5]) == Approx(5.27).epsilon(1e-7)); // Neighbors of point 6. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[6]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[6]), 0.70, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[6]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[6]), 1.78, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[6]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[6]), 2.05, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[6]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[6]), 2.15, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[6]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[6]), 2.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[6]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[6]), 2.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[6]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[6]), 2.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[6]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[6]), 3.00, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[6]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[6]), 3.25, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[6]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[6]), 7.05, 1e-5); + REQUIRE(neighbors(9, newFromOld[6]) == newFromOld[7]); + REQUIRE(distances(9, newFromOld[6]) == Approx(0.70).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[6]) == newFromOld[5]); + REQUIRE(distances(8, newFromOld[6]) == Approx(1.78).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[6]) == newFromOld[0]); + REQUIRE(distances(7, newFromOld[6]) == Approx(2.05).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[6]) == newFromOld[2]); + REQUIRE(distances(6, newFromOld[6]) == Approx(2.15).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[6]) == newFromOld[1]); + REQUIRE(distances(5, newFromOld[6]) == Approx(2.35).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[6]) == newFromOld[8]); + REQUIRE(distances(4, newFromOld[6]) == Approx(2.45).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[6]) == newFromOld[9]); + REQUIRE(distances(3, newFromOld[6]) == Approx(2.90).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[6]) == newFromOld[10]); + REQUIRE(distances(2, newFromOld[6]) == Approx(3.00).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[6]) == newFromOld[3]); + REQUIRE(distances(1, newFromOld[6]) == Approx(3.25).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[6]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[6]) == Approx(7.05).epsilon(1e-7)); // Neighbors of point 7. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[7]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[7]), 0.70, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[7]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[7]), 1.08, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[7]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[7]), 1.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[7]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[7]), 1.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[7]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[7]), 1.65, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[7]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[7]), 1.75, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[7]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[7]), 2.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[7]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[7]), 2.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[7]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[7]), 2.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[7]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[7]), 6.35, 1e-5); + REQUIRE(neighbors(9, newFromOld[7]) == newFromOld[6]); + REQUIRE(distances(9, newFromOld[7]) == Approx(0.70).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[7]) == newFromOld[5]); + REQUIRE(distances(8, newFromOld[7]) == Approx(1.08).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[7]) == newFromOld[0]); + REQUIRE(distances(7, newFromOld[7]) == Approx(1.35).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[7]) == newFromOld[2]); + REQUIRE(distances(6, newFromOld[7]) == Approx(1.45).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[7]) == newFromOld[1]); + REQUIRE(distances(5, newFromOld[7]) == Approx(1.65).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[7]) == newFromOld[8]); + REQUIRE(distances(4, newFromOld[7]) == Approx(1.75).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[7]) == newFromOld[9]); + REQUIRE(distances(3, newFromOld[7]) == Approx(2.20).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[7]) == newFromOld[10]); + REQUIRE(distances(2, newFromOld[7]) == Approx(2.30).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[7]) == newFromOld[3]); + REQUIRE(distances(1, newFromOld[7]) == Approx(2.55).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[7]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[7]) == Approx(6.35).epsilon(1e-7)); // Neighbors of point 8. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[8]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[8]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[8]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[8]), 0.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[8]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[8]), 0.40, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[8]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[8]), 0.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[8]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[8]), 0.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[8]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[8]), 0.67, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[8]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[8]), 0.80, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[8]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[8]), 1.75, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[8]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[8]), 2.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[8]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[8]), 4.60, 1e-5); + REQUIRE(neighbors(9, newFromOld[8]) == newFromOld[1]); + REQUIRE(distances(9, newFromOld[8]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[8]) == newFromOld[2]); + REQUIRE(distances(8, newFromOld[8]) == Approx(0.30).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[8]) == newFromOld[0]); + REQUIRE(distances(7, newFromOld[8]) == Approx(0.40).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[8]) == newFromOld[9]); + REQUIRE(distances(6, newFromOld[8]) == Approx(0.45).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[8]) == newFromOld[10]); + REQUIRE(distances(5, newFromOld[8]) == Approx(0.55).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[8]) == newFromOld[5]); + REQUIRE(distances(4, newFromOld[8]) == Approx(0.67).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[8]) == newFromOld[3]); + REQUIRE(distances(3, newFromOld[8]) == Approx(0.80).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[8]) == newFromOld[7]); + REQUIRE(distances(2, newFromOld[8]) == Approx(1.75).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[8]) == newFromOld[6]); + REQUIRE(distances(1, newFromOld[8]) == Approx(2.45).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[8]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[8]) == Approx(4.60).epsilon(1e-7)); // Neighbors of point 9. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[9]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[9]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[9]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[9]), 0.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[9]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[9]), 0.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[9]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[9]), 0.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[9]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[9]), 0.75, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[9]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[9]), 0.85, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[9]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[9]), 1.12, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[9]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[9]), 2.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[9]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[9]), 2.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[9]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[9]), 4.15, 1e-5); + REQUIRE(neighbors(9, newFromOld[9]) == newFromOld[10]); + REQUIRE(distances(9, newFromOld[9]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[9]) == newFromOld[3]); + REQUIRE(distances(8, newFromOld[9]) == Approx(0.35).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[9]) == newFromOld[8]); + REQUIRE(distances(7, newFromOld[9]) == Approx(0.45).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[9]) == newFromOld[1]); + REQUIRE(distances(6, newFromOld[9]) == Approx(0.55).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[9]) == newFromOld[2]); + REQUIRE(distances(5, newFromOld[9]) == Approx(0.75).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[9]) == newFromOld[0]); + REQUIRE(distances(4, newFromOld[9]) == Approx(0.85).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[9]) == newFromOld[5]); + REQUIRE(distances(3, newFromOld[9]) == Approx(1.12).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[9]) == newFromOld[7]); + REQUIRE(distances(2, newFromOld[9]) == Approx(2.20).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[9]) == newFromOld[6]); + REQUIRE(distances(1, newFromOld[9]) == Approx(2.90).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[9]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[9]) == Approx(4.15).epsilon(1e-7)); // Neighbors of point 10. - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[10]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[10]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[10]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[10]), 0.25, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[10]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[10]), 0.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[10]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[10]), 0.65, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[10]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[10]), 0.85, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[10]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[10]), 0.95, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[10]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[10]), 1.22, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[10]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[10]), 2.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[10]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[10]), 3.00, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[10]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[10]), 4.05, 1e-5); + REQUIRE(neighbors(9, newFromOld[10]) == newFromOld[9]); + REQUIRE(distances(9, newFromOld[10]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[10]) == newFromOld[3]); + REQUIRE(distances(8, newFromOld[10]) == Approx(0.25).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[10]) == newFromOld[8]); + REQUIRE(distances(7, newFromOld[10]) == Approx(0.55).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[10]) == newFromOld[1]); + REQUIRE(distances(6, newFromOld[10]) == Approx(0.65).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[10]) == newFromOld[2]); + REQUIRE(distances(5, newFromOld[10]) == Approx(0.85).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[10]) == newFromOld[0]); + REQUIRE(distances(4, newFromOld[10]) == Approx(0.95).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[10]) == newFromOld[5]); + REQUIRE(distances(3, newFromOld[10]) == Approx(1.22).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[10]) == newFromOld[7]); + REQUIRE(distances(2, newFromOld[10]) == Approx(2.30).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[10]) == newFromOld[6]); + REQUIRE(distances(1, newFromOld[10]) == Approx(3.00).epsilon(1e-7)); + REQUIRE(neighbors(0, newFromOld[10]) == newFromOld[4]); + REQUIRE(distances(0, newFromOld[10]) == Approx(4.05).epsilon(1e-7)); } } @@ -331,13 +329,13 @@ BOOST_AUTO_TEST_CASE(ExhaustiveSyntheticTest) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(DualTreeVsNaive1) +TEST_CASE("KFNDualTreeVsNaive1", "[KFNTest]") { arma::mat dataset; // Hard-coded filename: bad? if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KFN kfn(dataset); @@ -353,8 +351,8 @@ BOOST_AUTO_TEST_CASE(DualTreeVsNaive1) for (size_t i = 0; i < neighborsTree.n_elem; ++i) { - BOOST_REQUIRE(neighborsTree[i] == neighborsNaive[i]); - BOOST_REQUIRE_CLOSE(distancesTree[i], distancesNaive[i], 1e-5); + REQUIRE(neighborsTree[i] == neighborsNaive[i]); + REQUIRE(distancesTree[i] == Approx(distancesNaive[i]).epsilon(1e-7)); } } @@ -364,14 +362,14 @@ BOOST_AUTO_TEST_CASE(DualTreeVsNaive1) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(DualTreeVsNaive2) +TEST_CASE("KFNDualTreeVsNaive2", "[KFNTest]") { arma::mat dataset; // Hard-coded filename: bad? // Code duplication: also bad! if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KFN kfn(dataset); @@ -387,8 +385,8 @@ BOOST_AUTO_TEST_CASE(DualTreeVsNaive2) for (size_t i = 0; i < neighborsTree.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsTree[i], neighborsNaive[i]); - BOOST_REQUIRE_CLOSE(distancesTree[i], distancesNaive[i], 1e-5); + REQUIRE(neighborsTree[i] == neighborsNaive[i]); + REQUIRE(distancesTree[i] == Approx(distancesNaive[i]).epsilon(1e-7)); } } @@ -398,14 +396,14 @@ BOOST_AUTO_TEST_CASE(DualTreeVsNaive2) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(SingleTreeVsNaive) +TEST_CASE("KFNSingleTreeVsNaive", "[KFNTest]") { arma::mat dataset; // Hard-coded filename: bad! // Code duplication: also bad! if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KFN kfn(dataset, SINGLE_TREE_MODE); @@ -421,8 +419,8 @@ BOOST_AUTO_TEST_CASE(SingleTreeVsNaive) for (size_t i = 0; i < neighborsTree.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsTree[i], neighborsNaive[i]); - BOOST_REQUIRE_CLOSE(distancesTree[i], distancesNaive[i], 1e-5); + REQUIRE(neighborsTree[i] == neighborsNaive[i]); + REQUIRE(distancesTree[i] == Approx(distancesNaive[i]).epsilon(1e-7)); } } @@ -432,7 +430,7 @@ BOOST_AUTO_TEST_CASE(SingleTreeVsNaive) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) +TEST_CASE("KFNSingleCoverTreeTest", "[KFNTest]") { arma::mat data; data.randu(75, 1000); // 75 dimensional, 1000 points. @@ -456,8 +454,8 @@ BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) for (size_t i = 0; i < coverTreeNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(coverTreeNeighbors[i], naiveNeighbors[i]); - BOOST_REQUIRE_CLOSE(coverTreeDistances[i], naiveDistances[i], 1e-5); + REQUIRE(coverTreeNeighbors[i] == naiveNeighbors[i]); + REQUIRE(coverTreeDistances[i] == Approx(naiveDistances[i]).epsilon(1e-7)); } } @@ -465,7 +463,7 @@ BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) * Test the cover tree dual-tree furthest neighbors method against the naive * method. */ -BOOST_AUTO_TEST_CASE(DualCoverTreeTest) +TEST_CASE("KFNDualCoverTreeTest", "[KFNTest]") { arma::mat dataset; data::Load("test_data_3_1000.csv", dataset); @@ -490,8 +488,8 @@ BOOST_AUTO_TEST_CASE(DualCoverTreeTest) for (size_t i = 0; i < coverNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(coverNeighbors(i), kdNeighbors(i)); - BOOST_REQUIRE_CLOSE(coverDistances(i), kdDistances(i), 1e-5); + REQUIRE(coverNeighbors(i) == kdNeighbors(i)); + REQUIRE(coverDistances(i) == Approx(kdDistances(i)).epsilon(1e-7)); } } @@ -501,7 +499,7 @@ BOOST_AUTO_TEST_CASE(DualCoverTreeTest) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(SingleBallTreeTest) +TEST_CASE("KFNSingleBallTreeTest", "[KFNTest]") { arma::mat data; data.randu(75, 1000); // 75 dimensional, 1000 points. @@ -528,8 +526,8 @@ BOOST_AUTO_TEST_CASE(SingleBallTreeTest) for (size_t i = 0; i < ballTreeNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(ballTreeNeighbors[i], naiveNeighbors[i]); - BOOST_REQUIRE_CLOSE(ballTreeDistances[i], naiveDistances[i], 1e-5); + REQUIRE(ballTreeNeighbors[i] == naiveNeighbors[i]); + REQUIRE(ballTreeDistances[i] == Approx(naiveDistances[i]).epsilon(1e-7)); } } @@ -537,7 +535,7 @@ BOOST_AUTO_TEST_CASE(SingleBallTreeTest) * Test the ball tree dual-tree furthest neighbors method against the naive * method. */ -BOOST_AUTO_TEST_CASE(DualBallTreeTest) +TEST_CASE("KFNDualBallTreeTest", "[KFNTest]") { arma::mat dataset; data::Load("test_data_3_1000.csv", dataset); @@ -557,9 +555,7 @@ BOOST_AUTO_TEST_CASE(DualBallTreeTest) for (size_t i = 0; i < ballNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(ballNeighbors(i), kdNeighbors(i)); - BOOST_REQUIRE_CLOSE(ballDistances(i), kdDistances(i), 1e-5); + REQUIRE(ballNeighbors(i) == kdNeighbors(i)); + REQUIRE(ballDistances(i) == Approx(kdDistances(i)).epsilon(1e-7)); } } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/knn_test.cpp b/src/mlpack/tests/knn_test.cpp index ac6f429627..767abdb484 100644 --- a/src/mlpack/tests/knn_test.cpp +++ b/src/mlpack/tests/knn_test.cpp @@ -14,8 +14,8 @@ #include #include #include -#include -#include "test_tools.hpp" +#include "test_catch_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::neighbor; @@ -23,12 +23,10 @@ using namespace mlpack::tree; using namespace mlpack::metric; using namespace mlpack::bound; -BOOST_AUTO_TEST_SUITE(KNNTest); - /** * Test that Unmap() works in the dual-tree case (see unmap.hpp). */ -BOOST_AUTO_TEST_CASE(DualTreeUnmapTest) +TEST_CASE("KNNDualTreeUnmapTest", "[KNNTest]") { std::vector refMap; refMap.push_back(3); @@ -88,8 +86,8 @@ BOOST_AUTO_TEST_CASE(DualTreeUnmapTest) for (size_t i = 0; i < correctNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsOut[i], correctNeighbors[i]); - BOOST_REQUIRE_CLOSE(distancesOut[i], correctDistances[i], 1e-5); + REQUIRE(neighborsOut[i] ==correctNeighbors[i]); + REQUIRE(distancesOut[i] == Approx(correctDistances[i]).epsilon(1e-7)); } // Now try taking the square root. @@ -98,15 +96,15 @@ BOOST_AUTO_TEST_CASE(DualTreeUnmapTest) for (size_t i = 0; i < correctNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsOut[i], correctNeighbors[i]); - BOOST_REQUIRE_CLOSE(distancesOut[i], sqrt(correctDistances[i]), 1e-5); + REQUIRE(neighborsOut[i] ==correctNeighbors[i]); + REQUIRE(distancesOut[i] == Approx(sqrt(correctDistances[i])).epsilon(1e-7)); } } /** * Check that Unmap() works in the single-tree case. */ -BOOST_AUTO_TEST_CASE(SingleTreeUnmapTest) +TEST_CASE("KNNSingleTreeUnmapTest", "[KNNTest]") { std::vector refMap; refMap.push_back(3); @@ -152,8 +150,8 @@ BOOST_AUTO_TEST_CASE(SingleTreeUnmapTest) for (size_t i = 0; i < correctNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsOut[i], correctNeighbors[i]); - BOOST_REQUIRE_CLOSE(distancesOut[i], correctDistances[i], 1e-5); + REQUIRE(neighborsOut[i] ==correctNeighbors[i]); + REQUIRE(distancesOut[i] == Approx(correctDistances[i]).epsilon(1e-7)); } // Now try taking the square root. @@ -161,8 +159,8 @@ BOOST_AUTO_TEST_CASE(SingleTreeUnmapTest) for (size_t i = 0; i < correctNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsOut[i], correctNeighbors[i]); - BOOST_REQUIRE_CLOSE(distancesOut[i], sqrt(correctDistances[i]), 1e-5); + REQUIRE(neighborsOut[i] ==correctNeighbors[i]); + REQUIRE(distancesOut[i] == Approx(sqrt(correctDistances[i])).epsilon(1e-7)); } } @@ -170,7 +168,7 @@ BOOST_AUTO_TEST_CASE(SingleTreeUnmapTest) * Test that an empty KNN object will throw exceptions when Search() is * called. */ -BOOST_AUTO_TEST_CASE(EmptySearchTest) +TEST_CASE("KNNEmptySearchTest", "[KNNTest]") { KNN empty; @@ -179,18 +177,18 @@ BOOST_AUTO_TEST_CASE(EmptySearchTest) arma::Mat neighbors; arma::mat distances; - BOOST_REQUIRE_THROW(empty.Search(dataset, 5, neighbors, distances), + REQUIRE_THROWS_AS(empty.Search(dataset, 5, neighbors, distances), std::invalid_argument); - BOOST_REQUIRE_THROW(empty.Search(5, neighbors, distances), + REQUIRE_THROWS_AS(empty.Search(5, neighbors, distances), std::invalid_argument); - BOOST_REQUIRE_THROW(empty.Search(queryTree, 5, neighbors, distances), + REQUIRE_THROWS_AS(empty.Search(queryTree, 5, neighbors, distances), std::invalid_argument); } /** * Test that when training is performed, the results are the same. */ -BOOST_AUTO_TEST_CASE(TrainTest) +TEST_CASE("KNNTrainTest", "[KNNTest]") { KNN empty; @@ -205,26 +203,26 @@ BOOST_AUTO_TEST_CASE(TrainTest) empty.Search(5, neighbors, distances); baseline.Search(5, baselineNeighbors, baselineDistances); - BOOST_REQUIRE_EQUAL(neighbors.n_rows, baselineNeighbors.n_rows); - BOOST_REQUIRE_EQUAL(neighbors.n_cols, baselineNeighbors.n_cols); - BOOST_REQUIRE_EQUAL(distances.n_rows, baselineDistances.n_rows); - BOOST_REQUIRE_EQUAL(distances.n_cols, baselineDistances.n_cols); + REQUIRE(neighbors.n_rows ==baselineNeighbors.n_rows); + REQUIRE(neighbors.n_cols ==baselineNeighbors.n_cols); + REQUIRE(distances.n_rows ==baselineDistances.n_rows); + REQUIRE(distances.n_cols ==baselineDistances.n_cols); for (size_t i = 0; i < distances.n_elem; ++i) { if (std::abs(baselineDistances[i]) < 1e-5) - BOOST_REQUIRE_SMALL(distances[i], 1e-5); + REQUIRE(distances[i] == Approx(0.0).margin(1e-7)); else - BOOST_REQUIRE_CLOSE(distances[i], baselineDistances[i], 1e-5); + REQUIRE(distances[i] == Approx(baselineDistances[i]).epsilon(1e-7)); - BOOST_REQUIRE_EQUAL(neighbors[i], baselineNeighbors[i]); + REQUIRE(neighbors[i] ==baselineNeighbors[i]); } } /** * Test that when training is performed with a tree, the results are the same. */ -BOOST_AUTO_TEST_CASE(TrainTreeTest) +TEST_CASE("KNNTrainTreeTest", "[KNNTest]") { KNN empty; @@ -241,11 +239,11 @@ BOOST_AUTO_TEST_CASE(TrainTreeTest) empty.Search(5, neighbors, distances); baseline.Search(5, baselineNeighbors, baselineDistances); - BOOST_REQUIRE_EQUAL(neighbors.n_rows, baselineNeighbors.n_rows); - BOOST_REQUIRE_EQUAL(neighbors.n_cols, baselineNeighbors.n_cols); - BOOST_REQUIRE_EQUAL(distances.n_rows, baselineDistances.n_rows); - BOOST_REQUIRE_EQUAL(distances.n_cols, baselineDistances.n_cols); - BOOST_REQUIRE_EQUAL(oldFromNewReferences.size(), distances.n_cols); + REQUIRE(neighbors.n_rows ==baselineNeighbors.n_rows); + REQUIRE(neighbors.n_cols ==baselineNeighbors.n_cols); + REQUIRE(distances.n_rows ==baselineDistances.n_rows); + REQUIRE(distances.n_cols ==baselineDistances.n_cols); + REQUIRE(oldFromNewReferences.size() ==distances.n_cols); // We have to unmap the results. arma::mat tmpDistances(distances.n_rows, distances.n_cols); @@ -263,31 +261,31 @@ BOOST_AUTO_TEST_CASE(TrainTreeTest) for (size_t i = 0; i < distances.n_elem; ++i) { if (std::abs(baselineDistances[i]) < 1e-5) - BOOST_REQUIRE_SMALL(tmpDistances[i], 1e-5); + REQUIRE(tmpDistances[i] == Approx(0.0).margin(1e-7)); else - BOOST_REQUIRE_CLOSE(tmpDistances[i], baselineDistances[i], 1e-5); + REQUIRE(tmpDistances[i] == Approx(baselineDistances[i]).epsilon(1e-7)); - BOOST_REQUIRE_EQUAL(tmpNeighbors[i], baselineNeighbors[i]); + REQUIRE(tmpNeighbors[i] ==baselineNeighbors[i]); } } /** * Test that training with a tree throws an exception when in naive mode. */ -BOOST_AUTO_TEST_CASE(NaiveTrainTreeTest) +TEST_CASE("KNNNaiveTrainTreeTest", "[KNNTest]") { KNN empty(NAIVE_MODE); arma::mat dataset = arma::randu(5, 100); KNN::Tree tree(dataset); - BOOST_REQUIRE_THROW(empty.Train(std::move(tree)), std::invalid_argument); + REQUIRE_THROWS_AS(empty.Train(std::move(tree)), std::invalid_argument); } /** * Test that the rvalue reference move constructor works. */ -BOOST_AUTO_TEST_CASE(DatasetMoveConstructorTest) +TEST_CASE("KNNDatasetMoveConstructorTest", "[KNNTest]") { arma::mat dataset = arma::randu(3, 200); arma::mat copy(dataset); @@ -295,9 +293,9 @@ BOOST_AUTO_TEST_CASE(DatasetMoveConstructorTest) KNN moveknn(std::move(copy)); KNN knn(dataset); - BOOST_REQUIRE_EQUAL(copy.n_elem, 0); - BOOST_REQUIRE_EQUAL(moveknn.ReferenceSet().n_rows, 3); - BOOST_REQUIRE_EQUAL(moveknn.ReferenceSet().n_cols, 200); + REQUIRE(copy.n_elem ==0); + REQUIRE(moveknn.ReferenceSet().n_rows ==3); + REQUIRE(moveknn.ReferenceSet().n_cols ==200); arma::mat moveDistances, distances; arma::Mat moveNeighbors, neighbors; @@ -305,24 +303,24 @@ BOOST_AUTO_TEST_CASE(DatasetMoveConstructorTest) moveknn.Search(1, moveNeighbors, moveDistances); knn.Search(1, neighbors, distances); - BOOST_REQUIRE_EQUAL(moveNeighbors.n_rows, neighbors.n_rows); - BOOST_REQUIRE_EQUAL(moveNeighbors.n_cols, neighbors.n_cols); - BOOST_REQUIRE_EQUAL(moveDistances.n_rows, distances.n_rows); - BOOST_REQUIRE_EQUAL(moveDistances.n_cols, distances.n_cols); + REQUIRE(moveNeighbors.n_rows ==neighbors.n_rows); + REQUIRE(moveNeighbors.n_cols ==neighbors.n_cols); + REQUIRE(moveDistances.n_rows ==distances.n_rows); + REQUIRE(moveDistances.n_cols ==distances.n_cols); for (size_t i = 0; i < moveDistances.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(moveNeighbors[i], neighbors[i]); + REQUIRE(moveNeighbors[i] ==neighbors[i]); if (std::abs(distances[i]) < 1e-5) - BOOST_REQUIRE_SMALL(moveDistances[i], 1e-5); + REQUIRE(moveDistances[i] == Approx(0.0).margin(1e-7)); else - BOOST_REQUIRE_CLOSE(moveDistances[i], distances[i], 1e-5); + REQUIRE(moveDistances[i] == Approx(distances[i]).epsilon(1e-7)); } } /** * Test that the dataset can be retrained with the move Train() function. */ -BOOST_AUTO_TEST_CASE(MoveTrainTest) +TEST_CASE("KNNMoveTrainTest", "[KNNTest]") { arma::mat dataset = arma::randu(3, 200); @@ -334,18 +332,18 @@ BOOST_AUTO_TEST_CASE(MoveTrainTest) arma::Mat neighbors; knn.Search(1, neighbors, distances); - BOOST_REQUIRE_EQUAL(dataset.n_elem, 0); - BOOST_REQUIRE_EQUAL(neighbors.n_cols, 200); - BOOST_REQUIRE_EQUAL(distances.n_cols, 200); + REQUIRE(dataset.n_elem ==0); + REQUIRE(neighbors.n_cols ==200); + REQUIRE(distances.n_cols ==200); dataset = arma::randu(3, 300); knn.SearchMode() = NAIVE_MODE; knn.Train(std::move(dataset)); knn.Search(1, neighbors, distances); - BOOST_REQUIRE_EQUAL(dataset.n_elem, 0); - BOOST_REQUIRE_EQUAL(neighbors.n_cols, 300); - BOOST_REQUIRE_EQUAL(distances.n_cols, 300); + REQUIRE(dataset.n_elem ==0); + REQUIRE(neighbors.n_cols ==300); + REQUIRE(distances.n_cols ==300); } /** @@ -356,7 +354,7 @@ BOOST_AUTO_TEST_CASE(MoveTrainTest) * in one dimension for simplicity -- the correct functionality of distance * functions is not tested here. */ -BOOST_AUTO_TEST_CASE(ExhaustiveSyntheticTest) +TEST_CASE("KNNExhaustiveSyntheticTest", "[KNNTest]") { // Set up our data. arma::mat data(1, 11); @@ -409,246 +407,246 @@ BOOST_AUTO_TEST_CASE(ExhaustiveSyntheticTest) // readability. // Neighbors of point 0. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[0]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[0]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[0]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[0]), 0.27, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[0]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[0]), 0.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[0]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[0]), 0.40, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[0]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[0]), 0.85, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[0]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[0]), 0.95, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[0]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[0]), 1.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[0]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[0]), 1.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[0]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[0]), 2.05, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[0]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[0]), 5.00, 1e-5); + REQUIRE(neighbors(0, newFromOld[0]) ==newFromOld[2]); + REQUIRE(distances(0, newFromOld[0]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[0]) ==newFromOld[5]); + REQUIRE(distances(1, newFromOld[0]) == Approx(0.27).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[0]) ==newFromOld[1]); + REQUIRE(distances(2, newFromOld[0]) == Approx(0.30).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[0]) ==newFromOld[8]); + REQUIRE(distances(3, newFromOld[0]) == Approx(0.40).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[0]) ==newFromOld[9]); + REQUIRE(distances(4, newFromOld[0]) == Approx(0.85).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[0]) ==newFromOld[10]); + REQUIRE(distances(5, newFromOld[0]) == Approx(0.95).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[0]) ==newFromOld[3]); + REQUIRE(distances(6, newFromOld[0]) == Approx(1.20).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[0]) ==newFromOld[7]); + REQUIRE(distances(7, newFromOld[0]) == Approx(1.35).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[0]) ==newFromOld[6]); + REQUIRE(distances(8, newFromOld[0]) == Approx(2.05).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[0]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[0]) == Approx(5.00).epsilon(1e-7)); // Neighbors of point 1. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[1]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[1]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[1]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[1]), 0.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[1]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[1]), 0.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[1]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[1]), 0.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[1]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[1]), 0.57, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[1]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[1]), 0.65, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[1]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[1]), 0.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[1]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[1]), 1.65, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[1]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[1]), 2.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[1]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[1]), 4.70, 1e-5); + REQUIRE(neighbors(0, newFromOld[1]) ==newFromOld[8]); + REQUIRE(distances(0, newFromOld[1]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[1]) ==newFromOld[2]); + REQUIRE(distances(1, newFromOld[1]) == Approx(0.20).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[1]) ==newFromOld[0]); + REQUIRE(distances(2, newFromOld[1]) == Approx(0.30).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[1]) ==newFromOld[9]); + REQUIRE(distances(3, newFromOld[1]) == Approx(0.55).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[1]) ==newFromOld[5]); + REQUIRE(distances(4, newFromOld[1]) == Approx(0.57).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[1]) ==newFromOld[10]); + REQUIRE(distances(5, newFromOld[1]) == Approx(0.65).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[1]) ==newFromOld[3]); + REQUIRE(distances(6, newFromOld[1]) == Approx(0.90).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[1]) ==newFromOld[7]); + REQUIRE(distances(7, newFromOld[1]) == Approx(1.65).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[1]) ==newFromOld[6]); + REQUIRE(distances(8, newFromOld[1]) == Approx(2.35).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[1]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[1]) == Approx(4.70).epsilon(1e-7)); // Neighbors of point 2. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[2]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[2]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[2]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[2]), 0.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[2]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[2]), 0.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[2]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[2]), 0.37, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[2]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[2]), 0.75, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[2]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[2]), 0.85, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[2]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[2]), 1.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[2]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[2]), 1.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[2]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[2]), 2.15, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[2]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[2]), 4.90, 1e-5); + REQUIRE(neighbors(0, newFromOld[2]) ==newFromOld[0]); + REQUIRE(distances(0, newFromOld[2]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[2]) ==newFromOld[1]); + REQUIRE(distances(1, newFromOld[2]) == Approx(0.20).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[2]) ==newFromOld[8]); + REQUIRE(distances(2, newFromOld[2]) == Approx(0.30).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[2]) ==newFromOld[5]); + REQUIRE(distances(3, newFromOld[2]) == Approx(0.37).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[2]) ==newFromOld[9]); + REQUIRE(distances(4, newFromOld[2]) == Approx(0.75).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[2]) ==newFromOld[10]); + REQUIRE(distances(5, newFromOld[2]) == Approx(0.85).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[2]) ==newFromOld[3]); + REQUIRE(distances(6, newFromOld[2]) == Approx(1.10).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[2]) ==newFromOld[7]); + REQUIRE(distances(7, newFromOld[2]) == Approx(1.45).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[2]) ==newFromOld[6]); + REQUIRE(distances(8, newFromOld[2]) == Approx(2.15).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[2]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[2]) == Approx(4.90).epsilon(1e-7)); // Neighbors of point 3. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[3]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[3]), 0.25, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[3]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[3]), 0.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[3]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[3]), 0.80, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[3]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[3]), 0.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[3]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[3]), 1.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[3]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[3]), 1.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[3]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[3]), 1.47, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[3]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[3]), 2.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[3]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[3]), 3.25, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[3]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[3]), 3.80, 1e-5); + REQUIRE(neighbors(0, newFromOld[3]) ==newFromOld[10]); + REQUIRE(distances(0, newFromOld[3]) == Approx(0.25).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[3]) ==newFromOld[9]); + REQUIRE(distances(1, newFromOld[3]) == Approx(0.35).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[3]) ==newFromOld[8]); + REQUIRE(distances(2, newFromOld[3]) == Approx(0.80).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[3]) ==newFromOld[1]); + REQUIRE(distances(3, newFromOld[3]) == Approx(0.90).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[3]) ==newFromOld[2]); + REQUIRE(distances(4, newFromOld[3]) == Approx(1.10).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[3]) ==newFromOld[0]); + REQUIRE(distances(5, newFromOld[3]) == Approx(1.20).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[3]) ==newFromOld[5]); + REQUIRE(distances(6, newFromOld[3]) == Approx(1.47).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[3]) ==newFromOld[7]); + REQUIRE(distances(7, newFromOld[3]) == Approx(2.55).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[3]) ==newFromOld[6]); + REQUIRE(distances(8, newFromOld[3]) == Approx(3.25).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[3]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[3]) == Approx(3.80).epsilon(1e-7)); // Neighbors of point 4. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[4]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[4]), 3.80, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[4]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[4]), 4.05, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[4]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[4]), 4.15, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[4]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[4]), 4.60, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[4]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[4]), 4.70, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[4]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[4]), 4.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[4]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[4]), 5.00, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[4]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[4]), 5.27, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[4]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[4]), 6.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[4]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[4]), 7.05, 1e-5); + REQUIRE(neighbors(0, newFromOld[4]) ==newFromOld[3]); + REQUIRE(distances(0, newFromOld[4]) == Approx(3.80).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[4]) ==newFromOld[10]); + REQUIRE(distances(1, newFromOld[4]) == Approx(4.05).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[4]) ==newFromOld[9]); + REQUIRE(distances(2, newFromOld[4]) == Approx(4.15).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[4]) ==newFromOld[8]); + REQUIRE(distances(3, newFromOld[4]) == Approx(4.60).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[4]) ==newFromOld[1]); + REQUIRE(distances(4, newFromOld[4]) == Approx(4.70).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[4]) ==newFromOld[2]); + REQUIRE(distances(5, newFromOld[4]) == Approx(4.90).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[4]) ==newFromOld[0]); + REQUIRE(distances(6, newFromOld[4]) == Approx(5.00).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[4]) ==newFromOld[5]); + REQUIRE(distances(7, newFromOld[4]) == Approx(5.27).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[4]) ==newFromOld[7]); + REQUIRE(distances(8, newFromOld[4]) == Approx(6.35).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[4]) ==newFromOld[6]); + REQUIRE(distances(9, newFromOld[4]) == Approx(7.05).epsilon(1e-7)); // Neighbors of point 5. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[5]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[5]), 0.27, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[5]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[5]), 0.37, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[5]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[5]), 0.57, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[5]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[5]), 0.67, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[5]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[5]), 1.08, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[5]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[5]), 1.12, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[5]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[5]), 1.22, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[5]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[5]), 1.47, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[5]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[5]), 1.78, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[5]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[5]), 5.27, 1e-5); + REQUIRE(neighbors(0, newFromOld[5]) ==newFromOld[0]); + REQUIRE(distances(0, newFromOld[5]) == Approx(0.27).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[5]) ==newFromOld[2]); + REQUIRE(distances(1, newFromOld[5]) == Approx(0.37).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[5]) ==newFromOld[1]); + REQUIRE(distances(2, newFromOld[5]) == Approx(0.57).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[5]) ==newFromOld[8]); + REQUIRE(distances(3, newFromOld[5]) == Approx(0.67).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[5]) ==newFromOld[7]); + REQUIRE(distances(4, newFromOld[5]) == Approx(1.08).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[5]) ==newFromOld[9]); + REQUIRE(distances(5, newFromOld[5]) == Approx(1.12).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[5]) ==newFromOld[10]); + REQUIRE(distances(6, newFromOld[5]) == Approx(1.22).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[5]) ==newFromOld[3]); + REQUIRE(distances(7, newFromOld[5]) == Approx(1.47).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[5]) ==newFromOld[6]); + REQUIRE(distances(8, newFromOld[5]) == Approx(1.78).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[5]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[5]) == Approx(5.27).epsilon(1e-7)); // Neighbors of point 6. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[6]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[6]), 0.70, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[6]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[6]), 1.78, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[6]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[6]), 2.05, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[6]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[6]), 2.15, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[6]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[6]), 2.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[6]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[6]), 2.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[6]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[6]), 2.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[6]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[6]), 3.00, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[6]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[6]), 3.25, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[6]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[6]), 7.05, 1e-5); + REQUIRE(neighbors(0, newFromOld[6]) ==newFromOld[7]); + REQUIRE(distances(0, newFromOld[6]) == Approx(0.70).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[6]) ==newFromOld[5]); + REQUIRE(distances(1, newFromOld[6]) == Approx(1.78).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[6]) ==newFromOld[0]); + REQUIRE(distances(2, newFromOld[6]) == Approx(2.05).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[6]) ==newFromOld[2]); + REQUIRE(distances(3, newFromOld[6]) == Approx(2.15).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[6]) ==newFromOld[1]); + REQUIRE(distances(4, newFromOld[6]) == Approx(2.35).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[6]) ==newFromOld[8]); + REQUIRE(distances(5, newFromOld[6]) == Approx(2.45).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[6]) ==newFromOld[9]); + REQUIRE(distances(6, newFromOld[6]) == Approx(2.90).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[6]) ==newFromOld[10]); + REQUIRE(distances(7, newFromOld[6]) == Approx(3.00).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[6]) ==newFromOld[3]); + REQUIRE(distances(8, newFromOld[6]) == Approx(3.25).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[6]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[6]) == Approx(7.05).epsilon(1e-7)); // Neighbors of point 7. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[7]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[7]), 0.70, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[7]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[7]), 1.08, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[7]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[7]), 1.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[7]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[7]), 1.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[7]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[7]), 1.65, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[7]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[7]), 1.75, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[7]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[7]), 2.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[7]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[7]), 2.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[7]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[7]), 2.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[7]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[7]), 6.35, 1e-5); + REQUIRE(neighbors(0, newFromOld[7]) ==newFromOld[6]); + REQUIRE(distances(0, newFromOld[7]) == Approx(0.70).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[7]) ==newFromOld[5]); + REQUIRE(distances(1, newFromOld[7]) == Approx(1.08).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[7]) ==newFromOld[0]); + REQUIRE(distances(2, newFromOld[7]) == Approx(1.35).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[7]) ==newFromOld[2]); + REQUIRE(distances(3, newFromOld[7]) == Approx(1.45).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[7]) ==newFromOld[1]); + REQUIRE(distances(4, newFromOld[7]) == Approx(1.65).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[7]) ==newFromOld[8]); + REQUIRE(distances(5, newFromOld[7]) == Approx(1.75).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[7]) ==newFromOld[9]); + REQUIRE(distances(6, newFromOld[7]) == Approx(2.20).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[7]) ==newFromOld[10]); + REQUIRE(distances(7, newFromOld[7]) == Approx(2.30).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[7]) ==newFromOld[3]); + REQUIRE(distances(8, newFromOld[7]) == Approx(2.55).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[7]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[7]) == Approx(6.35).epsilon(1e-7)); // Neighbors of point 8. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[8]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[8]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[8]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[8]), 0.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[8]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[8]), 0.40, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[8]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[8]), 0.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[8]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[8]), 0.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[8]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[8]), 0.67, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[8]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[8]), 0.80, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[8]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[8]), 1.75, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[8]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[8]), 2.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[8]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[8]), 4.60, 1e-5); + REQUIRE(neighbors(0, newFromOld[8]) ==newFromOld[1]); + REQUIRE(distances(0, newFromOld[8]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[8]) ==newFromOld[2]); + REQUIRE(distances(1, newFromOld[8]) == Approx(0.30).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[8]) ==newFromOld[0]); + REQUIRE(distances(2, newFromOld[8]) == Approx(0.40).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[8]) ==newFromOld[9]); + REQUIRE(distances(3, newFromOld[8]) == Approx(0.45).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[8]) ==newFromOld[10]); + REQUIRE(distances(4, newFromOld[8]) == Approx(0.55).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[8]) ==newFromOld[5]); + REQUIRE(distances(5, newFromOld[8]) == Approx(0.67).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[8]) ==newFromOld[3]); + REQUIRE(distances(6, newFromOld[8]) == Approx(0.80).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[8]) ==newFromOld[7]); + REQUIRE(distances(7, newFromOld[8]) == Approx(1.75).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[8]) ==newFromOld[6]); + REQUIRE(distances(8, newFromOld[8]) == Approx(2.45).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[8]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[8]) == Approx(4.60).epsilon(1e-7)); // Neighbors of point 9. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[9]), newFromOld[10]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[9]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[9]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[9]), 0.35, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[9]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[9]), 0.45, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[9]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[9]), 0.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[9]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[9]), 0.75, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[9]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[9]), 0.85, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[9]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[9]), 1.12, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[9]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[9]), 2.20, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[9]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[9]), 2.90, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[9]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[9]), 4.15, 1e-5); + REQUIRE(neighbors(0, newFromOld[9]) ==newFromOld[10]); + REQUIRE(distances(0, newFromOld[9]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[9]) ==newFromOld[3]); + REQUIRE(distances(1, newFromOld[9]) == Approx(0.35).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[9]) ==newFromOld[8]); + REQUIRE(distances(2, newFromOld[9]) == Approx(0.45).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[9]) ==newFromOld[1]); + REQUIRE(distances(3, newFromOld[9]) == Approx(0.55).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[9]) ==newFromOld[2]); + REQUIRE(distances(4, newFromOld[9]) == Approx(0.75).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[9]) ==newFromOld[0]); + REQUIRE(distances(5, newFromOld[9]) == Approx(0.85).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[9]) ==newFromOld[5]); + REQUIRE(distances(6, newFromOld[9]) == Approx(1.12).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[9]) ==newFromOld[7]); + REQUIRE(distances(7, newFromOld[9]) == Approx(2.20).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[9]) ==newFromOld[6]); + REQUIRE(distances(8, newFromOld[9]) == Approx(2.90).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[9]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[9]) == Approx(4.15).epsilon(1e-7)); // Neighbors of point 10. - BOOST_REQUIRE_EQUAL(neighbors(0, newFromOld[10]), newFromOld[9]); - BOOST_REQUIRE_CLOSE(distances(0, newFromOld[10]), 0.10, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(1, newFromOld[10]), newFromOld[3]); - BOOST_REQUIRE_CLOSE(distances(1, newFromOld[10]), 0.25, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(2, newFromOld[10]), newFromOld[8]); - BOOST_REQUIRE_CLOSE(distances(2, newFromOld[10]), 0.55, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(3, newFromOld[10]), newFromOld[1]); - BOOST_REQUIRE_CLOSE(distances(3, newFromOld[10]), 0.65, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(4, newFromOld[10]), newFromOld[2]); - BOOST_REQUIRE_CLOSE(distances(4, newFromOld[10]), 0.85, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(5, newFromOld[10]), newFromOld[0]); - BOOST_REQUIRE_CLOSE(distances(5, newFromOld[10]), 0.95, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(6, newFromOld[10]), newFromOld[5]); - BOOST_REQUIRE_CLOSE(distances(6, newFromOld[10]), 1.22, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(7, newFromOld[10]), newFromOld[7]); - BOOST_REQUIRE_CLOSE(distances(7, newFromOld[10]), 2.30, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(8, newFromOld[10]), newFromOld[6]); - BOOST_REQUIRE_CLOSE(distances(8, newFromOld[10]), 3.00, 1e-5); - BOOST_REQUIRE_EQUAL(neighbors(9, newFromOld[10]), newFromOld[4]); - BOOST_REQUIRE_CLOSE(distances(9, newFromOld[10]), 4.05, 1e-5); + REQUIRE(neighbors(0, newFromOld[10]) ==newFromOld[9]); + REQUIRE(distances(0, newFromOld[10]) == Approx(0.10).epsilon(1e-7)); + REQUIRE(neighbors(1, newFromOld[10]) ==newFromOld[3]); + REQUIRE(distances(1, newFromOld[10]) == Approx(0.25).epsilon(1e-7)); + REQUIRE(neighbors(2, newFromOld[10]) ==newFromOld[8]); + REQUIRE(distances(2, newFromOld[10]) == Approx(0.55).epsilon(1e-7)); + REQUIRE(neighbors(3, newFromOld[10]) ==newFromOld[1]); + REQUIRE(distances(3, newFromOld[10]) == Approx(0.65).epsilon(1e-7)); + REQUIRE(neighbors(4, newFromOld[10]) ==newFromOld[2]); + REQUIRE(distances(4, newFromOld[10]) == Approx(0.85).epsilon(1e-7)); + REQUIRE(neighbors(5, newFromOld[10]) ==newFromOld[0]); + REQUIRE(distances(5, newFromOld[10]) == Approx(0.95).epsilon(1e-7)); + REQUIRE(neighbors(6, newFromOld[10]) ==newFromOld[5]); + REQUIRE(distances(6, newFromOld[10]) == Approx(1.22).epsilon(1e-7)); + REQUIRE(neighbors(7, newFromOld[10]) ==newFromOld[7]); + REQUIRE(distances(7, newFromOld[10]) == Approx(2.30).epsilon(1e-7)); + REQUIRE(neighbors(8, newFromOld[10]) ==newFromOld[6]); + REQUIRE(distances(8, newFromOld[10]) == Approx(3.00).epsilon(1e-7)); + REQUIRE(neighbors(9, newFromOld[10]) ==newFromOld[4]); + REQUIRE(distances(9, newFromOld[10]) == Approx(4.05).epsilon(1e-7)); } } @@ -658,13 +656,13 @@ BOOST_AUTO_TEST_CASE(ExhaustiveSyntheticTest) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(DualTreeVsNaive1) +TEST_CASE("KNNDualTreeVsNaive", "[KNNTest]") { arma::mat dataset; // Hard-coded filename: bad? if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KNN knn(dataset); @@ -680,8 +678,8 @@ BOOST_AUTO_TEST_CASE(DualTreeVsNaive1) for (size_t i = 0; i < neighborsTree.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsTree(i), neighborsNaive(i)); - BOOST_REQUIRE_CLOSE(distancesTree(i), distancesNaive(i), 1e-5); + REQUIRE(neighborsTree(i) ==neighborsNaive(i)); + REQUIRE(distancesTree(i) == Approx(distancesNaive(i)).epsilon(1e-7)); } } @@ -691,14 +689,14 @@ BOOST_AUTO_TEST_CASE(DualTreeVsNaive1) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(DualTreeVsNaive2) +TEST_CASE("KNNDualTreeVsNaive2", "[KNNTest]") { arma::mat dataset; // Hard-coded filename: bad? // Code duplication: also bad! if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KNN knn(dataset); @@ -715,8 +713,8 @@ BOOST_AUTO_TEST_CASE(DualTreeVsNaive2) for (size_t i = 0; i < neighborsTree.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsTree[i], neighborsNaive[i]); - BOOST_REQUIRE_CLOSE(distancesTree[i], distancesNaive[i], 1e-5); + REQUIRE(neighborsTree[i] ==neighborsNaive[i]); + REQUIRE(distancesTree[i] == Approx(distancesNaive[i]).epsilon(1e-7)); } } @@ -726,14 +724,14 @@ BOOST_AUTO_TEST_CASE(DualTreeVsNaive2) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(SingleTreeVsNaive) +TEST_CASE("KNNSingleTreeVsNaive", "[KNNTest]") { arma::mat dataset; // Hard-coded filename: bad? // Code duplication: also bad! if (!data::Load("test_data_3_1000.csv", dataset)) - BOOST_FAIL("Cannot load test dataset test_data_3_1000.csv!"); + FAIL("Cannot load test dataset test_data_3_1000.csv!"); KNN knn(dataset, SINGLE_TREE_MODE); @@ -750,8 +748,8 @@ BOOST_AUTO_TEST_CASE(SingleTreeVsNaive) for (size_t i = 0; i < neighborsTree.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsTree[i], neighborsNaive[i]); - BOOST_REQUIRE_CLOSE(distancesTree[i], distancesNaive[i], 1e-5); + REQUIRE(neighborsTree[i] ==neighborsNaive[i]); + REQUIRE(distancesTree[i] == Approx(distancesNaive[i]).epsilon(1e-7)); } } @@ -761,7 +759,7 @@ BOOST_AUTO_TEST_CASE(SingleTreeVsNaive) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) +TEST_CASE("KNNSingleCoverTreeTest", "[KNNTest]") { arma::mat data; data.randu(75, 1000); // 75 dimensional, 1000 points. @@ -784,8 +782,8 @@ BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) for (size_t i = 0; i < coverTreeNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(coverTreeNeighbors[i], naiveNeighbors[i]); - BOOST_REQUIRE_CLOSE(coverTreeDistances[i], naiveDistances[i], 1e-5); + REQUIRE(coverTreeNeighbors[i] ==naiveNeighbors[i]); + REQUIRE(coverTreeDistances[i] == Approx(naiveDistances[i]).epsilon(1e-7)); } } @@ -793,7 +791,7 @@ BOOST_AUTO_TEST_CASE(SingleCoverTreeTest) * Test the cover tree dual-tree nearest neighbors method against the naive * method. */ -BOOST_AUTO_TEST_CASE(DualCoverTreeTest) +TEST_CASE("KNNDualCoverTreeTest", "[KNNTest]") { arma::mat dataset; data::Load("test_data_3_1000.csv", dataset); @@ -816,8 +814,8 @@ BOOST_AUTO_TEST_CASE(DualCoverTreeTest) for (size_t i = 0; i < coverNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(coverNeighbors(i), kdNeighbors(i)); - BOOST_REQUIRE_CLOSE(coverDistances(i), kdDistances(i), 1e-5); + REQUIRE(coverNeighbors(i) ==kdNeighbors(i)); + REQUIRE(coverDistances(i) == Approx(kdDistances(i)).epsilon(1e-7)); } } @@ -827,7 +825,7 @@ BOOST_AUTO_TEST_CASE(DualCoverTreeTest) * * Errors are produced if the results are not identical. */ -BOOST_AUTO_TEST_CASE(SingleBallTreeTest) +TEST_CASE("KNNSingleBallTreeTest", "[KNNTest]") { arma::mat data; data.randu(50, 300); // 50 dimensional, 300 points. @@ -855,8 +853,8 @@ BOOST_AUTO_TEST_CASE(SingleBallTreeTest) for (size_t i = 0; i < ballTreeNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(ballTreeNeighbors[i], naiveNeighbors[i]); - BOOST_REQUIRE_CLOSE(ballTreeDistances[i], naiveDistances[i], 1e-5); + REQUIRE(ballTreeNeighbors[i] ==naiveNeighbors[i]); + REQUIRE(ballTreeDistances[i] == Approx(naiveDistances[i]).epsilon(1e-7)); } } @@ -864,7 +862,7 @@ BOOST_AUTO_TEST_CASE(SingleBallTreeTest) * Test the ball tree dual-tree nearest neighbors method against the naive * method. */ -BOOST_AUTO_TEST_CASE(DualBallTreeTest) +TEST_CASE("KNNDualBallTreeTest", "[KNNTest]") { arma::mat dataset; data::Load("test_data_3_1000.csv", dataset); @@ -884,8 +882,8 @@ BOOST_AUTO_TEST_CASE(DualBallTreeTest) for (size_t i = 0; i < ballNeighbors.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(ballNeighbors(i), kdNeighbors(i)); - BOOST_REQUIRE_CLOSE(ballDistances(i), kdDistances(i), 1e-5); + REQUIRE(ballNeighbors(i) ==kdNeighbors(i)); + REQUIRE(ballDistances(i) == Approx(kdDistances(i)).epsilon(1e-7)); } } @@ -894,7 +892,7 @@ BOOST_AUTO_TEST_CASE(DualBallTreeTest) * nodes, and backtracking in non-overlapping nodes) against the naive method. * This uses only a random reference dataset. */ -BOOST_AUTO_TEST_CASE(HybridSpillSearchTest) +TEST_CASE("KNNHybridSpillSearchTest", "[KNNTest]") { arma::mat dataset; dataset.randu(50, 300); // 50 dimensional, 300 points. @@ -928,8 +926,8 @@ BOOST_AUTO_TEST_CASE(HybridSpillSearchTest) for (size_t i = 0; i < neighborsSPTree.n_elem; ++i) { - BOOST_REQUIRE_EQUAL(neighborsSPTree(i), neighborsNaive(i)); - BOOST_REQUIRE_CLOSE(distancesSPTree(i), distancesNaive(i), 1e-5); + REQUIRE(neighborsSPTree(i) ==neighborsNaive(i)); + REQUIRE(distancesSPTree(i) == Approx(distancesNaive(i)).epsilon(1e-7)); } } } @@ -938,7 +936,7 @@ BOOST_AUTO_TEST_CASE(HybridSpillSearchTest) * Test hybrid sp-tree search doesn't repeat points. * This uses only a random reference dataset. */ -BOOST_AUTO_TEST_CASE(DuplicatedSpillSearchTest) +TEST_CASE("KNNDuplicatedSpillSearchTest", "[KNNTest]") { arma::mat dataset; dataset.randu(50, 300); // 50 dimensional, 300 points. @@ -965,7 +963,7 @@ BOOST_AUTO_TEST_CASE(DuplicatedSpillSearchTest) for (size_t i = 0; i < neighborsSPTree.n_cols; ++i) { // Test that at least one point was found. - BOOST_REQUIRE(distancesSPTree(0, i) != DBL_MAX); + REQUIRE(distancesSPTree(0, i) != DBL_MAX); for (size_t j = 0; j < neighborsSPTree.n_rows; ++j) { @@ -974,7 +972,7 @@ BOOST_AUTO_TEST_CASE(DuplicatedSpillSearchTest) // All candidates with same distances must be different points. for (size_t k = j + 1; k < neighborsSPTree.n_rows && distancesSPTree(k, i) == distancesSPTree(j, i); ++k) - BOOST_REQUIRE(neighborsSPTree(k, i) != neighborsSPTree(j, i)); + REQUIRE(neighborsSPTree(k, i) != neighborsSPTree(j, i)); } } } @@ -984,7 +982,7 @@ BOOST_AUTO_TEST_CASE(DuplicatedSpillSearchTest) /** * Make sure sparse nearest neighbors works with kd trees. */ -BOOST_AUTO_TEST_CASE(SparseKNNKDTreeTest) +TEST_CASE("SparseKNNKDTreeTest", "[KNNTest]") { // The dimensionality of these datasets must be high so that the probability // of a completely empty point is very low. In this case, with dimensionality @@ -1015,14 +1013,15 @@ BOOST_AUTO_TEST_CASE(SparseKNNKDTreeTest) { for (size_t j = 0; j < naiveNeighbors.n_rows; ++j) { - BOOST_REQUIRE_EQUAL(naiveNeighbors(j, i), sparseNeighbors(j, i)); - BOOST_REQUIRE_CLOSE(naiveDistances(j, i), sparseDistances(j, i), 1e-5); + REQUIRE(naiveNeighbors(j, i) == sparseNeighbors(j, i)); + REQUIRE(naiveDistances(j, i) == + Approx(sparseDistances(j, i)).epsilon(1e-7)); } } } /* -BOOST_AUTO_TEST_CASE(SparseKNNCoverTreeTest) +TEST_CASE("SparseKNNCoverTreeTest", "[KNNTest]") { typedef CoverTree, FirstPointIsRoot, NeighborSearchStat, arma::sp_mat> SparseCoverTree; @@ -1053,14 +1052,14 @@ BOOST_AUTO_TEST_CASE(SparseKNNCoverTreeTest) { for (size_t j = 0; j < naiveNeighbors.n_rows; ++j) { - BOOST_REQUIRE_EQUAL(naiveNeighbors(j, i), sparseNeighbors(j, i)); - BOOST_REQUIRE_CLOSE(naiveDistances(j, i), sparseDistances(j, i), 1e-5); + REQUIRE(naiveNeighbors(j, i) == sparseNeighbors(j, i)); + REQUIRE(naiveDistances(j, i) == Approx(sparseDistances(j, i)).epsilon(1e-7)); } } } */ -BOOST_AUTO_TEST_CASE(KNNModelTest) +TEST_CASE("KNNModelTest", "[KNNTest]") { // Ensure that we can build an NSModel and get correct // results. @@ -1126,25 +1125,25 @@ BOOST_AUTO_TEST_CASE(KNNModelTest) models[i].Search(std::move(queryCopy), 3, neighbors, distances); - BOOST_REQUIRE_EQUAL(neighbors.n_rows, baselineNeighbors.n_rows); - BOOST_REQUIRE_EQUAL(neighbors.n_cols, baselineNeighbors.n_cols); - BOOST_REQUIRE_EQUAL(neighbors.n_elem, baselineNeighbors.n_elem); - BOOST_REQUIRE_EQUAL(distances.n_rows, baselineDistances.n_rows); - BOOST_REQUIRE_EQUAL(distances.n_cols, baselineDistances.n_cols); - BOOST_REQUIRE_EQUAL(distances.n_elem, baselineDistances.n_elem); + REQUIRE(neighbors.n_rows ==baselineNeighbors.n_rows); + REQUIRE(neighbors.n_cols ==baselineNeighbors.n_cols); + REQUIRE(neighbors.n_elem ==baselineNeighbors.n_elem); + REQUIRE(distances.n_rows ==baselineDistances.n_rows); + REQUIRE(distances.n_cols ==baselineDistances.n_cols); + REQUIRE(distances.n_elem ==baselineDistances.n_elem); for (size_t k = 0; k < distances.n_elem; ++k) { - BOOST_REQUIRE_EQUAL(neighbors[k], baselineNeighbors[k]); + REQUIRE(neighbors[k] ==baselineNeighbors[k]); if (std::abs(baselineDistances[k]) < 1e-5) - BOOST_REQUIRE_SMALL(distances[k], 1e-5); + REQUIRE(distances[k] == Approx(0.0).margin(1e-7)); else - BOOST_REQUIRE_CLOSE(distances[k], baselineDistances[k], 1e-5); + REQUIRE(distances[k] == Approx(baselineDistances[k]).epsilon(1e-7)); } } } } -BOOST_AUTO_TEST_CASE(KNNModelMonochromaticTest) +TEST_CASE("KNNModelMonochromaticTest", "[KNNTest]") { // Ensure that we can build an NSModel and get correct // results, in the case where the reference set is the same as the query set. @@ -1208,19 +1207,19 @@ BOOST_AUTO_TEST_CASE(KNNModelMonochromaticTest) models[i].Search(3, neighbors, distances); - BOOST_REQUIRE_EQUAL(neighbors.n_rows, baselineNeighbors.n_rows); - BOOST_REQUIRE_EQUAL(neighbors.n_cols, baselineNeighbors.n_cols); - BOOST_REQUIRE_EQUAL(neighbors.n_elem, baselineNeighbors.n_elem); - BOOST_REQUIRE_EQUAL(distances.n_rows, baselineDistances.n_rows); - BOOST_REQUIRE_EQUAL(distances.n_cols, baselineDistances.n_cols); - BOOST_REQUIRE_EQUAL(distances.n_elem, baselineDistances.n_elem); + REQUIRE(neighbors.n_rows ==baselineNeighbors.n_rows); + REQUIRE(neighbors.n_cols ==baselineNeighbors.n_cols); + REQUIRE(neighbors.n_elem ==baselineNeighbors.n_elem); + REQUIRE(distances.n_rows ==baselineDistances.n_rows); + REQUIRE(distances.n_cols ==baselineDistances.n_cols); + REQUIRE(distances.n_elem ==baselineDistances.n_elem); for (size_t k = 0; k < distances.n_elem; ++k) { - BOOST_REQUIRE_EQUAL(neighbors[k], baselineNeighbors[k]); + REQUIRE(neighbors[k] ==baselineNeighbors[k]); if (std::abs(baselineDistances[k]) < 1e-5) - BOOST_REQUIRE_SMALL(distances[k], 1e-5); + REQUIRE(distances[k] == Approx(0.0).margin(1e-7)); else - BOOST_REQUIRE_CLOSE(distances[k], baselineDistances[k], 1e-5); + REQUIRE(distances[k] == Approx(baselineDistances[k]).epsilon(1e-7)); } } } @@ -1231,7 +1230,7 @@ BOOST_AUTO_TEST_CASE(KNNModelMonochromaticTest) * before the second search. This test ensures that that happens, by making * sure the number of scores and base cases are equivalent for each search. */ -BOOST_AUTO_TEST_CASE(DoubleReferenceSearchTest) +TEST_CASE("KNNDoubleReferenceSearchTest", "[KNNTest]") { arma::mat dataset = arma::randu(5, 500); KNN knn(std::move(dataset)); @@ -1244,15 +1243,15 @@ BOOST_AUTO_TEST_CASE(DoubleReferenceSearchTest) knn.Search(3, secondNeighbors, secondDistances); - BOOST_REQUIRE_EQUAL(knn.BaseCases(), baseCases); - BOOST_REQUIRE_EQUAL(knn.Scores(), scores); + REQUIRE(knn.BaseCases() ==baseCases); + REQUIRE(knn.Scores() ==scores); } /** * Make sure that the neighborPtr matrix isn't accidentally deleted. * See issue #478. */ -BOOST_AUTO_TEST_CASE(NeighborPtrDeleteTest) +TEST_CASE("KNNNeighborPtrDeleteTest", "[KNNTest]") { arma::mat dataset = arma::randu(5, 100); @@ -1269,16 +1268,16 @@ BOOST_AUTO_TEST_CASE(NeighborPtrDeleteTest) // These will (hopefully) fail is either the neighbors or the distances matrix // has been accidentally deleted. - BOOST_REQUIRE_EQUAL(neighbors.n_cols, 50); - BOOST_REQUIRE_EQUAL(neighbors.n_rows, 3); - BOOST_REQUIRE_EQUAL(distances.n_cols, 50); - BOOST_REQUIRE_EQUAL(distances.n_rows, 3); + REQUIRE(neighbors.n_cols ==50); + REQUIRE(neighbors.n_rows ==3); + REQUIRE(distances.n_cols ==50); + REQUIRE(distances.n_rows ==3); } /** * Test the copy constructor and copy operator. */ -BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorTest) +TEST_CASE("KNNCopyConstructorAndOperatorTest", "[KNNTest]") { arma::mat dataset = arma::randu(5, 500); KNN knn(std::move(dataset)); @@ -1304,7 +1303,7 @@ BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorTest) /** * Test the copy constructor and copy operator using the RectangleTree. */ -BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorRTreeTest) +TEST_CASE("KNNCopyConstructorAndOperatorRTreeTest", "[KNNTest]") { arma::mat dataset = arma::randu(5, 500); typedef NeighborSearch(5, 500); typedef NeighborSearch(5, 500); typedef NeighborSearch(5, 500); typedef NeighborSearch(5, 500); typedef NeighborSearch(5, 500); KNN* knn = new KNN(std::move(dataset)); @@ -1469,7 +1468,7 @@ BOOST_AUTO_TEST_CASE(MoveConstructorTest) /** * Test the move constructor & move assignment using R trees. */ -BOOST_AUTO_TEST_CASE(MoveConstructorRTreeTest) +TEST_CASE("KNNMoveConstructorRTreeTest", "[KNNTest]") { arma::mat dataset = arma::randu(5, 500); typedef NeighborSearch(5, 500); typedef NeighborSearch(5, 500); typedef NeighborSearch(5, 500); typedef NeighborSearch(5, 500); typedef NeighborSearch(5, 500); KNN* knn = new KNN(std::move(dataset)); @@ -1661,7 +1660,7 @@ BOOST_AUTO_TEST_CASE(MoveOperatorTest) * Test the copy constructor and copy operator in naive mode (so there is no * tree). */ -BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorNaiveTest) +TEST_CASE("KNNCopyConstructorAndOperatorNaiveTest", "[KNNTest]") { arma::mat dataset = arma::randu(5, 50); KNN knn(std::move(dataset), NAIVE_MODE); @@ -1670,8 +1669,8 @@ BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorNaiveTest) KNN knn2(knn); KNN knn3 = knn; - BOOST_REQUIRE_EQUAL(knn2.SearchMode(), NAIVE_MODE); - BOOST_REQUIRE_EQUAL(knn3.SearchMode(), NAIVE_MODE); + REQUIRE(knn2.SearchMode() ==NAIVE_MODE); + REQUIRE(knn3.SearchMode() ==NAIVE_MODE); // Get results. arma::mat distances, distances2, distances3; @@ -1690,7 +1689,7 @@ BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorNaiveTest) /** * Test the move constructor in naive mode (so there is no tree). */ -BOOST_AUTO_TEST_CASE(MoveConstructorNaiveTest) +TEST_CASE("KNNMoveConstructorNaiveTest", "[KNNTest]") { arma::mat dataset = arma::randu(5, 50); KNN* knn = new KNN(std::move(dataset), NAIVE_MODE); @@ -1706,7 +1705,7 @@ BOOST_AUTO_TEST_CASE(MoveConstructorNaiveTest) delete knn; - BOOST_REQUIRE_EQUAL(knn2.SearchMode(), NAIVE_MODE); + REQUIRE(knn2.SearchMode() ==NAIVE_MODE); knn2.Search(3, neighbors2, distances2); @@ -1717,7 +1716,7 @@ BOOST_AUTO_TEST_CASE(MoveConstructorNaiveTest) /** * Test the move operator in naive mode (so there is no tree). */ -BOOST_AUTO_TEST_CASE(MoveOperatorNaiveTest) +TEST_CASE("KNNMoveOperatorNaiveTest", "[KNNTest]") { arma::mat dataset = arma::randu(5, 500); KNN* knn = new KNN(std::move(dataset), NAIVE_MODE); @@ -1733,7 +1732,7 @@ BOOST_AUTO_TEST_CASE(MoveOperatorNaiveTest) delete knn; - BOOST_REQUIRE_EQUAL(knn2.SearchMode(), NAIVE_MODE); + REQUIRE(knn2.SearchMode() ==NAIVE_MODE); knn2.Search(3, neighbors2, distances2); @@ -1745,7 +1744,7 @@ BOOST_AUTO_TEST_CASE(MoveOperatorNaiveTest) * Check that no garbage value is returned when greedy tree traversal * is performed over kd-tree. */ -BOOST_AUTO_TEST_CASE(GreedyTreeSearch) +TEST_CASE("KNNGreedyTreeSearch", "[KNNTest]") { // Initalize dataset. arma::mat dataset = arma::randu(3, 100); @@ -1765,12 +1764,9 @@ BOOST_AUTO_TEST_CASE(GreedyTreeSearch) // Check that all neighbour values are between 0 and 100, as only 100 points // are present in dataset. - BOOST_REQUIRE_EQUAL(arma::accu(neighbors < 0 || neighbors >= 100), 0); + REQUIRE(arma::accu(neighbors < 0 || neighbors >= 100) ==0); // Check that all distances values are between 0.0 and 1.0 as arma::randu // generates a uniform distribution in [0, 1]. - BOOST_REQUIRE_EQUAL(arma::accu(distances < 0.0 || distances > std::sqrt(3.0)), - 0); + REQUIRE(arma::accu(distances < 0.0 || distances > std::sqrt(3.0)) == 0); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/load_save_test.cpp b/src/mlpack/tests/load_save_test.cpp index db2e24a29f..12429e43ed 100644 --- a/src/mlpack/tests/load_save_test.cpp +++ b/src/mlpack/tests/load_save_test.cpp @@ -14,46 +14,44 @@ #include #include #include -#include -#include "test_tools.hpp" +#include "catch.hpp" +#include "test_catch_tools.hpp" using namespace mlpack; using namespace mlpack::data; using namespace std; -BOOST_AUTO_TEST_SUITE(LoadSaveTest); - /** * Make sure failure occurs when no extension given. */ -BOOST_AUTO_TEST_CASE(NoExtensionLoad) +TEST_CASE("NoExtensionLoad", "[LoadSaveTest]") { arma::mat out; - BOOST_REQUIRE(data::Load("noextension", out) == false); + REQUIRE(data::Load("noextension", out) == false); } /** * Make sure failure occurs when no extension given. */ -BOOST_AUTO_TEST_CASE(NoExtensionSave) +TEST_CASE("NoExtensionSave", "[LoadSaveTest]") { arma::mat out; - BOOST_REQUIRE(data::Save("noextension", out) == false); + REQUIRE(data::Save("noextension", out) == false); } /** * Make sure load fails if the file does not exist. */ -BOOST_AUTO_TEST_CASE(NotExistLoad) +TEST_CASE("NotExistLoad", "[LoadSaveTest]") { arma::mat out; - BOOST_REQUIRE(data::Load("nonexistentfile_______________.csv", out) == false); + REQUIRE(data::Load("nonexistentfile_______________.csv", out) == false); } /** * Make sure a CSV is loaded correctly. */ -BOOST_AUTO_TEST_CASE(LoadCSVTest) +TEST_CASE("LoadCSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -64,13 +62,13 @@ BOOST_AUTO_TEST_CASE(LoadCSVTest) f.close(); arma::mat test; - BOOST_REQUIRE(data::Load("test_file.csv", test) == true); + REQUIRE(data::Load("test_file.csv", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -79,7 +77,7 @@ BOOST_AUTO_TEST_CASE(LoadCSVTest) /** * Make sure a TSV is loaded correctly to a sparse matrix. */ -BOOST_AUTO_TEST_CASE(LoadSparseTSVTest) +TEST_CASE("LoadSparseTSVTest", "[LoadSaveTest]") { fstream f; f.open("test_sparse_file.tsv", fstream::out); @@ -96,11 +94,11 @@ BOOST_AUTO_TEST_CASE(LoadSparseTSVTest) arma::sp_mat test; - BOOST_REQUIRE(data::Load( + REQUIRE(data::Load( "test_sparse_file.tsv", test, true, false) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 8); - BOOST_REQUIRE_EQUAL(test.n_cols, 9); + REQUIRE(test.n_rows == 8); + REQUIRE(test.n_cols == 9); arma::sp_mat::const_iterator it = test.begin(); arma::sp_mat::const_iterator it_end = test.end(); @@ -108,9 +106,9 @@ BOOST_AUTO_TEST_CASE(LoadSparseTSVTest) double temp = 0.1; for (int i = 0; it != it_end; ++it, temp += 0.1, ++i) { - BOOST_REQUIRE_CLOSE((double)(*it), temp, 1e-5); - BOOST_REQUIRE_EQUAL((int)(it.row()), i + 1); - BOOST_REQUIRE_EQUAL((int)it.col(), i + 2); + REQUIRE((double)(*it) == Approx(temp).epsilon(1e-7)); + REQUIRE((int)(it.row()) == i + 1); + REQUIRE((int)it.col() == i + 2); } // Remove the file. remove("test_sparse_file.tsv"); @@ -119,7 +117,7 @@ BOOST_AUTO_TEST_CASE(LoadSparseTSVTest) /** * Make sure a CSV in text format is loaded correctly to a sparse matrix. */ -BOOST_AUTO_TEST_CASE(LoadSparseTXTTest) +TEST_CASE("LoadSparseTXTTest", "[LoadSaveTest]") { fstream f; f.open("test_sparse_file.txt", fstream::out); @@ -136,10 +134,10 @@ BOOST_AUTO_TEST_CASE(LoadSparseTXTTest) arma::sp_mat test; - BOOST_REQUIRE(data::Load("test_sparse_file.txt", test, true, false) == true); + REQUIRE(data::Load("test_sparse_file.txt", test, true, false) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 8); - BOOST_REQUIRE_EQUAL(test.n_cols, 9); + REQUIRE(test.n_rows == 8); + REQUIRE(test.n_cols == 9); arma::sp_mat::const_iterator it = test.begin(); arma::sp_mat::const_iterator it_end = test.end(); @@ -147,9 +145,9 @@ BOOST_AUTO_TEST_CASE(LoadSparseTXTTest) double temp = 0.1; for (int i = 0; it != it_end; ++it, temp += 0.1, ++i) { - BOOST_REQUIRE_CLOSE((double)(*it), temp, 1e-5); - BOOST_REQUIRE_EQUAL((int)(it.row()), i + 1); - BOOST_REQUIRE_EQUAL((int)it.col(), i + 2); + REQUIRE((double)(*it) == Approx(temp).epsilon(1e-7)); + REQUIRE((int)(it.row()) == i + 1); + REQUIRE((int)it.col() == i + 2); } // Remove the file. remove("test_sparse_file.txt"); @@ -158,7 +156,7 @@ BOOST_AUTO_TEST_CASE(LoadSparseTXTTest) /** * Make sure a TSV is loaded correctly. */ -BOOST_AUTO_TEST_CASE(LoadTSVTest) +TEST_CASE("LoadTSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -169,13 +167,13 @@ BOOST_AUTO_TEST_CASE(LoadTSVTest) f.close(); arma::mat test; - BOOST_REQUIRE(data::Load("test_file.csv", test) == true); + REQUIRE(data::Load("test_file.csv", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -184,7 +182,7 @@ BOOST_AUTO_TEST_CASE(LoadTSVTest) /** * Test TSV loading with .tsv extension. */ -BOOST_AUTO_TEST_CASE(LoadTSVExtensionTest) +TEST_CASE("LoadTSVExtensionTest", "[LoadSaveTest]") { fstream f; f.open("test_file.tsv", fstream::out); @@ -195,13 +193,13 @@ BOOST_AUTO_TEST_CASE(LoadTSVExtensionTest) f.close(); arma::mat test; - BOOST_REQUIRE(data::Load("test_file.tsv", test) == true); + REQUIRE(data::Load("test_file.tsv", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.tsv"); @@ -210,24 +208,24 @@ BOOST_AUTO_TEST_CASE(LoadTSVExtensionTest) /** * Make sure a CSV is saved correctly. */ -BOOST_AUTO_TEST_CASE(SaveCSVTest) +TEST_CASE("SaveCSVTest", "[LoadSaveTest]") { arma::mat test = "1 5;" "2 6;" "3 7;" "4 8;"; - BOOST_REQUIRE(data::Save("test_file.csv", test) == true); + REQUIRE(data::Save("test_file.csv", test) == true); // Load it in and make sure it is the same. arma::mat test2; - BOOST_REQUIRE(data::Load("test_file.csv", test2) == true); + REQUIRE(data::Load("test_file.csv", test2) == true); - BOOST_REQUIRE_EQUAL(test2.n_rows, 4); - BOOST_REQUIRE_EQUAL(test2.n_cols, 2); + REQUIRE(test2.n_rows == 4); + REQUIRE(test2.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test2[i], (double) (i + 1), 1e-5); + REQUIRE(test2[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -236,21 +234,21 @@ BOOST_AUTO_TEST_CASE(SaveCSVTest) /** * Make sure a TSV is saved correctly for a sparse matrix */ -BOOST_AUTO_TEST_CASE(SaveSparseTSVTest) +TEST_CASE("SaveSparseTSVTest", "[LoadSaveTest]") { arma::sp_mat test = "0.1\t0\t0\t0;" "0\t0.2\t0\t0;" "0\t0\t0.3\t0;" "0\t0\t0\t0.4;"; - BOOST_REQUIRE(data::Save("test_sparse_file.tsv", test, true, false) == true); + REQUIRE(data::Save("test_sparse_file.tsv", test, true, false) == true); // Load it in and make sure it is the same. arma::sp_mat test2; - BOOST_REQUIRE(data::Load("test_sparse_file.tsv", test2, true, false) == true); + REQUIRE(data::Load("test_sparse_file.tsv", test2, true, false) == true); - BOOST_REQUIRE_EQUAL(test2.n_rows, 4); - BOOST_REQUIRE_EQUAL(test2.n_cols, 4); + REQUIRE(test2.n_rows == 4); + REQUIRE(test2.n_cols == 4); arma::sp_mat::const_iterator it = test2.begin(); arma::sp_mat::const_iterator it_end = test2.end(); @@ -259,9 +257,9 @@ BOOST_AUTO_TEST_CASE(SaveSparseTSVTest) for (int i = 0; it != it_end; ++it, temp += 0.1, ++i) { double val = (*it); - BOOST_REQUIRE_CLOSE(val, temp, 1e-5); - BOOST_REQUIRE_EQUAL((int)(it.row()), i); - BOOST_REQUIRE_EQUAL((int)it.col(), i); + REQUIRE(val == Approx(temp).epsilon(1e-7)); + REQUIRE((int)(it.row()) == i); + REQUIRE((int)it.col() == i); } // Remove the file. @@ -271,21 +269,21 @@ BOOST_AUTO_TEST_CASE(SaveSparseTSVTest) /** * Make sure a TSV is saved correctly for a sparse matrix */ -BOOST_AUTO_TEST_CASE(SaveSparseTXTTest) +TEST_CASE("SaveSparseTXTTest", "[LoadSaveTest]") { arma::sp_mat test = "0.1 0 0 0;" "0 0.2 0 0;" "0 0 0.3 0;" "0 0 0 0.4;"; - BOOST_REQUIRE(data::Save("test_sparse_file.txt", test, true, true) == true); + REQUIRE(data::Save("test_sparse_file.txt", test, true, true) == true); // Load it in and make sure it is the same. arma::sp_mat test2; - BOOST_REQUIRE(data::Load("test_sparse_file.txt", test2, true, true) == true); + REQUIRE(data::Load("test_sparse_file.txt", test2, true, true) == true); - BOOST_REQUIRE_EQUAL(test2.n_rows, 4); - BOOST_REQUIRE_EQUAL(test2.n_cols, 4); + REQUIRE(test2.n_rows == 4); + REQUIRE(test2.n_cols == 4); arma::sp_mat::const_iterator it = test2.begin(); arma::sp_mat::const_iterator it_end = test2.end(); @@ -294,9 +292,9 @@ BOOST_AUTO_TEST_CASE(SaveSparseTXTTest) for (int i = 0; it != it_end; ++it, temp += 0.1, ++i) { double val = (*it); - BOOST_REQUIRE_CLOSE(val, temp, 1e-5); - BOOST_REQUIRE_EQUAL((int)(it.row()), i); - BOOST_REQUIRE_EQUAL((int)it.col(), i); + REQUIRE(val == Approx(temp).epsilon(1e-7)); + REQUIRE((int)(it.row()) == i); + REQUIRE((int)it.col() == i); } // Remove the file. @@ -306,21 +304,21 @@ BOOST_AUTO_TEST_CASE(SaveSparseTXTTest) /** * Make sure a Sparse Matrix is saved and loaded correctly in binary format */ -BOOST_AUTO_TEST_CASE(SaveSparseBinaryTest) +TEST_CASE("SaveSparseBinaryTest", "[LoadSaveTest]") { arma::sp_mat test = "0.1 0 0 0;" "0 0.2 0 0;" "0 0 0.3 0;" "0 0 0 0.4;"; - BOOST_REQUIRE(data::Save("test_sparse_file.bin", test, true, false) == true); + REQUIRE(data::Save("test_sparse_file.bin", test, true, false) == true); // Load it in and make sure it is the same. arma::sp_mat test2; - BOOST_REQUIRE(data::Load("test_sparse_file.bin", test2, true, false) == true); + REQUIRE(data::Load("test_sparse_file.bin", test2, true, false) == true); - BOOST_REQUIRE_EQUAL(test2.n_rows, 4); - BOOST_REQUIRE_EQUAL(test2.n_cols, 4); + REQUIRE(test2.n_rows == 4); + REQUIRE(test2.n_cols == 4); arma::sp_mat::const_iterator it = test2.begin(); arma::sp_mat::const_iterator it_end = test2.end(); @@ -329,9 +327,9 @@ BOOST_AUTO_TEST_CASE(SaveSparseBinaryTest) for (int i = 0; it != it_end; ++it, temp += 0.1, ++i) { double val = (*it); - BOOST_REQUIRE_CLOSE(val, temp, 1e-5); - BOOST_REQUIRE_EQUAL((int)(it.row()), i); - BOOST_REQUIRE_EQUAL((int)it.col(), i); + REQUIRE(val == Approx(temp).epsilon(1e-7)); + REQUIRE((int)(it.row()) == i); + REQUIRE((int)it.col() == i); } // Remove the file. @@ -341,7 +339,7 @@ BOOST_AUTO_TEST_CASE(SaveSparseBinaryTest) /** * Make sure CSVs can be loaded in transposed form. */ -BOOST_AUTO_TEST_CASE(LoadTransposedCSVTest) +TEST_CASE("LoadTransposedCSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -352,13 +350,13 @@ BOOST_AUTO_TEST_CASE(LoadTransposedCSVTest) f.close(); arma::mat test; - BOOST_REQUIRE(data::Load("test_file.csv", test, false, true) == true); + REQUIRE(data::Load("test_file.csv", test, false, true) == true); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); + REQUIRE(test.n_cols == 2); + REQUIRE(test.n_rows == 4); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -367,7 +365,7 @@ BOOST_AUTO_TEST_CASE(LoadTransposedCSVTest) /** * Make sure ColVec can be loaded. */ -BOOST_AUTO_TEST_CASE(LoadColVecCSVTest) +TEST_CASE("LoadColVecCSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -378,13 +376,13 @@ BOOST_AUTO_TEST_CASE(LoadColVecCSVTest) f.close(); arma::colvec test; - BOOST_REQUIRE(data::Load("test_file.csv", test, false) == true); + REQUIRE(data::Load("test_file.csv", test, false) == true); - BOOST_REQUIRE_EQUAL(test.n_cols, 1); - BOOST_REQUIRE_EQUAL(test.n_rows, 8); + REQUIRE(test.n_cols == 1); + REQUIRE(test.n_rows == 8); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) i, 1e-5); + REQUIRE(test[i] == Approx((double) i).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -393,7 +391,7 @@ BOOST_AUTO_TEST_CASE(LoadColVecCSVTest) /** * Make sure we can load a transposed column vector. */ -BOOST_AUTO_TEST_CASE(LoadColVecTransposedCSVTest) +TEST_CASE("LoadColVecTransposedCSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -404,13 +402,13 @@ BOOST_AUTO_TEST_CASE(LoadColVecTransposedCSVTest) f.close(); arma::colvec test; - BOOST_REQUIRE(data::Load("test_file.csv", test, false) == true); + REQUIRE(data::Load("test_file.csv", test, false) == true); - BOOST_REQUIRE_EQUAL(test.n_cols, 1); - BOOST_REQUIRE_EQUAL(test.n_rows, 9); + REQUIRE(test.n_cols == 1); + REQUIRE(test.n_rows == 9); for (size_t i = 0; i < 9; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) i, 1e-5); + REQUIRE(test[i] == Approx((double) i).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -420,7 +418,7 @@ BOOST_AUTO_TEST_CASE(LoadColVecTransposedCSVTest) * Make sure besides numeric data "quoted strings" or * 'quoted strings' in csv files are loaded correctly. */ -BOOST_AUTO_TEST_CASE(LoadQuotedStringInCSVTest) +TEST_CASE("LoadQuotedStringInCSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -442,21 +440,21 @@ BOOST_AUTO_TEST_CASE(LoadQuotedStringInCSVTest) arma::mat test; data::DatasetInfo info; - BOOST_REQUIRE(data::Load("test_file.csv", test, info, false, true) == true); + REQUIRE(data::Load("test_file.csv", test, info, false, true) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 3); - BOOST_REQUIRE_EQUAL(test.n_cols, 5); - BOOST_REQUIRE_EQUAL(info.Dimensionality(), 3); + REQUIRE(test.n_rows == 3); + REQUIRE(test.n_cols == 5); + REQUIRE(info.Dimensionality() == 3); // Check each element for equality/ closeness. for (size_t i = 0; i < 5; ++i) - BOOST_REQUIRE_CLOSE(test.at(0, i), (double) (i + 1), 1e-5); + REQUIRE(test.at(0, i) == Approx((double) (i + 1)).epsilon(1e-7)); for (size_t i = 0; i < 5; ++i) - BOOST_REQUIRE_EQUAL(info.UnmapString(test.at(1, i), 1, 0), elements[i]); + REQUIRE(info.UnmapString(test.at(1, i), 1, 0) == elements[i]); for (size_t i = 0; i < 5; ++i) - BOOST_REQUIRE_EQUAL(info.UnmapString(test.at(2, i), 2, 0), "field 3"); + REQUIRE(info.UnmapString(test.at(2, i), 2, 0) == "field 3"); // Clear the vector to free the space. elements.clear(); @@ -468,7 +466,7 @@ BOOST_AUTO_TEST_CASE(LoadQuotedStringInCSVTest) * Make sure besides numeric data "quoted strings" or * 'quoted strings' in txt files are loaded correctly. */ -BOOST_AUTO_TEST_CASE(LoadQuotedStringInTXTTest) +TEST_CASE("LoadQuotedStringInTXTTest", "[LoadSaveTest]") { fstream f; f.open("test_file.txt", fstream::out); @@ -484,21 +482,21 @@ BOOST_AUTO_TEST_CASE(LoadQuotedStringInTXTTest) arma::mat test; data::DatasetInfo info; - BOOST_REQUIRE(data::Load("test_file.txt", test, info, false, true) == true); + REQUIRE(data::Load("test_file.txt", test, info, false, true) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 3); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); - BOOST_REQUIRE_EQUAL(info.Dimensionality(), 3); + REQUIRE(test.n_rows == 3); + REQUIRE(test.n_cols == 2); + REQUIRE(info.Dimensionality() == 3); // Check each element for equality/ closeness. for (size_t i = 0; i < 2; ++i) - BOOST_REQUIRE_CLOSE(test.at(0, i), (double) (i + 1), 1e-5); + REQUIRE(test.at(0, i) == Approx((double) (i + 1)).epsilon(1e-7)); for (size_t i = 0; i < 2; ++i) - BOOST_REQUIRE_EQUAL(info.UnmapString(test.at(1, i), 1, 0), elements[i]); + REQUIRE(info.UnmapString(test.at(1, i), 1, 0) == elements[i]); for (size_t i = 0; i < 2; ++i) - BOOST_REQUIRE_EQUAL(info.UnmapString(test.at(2, i), 2, 0), "field3"); + REQUIRE(info.UnmapString(test.at(2, i), 2, 0) == "field3"); // Clear the vector to free the space. elements.clear(); @@ -510,7 +508,7 @@ BOOST_AUTO_TEST_CASE(LoadQuotedStringInTXTTest) * Make sure besides numeric data "quoted strings" or * 'quoted strings' in tsv files are loaded correctly. */ -BOOST_AUTO_TEST_CASE(LoadQuotedStringInTSVTest) +TEST_CASE("LoadQuotedStringInTSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.tsv", fstream::out); @@ -532,21 +530,21 @@ BOOST_AUTO_TEST_CASE(LoadQuotedStringInTSVTest) arma::mat test; data::DatasetInfo info; - BOOST_REQUIRE(data::Load("test_file.tsv", test, info, false, true) == true); + REQUIRE(data::Load("test_file.tsv", test, info, false, true) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 3); - BOOST_REQUIRE_EQUAL(test.n_cols, 5); - BOOST_REQUIRE_EQUAL(info.Dimensionality(), 3); + REQUIRE(test.n_rows == 3); + REQUIRE(test.n_cols == 5); + REQUIRE(info.Dimensionality() == 3); // Check each element for equality/ closeness. for (size_t i = 0; i < 5; ++i) - BOOST_REQUIRE_CLOSE(test.at(0, i), (double) (i + 1), 1e-5); + REQUIRE(test.at(0, i) == Approx((double) (i + 1)).epsilon(1e-7)); for (size_t i = 0; i < 5; ++i) - BOOST_REQUIRE_EQUAL(info.UnmapString(test.at(1, i), 1, 0), elements[i]); + REQUIRE(info.UnmapString(test.at(1, i), 1, 0) == elements[i]); for (size_t i = 0; i < 5; ++i) - BOOST_REQUIRE_EQUAL(info.UnmapString(test.at(2, i), 2, 0), "field 3"); + REQUIRE(info.UnmapString(test.at(2, i), 2, 0) == "field 3"); // Clear the vector to free the space. elements.clear(); @@ -558,7 +556,7 @@ BOOST_AUTO_TEST_CASE(LoadQuotedStringInTSVTest) * Make sure Load() throws an exception when trying to load a matrix into a * colvec or rowvec. */ -BOOST_AUTO_TEST_CASE(LoadMatinVec) +TEST_CASE("LoadMatinVec", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -573,11 +571,11 @@ BOOST_AUTO_TEST_CASE(LoadMatinVec) */ Log::Fatal.ignoreInput = true; arma::vec coltest; - BOOST_REQUIRE_THROW(data::Load("test_file.csv", coltest, true), + REQUIRE_THROWS_AS(data::Load("test_file.csv", coltest, true), std::runtime_error); arma::rowvec rowtest; - BOOST_REQUIRE_THROW(data::Load("test_file.csv", rowtest, true), + REQUIRE_THROWS_AS(data::Load("test_file.csv", rowtest, true), std::runtime_error); Log::Fatal.ignoreInput = false; @@ -587,7 +585,7 @@ BOOST_AUTO_TEST_CASE(LoadMatinVec) /** * Make sure that rowvecs can be loaded successfully. */ -BOOST_AUTO_TEST_CASE(LoadRowVecCSVTest) +TEST_CASE("LoadRowVecCSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -600,13 +598,13 @@ BOOST_AUTO_TEST_CASE(LoadRowVecCSVTest) f.close(); arma::rowvec test; - BOOST_REQUIRE(data::Load("test_file.csv", test, false) == true); + REQUIRE(data::Load("test_file.csv", test, false) == true); - BOOST_REQUIRE_EQUAL(test.n_cols, 8); - BOOST_REQUIRE_EQUAL(test.n_rows, 1); + REQUIRE(test.n_cols == 8); + REQUIRE(test.n_rows == 1); for (size_t i = 0; i < 8 ; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) i , 1e-5); + REQUIRE(test[i] == Approx((double) i).epsilon(1e-7)); remove("test_file.csv"); } @@ -614,7 +612,7 @@ BOOST_AUTO_TEST_CASE(LoadRowVecCSVTest) /** * Make sure that we can load transposed row vectors. */ -BOOST_AUTO_TEST_CASE(LoadRowVecTransposedCSVTest) +TEST_CASE("LoadRowVecTransposedCSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -625,13 +623,13 @@ BOOST_AUTO_TEST_CASE(LoadRowVecTransposedCSVTest) f.close(); arma::rowvec test; - BOOST_REQUIRE(data::Load("test_file.csv", test, false) == true); + REQUIRE(data::Load("test_file.csv", test, false) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 1); - BOOST_REQUIRE_EQUAL(test.n_cols, 8); + REQUIRE(test.n_rows == 1); + REQUIRE(test.n_cols == 8); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) i, 1e-5); + REQUIRE(test[i] == Approx((double) i).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -640,7 +638,7 @@ BOOST_AUTO_TEST_CASE(LoadRowVecTransposedCSVTest) /** * Make sure TSVs can be loaded in transposed form. */ -BOOST_AUTO_TEST_CASE(LoadTransposedTSVTest) +TEST_CASE("LoadTransposedTSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -651,13 +649,13 @@ BOOST_AUTO_TEST_CASE(LoadTransposedTSVTest) f.close(); arma::mat test; - BOOST_REQUIRE(data::Load("test_file.csv", test, false, true) == true); + REQUIRE(data::Load("test_file.csv", test, false, true) == true); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); + REQUIRE(test.n_cols == 2); + REQUIRE(test.n_rows == 4); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -666,7 +664,7 @@ BOOST_AUTO_TEST_CASE(LoadTransposedTSVTest) /** * Check TSV loading with .tsv extension. */ -BOOST_AUTO_TEST_CASE(LoadTransposedTSVExtensionTest) +TEST_CASE("LoadTransposedTSVExtensionTest", "[LoadSaveTest]") { fstream f; f.open("test_file.tsv", fstream::out); @@ -677,13 +675,13 @@ BOOST_AUTO_TEST_CASE(LoadTransposedTSVExtensionTest) f.close(); arma::mat test; - BOOST_REQUIRE(data::Load("test_file.tsv", test, false, true) == true); + REQUIRE(data::Load("test_file.tsv", test, false, true) == true); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); + REQUIRE(test.n_cols == 2); + REQUIRE(test.n_rows == 4); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.tsv"); @@ -692,7 +690,7 @@ BOOST_AUTO_TEST_CASE(LoadTransposedTSVExtensionTest) /** * Make sure CSVs can be loaded in non-transposed form. */ -BOOST_AUTO_TEST_CASE(LoadNonTransposedCSVTest) +TEST_CASE("LoadNonTransposedCSVTest", "[LoadSaveTest]") { fstream f; f.open("test_file.csv", fstream::out); @@ -703,13 +701,13 @@ BOOST_AUTO_TEST_CASE(LoadNonTransposedCSVTest) f.close(); arma::mat test; - BOOST_REQUIRE(data::Load("test_file.csv", test, false, false) == true); + REQUIRE(data::Load("test_file.csv", test, false, false) == true); - BOOST_REQUIRE_EQUAL(test.n_cols, 4); - BOOST_REQUIRE_EQUAL(test.n_rows, 2); + REQUIRE(test.n_cols == 4); + REQUIRE(test.n_rows == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -718,24 +716,24 @@ BOOST_AUTO_TEST_CASE(LoadNonTransposedCSVTest) /** * Make sure CSVs can be saved in non-transposed form. */ -BOOST_AUTO_TEST_CASE(SaveNonTransposedCSVTest) +TEST_CASE("SaveNonTransposedCSVTest", "[LoadSaveTest]") { arma::mat test = "1 2;" "3 4;" "5 6;" "7 8;"; - BOOST_REQUIRE(data::Save("test_file.csv", test, false, false) == true); + REQUIRE(data::Save("test_file.csv", test, false, false) == true); // Load it in and make sure it is in the same. arma::mat test2; - BOOST_REQUIRE(data::Load("test_file.csv", test2, false, false) == true); + REQUIRE(data::Load("test_file.csv", test2, false, false) == true); - BOOST_REQUIRE_EQUAL(test2.n_rows, 4); - BOOST_REQUIRE_EQUAL(test2.n_cols, 2); + REQUIRE(test2.n_rows == 4); + REQUIRE(test2.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], test2[i], 1e-5); + REQUIRE(test[i] == Approx(test2[i]).epsilon(1e-7)); // Remove the file. remove("test_file.csv"); @@ -744,7 +742,7 @@ BOOST_AUTO_TEST_CASE(SaveNonTransposedCSVTest) /** * Make sure arma_ascii is loaded correctly. */ -BOOST_AUTO_TEST_CASE(LoadArmaASCIITest) +TEST_CASE("LoadArmaASCIITest", "[LoadSaveTest]") { arma::mat test = "1 5;" "2 6;" @@ -752,15 +750,15 @@ BOOST_AUTO_TEST_CASE(LoadArmaASCIITest) "4 8;"; arma::mat testTrans = trans(test); - BOOST_REQUIRE(testTrans.save("test_file.txt", arma::arma_ascii)); + REQUIRE(testTrans.save("test_file.txt", arma::arma_ascii)); - BOOST_REQUIRE(data::Load("test_file.txt", test) == true); + REQUIRE(data::Load("test_file.txt", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.txt"); @@ -769,23 +767,23 @@ BOOST_AUTO_TEST_CASE(LoadArmaASCIITest) /** * Make sure a CSV is saved correctly. */ -BOOST_AUTO_TEST_CASE(SaveArmaASCIITest) +TEST_CASE("SaveArmaASCIITest", "[LoadSaveTest]") { arma::mat test = "1 5;" "2 6;" "3 7;" "4 8;"; - BOOST_REQUIRE(data::Save("test_file.txt", test) == true); + REQUIRE(data::Save("test_file.txt", test) == true); // Load it in and make sure it is the same. - BOOST_REQUIRE(data::Load("test_file.txt", test) == true); + REQUIRE(data::Load("test_file.txt", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.txt"); @@ -794,7 +792,7 @@ BOOST_AUTO_TEST_CASE(SaveArmaASCIITest) /** * Make sure raw_ascii is loaded correctly. */ -BOOST_AUTO_TEST_CASE(LoadRawASCIITest) +TEST_CASE("LoadRawASCIITest", "[LoadSaveTest]") { fstream f; f.open("test_file.txt", fstream::out); @@ -805,13 +803,13 @@ BOOST_AUTO_TEST_CASE(LoadRawASCIITest) f.close(); arma::mat test; - BOOST_REQUIRE(data::Load("test_file.txt", test) == true); + REQUIRE(data::Load("test_file.txt", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.txt"); @@ -820,7 +818,7 @@ BOOST_AUTO_TEST_CASE(LoadRawASCIITest) /** * Make sure CSV is loaded correctly as .txt. */ -BOOST_AUTO_TEST_CASE(LoadCSVTxtTest) +TEST_CASE("LoadCSVTxtTest", "[LoadSaveTest]") { fstream f; f.open("test_file.txt", fstream::out); @@ -831,13 +829,13 @@ BOOST_AUTO_TEST_CASE(LoadCSVTxtTest) f.close(); arma::mat test; - BOOST_REQUIRE(data::Load("test_file.txt", test) == true); + REQUIRE(data::Load("test_file.txt", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.txt"); @@ -846,7 +844,7 @@ BOOST_AUTO_TEST_CASE(LoadCSVTxtTest) /** * Make sure arma_binary is loaded correctly. */ -BOOST_AUTO_TEST_CASE(LoadArmaBinaryTest) +TEST_CASE("LoadArmaBinaryTest", "[LoadSaveTest]") { arma::mat test = "1 5;" "2 6;" @@ -854,17 +852,17 @@ BOOST_AUTO_TEST_CASE(LoadArmaBinaryTest) "4 8;"; arma::mat testTrans = trans(test); - BOOST_REQUIRE(testTrans.quiet_save("test_file.bin", arma::arma_binary) + REQUIRE(testTrans.quiet_save("test_file.bin", arma::arma_binary) == true); // Now reload through our interface. - BOOST_REQUIRE(data::Load("test_file.bin", test) == true); + REQUIRE(data::Load("test_file.bin", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.bin"); @@ -873,22 +871,22 @@ BOOST_AUTO_TEST_CASE(LoadArmaBinaryTest) /** * Make sure arma_binary is saved correctly. */ -BOOST_AUTO_TEST_CASE(SaveArmaBinaryTest) +TEST_CASE("SaveArmaBinaryTest", "[LoadSaveTest]") { arma::mat test = "1 5;" "2 6;" "3 7;" "4 8;"; - BOOST_REQUIRE(data::Save("test_file.bin", test) == true); + REQUIRE(data::Save("test_file.bin", test) == true); - BOOST_REQUIRE(data::Load("test_file.bin", test) == true); + REQUIRE(data::Load("test_file.bin", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.bin"); @@ -897,7 +895,7 @@ BOOST_AUTO_TEST_CASE(SaveArmaBinaryTest) /** * Make sure raw_binary is loaded correctly. */ -BOOST_AUTO_TEST_CASE(LoadRawBinaryTest) +TEST_CASE("LoadRawBinaryTest", "[LoadSaveTest]") { arma::mat test = "1 2;" "3 4;" @@ -905,17 +903,17 @@ BOOST_AUTO_TEST_CASE(LoadRawBinaryTest) "7 8;"; arma::mat testTrans = trans(test); - BOOST_REQUIRE(testTrans.quiet_save("test_file.bin", arma::raw_binary) + REQUIRE(testTrans.quiet_save("test_file.bin", arma::raw_binary) == true); // Now reload through our interface. - BOOST_REQUIRE(data::Load("test_file.bin", test) == true); + REQUIRE(data::Load("test_file.bin", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 1); - BOOST_REQUIRE_EQUAL(test.n_cols, 8); + REQUIRE(test.n_rows == 1); + REQUIRE(test.n_cols == 8); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.bin"); @@ -924,7 +922,7 @@ BOOST_AUTO_TEST_CASE(LoadRawBinaryTest) /** * Make sure load as PGM is successful. */ -BOOST_AUTO_TEST_CASE(LoadPGMBinaryTest) +TEST_CASE("LoadPGMBinaryTest", "[LoadSaveTest]") { arma::mat test = "1 5;" "2 6;" @@ -932,17 +930,17 @@ BOOST_AUTO_TEST_CASE(LoadPGMBinaryTest) "4 8;"; arma::mat testTrans = trans(test); - BOOST_REQUIRE(testTrans.quiet_save("test_file.pgm", arma::pgm_binary) + REQUIRE(testTrans.quiet_save("test_file.pgm", arma::pgm_binary) == true); // Now reload through our interface. - BOOST_REQUIRE(data::Load("test_file.pgm", test) == true); + REQUIRE(data::Load("test_file.pgm", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.pgm"); @@ -951,23 +949,23 @@ BOOST_AUTO_TEST_CASE(LoadPGMBinaryTest) /** * Make sure save as PGM is successful. */ -BOOST_AUTO_TEST_CASE(SavePGMBinaryTest) +TEST_CASE("SavePGMBinaryTest", "[LoadSaveTest]") { arma::mat test = "1 5;" "2 6;" "3 7;" "4 8;"; - BOOST_REQUIRE(data::Save("test_file.pgm", test) == true); + REQUIRE(data::Save("test_file.pgm", test) == true); // Now reload through our interface. - BOOST_REQUIRE(data::Load("test_file.pgm", test) == true); + REQUIRE(data::Load("test_file.pgm", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Remove the file. remove("test_file.pgm"); @@ -977,55 +975,55 @@ BOOST_AUTO_TEST_CASE(SavePGMBinaryTest) /** * Make sure load as HDF5 is successful. */ -BOOST_AUTO_TEST_CASE(LoadHDF5Test) +TEST_CASE("LoadHDF5Test", "[LoadSaveTest]") { arma::mat test = "1 5;" "2 6;" "3 7;" "4 8;"; arma::mat testTrans = trans(test); - BOOST_REQUIRE(testTrans.quiet_save("test_file.h5", arma::hdf5_binary) + REQUIRE(testTrans.quiet_save("test_file.h5", arma::hdf5_binary) == true); - BOOST_REQUIRE(testTrans.quiet_save("test_file.hdf5", arma::hdf5_binary) + REQUIRE(testTrans.quiet_save("test_file.hdf5", arma::hdf5_binary) == true); - BOOST_REQUIRE(testTrans.quiet_save("test_file.hdf", arma::hdf5_binary) + REQUIRE(testTrans.quiet_save("test_file.hdf", arma::hdf5_binary) == true); - BOOST_REQUIRE(testTrans.quiet_save("test_file.he5", arma::hdf5_binary) + REQUIRE(testTrans.quiet_save("test_file.he5", arma::hdf5_binary) == true); // Now reload through our interface. - BOOST_REQUIRE(data::Load("test_file.h5", test) == true); + REQUIRE(data::Load("test_file.h5", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Make sure the other extensions work too. - BOOST_REQUIRE(data::Load("test_file.hdf5", test) == true); + REQUIRE(data::Load("test_file.hdf5", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); - BOOST_REQUIRE(data::Load("test_file.hdf", test) == true); + REQUIRE(data::Load("test_file.hdf", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); - BOOST_REQUIRE(data::Load("test_file.he5", test) == true); + REQUIRE(data::Load("test_file.he5", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); remove("test_file.h5"); remove("test_file.hdf"); @@ -1036,50 +1034,50 @@ BOOST_AUTO_TEST_CASE(LoadHDF5Test) /** * Make sure save as HDF5 is successful. */ -BOOST_AUTO_TEST_CASE(SaveHDF5Test) +TEST_CASE("SaveHDF5Test", "[LoadSaveTest]") { arma::mat test = "1 5;" "2 6;" "3 7;" "4 8;"; - BOOST_REQUIRE(data::Save("test_file.h5", test) == true); - BOOST_REQUIRE(data::Save("test_file.hdf5", test) == true); - BOOST_REQUIRE(data::Save("test_file.hdf", test) == true); - BOOST_REQUIRE(data::Save("test_file.he5", test) == true); + REQUIRE(data::Save("test_file.h5", test) == true); + REQUIRE(data::Save("test_file.hdf5", test) == true); + REQUIRE(data::Save("test_file.hdf", test) == true); + REQUIRE(data::Save("test_file.he5", test) == true); // Now load them all and verify they were saved okay. - BOOST_REQUIRE(data::Load("test_file.h5", test) == true); + REQUIRE(data::Load("test_file.h5", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); // Make sure the other extensions work too. - BOOST_REQUIRE(data::Load("test_file.hdf5", test) == true); + REQUIRE(data::Load("test_file.hdf5", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); - BOOST_REQUIRE(data::Load("test_file.hdf", test) == true); + REQUIRE(data::Load("test_file.hdf", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); - BOOST_REQUIRE(data::Load("test_file.he5", test) == true); + REQUIRE(data::Load("test_file.he5", test) == true); - BOOST_REQUIRE_EQUAL(test.n_rows, 4); - BOOST_REQUIRE_EQUAL(test.n_cols, 2); + REQUIRE(test.n_rows == 4); + REQUIRE(test.n_cols == 2); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(test[i], (double) (i + 1), 1e-5); + REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7)); remove("test_file.h5"); remove("test_file.hdf"); @@ -1092,7 +1090,7 @@ BOOST_AUTO_TEST_CASE(SaveHDF5Test) /** * Test one hot encoding. */ -BOOST_AUTO_TEST_CASE(OneHotEncodingTest) +TEST_CASE("OneHotEncodingTest", "[LoadSaveTest]") { arma::Mat matrix; matrix = "1 0;" @@ -1108,15 +1106,15 @@ BOOST_AUTO_TEST_CASE(OneHotEncodingTest) arma::irowvec labels("-1 1 -1 -1 -1 -1 1 -1"); data::OneHotEncoding(labels, output); - BOOST_REQUIRE_EQUAL(matrix.n_cols, output.n_cols); - BOOST_REQUIRE_EQUAL(matrix.n_rows, output.n_rows); + REQUIRE(matrix.n_cols == output.n_cols); + REQUIRE(matrix.n_rows == output.n_rows); CheckMatrices(output, matrix); } /** * Test normalization of labels. */ -BOOST_AUTO_TEST_CASE(NormalizeLabelSmallDatasetTest) +TEST_CASE("NormalizeLabelSmallDatasetTest", "[LoadSaveTest]") { arma::irowvec labels("-1 1 1 -1 -1 -1 1 1"); arma::Row newLabels; @@ -1124,30 +1122,30 @@ BOOST_AUTO_TEST_CASE(NormalizeLabelSmallDatasetTest) data::NormalizeLabels(labels, newLabels, mappings); - BOOST_REQUIRE_EQUAL(mappings[0], -1); - BOOST_REQUIRE_EQUAL(mappings[1], 1); + REQUIRE(mappings[0] == -1); + REQUIRE(mappings[1] == 1); - BOOST_REQUIRE_EQUAL(newLabels[0], 0); - BOOST_REQUIRE_EQUAL(newLabels[1], 1); - BOOST_REQUIRE_EQUAL(newLabels[2], 1); - BOOST_REQUIRE_EQUAL(newLabels[3], 0); - BOOST_REQUIRE_EQUAL(newLabels[4], 0); - BOOST_REQUIRE_EQUAL(newLabels[5], 0); - BOOST_REQUIRE_EQUAL(newLabels[6], 1); - BOOST_REQUIRE_EQUAL(newLabels[7], 1); + REQUIRE(newLabels[0] == 0); + REQUIRE(newLabels[1] == 1); + REQUIRE(newLabels[2] == 1); + REQUIRE(newLabels[3] == 0); + REQUIRE(newLabels[4] == 0); + REQUIRE(newLabels[5] == 0); + REQUIRE(newLabels[6] == 1); + REQUIRE(newLabels[7] == 1); arma::irowvec revertedLabels; data::RevertLabels(newLabels, mappings, revertedLabels); for (size_t i = 0; i < labels.n_elem; ++i) - BOOST_REQUIRE_EQUAL(labels[i], revertedLabels[i]); + REQUIRE(labels[i] == revertedLabels[i]); } /** * Harder label normalization test. */ -BOOST_AUTO_TEST_CASE(NormalizeLabelTest) +TEST_CASE("NormalizeLabelTest", "[LoadSaveTest]") { arma::rowvec randLabels(5000); for (size_t i = 0; i < 5000; ++i) @@ -1164,7 +1162,7 @@ BOOST_AUTO_TEST_CASE(NormalizeLabelTest) data::RevertLabels(newLabels, mappings, revertedLabels); for (size_t i = 0; i < 5000; ++i) - BOOST_REQUIRE_EQUAL(randLabels[i], revertedLabels[i]); + REQUIRE(randLabels[i] == revertedLabels[i]); } // Test structures. @@ -1209,81 +1207,81 @@ class Test /** * Make sure we can load and save. */ -BOOST_AUTO_TEST_CASE(LoadBinaryTest) +TEST_CASE("LoadBinaryTest", "[LoadSaveTest]") { Test x(10, 12); - BOOST_REQUIRE_EQUAL(data::Save("test.bin", "x", x, false), true); + REQUIRE(data::Save("test.bin", "x", x, false) == true); // Now reload. Test y(11, 14); - BOOST_REQUIRE_EQUAL(data::Load("test.bin", "x", y, false), true); + REQUIRE(data::Load("test.bin", "x", y, false) == true); - BOOST_REQUIRE_EQUAL(y.x, x.x); - BOOST_REQUIRE_EQUAL(y.y, x.y); - BOOST_REQUIRE_EQUAL(y.ina.c, x.ina.c); - BOOST_REQUIRE_EQUAL(y.ina.s, x.ina.s); - BOOST_REQUIRE_EQUAL(y.inb.c, x.inb.c); - BOOST_REQUIRE_EQUAL(y.inb.s, x.inb.s); + REQUIRE(y.x == x.x); + REQUIRE(y.y == x.y); + REQUIRE(y.ina.c == x.ina.c); + REQUIRE(y.ina.s == x.ina.s); + REQUIRE(y.inb.c == x.inb.c); + REQUIRE(y.inb.s == x.inb.s); } /** * Make sure we can load and save. */ -BOOST_AUTO_TEST_CASE(LoadXMLTest) +TEST_CASE("LoadXMLTest", "[LoadSaveTest]") { Test x(10, 12); - BOOST_REQUIRE_EQUAL(data::Save("test.xml", "x", x, false), true); + REQUIRE(data::Save("test.xml", "x", x, false) == true); // Now reload. Test y(11, 14); - BOOST_REQUIRE_EQUAL(data::Load("test.xml", "x", y, false), true); + REQUIRE(data::Load("test.xml", "x", y, false) == true); - BOOST_REQUIRE_EQUAL(y.x, x.x); - BOOST_REQUIRE_EQUAL(y.y, x.y); - BOOST_REQUIRE_EQUAL(y.ina.c, x.ina.c); - BOOST_REQUIRE_EQUAL(y.ina.s, x.ina.s); - BOOST_REQUIRE_EQUAL(y.inb.c, x.inb.c); - BOOST_REQUIRE_EQUAL(y.inb.s, x.inb.s); + REQUIRE(y.x == x.x); + REQUIRE(y.y == x.y); + REQUIRE(y.ina.c == x.ina.c); + REQUIRE(y.ina.s == x.ina.s); + REQUIRE(y.inb.c == x.inb.c); + REQUIRE(y.inb.s == x.inb.s); } /** * Make sure we can load and save. */ -BOOST_AUTO_TEST_CASE(LoadTextTest) +TEST_CASE("LoadTextTest", "[LoadSaveTest]") { Test x(10, 12); - BOOST_REQUIRE_EQUAL(data::Save("test.txt", "x", x, false), true); + REQUIRE(data::Save("test.txt", "x", x, false) == true); // Now reload. Test y(11, 14); - BOOST_REQUIRE_EQUAL(data::Load("test.txt", "x", y, false), true); + REQUIRE(data::Load("test.txt", "x", y, false) == true); - BOOST_REQUIRE_EQUAL(y.x, x.x); - BOOST_REQUIRE_EQUAL(y.y, x.y); - BOOST_REQUIRE_EQUAL(y.ina.c, x.ina.c); - BOOST_REQUIRE_EQUAL(y.ina.s, x.ina.s); - BOOST_REQUIRE_EQUAL(y.inb.c, x.inb.c); - BOOST_REQUIRE_EQUAL(y.inb.s, x.inb.s); + REQUIRE(y.x == x.x); + REQUIRE(y.y == x.y); + REQUIRE(y.ina.c == x.ina.c); + REQUIRE(y.ina.s == x.ina.s); + REQUIRE(y.inb.c == x.inb.c); + REQUIRE(y.inb.s == x.inb.s); } /** * Test DatasetInfo by making a map for a dimension. */ -BOOST_AUTO_TEST_CASE(DatasetInfoTest) +TEST_CASE("DatasetInfoTest", "[LoadSaveTest]") { DatasetInfo di(100); // Do all types default to numeric? for (size_t i = 0; i < 100; ++i) { - BOOST_REQUIRE(di.Type(i) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(di.NumMappings(i), 0); + REQUIRE(di.Type(i) == Datatype::numeric); + REQUIRE(di.NumMappings(i) == 0); } // Okay. Add some mappings for dimension 3. @@ -1291,22 +1289,22 @@ BOOST_AUTO_TEST_CASE(DatasetInfoTest) const size_t second = di.MapString("test_mapping_2", 3); const size_t third = di.MapString("test_mapping_3", 3); - BOOST_REQUIRE_EQUAL(first, 0); - BOOST_REQUIRE_EQUAL(second, 1); - BOOST_REQUIRE_EQUAL(third, 2); + REQUIRE(first == 0); + REQUIRE(second == 1); + REQUIRE(third == 2); // Now dimension 3 should be categorical. for (size_t i = 0; i < 100; ++i) { if (i == 3) { - BOOST_REQUIRE(di.Type(i) == Datatype::categorical); - BOOST_REQUIRE_EQUAL(di.NumMappings(i), 3); + REQUIRE(di.Type(i) == Datatype::categorical); + REQUIRE(di.NumMappings(i) == 3); } else { - BOOST_REQUIRE(di.Type(i) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(di.NumMappings(i), 0); + REQUIRE(di.Type(i) == Datatype::numeric); + REQUIRE(di.NumMappings(i) == 0); } } @@ -1315,15 +1313,15 @@ BOOST_AUTO_TEST_CASE(DatasetInfoTest) const string& strSecond = di.UnmapString(second, 3); const string& strThird = di.UnmapString(third, 3); - BOOST_REQUIRE_EQUAL(strFirst, "test_mapping_1"); - BOOST_REQUIRE_EQUAL(strSecond, "test_mapping_2"); - BOOST_REQUIRE_EQUAL(strThird, "test_mapping_3"); + REQUIRE(strFirst == "test_mapping_1"); + REQUIRE(strSecond == "test_mapping_2"); + REQUIRE(strThird == "test_mapping_3"); } /** * Test loading regular CSV with DatasetInfo. Everything should be numeric. */ -BOOST_AUTO_TEST_CASE(RegularCSVDatasetInfoLoad) +TEST_CASE("RegularCSVDatasetInfoLoad", "[LoadSaveTest]") { vector testFiles; testFiles.push_back("fake.csv"); @@ -1342,20 +1340,20 @@ BOOST_AUTO_TEST_CASE(RegularCSVDatasetInfoLoad) data::Load(testFiles[i], two, info); // Check that the matrices contain the same information. - BOOST_REQUIRE_EQUAL(one.n_elem, two.n_elem); - BOOST_REQUIRE_EQUAL(one.n_rows, two.n_rows); - BOOST_REQUIRE_EQUAL(one.n_cols, two.n_cols); + REQUIRE(one.n_elem == two.n_elem); + REQUIRE(one.n_rows == two.n_rows); + REQUIRE(one.n_cols == two.n_cols); for (size_t i = 0; i < one.n_elem; ++i) { if (std::abs(one[i]) < 1e-8) - BOOST_REQUIRE_SMALL(two[i], 1e-8); + REQUIRE(two[i] == Approx(.0).margin(1e-10)); else - BOOST_REQUIRE_CLOSE(one[i], two[i], 1e-8); + REQUIRE(one[i] == Approx(two[i]).epsilon(1e-7)); } // Check that all dimensions are numeric. for (size_t i = 0; i < two.n_rows; ++i) - BOOST_REQUIRE(info.Type(i) == Datatype::numeric); + REQUIRE(info.Type(i) == Datatype::numeric); } } @@ -1363,7 +1361,7 @@ BOOST_AUTO_TEST_CASE(RegularCSVDatasetInfoLoad) * Test non-transposed loading of regular CSVs with DatasetInfo. Everything * should be numeric. */ -BOOST_AUTO_TEST_CASE(NontransposedCSVDatasetInfoLoad) +TEST_CASE("NontransposedCSVDatasetInfoLoad", "[LoadSaveTest]") { vector testFiles; testFiles.push_back("fake.csv"); @@ -1382,27 +1380,27 @@ BOOST_AUTO_TEST_CASE(NontransposedCSVDatasetInfoLoad) data::Load(testFiles[i], two, info, true, false); // Check that the matrices contain the same information. - BOOST_REQUIRE_EQUAL(one.n_elem, two.n_elem); - BOOST_REQUIRE_EQUAL(one.n_rows, two.n_rows); - BOOST_REQUIRE_EQUAL(one.n_cols, two.n_cols); + REQUIRE(one.n_elem == two.n_elem); + REQUIRE(one.n_rows == two.n_rows); + REQUIRE(one.n_cols == two.n_cols); for (size_t i = 0; i < one.n_elem; ++i) { if (std::abs(one[i]) < 1e-8) - BOOST_REQUIRE_SMALL(two[i], 1e-8); + REQUIRE(two[i] == Approx(.0).margin(1e-10)); else - BOOST_REQUIRE_CLOSE(one[i], two[i], 1e-8); + REQUIRE(one[i] == Approx(two[i]).epsilon(1e-7)); } // Check that all dimensions are numeric. for (size_t i = 0; i < two.n_rows; ++i) - BOOST_REQUIRE(info.Type(i) == Datatype::numeric); + REQUIRE(info.Type(i) == Datatype::numeric); } } /** * Create a file with a categorical string feature, then load it. */ -BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest00) +TEST_CASE("CategoricalCSVLoadTest00", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1420,49 +1418,49 @@ BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest00) DatasetInfo info; data::Load("test.csv", matrix, info); - BOOST_REQUIRE_EQUAL(matrix.n_cols, 7); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 3); + REQUIRE(matrix.n_cols == 7); + REQUIRE(matrix.n_rows == 3); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 2); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 3); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 4); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 5); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 6); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 2); - BOOST_REQUIRE_EQUAL(matrix(0, 3), 7); - BOOST_REQUIRE_EQUAL(matrix(1, 3), 8); - BOOST_REQUIRE_EQUAL(matrix(2, 3), 3); - BOOST_REQUIRE_EQUAL(matrix(0, 4), 9); - BOOST_REQUIRE_EQUAL(matrix(1, 4), 10); - BOOST_REQUIRE_EQUAL(matrix(2, 4), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 5), 11); - BOOST_REQUIRE_EQUAL(matrix(1, 5), 12); - BOOST_REQUIRE_EQUAL(matrix(2, 5), 3); - BOOST_REQUIRE_EQUAL(matrix(0, 6), 13); - BOOST_REQUIRE_EQUAL(matrix(1, 6), 14); - BOOST_REQUIRE_EQUAL(matrix(2, 6), 3); + REQUIRE(matrix(0, 0) == 1); + REQUIRE(matrix(1, 0) == 2); + REQUIRE(matrix(2, 0) == 0); + REQUIRE(matrix(0, 1) == 3); + REQUIRE(matrix(1, 1) == 4); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(0, 2) == 5); + REQUIRE(matrix(1, 2) == 6); + REQUIRE(matrix(2, 2) == 2); + REQUIRE(matrix(0, 3) == 7); + REQUIRE(matrix(1, 3) == 8); + REQUIRE(matrix(2, 3) == 3); + REQUIRE(matrix(0, 4) == 9); + REQUIRE(matrix(1, 4) == 10); + REQUIRE(matrix(2, 4) == 0); + REQUIRE(matrix(0, 5) == 11); + REQUIRE(matrix(1, 5) == 12); + REQUIRE(matrix(2, 5) == 3); + REQUIRE(matrix(0, 6) == 13); + REQUIRE(matrix(1, 6) == 14); + REQUIRE(matrix(2, 6) == 3); - BOOST_REQUIRE(info.Type(0) == Datatype::numeric); - BOOST_REQUIRE(info.Type(1) == Datatype::numeric); - BOOST_REQUIRE(info.Type(2) == Datatype::categorical); + REQUIRE(info.Type(0) == Datatype::numeric); + REQUIRE(info.Type(1) == Datatype::numeric); + REQUIRE(info.Type(2) == Datatype::categorical); - BOOST_REQUIRE_EQUAL(info.MapString("hello", 2), 0); - BOOST_REQUIRE_EQUAL(info.MapString("goodbye", 2), 1); - BOOST_REQUIRE_EQUAL(info.MapString("coffee", 2), 2); - BOOST_REQUIRE_EQUAL(info.MapString("confusion", 2), 3); + REQUIRE(info.MapString("hello", 2) == 0); + REQUIRE(info.MapString("goodbye", 2) == 1); + REQUIRE(info.MapString("coffee", 2) == 2); + REQUIRE(info.MapString("confusion", 2) == 3); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 2), "hello"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 2), "goodbye"); - BOOST_REQUIRE_EQUAL(info.UnmapString(2, 2), "coffee"); - BOOST_REQUIRE_EQUAL(info.UnmapString(3, 2), "confusion"); + REQUIRE(info.UnmapString(0, 2) == "hello"); + REQUIRE(info.UnmapString(1, 2) == "goodbye"); + REQUIRE(info.UnmapString(2, 2) == "coffee"); + REQUIRE(info.UnmapString(3, 2) == "confusion"); remove("test.csv"); } -BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest01) +TEST_CASE("CategoricalCSVLoadTest01", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1477,37 +1475,37 @@ BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest01) DatasetInfo info; data::Load("test.csv", matrix, info, true); - BOOST_REQUIRE_EQUAL(matrix.n_cols, 4); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 3); + REQUIRE(matrix.n_cols == 4); + REQUIRE(matrix.n_rows == 3); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 3), 0); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 3), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 3), 1); + REQUIRE(matrix(0, 0) == 0); + REQUIRE(matrix(0, 1) == 0); + REQUIRE(matrix(0, 2) == 1); + REQUIRE(matrix(0, 3) == 0); + REQUIRE(matrix(1, 0) == 1); + REQUIRE(matrix(1, 1) == 1); + REQUIRE(matrix(1, 2) == 1); + REQUIRE(matrix(1, 3) == 1); + REQUIRE(matrix(2, 0) == 1); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(2, 2) == 1); + REQUIRE(matrix(2, 3) == 1); - BOOST_REQUIRE(info.Type(0) == Datatype::categorical); - BOOST_REQUIRE(info.Type(1) == Datatype::numeric); - BOOST_REQUIRE(info.Type(2) == Datatype::numeric); - BOOST_REQUIRE(info.Type(3) == Datatype::numeric); + REQUIRE(info.Type(0) == Datatype::categorical); + REQUIRE(info.Type(1) == Datatype::numeric); + REQUIRE(info.Type(2) == Datatype::numeric); + REQUIRE(info.Type(3) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(info.MapString("1", 0), 0); - BOOST_REQUIRE_EQUAL(info.MapString("", 0), 1); + REQUIRE(info.MapString("1", 0) == 0); + REQUIRE(info.MapString("", 0) == 1); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 0), "1"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 0), ""); + REQUIRE(info.UnmapString(0, 0) == "1"); + REQUIRE(info.UnmapString(1, 0) == ""); remove("test.csv"); } -BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest02) +TEST_CASE("CategoricalCSVLoadTest02", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1522,36 +1520,36 @@ BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest02) DatasetInfo info; data::Load("test.csv", matrix, info, true); - BOOST_REQUIRE_EQUAL(matrix.n_cols, 4); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 3); + REQUIRE(matrix.n_cols == 4); + REQUIRE(matrix.n_rows == 3); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 3), 0); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 3), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 3), 1); + REQUIRE(matrix(0, 0) == 0); + REQUIRE(matrix(0, 1) == 1); + REQUIRE(matrix(0, 2) == 0); + REQUIRE(matrix(0, 3) == 0); + REQUIRE(matrix(1, 0) == 1); + REQUIRE(matrix(1, 1) == 1); + REQUIRE(matrix(1, 2) == 1); + REQUIRE(matrix(1, 3) == 1); + REQUIRE(matrix(2, 0) == 1); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(2, 2) == 1); + REQUIRE(matrix(2, 3) == 1); - BOOST_REQUIRE(info.Type(0) == Datatype::categorical); - BOOST_REQUIRE(info.Type(1) == Datatype::numeric); - BOOST_REQUIRE(info.Type(2) == Datatype::numeric); + REQUIRE(info.Type(0) == Datatype::categorical); + REQUIRE(info.Type(1) == Datatype::numeric); + REQUIRE(info.Type(2) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(info.MapString("", 0), 1); - BOOST_REQUIRE_EQUAL(info.MapString("1", 0), 0); + REQUIRE(info.MapString("", 0) == 1); + REQUIRE(info.MapString("1", 0) == 0); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 0), "1"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 0), ""); + REQUIRE(info.UnmapString(0, 0) == "1"); + REQUIRE(info.UnmapString(1, 0) == ""); remove("test.csv"); } -BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest03) +TEST_CASE("CategoricalCSVLoadTest03", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1566,36 +1564,36 @@ BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest03) DatasetInfo info; data::Load("test.csv", matrix, info, true); - BOOST_REQUIRE_EQUAL(matrix.n_cols, 4); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 3); + REQUIRE(matrix.n_cols == 4); + REQUIRE(matrix.n_rows == 3); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 3), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 3), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 3), 1); + REQUIRE(matrix(0, 0) == 0); + REQUIRE(matrix(0, 1) == 1); + REQUIRE(matrix(0, 2) == 1); + REQUIRE(matrix(0, 3) == 1); + REQUIRE(matrix(1, 0) == 1); + REQUIRE(matrix(1, 1) == 1); + REQUIRE(matrix(1, 2) == 1); + REQUIRE(matrix(1, 3) == 1); + REQUIRE(matrix(2, 0) == 1); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(2, 2) == 1); + REQUIRE(matrix(2, 3) == 1); - BOOST_REQUIRE(info.Type(0) == Datatype::categorical); - BOOST_REQUIRE(info.Type(1) == Datatype::numeric); - BOOST_REQUIRE(info.Type(2) == Datatype::numeric); + REQUIRE(info.Type(0) == Datatype::categorical); + REQUIRE(info.Type(1) == Datatype::numeric); + REQUIRE(info.Type(2) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(info.MapString("", 0), 0); - BOOST_REQUIRE_EQUAL(info.MapString("1", 0), 1); + REQUIRE(info.MapString("", 0) == 0); + REQUIRE(info.MapString("1", 0) == 1); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 0), ""); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 0), "1"); + REQUIRE(info.UnmapString(0, 0) == ""); + REQUIRE(info.UnmapString(1, 0) == "1"); remove("test.csv"); } -BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest04) +TEST_CASE("CategoricalCSVLoadTest04", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1610,36 +1608,36 @@ BOOST_AUTO_TEST_CASE(CategoricalCSVLoadTest04) DatasetInfo info; data::Load("test.csv", matrix, info, true); - BOOST_REQUIRE_EQUAL(matrix.n_cols, 4); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 3); + REQUIRE(matrix.n_cols == 4); + REQUIRE(matrix.n_rows == 3); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 3), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 3), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 3), 1); + REQUIRE(matrix(0, 0) == 0); + REQUIRE(matrix(0, 1) == 1); + REQUIRE(matrix(0, 2) == 1); + REQUIRE(matrix(0, 3) == 1); + REQUIRE(matrix(1, 0) == 1); + REQUIRE(matrix(1, 1) == 1); + REQUIRE(matrix(1, 2) == 1); + REQUIRE(matrix(1, 3) == 1); + REQUIRE(matrix(2, 0) == 1); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(2, 2) == 1); + REQUIRE(matrix(2, 3) == 1); - BOOST_REQUIRE(info.Type(0) == Datatype::categorical); - BOOST_REQUIRE(info.Type(1) == Datatype::numeric); - BOOST_REQUIRE(info.Type(2) == Datatype::numeric); + REQUIRE(info.Type(0) == Datatype::categorical); + REQUIRE(info.Type(1) == Datatype::numeric); + REQUIRE(info.Type(2) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(info.MapString("200-DM", 0), 0); - BOOST_REQUIRE_EQUAL(info.MapString("1", 0), 1); + REQUIRE(info.MapString("200-DM", 0) == 0); + REQUIRE(info.MapString("1", 0) == 1); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 0), "200-DM"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 0), "1"); + REQUIRE(info.UnmapString(0, 0) == "200-DM"); + REQUIRE(info.UnmapString(1, 0) == "1"); remove("test.csv"); } -BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest00) +TEST_CASE("CategoricalNontransposedCSVLoadTest00", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1657,81 +1655,81 @@ BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest00) DatasetInfo info; data::Load("test.csv", matrix, info, true, false); // No transpose. - BOOST_REQUIRE_EQUAL(matrix.n_cols, 3); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 7); + REQUIRE(matrix.n_cols == 3); + REQUIRE(matrix.n_rows == 7); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 2); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 2); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 2); - BOOST_REQUIRE_EQUAL(matrix(3, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(3, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 2), 2); - BOOST_REQUIRE_EQUAL(matrix(4, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(4, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(4, 2), 2); - BOOST_REQUIRE_EQUAL(matrix(5, 0), 11); - BOOST_REQUIRE_EQUAL(matrix(5, 1), 12); - BOOST_REQUIRE_EQUAL(matrix(5, 2), 15); - BOOST_REQUIRE_EQUAL(matrix(6, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(6, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(6, 2), 2); + REQUIRE(matrix(0, 0) == 0); + REQUIRE(matrix(0, 1) == 1); + REQUIRE(matrix(0, 2) == 2); + REQUIRE(matrix(1, 0) == 0); + REQUIRE(matrix(1, 1) == 1); + REQUIRE(matrix(1, 2) == 2); + REQUIRE(matrix(2, 0) == 0); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(2, 2) == 2); + REQUIRE(matrix(3, 0) == 0); + REQUIRE(matrix(3, 1) == 1); + REQUIRE(matrix(3, 2) == 2); + REQUIRE(matrix(4, 0) == 0); + REQUIRE(matrix(4, 1) == 1); + REQUIRE(matrix(4, 2) == 2); + REQUIRE(matrix(5, 0) == 11); + REQUIRE(matrix(5, 1) == 12); + REQUIRE(matrix(5, 2) == 15); + REQUIRE(matrix(6, 0) == 0); + REQUIRE(matrix(6, 1) == 1); + REQUIRE(matrix(6, 2) == 2); - BOOST_REQUIRE(info.Type(0) == Datatype::categorical); - BOOST_REQUIRE(info.Type(1) == Datatype::categorical); - BOOST_REQUIRE(info.Type(2) == Datatype::categorical); - BOOST_REQUIRE(info.Type(3) == Datatype::categorical); - BOOST_REQUIRE(info.Type(4) == Datatype::categorical); - BOOST_REQUIRE(info.Type(5) == Datatype::numeric); - BOOST_REQUIRE(info.Type(6) == Datatype::categorical); + REQUIRE(info.Type(0) == Datatype::categorical); + REQUIRE(info.Type(1) == Datatype::categorical); + REQUIRE(info.Type(2) == Datatype::categorical); + REQUIRE(info.Type(3) == Datatype::categorical); + REQUIRE(info.Type(4) == Datatype::categorical); + REQUIRE(info.Type(5) == Datatype::numeric); + REQUIRE(info.Type(6) == Datatype::categorical); - BOOST_REQUIRE_EQUAL(info.MapString("1", 0), 0); - BOOST_REQUIRE_EQUAL(info.MapString("2", 0), 1); - BOOST_REQUIRE_EQUAL(info.MapString("hello", 0), 2); - BOOST_REQUIRE_EQUAL(info.MapString("3", 1), 0); - BOOST_REQUIRE_EQUAL(info.MapString("4", 1), 1); - BOOST_REQUIRE_EQUAL(info.MapString("goodbye", 1), 2); - BOOST_REQUIRE_EQUAL(info.MapString("5", 2), 0); - BOOST_REQUIRE_EQUAL(info.MapString("6", 2), 1); - BOOST_REQUIRE_EQUAL(info.MapString("coffee", 2), 2); - BOOST_REQUIRE_EQUAL(info.MapString("7", 3), 0); - BOOST_REQUIRE_EQUAL(info.MapString("8", 3), 1); - BOOST_REQUIRE_EQUAL(info.MapString("confusion", 3), 2); - BOOST_REQUIRE_EQUAL(info.MapString("9", 4), 0); - BOOST_REQUIRE_EQUAL(info.MapString("10", 4), 1); - BOOST_REQUIRE_EQUAL(info.MapString("hello", 4), 2); - BOOST_REQUIRE_EQUAL(info.MapString("13", 6), 0); - BOOST_REQUIRE_EQUAL(info.MapString("14", 6), 1); - BOOST_REQUIRE_EQUAL(info.MapString("confusion", 6), 2); + REQUIRE(info.MapString("1", 0) == 0); + REQUIRE(info.MapString("2", 0) == 1); + REQUIRE(info.MapString("hello", 0) == 2); + REQUIRE(info.MapString("3", 1) == 0); + REQUIRE(info.MapString("4", 1) == 1); + REQUIRE(info.MapString("goodbye", 1) == 2); + REQUIRE(info.MapString("5", 2) == 0); + REQUIRE(info.MapString("6", 2) == 1); + REQUIRE(info.MapString("coffee", 2) == 2); + REQUIRE(info.MapString("7", 3) == 0); + REQUIRE(info.MapString("8", 3) == 1); + REQUIRE(info.MapString("confusion", 3) == 2); + REQUIRE(info.MapString("9", 4) == 0); + REQUIRE(info.MapString("10", 4) == 1); + REQUIRE(info.MapString("hello", 4) == 2); + REQUIRE(info.MapString("13", 6) == 0); + REQUIRE(info.MapString("14", 6) == 1); + REQUIRE(info.MapString("confusion", 6) == 2); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 0), "1"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 0), "2"); - BOOST_REQUIRE_EQUAL(info.UnmapString(2, 0), "hello"); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 1), "3"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 1), "4"); - BOOST_REQUIRE_EQUAL(info.UnmapString(2, 1), "goodbye"); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 2), "5"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 2), "6"); - BOOST_REQUIRE_EQUAL(info.UnmapString(2, 2), "coffee"); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 3), "7"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 3), "8"); - BOOST_REQUIRE_EQUAL(info.UnmapString(2, 3), "confusion"); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 4), "9"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 4), "10"); - BOOST_REQUIRE_EQUAL(info.UnmapString(2, 4), "hello"); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 6), "13"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 6), "14"); - BOOST_REQUIRE_EQUAL(info.UnmapString(2, 6), "confusion"); + REQUIRE(info.UnmapString(0, 0) == "1"); + REQUIRE(info.UnmapString(1, 0) == "2"); + REQUIRE(info.UnmapString(2, 0) == "hello"); + REQUIRE(info.UnmapString(0, 1) == "3"); + REQUIRE(info.UnmapString(1, 1) == "4"); + REQUIRE(info.UnmapString(2, 1) == "goodbye"); + REQUIRE(info.UnmapString(0, 2) == "5"); + REQUIRE(info.UnmapString(1, 2) == "6"); + REQUIRE(info.UnmapString(2, 2) == "coffee"); + REQUIRE(info.UnmapString(0, 3) == "7"); + REQUIRE(info.UnmapString(1, 3) == "8"); + REQUIRE(info.UnmapString(2, 3) == "confusion"); + REQUIRE(info.UnmapString(0, 4) == "9"); + REQUIRE(info.UnmapString(1, 4) == "10"); + REQUIRE(info.UnmapString(2, 4) == "hello"); + REQUIRE(info.UnmapString(0, 6) == "13"); + REQUIRE(info.UnmapString(1, 6) == "14"); + REQUIRE(info.UnmapString(2, 6) == "confusion"); remove("test.csv"); } -BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest01) +TEST_CASE("CategoricalNontransposedCSVLoadTest01", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1746,37 +1744,37 @@ BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest01) DatasetInfo info; data::Load("test.csv", matrix, info, true, false); // No transpose. - BOOST_REQUIRE_EQUAL(matrix.n_cols, 3); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 4); + REQUIRE(matrix.n_cols == 3); + REQUIRE(matrix.n_rows == 4); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 2), 1); + REQUIRE(matrix(0, 0) == 1); + REQUIRE(matrix(0, 1) == 1); + REQUIRE(matrix(0, 2) == 1); + REQUIRE(matrix(1, 0) == 1); + REQUIRE(matrix(1, 1) == 1); + REQUIRE(matrix(1, 2) == 1); + REQUIRE(matrix(2, 0) == 0); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(2, 2) == 1); + REQUIRE(matrix(3, 0) == 1); + REQUIRE(matrix(3, 1) == 1); + REQUIRE(matrix(3, 2) == 1); - BOOST_REQUIRE(info.Type(0) == Datatype::numeric); - BOOST_REQUIRE(info.Type(1) == Datatype::numeric); - BOOST_REQUIRE(info.Type(2) == Datatype::categorical); - BOOST_REQUIRE(info.Type(3) == Datatype::numeric); + REQUIRE(info.Type(0) == Datatype::numeric); + REQUIRE(info.Type(1) == Datatype::numeric); + REQUIRE(info.Type(2) == Datatype::categorical); + REQUIRE(info.Type(3) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(info.MapString("", 2), 0); - BOOST_REQUIRE_EQUAL(info.MapString("1", 2), 1); + REQUIRE(info.MapString("", 2) == 0); + REQUIRE(info.MapString("1", 2) == 1); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 2), ""); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 2), "1"); + REQUIRE(info.UnmapString(0, 2) == ""); + REQUIRE(info.UnmapString(1, 2) == "1"); remove("test.csv"); } -BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest02) +TEST_CASE("CategoricalNontransposedCSVLoadTest02", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1791,37 +1789,37 @@ BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest02) DatasetInfo info; data::Load("test.csv", matrix, info, true, false); // No transpose. - BOOST_REQUIRE_EQUAL(matrix.n_cols, 3); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 4); + REQUIRE(matrix.n_cols == 3); + REQUIRE(matrix.n_rows == 4); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 2), 1); + REQUIRE(matrix(0, 0) == 1); + REQUIRE(matrix(0, 1) == 1); + REQUIRE(matrix(0, 2) == 1); + REQUIRE(matrix(1, 0) == 0); + REQUIRE(matrix(1, 1) == 1); + REQUIRE(matrix(1, 2) == 1); + REQUIRE(matrix(2, 0) == 1); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(2, 2) == 1); + REQUIRE(matrix(3, 0) == 1); + REQUIRE(matrix(3, 1) == 1); + REQUIRE(matrix(3, 2) == 1); - BOOST_REQUIRE(info.Type(0) == Datatype::numeric); - BOOST_REQUIRE(info.Type(1) == Datatype::categorical); - BOOST_REQUIRE(info.Type(2) == Datatype::numeric); - BOOST_REQUIRE(info.Type(3) == Datatype::numeric); + REQUIRE(info.Type(0) == Datatype::numeric); + REQUIRE(info.Type(1) == Datatype::categorical); + REQUIRE(info.Type(2) == Datatype::numeric); + REQUIRE(info.Type(3) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(info.MapString("", 1), 0); - BOOST_REQUIRE_EQUAL(info.MapString("1", 1), 1); + REQUIRE(info.MapString("", 1) == 0); + REQUIRE(info.MapString("1", 1) == 1); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 1), ""); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 1), "1"); + REQUIRE(info.UnmapString(0, 1) == ""); + REQUIRE(info.UnmapString(1, 1) == "1"); remove("test.csv"); } -BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest03) +TEST_CASE("CategoricalNontransposedCSVLoadTest03", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1836,37 +1834,37 @@ BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest03) DatasetInfo info; data::Load("test.csv", matrix, info, true, false); // No transpose. - BOOST_REQUIRE_EQUAL(matrix.n_cols, 3); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 4); + REQUIRE(matrix.n_cols == 3); + REQUIRE(matrix.n_rows == 4); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 2), 1); + REQUIRE(matrix(0, 0) == 0); + REQUIRE(matrix(0, 1) == 1); + REQUIRE(matrix(0, 2) == 1); + REQUIRE(matrix(1, 0) == 1); + REQUIRE(matrix(1, 1) == 1); + REQUIRE(matrix(1, 2) == 1); + REQUIRE(matrix(2, 0) == 1); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(2, 2) == 1); + REQUIRE(matrix(3, 0) == 1); + REQUIRE(matrix(3, 1) == 1); + REQUIRE(matrix(3, 2) == 1); - BOOST_REQUIRE(info.Type(0) == Datatype::categorical); - BOOST_REQUIRE(info.Type(1) == Datatype::numeric); - BOOST_REQUIRE(info.Type(2) == Datatype::numeric); - BOOST_REQUIRE(info.Type(3) == Datatype::numeric); + REQUIRE(info.Type(0) == Datatype::categorical); + REQUIRE(info.Type(1) == Datatype::numeric); + REQUIRE(info.Type(2) == Datatype::numeric); + REQUIRE(info.Type(3) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(info.MapString("", 1), 0); - BOOST_REQUIRE_EQUAL(info.MapString("1", 1), 1); + REQUIRE(info.MapString("", 1) == 0); + REQUIRE(info.MapString("1", 1) == 1); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 1), ""); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 1), "1"); + REQUIRE(info.UnmapString(0, 1) == ""); + REQUIRE(info.UnmapString(1, 1) == "1"); remove("test.csv"); } -BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest04) +TEST_CASE("CategoricalNontransposedCSVLoadTest04", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1881,32 +1879,32 @@ BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest04) DatasetInfo info; data::Load("test.csv", matrix, info, true, false); // No transpose. - BOOST_REQUIRE_EQUAL(matrix.n_cols, 3); - BOOST_REQUIRE_EQUAL(matrix.n_rows, 4); + REQUIRE(matrix.n_cols == 3); + REQUIRE(matrix.n_rows == 4); - BOOST_REQUIRE(info.Type(0) == Datatype::categorical); - BOOST_REQUIRE(info.Type(1) == Datatype::numeric); - BOOST_REQUIRE(info.Type(2) == Datatype::numeric); - BOOST_REQUIRE(info.Type(3) == Datatype::numeric); + REQUIRE(info.Type(0) == Datatype::categorical); + REQUIRE(info.Type(1) == Datatype::numeric); + REQUIRE(info.Type(2) == Datatype::numeric); + REQUIRE(info.Type(3) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(matrix(0, 0), 0); - BOOST_REQUIRE_EQUAL(matrix(0, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(0, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(1, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(2, 2), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 0), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 1), 1); - BOOST_REQUIRE_EQUAL(matrix(3, 2), 1); + REQUIRE(matrix(0, 0) == 0); + REQUIRE(matrix(0, 1) == 1); + REQUIRE(matrix(0, 2) == 1); + REQUIRE(matrix(1, 0) == 1); + REQUIRE(matrix(1, 1) == 1); + REQUIRE(matrix(1, 2) == 1); + REQUIRE(matrix(2, 0) == 1); + REQUIRE(matrix(2, 1) == 1); + REQUIRE(matrix(2, 2) == 1); + REQUIRE(matrix(3, 0) == 1); + REQUIRE(matrix(3, 1) == 1); + REQUIRE(matrix(3, 2) == 1); - BOOST_REQUIRE_EQUAL(info.MapString("200-DM", 1), 0); - BOOST_REQUIRE_EQUAL(info.MapString("1", 1), 1); + REQUIRE(info.MapString("200-DM", 1) == 0); + REQUIRE(info.MapString("1", 1) == 1); - BOOST_REQUIRE_EQUAL(info.UnmapString(0, 1), "200-DM"); - BOOST_REQUIRE_EQUAL(info.UnmapString(1, 1), "1"); + REQUIRE(info.UnmapString(0, 1) == "200-DM"); + REQUIRE(info.UnmapString(1, 1) == "1"); remove("test.csv"); } @@ -1914,7 +1912,7 @@ BOOST_AUTO_TEST_CASE(CategoricalNontransposedCSVLoadTest04) /** * A harder test CSV based on the concerns in #658. */ -BOOST_AUTO_TEST_CASE(HarderKeonTest) +TEST_CASE("HarderKeonTest", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -1929,28 +1927,28 @@ BOOST_AUTO_TEST_CASE(HarderKeonTest) data::DatasetInfo info; data::Load("test.csv", dataset, info, true, true); - BOOST_REQUIRE_EQUAL(dataset.n_rows, 5); - BOOST_REQUIRE_EQUAL(dataset.n_cols, 4); + REQUIRE(dataset.n_rows == 5); + REQUIRE(dataset.n_cols == 4); - BOOST_REQUIRE_EQUAL(info.Dimensionality(), 5); - BOOST_REQUIRE_EQUAL(info.NumMappings(0), 3); - BOOST_REQUIRE_EQUAL(info.NumMappings(1), 4); - BOOST_REQUIRE_EQUAL(info.NumMappings(2), 0); - BOOST_REQUIRE_EQUAL(info.NumMappings(3), 2); // \t and "" are equivalent. - BOOST_REQUIRE_EQUAL(info.NumMappings(4), 4); + REQUIRE(info.Dimensionality() == 5); + REQUIRE(info.NumMappings(0) == 3); + REQUIRE(info.NumMappings(1) == 4); + REQUIRE(info.NumMappings(2) == 0); + REQUIRE(info.NumMappings(3) == 2); // \t and "" are equivalent. + REQUIRE(info.NumMappings(4) == 4); // Now load non-transposed. data::DatasetInfo ntInfo; data::Load("test.csv", dataset, ntInfo, true, false); - BOOST_REQUIRE_EQUAL(dataset.n_rows, 4); - BOOST_REQUIRE_EQUAL(dataset.n_cols, 5); + REQUIRE(dataset.n_rows == 4); + REQUIRE(dataset.n_cols == 5); - BOOST_REQUIRE_EQUAL(ntInfo.Dimensionality(), 4); - BOOST_REQUIRE_EQUAL(ntInfo.NumMappings(0), 4); - BOOST_REQUIRE_EQUAL(ntInfo.NumMappings(1), 5); - BOOST_REQUIRE_EQUAL(ntInfo.NumMappings(2), 5); - BOOST_REQUIRE_EQUAL(ntInfo.NumMappings(3), 3); + REQUIRE(ntInfo.Dimensionality() == 4); + REQUIRE(ntInfo.NumMappings(0) == 4); + REQUIRE(ntInfo.NumMappings(1) == 5); + REQUIRE(ntInfo.NumMappings(2) == 5); + REQUIRE(ntInfo.NumMappings(3) == 3); remove("test.csv"); } @@ -1958,7 +1956,7 @@ BOOST_AUTO_TEST_CASE(HarderKeonTest) /** * A simple ARFF load test. Two attributes, both numeric. */ -BOOST_AUTO_TEST_CASE(SimpleARFFTest) +TEST_CASE("SimpleARFFTest", "[LoadSaveTest]") { fstream f; f.open("test.arff", fstream::out); @@ -1978,15 +1976,15 @@ BOOST_AUTO_TEST_CASE(SimpleARFFTest) DatasetInfo info; data::Load("test.arff", dataset, info); - BOOST_REQUIRE_EQUAL(info.Dimensionality(), 2); - BOOST_REQUIRE(info.Type(0) == Datatype::numeric); - BOOST_REQUIRE(info.Type(1) == Datatype::numeric); + REQUIRE(info.Dimensionality() == 2); + REQUIRE(info.Type(0) == Datatype::numeric); + REQUIRE(info.Type(1) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(dataset.n_rows, 2); - BOOST_REQUIRE_EQUAL(dataset.n_cols, 4); + REQUIRE(dataset.n_rows == 2); + REQUIRE(dataset.n_cols == 4); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_CLOSE(dataset[i], double(i + 1), 1e-5); + REQUIRE(dataset[i] == Approx(double(i + 1)).epsilon(1e-7)); remove("test.arff"); } @@ -1995,7 +1993,7 @@ BOOST_AUTO_TEST_CASE(SimpleARFFTest) * Another simple ARFF load test. Three attributes, two categorical, one * numeric. */ -BOOST_AUTO_TEST_CASE(SimpleARFFCategoricalTest) +TEST_CASE("SimpleARFFCategoricalTest", "[LoadSaveTest]") { fstream f; f.open("test.arff", fstream::out); @@ -2019,32 +2017,32 @@ BOOST_AUTO_TEST_CASE(SimpleARFFCategoricalTest) DatasetInfo info; data::Load("test.arff", dataset, info); - 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"); } @@ -2053,7 +2051,7 @@ BOOST_AUTO_TEST_CASE(SimpleARFFCategoricalTest) * A harder ARFF test, where we have each type of supported value, and some * random whitespace too. */ -BOOST_AUTO_TEST_CASE(HarderARFFTest) +TEST_CASE("HarderARFFTest", "[LoadSaveTest]") { fstream f; f.open("test.arff", fstream::out); @@ -2078,39 +2076,39 @@ BOOST_AUTO_TEST_CASE(HarderARFFTest) DatasetInfo info; data::Load("test.arff", dataset, info); - BOOST_REQUIRE_EQUAL(info.Dimensionality(), 5); + REQUIRE(info.Dimensionality() == 5); - BOOST_REQUIRE(info.Type(0) == Datatype::numeric); + REQUIRE(info.Type(0) == Datatype::numeric); - BOOST_REQUIRE(info.Type(1) == Datatype::categorical); - BOOST_REQUIRE_EQUAL(info.NumMappings(1), 3); + REQUIRE(info.Type(1) == Datatype::categorical); + REQUIRE(info.NumMappings(1) == 3); - BOOST_REQUIRE(info.Type(2) == Datatype::numeric); - BOOST_REQUIRE(info.Type(3) == Datatype::numeric); - BOOST_REQUIRE(info.Type(4) == Datatype::numeric); + REQUIRE(info.Type(2) == Datatype::numeric); + REQUIRE(info.Type(3) == Datatype::numeric); + REQUIRE(info.Type(4) == Datatype::numeric); - BOOST_REQUIRE_EQUAL(dataset.n_rows, 5); - BOOST_REQUIRE_EQUAL(dataset.n_cols, 3); + REQUIRE(dataset.n_rows == 5); + REQUIRE(dataset.n_cols == 3); - BOOST_REQUIRE_CLOSE(dataset(0, 0), 1.0, 1e-5); - BOOST_REQUIRE_CLOSE(dataset(0, 1), 2.0, 1e-5); - BOOST_REQUIRE_CLOSE(dataset(0, 2), 3.0, 1e-5); + REQUIRE(dataset(0, 0) == Approx(1.0).epsilon(1e-7)); + REQUIRE(dataset(0, 1) == Approx(2.0).epsilon(1e-7)); + REQUIRE(dataset(0, 2) == Approx(3.0).epsilon(1e-7)); - BOOST_REQUIRE_NE(dataset(1, 0), dataset(1, 1)); - BOOST_REQUIRE_NE(dataset(1, 1), dataset(1, 2)); - BOOST_REQUIRE_NE(dataset(1, 0), dataset(1, 2)); + REQUIRE(dataset(1, 0) != dataset(1, 1)); + REQUIRE(dataset(1, 1) != dataset(1, 2)); + REQUIRE(dataset(1, 0) != dataset(1, 2)); - BOOST_REQUIRE_CLOSE(dataset(2, 0), 3.0, 1e-5); - BOOST_REQUIRE_CLOSE(dataset(2, 1), 4.0, 1e-5); - BOOST_REQUIRE_CLOSE(dataset(2, 2), 5.0, 1e-5); + REQUIRE(dataset(2, 0) == Approx(3.0).epsilon(1e-7)); + REQUIRE(dataset(2, 1) == Approx(4.0).epsilon(1e-7)); + REQUIRE(dataset(2, 2) == Approx(5.0).epsilon(1e-7)); - BOOST_REQUIRE_CLOSE(dataset(3, 0), 4.5, 1e-5); - BOOST_REQUIRE_CLOSE(dataset(3, 1), 5.5, 1e-5); - BOOST_REQUIRE_CLOSE(dataset(3, 2), 6.5, 1e-5); + REQUIRE(dataset(3, 0) == Approx(4.5).epsilon(1e-7)); + REQUIRE(dataset(3, 1) == Approx(5.5).epsilon(1e-7)); + REQUIRE(dataset(3, 2) == Approx(6.5).epsilon(1e-7)); - BOOST_REQUIRE_CLOSE(dataset(4, 0), 6.0, 1e-5); - BOOST_REQUIRE_CLOSE(dataset(4, 1), 7.0, 1e-5); - BOOST_REQUIRE_CLOSE(dataset(4, 2), 8.0, 1e-5); + REQUIRE(dataset(4, 0) == Approx(6.0).epsilon(1e-7)); + REQUIRE(dataset(4, 1) == Approx(7.0).epsilon(1e-7)); + REQUIRE(dataset(4, 2) == Approx(8.0).epsilon(1e-7)); remove("test.arff"); } @@ -2118,7 +2116,7 @@ BOOST_AUTO_TEST_CASE(HarderARFFTest) /** * If we pass a bad DatasetInfo, it should throw. */ -BOOST_AUTO_TEST_CASE(BadDatasetInfoARFFTest) +TEST_CASE("BadDatasetInfoARFFTest", "[LoadSaveTest]") { fstream f; f.open("test.arff", fstream::out); @@ -2142,7 +2140,7 @@ BOOST_AUTO_TEST_CASE(BadDatasetInfoARFFTest) arma::mat dataset; DatasetInfo info(6); - BOOST_REQUIRE_THROW(data::LoadARFF("test.arff", dataset, info), + REQUIRE_THROWS_AS(data::LoadARFF("test.arff", dataset, info), std::invalid_argument); remove("test.arff"); @@ -2151,13 +2149,13 @@ BOOST_AUTO_TEST_CASE(BadDatasetInfoARFFTest) /** * If file is not found, it should throw. */ -BOOST_AUTO_TEST_CASE(NonExistentFileARFFTest) +TEST_CASE("NonExistentFileARFFTest", "[LoadSaveTest]") { arma::mat dataset; DatasetInfo info; Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(data::LoadARFF("nonexistentfile.arff", dataset, info), + REQUIRE_THROWS_AS(data::LoadARFF("nonexistentfile.arff", dataset, info), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -2166,7 +2164,7 @@ BOOST_AUTO_TEST_CASE(NonExistentFileARFFTest) * A test to check whether the arff loader is case insensitive to declarations: * @relation, @attribute, @data. */ -BOOST_AUTO_TEST_CASE(CaseTest) +TEST_CASE("CaseTest", "[LoadSaveTest]") { arma::mat dataset; @@ -2174,15 +2172,15 @@ BOOST_AUTO_TEST_CASE(CaseTest) LoadARFF("casecheck.arff", dataset, info); - BOOST_CHECK_EQUAL(dataset.n_rows, 2); - BOOST_CHECK_EQUAL(dataset.n_cols, 3); + REQUIRE(dataset.n_rows == 2); + REQUIRE(dataset.n_cols == 3); } /** * Ensure that a failure happens if we set a category to use capital letters but * it receives them in lowercase. */ -BOOST_AUTO_TEST_CASE(CategoryCaseTest) +TEST_CASE("CategoryCaseTest", "[LoadSaveTest]") { fstream f; f.open("test.arff", fstream::out); @@ -2209,7 +2207,7 @@ BOOST_AUTO_TEST_CASE(CategoryCaseTest) // Make sure to parse with fatal errors (that's what the `true` parameter // means). Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(data::Load("test.arff", dataset, info, true), + REQUIRE_THROWS_AS(data::Load("test.arff", dataset, info, true), std::runtime_error); Log::Fatal.ignoreInput = false; @@ -2219,7 +2217,7 @@ BOOST_AUTO_TEST_CASE(CategoryCaseTest) /** * Test that a CSV with the wrong number of columns fails. */ -BOOST_AUTO_TEST_CASE(MalformedCSVTest) +TEST_CASE("MalformedCSVTest", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -2231,7 +2229,7 @@ BOOST_AUTO_TEST_CASE(MalformedCSVTest) arma::mat dataset; DatasetInfo di; - BOOST_REQUIRE(!data::Load("test.csv", dataset, di, false)); + REQUIRE(!data::Load("test.csv", dataset, di, false)); remove("test.csv"); } @@ -2239,7 +2237,7 @@ BOOST_AUTO_TEST_CASE(MalformedCSVTest) /** * Test that a TSV can load with LoadCSV. */ -BOOST_AUTO_TEST_CASE(LoadCSVTSVTest) +TEST_CASE("LoadCSVTSVTest", "[LoadSaveTest]") { fstream f; f.open("test.tsv", fstream::out); @@ -2250,13 +2248,13 @@ BOOST_AUTO_TEST_CASE(LoadCSVTSVTest) arma::mat dataset; DatasetInfo di; - BOOST_REQUIRE(data::Load("test.tsv", dataset, di, false)); + REQUIRE(data::Load("test.tsv", dataset, di, false)); - BOOST_REQUIRE_EQUAL(dataset.n_cols, 2); - BOOST_REQUIRE_EQUAL(dataset.n_rows, 4); + REQUIRE(dataset.n_cols == 2); + REQUIRE(dataset.n_rows == 4); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_EQUAL(dataset[i], i + 1); + REQUIRE(dataset[i] == i + 1); remove("test.tsv"); } @@ -2264,7 +2262,7 @@ BOOST_AUTO_TEST_CASE(LoadCSVTSVTest) /** * Test that a text file can load with LoadCSV. */ -BOOST_AUTO_TEST_CASE(LoadCSVTXTTest) +TEST_CASE("LoadCSVTXTTest", "[LoadSaveTest]") { fstream f; f.open("test.txt", fstream::out); @@ -2275,13 +2273,13 @@ BOOST_AUTO_TEST_CASE(LoadCSVTXTTest) arma::mat dataset; DatasetInfo di; - BOOST_REQUIRE(data::Load("test.txt", dataset, di, false)); + REQUIRE(data::Load("test.txt", dataset, di, false)); - BOOST_REQUIRE_EQUAL(dataset.n_cols, 2); - BOOST_REQUIRE_EQUAL(dataset.n_rows, 4); + REQUIRE(dataset.n_cols == 2); + REQUIRE(dataset.n_rows == 4); for (size_t i = 0; i < 8; ++i) - BOOST_REQUIRE_EQUAL(dataset[i], i + 1); + REQUIRE(dataset[i] == i + 1); remove("test.txt"); } @@ -2289,7 +2287,7 @@ BOOST_AUTO_TEST_CASE(LoadCSVTXTTest) /** * Test that a non-transposed CSV with the wrong number of columns fails. */ -BOOST_AUTO_TEST_CASE(MalformedNoTransposeCSVTest) +TEST_CASE("MalformedNoTransposeCSVTest", "[LoadSaveTest]") { fstream f; f.open("test.csv", fstream::out); @@ -2301,7 +2299,7 @@ BOOST_AUTO_TEST_CASE(MalformedNoTransposeCSVTest) arma::mat dataset; DatasetInfo di; - BOOST_REQUIRE(!data::Load("test.csv", dataset, di, false, false)); + REQUIRE(!data::Load("test.csv", dataset, di, false, false)); remove("test.csv"); } @@ -2309,7 +2307,7 @@ BOOST_AUTO_TEST_CASE(MalformedNoTransposeCSVTest) /** * Test that a non-transposed TSV can load with LoadCSV. */ -BOOST_AUTO_TEST_CASE(LoadCSVNoTransposeTSVTest) +TEST_CASE("LoadCSVNoTransposeTSVTest", "[LoadSaveTest]") { fstream f; f.open("test.tsv", fstream::out); @@ -2320,19 +2318,19 @@ BOOST_AUTO_TEST_CASE(LoadCSVNoTransposeTSVTest) arma::mat dataset; DatasetInfo di; - BOOST_REQUIRE(data::Load("test.tsv", dataset, di, false, false)); + REQUIRE(data::Load("test.tsv", dataset, di, false, false)); - BOOST_REQUIRE_EQUAL(dataset.n_cols, 4); - BOOST_REQUIRE_EQUAL(dataset.n_rows, 2); + REQUIRE(dataset.n_cols == 4); + REQUIRE(dataset.n_rows == 2); - BOOST_REQUIRE_EQUAL(dataset[0], 1); - BOOST_REQUIRE_EQUAL(dataset[1], 5); - BOOST_REQUIRE_EQUAL(dataset[2], 2); - BOOST_REQUIRE_EQUAL(dataset[3], 6); - BOOST_REQUIRE_EQUAL(dataset[4], 3); - BOOST_REQUIRE_EQUAL(dataset[5], 7); - BOOST_REQUIRE_EQUAL(dataset[6], 4); - BOOST_REQUIRE_EQUAL(dataset[7], 8); + REQUIRE(dataset[0] == 1); + REQUIRE(dataset[1] == 5); + REQUIRE(dataset[2] == 2); + REQUIRE(dataset[3] == 6); + REQUIRE(dataset[4] == 3); + REQUIRE(dataset[5] == 7); + REQUIRE(dataset[6] == 4); + REQUIRE(dataset[7] == 8); remove("test.tsv"); } @@ -2340,7 +2338,7 @@ BOOST_AUTO_TEST_CASE(LoadCSVNoTransposeTSVTest) /** * Test that a non-transposed text file can load with LoadCSV. */ -BOOST_AUTO_TEST_CASE(LoadCSVNoTransposeTXTTest) +TEST_CASE("LoadCSVNoTransposeTXTTest", "[LoadSaveTest]") { fstream f; f.open("test.txt", fstream::out); @@ -2351,19 +2349,19 @@ BOOST_AUTO_TEST_CASE(LoadCSVNoTransposeTXTTest) arma::mat dataset; DatasetInfo di; - BOOST_REQUIRE(data::Load("test.txt", dataset, di, false, false)); + REQUIRE(data::Load("test.txt", dataset, di, false, false)); - BOOST_REQUIRE_EQUAL(dataset.n_cols, 4); - BOOST_REQUIRE_EQUAL(dataset.n_rows, 2); + REQUIRE(dataset.n_cols == 4); + REQUIRE(dataset.n_rows == 2); - BOOST_REQUIRE_EQUAL(dataset[0], 1); - BOOST_REQUIRE_EQUAL(dataset[1], 5); - BOOST_REQUIRE_EQUAL(dataset[2], 2); - BOOST_REQUIRE_EQUAL(dataset[3], 6); - BOOST_REQUIRE_EQUAL(dataset[4], 3); - BOOST_REQUIRE_EQUAL(dataset[5], 7); - BOOST_REQUIRE_EQUAL(dataset[6], 4); - BOOST_REQUIRE_EQUAL(dataset[7], 8); + REQUIRE(dataset[0] == 1); + REQUIRE(dataset[1] == 5); + REQUIRE(dataset[2] == 2); + REQUIRE(dataset[3] == 6); + REQUIRE(dataset[4] == 3); + REQUIRE(dataset[5] == 7); + REQUIRE(dataset[6] == 4); + REQUIRE(dataset[7] == 8); remove("test.txt"); } @@ -2371,7 +2369,7 @@ BOOST_AUTO_TEST_CASE(LoadCSVNoTransposeTXTTest) /** * Make sure DatasetMapper properly unmaps from non-unique strings. */ -BOOST_AUTO_TEST_CASE(DatasetMapperNonUniqueTest) +TEST_CASE("DatasetMapperNonUniqueTest", "[LoadSaveTest]") { DatasetMapper dm(1); @@ -2382,13 +2380,11 @@ BOOST_AUTO_TEST_CASE(DatasetMapperNonUniqueTest) dm.MapString("cheese", 0); double nan = std::numeric_limits::quiet_NaN(); - BOOST_REQUIRE_EQUAL(dm.NumMappings(0), 3); - BOOST_REQUIRE_EQUAL(dm.NumUnmappings(nan, 0), 3); + REQUIRE(dm.NumMappings(0) == 3); + REQUIRE(dm.NumUnmappings(nan, 0) == 3); - BOOST_REQUIRE_EQUAL(dm.UnmapString(nan, 0), "hello"); - BOOST_REQUIRE_EQUAL(dm.UnmapString(nan, 0, 0), "hello"); - BOOST_REQUIRE_EQUAL(dm.UnmapString(nan, 0, 1), "goodbye"); - BOOST_REQUIRE_EQUAL(dm.UnmapString(nan, 0, 2), "cheese"); + REQUIRE(dm.UnmapString(nan, 0) == "hello"); + REQUIRE(dm.UnmapString(nan, 0, 0) == "hello"); + REQUIRE(dm.UnmapString(nan, 0, 1) == "goodbye"); + REQUIRE(dm.UnmapString(nan, 0, 2) == "cheese"); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/loss_functions_test.cpp b/src/mlpack/tests/loss_functions_test.cpp index 180e374402..5af527ac8c 100644 --- a/src/mlpack/tests/loss_functions_test.cpp +++ b/src/mlpack/tests/loss_functions_test.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -816,4 +817,59 @@ BOOST_AUTO_TEST_CASE(MarginRankingLossTest) "-0.753830 1.336900 0.000000 0.000000 -0.207000 0.328810"), 1e-6); } +/** + * Simple test for the Softmargin Loss function. + */ +BOOST_AUTO_TEST_CASE(SoftMarginLossTest) +{ + arma::mat input, target, output, expectedOutput; + double loss; + SoftMarginLoss<> module1; + SoftMarginLoss<> module2(false); + + input = arma::mat("0.1778 0.0957 0.1397 0.1203 0.2403 0.1925 -0.2264 -0.3400 " + "-0.3336"); + target = arma::mat("1 1 -1 1 -1 1 -1 1 1"); + input.reshape(3, 3); + target.reshape(3, 3); + + // Test for sum reduction. + + // Calculated using torch.nn.SoftMarginLoss(reduction='sum'). + expectedOutput = arma::mat("-0.4557 -0.4761 0.5349 -0.4700 0.5598 -0.4520 " + "0.4436 -0.5842 -0.5826"); + expectedOutput.reshape(3, 3); + + // Test the Forward function. Loss should be 6.41456. + // Value calculated using torch.nn.SoftMarginLoss(reduction='sum'). + loss = module1.Forward(input, target); + BOOST_REQUIRE_CLOSE(loss, 6.41456, 1e-3); + + // Test the Backward function. + module1.Backward(input, target, output); + BOOST_REQUIRE_CLOSE(arma::as_scalar(arma::accu(output)), -1.48227, 1e-3); + BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); + BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + CheckMatrices(output, expectedOutput, 0.1); + + // Test for mean reduction. + + // Calculated using torch.nn.SoftMarginLoss(reduction='mean'). + expectedOutput = arma::mat("-0.0506 -0.0529 0.0594 -0.0522 0.0622 -0.0502 " + "0.0493 -0.0649 -0.0647"); + expectedOutput.reshape(3, 3); + + // Test the Forward function. Loss should be 0.712729. + // Value calculated using torch.nn.SoftMarginLoss(reduction='mean'). + loss = module2.Forward(input, target); + BOOST_REQUIRE_CLOSE(loss, 0.712729, 1e-3); + + // Test the Backward function. + module2.Backward(input, target, output); + BOOST_REQUIRE_CLOSE(arma::as_scalar(arma::accu(output)), -0.164697, 1e-3); + BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows); + BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols); + CheckMatrices(output, expectedOutput, 0.1); +} + BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/approx_kfn_test.cpp b/src/mlpack/tests/main_tests/approx_kfn_test.cpp index f0da4ea101..375bbe2678 100644 --- a/src/mlpack/tests/main_tests/approx_kfn_test.cpp +++ b/src/mlpack/tests/main_tests/approx_kfn_test.cpp @@ -19,8 +19,8 @@ static const std::string testName = "ApproxK-FurthestNeighbors"; #include "test_helper.hpp" #include -#include -#include "../test_tools.hpp" +#include "../catch.hpp" +#include "../test_catch_tools.hpp" using namespace mlpack; @@ -41,12 +41,11 @@ struct ApproxKFNTestFixture } }; -BOOST_FIXTURE_TEST_SUITE(ApproxKFNMainTest, ApproxKFNTestFixture); - /** * Check that we can't specify both a reference set and an input model. */ -BOOST_AUTO_TEST_CASE(ApproxKFNRefModelTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNRefModelTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -61,14 +60,15 @@ BOOST_AUTO_TEST_CASE(ApproxKFNRefModelTest) // Input pre-trained model. 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 can't specify an invalid k. */ -BOOST_AUTO_TEST_CASE(ApproxKFNInvalidKTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNInvalidKTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(ApproxKFNInvalidKTest) SetInputParam("k", (int) 81); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -86,7 +86,8 @@ BOOST_AUTO_TEST_CASE(ApproxKFNInvalidKTest) * Make sure that the dimensions of neighbors and distances is correct given a * value of k. */ -BOOST_AUTO_TEST_CASE(ApproxKFNOutputDimensionTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNOutputDimensionTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -98,18 +99,19 @@ BOOST_AUTO_TEST_CASE(ApproxKFNOutputDimensionTest) mlpackMain(); // Check the neighbors matrix has 10 points for each of the 80 input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("neighbors").n_rows, 10); - BOOST_REQUIRE_EQUAL(IO::GetParam>("neighbors").n_cols, 80); + REQUIRE(IO::GetParam>("neighbors").n_rows == 10); + REQUIRE(IO::GetParam>("neighbors").n_cols == 80); // Check the distances matrix has 10 points for each of the 80 input points. - BOOST_REQUIRE_EQUAL(IO::GetParam("distances").n_rows, 10); - BOOST_REQUIRE_EQUAL(IO::GetParam("distances").n_cols, 80); + REQUIRE(IO::GetParam("distances").n_rows == 10); + REQUIRE(IO::GetParam("distances").n_cols == 80); } /** * Check that we can't specify an invalid algorithm. */ -BOOST_AUTO_TEST_CASE(ApproxKFNInvalidAlgorithmTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNInvalidAlgorithmTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -118,14 +120,15 @@ BOOST_AUTO_TEST_CASE(ApproxKFNInvalidAlgorithmTest) SetInputParam("algorithm", (string) "any_algo"); // Invalid. 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 can't specify num_projections as zero. */ -BOOST_AUTO_TEST_CASE(ApproxKFNZeroNumProjTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNZeroNumProjTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -135,14 +138,15 @@ BOOST_AUTO_TEST_CASE(ApproxKFNZeroNumProjTest) SetInputParam("num_projections", (int) 0); // Invalid. 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 can't specify num_projections as negative. */ -BOOST_AUTO_TEST_CASE(ApproxKFNNegativeNumProjTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNegativeNumProjTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -152,14 +156,15 @@ BOOST_AUTO_TEST_CASE(ApproxKFNNegativeNumProjTest) SetInputParam("num_projections", (int) -5); // Invalid. 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 can't specify num_tables as zero. */ -BOOST_AUTO_TEST_CASE(ApproxKFNZeroNumTablesTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNZeroNumTablesTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -169,14 +174,15 @@ BOOST_AUTO_TEST_CASE(ApproxKFNZeroNumTablesTest) SetInputParam("num_tables", (int) 0); // Invalid. 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 can't specify num_tables as negative. */ -BOOST_AUTO_TEST_CASE(ApproxKFNNegativeNumTablesTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNegativeNumTablesTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -186,14 +192,15 @@ BOOST_AUTO_TEST_CASE(ApproxKFNNegativeNumTablesTest) SetInputParam("num_tables", (int) -5); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Ensuring that a saved model can be loaded and used again correctly. */ -BOOST_AUTO_TEST_CASE(ApproxKFNModelReuseTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNModelReuseTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -236,7 +243,8 @@ BOOST_AUTO_TEST_CASE(ApproxKFNModelReuseTest) /** * Ensuring that num_tables has some effects on output. */ -BOOST_AUTO_TEST_CASE(ApproxKFNNumTablesChangeTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNumTablesChangeTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -285,7 +293,8 @@ BOOST_AUTO_TEST_CASE(ApproxKFNNumTablesChangeTest) /** * Ensuring that num_projections has some effects on output. */ -BOOST_AUTO_TEST_CASE(ApproxKFNNumProjectionsChangeTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNNumProjectionsChangeTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -333,7 +342,8 @@ BOOST_AUTO_TEST_CASE(ApproxKFNNumProjectionsChangeTest) /** * Make sure that the dimensions of the exact distances matrix are correct. */ -BOOST_AUTO_TEST_CASE(ApproxKFNExactDistDimensionTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNExactDistDimensionTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(2, 80); // 80 points in 2 dimensions. @@ -351,15 +361,16 @@ BOOST_AUTO_TEST_CASE(ApproxKFNExactDistDimensionTest) SetInputParam("exact_distances", std::move(exactDistances)); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** - * Make sure that the two strategie (Drusilla Select and QDAFN) output different - * results. + * Make sure that the two strategie (Drusilla Select and QDAFN) output + * different results. */ -BOOST_AUTO_TEST_CASE(ApproxKFNDifferentAlgoTest) +TEST_CASE_METHOD(ApproxKFNTestFixture, "ApproxKFNDifferentAlgoTest", + "[ApproxKFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(6, 100); // 100 points in 6 dimensions. @@ -402,5 +413,3 @@ BOOST_AUTO_TEST_CASE(ApproxKFNDifferentAlgoTest) CheckMatricesNotEqual(firstOutputDistances, secondOutputDistances); CheckMatricesNotEqual(firstOutputNeighbors, secondOutputNeighbors); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/bayesian_linear_regression_test.cpp b/src/mlpack/tests/main_tests/bayesian_linear_regression_test.cpp new file mode 100644 index 0000000000..e1b6773a5e --- /dev/null +++ b/src/mlpack/tests/main_tests/bayesian_linear_regression_test.cpp @@ -0,0 +1,143 @@ +/** + * @file tests/main_tests/bayesian_linear_regression_test.cpp + * @author Clement Mercier + * + * Test mlpackMain() of bayesian_linear_regression_main.cpp. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#include + +#define BINDING_TYPE BINDING_TYPE_TEST +static const std::string testName = "BayesianLinearRegression"; + +#include +#include +#include "test_helper.hpp" +#include + +#include +#include "../test_tools.hpp" + +using namespace mlpack; + +struct BRTestFixture +{ + public: + BRTestFixture() + { + // Cache in the options for this program. + IO::RestoreSettings(testName); + } + + ~BRTestFixture() + { + // Clear the settings. + bindings::tests::CleanMemory(); + IO::ClearSettings(); + } +}; + +BOOST_FIXTURE_TEST_SUITE(BayesianLinearRegressionMainTest, BRTestFixture); + +/** + * Check the center and scale options. + */ +BOOST_AUTO_TEST_CASE(BRCenter0Scale0) +{ + int n = 50, m = 4; + arma::mat matX = arma::randu(m, n); + arma::rowvec omega = arma::randu(m); + arma::rowvec y = omega * matX; + + SetInputParam("input", std::move(matX)); + SetInputParam("responses", std::move(y)); + SetInputParam("center", false); + + mlpackMain(); + + BayesianLinearRegression* estimator = + IO::GetParam("output_model"); + + BOOST_REQUIRE(estimator->DataOffset().n_elem == 0); + BOOST_REQUIRE(estimator->DataScale().n_elem == 0); +} + +/** + * Check predictions of saved model and in code model are equal. + */ +BOOST_AUTO_TEST_CASE(BayesianLinearRegressionSavedEqualCode) +{ + int n = 10, m = 4; + arma::mat matX = arma::randu(m, n); + arma::mat matXtest = arma::randu(m, 2 * n); + const arma::rowvec omega = arma::randu(m); + arma::rowvec y = omega * matX; + + BayesianLinearRegression model; + model.Train(matX, y); + + arma::rowvec responses; + model.Predict(matXtest, responses); + + SetInputParam("input", std::move(matX)); + SetInputParam("responses", std::move(y)); + + mlpackMain(); + + IO::GetSingleton().Parameters()["input"].wasPassed = false; + IO::GetSingleton().Parameters()["responses"].wasPassed = false; + + SetInputParam("input_model", + IO::GetParam("output_model")); + SetInputParam("test", std::move(matXtest)); + + mlpackMain(); + + arma::mat ytest = std::move(responses); + // Check that initial output and output using saved model are same. + CheckMatrices(ytest, IO::GetParam("predictions")); +} + +/** + * Check a crash happens if neither input or input_model are specified. + * Check a crash happens if both input and input_model are specified. + */ +BOOST_AUTO_TEST_CASE(CheckParamsPassed) +{ + int n = 10, m = 4; + arma::mat matX = arma::randu(m, n); + arma::mat matXtest = arma::randu(m, 2 * n); + const arma::rowvec omega = arma::randu(m); + arma::rowvec y = omega * matX; + + BayesianLinearRegression model; + model.Train(matX, y); + + arma::rowvec responses; + model.Predict(matXtest, responses); + + // Check that std::runtime_error is thrown if neither input or input_model + // is specified. + SetInputParam("responses", std::move(y)); + + BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + + // Continue only with input passed. + SetInputParam("input", std::move(matX)); + mlpackMain(); + + // Now pass the previous trained model and one input matrix at the same time. + // An error should occur. + SetInputParam("input", std::move(matX)); + SetInputParam("input_model", + IO::GetParam("output_model")); + SetInputParam("test", std::move(matXtest)); + + BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/decision_stump_test.cpp b/src/mlpack/tests/main_tests/decision_stump_test.cpp index 8f6c77f05b..8919a7b973 100644 --- a/src/mlpack/tests/main_tests/decision_stump_test.cpp +++ b/src/mlpack/tests/main_tests/decision_stump_test.cpp @@ -18,8 +18,8 @@ static const std::string testName = "DecisionStump"; #include #include "test_helper.hpp" -#include -#include "../test_tools.hpp" +#include "../test_catch_tools.hpp" +#include "../catch.hpp" using namespace mlpack; @@ -40,17 +40,16 @@ struct DecisionStumpTestFixture } }; -BOOST_FIXTURE_TEST_SUITE(DecisionStumpMainTest, DecisionStumpTestFixture); - /** * Ensure that we get desired dimensions when both training * data and labels are passed. */ -BOOST_AUTO_TEST_CASE(DecisionStumpOutputDimensionTest) +TEST_CASE_METHOD(DecisionStumpTestFixture, "DecisionStumpOutputDimensionTest", + "[DecisionStumpMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) - BOOST_FAIL("Cannot load train dataset trainSet.csv!"); + FAIL("Cannot load train dataset trainSet.csv!"); // Get the labels out. arma::Row labels(inputData.n_cols); @@ -62,7 +61,7 @@ BOOST_AUTO_TEST_CASE(DecisionStumpOutputDimensionTest) arma::mat testData; if (!data::Load("testSet.csv", testData)) - BOOST_FAIL("Cannot load test dataset testSet.csv!"); + FAIL("Cannot load test dataset testSet.csv!"); // Delete the last row containing labels from test dataset. testData.shed_row(testData.n_rows - 1); @@ -79,12 +78,10 @@ BOOST_AUTO_TEST_CASE(DecisionStumpOutputDimensionTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); // Check prediction have only single row. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_rows, - 1); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); } /** @@ -92,12 +89,14 @@ BOOST_AUTO_TEST_CASE(DecisionStumpOutputDimensionTest) * when labels are not passed specifically and results * are same from both label and labeless models. */ -BOOST_AUTO_TEST_CASE(DecisionStumpLabelsLessDimensionTest) +TEST_CASE_METHOD(DecisionStumpTestFixture, + "DecisionStumpLabelsLessDimensionTest", + "[DecisionStumpMainTest][BindingTests]") { // Train DS without providing labels. arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) - BOOST_FAIL("Cannot load train dataset trainSet.csv!"); + FAIL("Cannot load train dataset trainSet.csv!"); // Get the labels out. arma::Row labels(inputData.n_cols); @@ -106,7 +105,7 @@ BOOST_AUTO_TEST_CASE(DecisionStumpLabelsLessDimensionTest) arma::mat testData; if (!data::Load("testSet.csv", testData)) - BOOST_FAIL("Cannot load test dataset testSet.csv!"); + FAIL("Cannot load test dataset testSet.csv!"); // Delete the last row containing labels from test dataset. testData.shed_row(testData.n_rows - 1); @@ -122,12 +121,10 @@ BOOST_AUTO_TEST_CASE(DecisionStumpLabelsLessDimensionTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); // Check prediction have only single row. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_rows, - 1); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); // Reset data passed. IO::GetSingleton().Parameters()["training"].wasPassed = false; @@ -154,12 +151,10 @@ BOOST_AUTO_TEST_CASE(DecisionStumpLabelsLessDimensionTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); // Check prediction have only single row. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_rows, - 1); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); // Check that initial output and final output matrix // from two models are same. @@ -169,15 +164,16 @@ BOOST_AUTO_TEST_CASE(DecisionStumpLabelsLessDimensionTest) /** * Ensure that saved model can be used again. */ -BOOST_AUTO_TEST_CASE(DecisionStumpModelReuseTest) +TEST_CASE_METHOD(DecisionStumpTestFixture, "DecisionStumpModelReuseTest", + "[DecisionStumpMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) - BOOST_FAIL("Cannot load train dataset trainSet.csv!"); + FAIL("Cannot load train dataset trainSet.csv!"); arma::mat testData; if (!data::Load("testSet.csv", testData)) - BOOST_FAIL("Cannot load test dataset testSet.csv!"); + FAIL("Cannot load test dataset testSet.csv!"); // Delete the last row containing labels from test dataset. testData.shed_row(testData.n_rows - 1); @@ -207,12 +203,10 @@ BOOST_AUTO_TEST_CASE(DecisionStumpModelReuseTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); // Check predictions have only single row. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_rows, - 1); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); // Check that initial predictions and final predicitons matrix // using saved model are same. @@ -222,29 +216,31 @@ BOOST_AUTO_TEST_CASE(DecisionStumpModelReuseTest) /** * Ensure that bucket_size is always positive. */ -BOOST_AUTO_TEST_CASE(DecisionStumpBucketSizeTest) +TEST_CASE_METHOD(DecisionStumpTestFixture, "DecisionStumpBucketSizeTest", + "[DecisionStumpMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) - BOOST_FAIL("Cannot load train dataset trainSet.csv!"); + FAIL("Cannot load train dataset trainSet.csv!"); // Input training data. SetInputParam("training", std::move(inputData)); SetInputParam("bucket_size", (int) 0); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Make sure only one of training data or pre-trained model is passed. */ -BOOST_AUTO_TEST_CASE(DecisionStumpTrainingVerTest) +TEST_CASE_METHOD(DecisionStumpTestFixture, "DecisionStumpTrainingVerTest", + "[DecisionStumpMainTest][BindingTests]") { arma::mat inputData; if (!data::Load("trainSet.csv", inputData)) - BOOST_FAIL("Cannot load train dataset trainSet.csv!"); + FAIL("Cannot load train dataset trainSet.csv!"); // Input training data. SetInputParam("training", std::move(inputData)); @@ -256,8 +252,6 @@ BOOST_AUTO_TEST_CASE(DecisionStumpTrainingVerTest) std::move(IO::GetParam("output_model"))); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/decision_tree_test.cpp b/src/mlpack/tests/main_tests/decision_tree_test.cpp index e833d46217..a7c7ae9fa4 100644 --- a/src/mlpack/tests/main_tests/decision_tree_test.cpp +++ b/src/mlpack/tests/main_tests/decision_tree_test.cpp @@ -18,8 +18,8 @@ static const std::string testName = "DecisionTree"; #include #include "test_helper.hpp" -#include -#include "../test_tools.hpp" +#include "../test_catch_tools.hpp" +#include "../catch.hpp" using namespace mlpack; using namespace data; @@ -47,30 +47,28 @@ void ResetDTSettings() IO::RestoreSettings(testName); } -BOOST_FIXTURE_TEST_SUITE(DecisionTreeMainTest, - DecisionTreeTestFixture); - /** * Check that number of output points and * number of input points are equal. */ -BOOST_AUTO_TEST_CASE(DecisionTreeOutputDimensionTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionTreeOutputDimensionTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); 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; @@ -85,39 +83,38 @@ BOOST_AUTO_TEST_CASE(DecisionTreeOutputDimensionTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); + REQUIRE(IO::GetParam("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>("predictions").n_rows, 1); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_rows, 3); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); + REQUIRE(IO::GetParam("probabilities").n_rows == 3); } /** * Check that number of output points and number * of input points are equal for categorical dataset. */ -BOOST_AUTO_TEST_CASE(DecisionTreeCategoricalOutputDimensionTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, + "DecisionTreeCategoricalOutputDimensionTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); 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; @@ -132,31 +129,29 @@ BOOST_AUTO_TEST_CASE(DecisionTreeCategoricalOutputDimensionTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); + REQUIRE(IO::GetParam("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>("predictions").n_rows, 1); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_rows, 6); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); + REQUIRE(IO::GetParam("probabilities").n_rows == 6); } /** * Make sure minimum leaf size is always a non-negative number. */ -BOOST_AUTO_TEST_CASE(DecisionTreeMinimumLeafSizeTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionTreeMinimumLeafSizeTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); @@ -169,23 +164,25 @@ BOOST_AUTO_TEST_CASE(DecisionTreeMinimumLeafSizeTest) SetInputParam("minimum_leaf_size", (int) -1); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Make sure maximum depth is always a non-negative number. */ -BOOST_AUTO_TEST_CASE(DecisionTreeNonNegativeMaximumDepthTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, + "DecisionTreeNonNegativeMaximumDepthTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); @@ -198,23 +195,24 @@ BOOST_AUTO_TEST_CASE(DecisionTreeNonNegativeMaximumDepthTest) SetInputParam("maximum_depth", (int) -1); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Make sure minimum gain split is always a fraction in range [0,1]. */ -BOOST_AUTO_TEST_CASE(DecisionMinimumGainSplitTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionMinimumGainSplitTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); @@ -227,23 +225,24 @@ BOOST_AUTO_TEST_CASE(DecisionMinimumGainSplitTest) SetInputParam("minimum_gain_split", 1.5); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Make sure minimum gain split produces regularised tree. */ -BOOST_AUTO_TEST_CASE(DecisionRegularisationTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionRegularisationTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); @@ -277,36 +276,37 @@ BOOST_AUTO_TEST_CASE(DecisionRegularisationTest) predRegularised = std::move(IO::GetParam>("predictions")); size_t count = 0; - BOOST_REQUIRE_EQUAL(pred.n_elem, predRegularised.n_elem); + REQUIRE(pred.n_elem == predRegularised.n_elem); for (size_t i = 0; i < pred.n_elem; ++i) { if (pred[i] != predRegularised[i]) count++; } - BOOST_REQUIRE_GT(count, 0); + REQUIRE(count > 0); } /** * Ensure that saved model can be used again. */ -BOOST_AUTO_TEST_CASE(DecisionModelReuseTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionModelReuseTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); 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; @@ -339,16 +339,13 @@ BOOST_AUTO_TEST_CASE(DecisionModelReuseTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); + REQUIRE(IO::GetParam("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predicitions. - BOOST_REQUIRE_EQUAL( - IO::GetParam>("predictions").n_rows, 1); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_rows, 3); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); + REQUIRE(IO::GetParam("probabilities").n_rows == 3); // Check that initial predictions and predictions using saved model are same. CheckMatrices(predictions, IO::GetParam>("predictions")); @@ -358,16 +355,17 @@ BOOST_AUTO_TEST_CASE(DecisionModelReuseTest) /** * Make sure only one of training data or pre-trained model is passed. */ -BOOST_AUTO_TEST_CASE(DecisionTreeTrainingVerTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionTreeTrainingVerTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); @@ -388,30 +386,31 @@ BOOST_AUTO_TEST_CASE(DecisionTreeTrainingVerTest) SetInputParam("input_model", model); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /** * Ensure that saved model trained on categorical dataset can be used again. */ -BOOST_AUTO_TEST_CASE(DecisionModelCategoricalReuseTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionModelCategoricalReuseTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); 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; @@ -448,16 +447,13 @@ BOOST_AUTO_TEST_CASE(DecisionModelCategoricalReuseTest) mlpackMain(); // Check that number of output points are equal to number of input points. - BOOST_REQUIRE_EQUAL(IO::GetParam>("predictions").n_cols, - testSize); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_cols, - testSize); + REQUIRE(IO::GetParam>("predictions").n_cols == testSize); + REQUIRE(IO::GetParam("probabilities").n_cols == testSize); // Check number of output rows equals number of classes in case of // probabilities and 1 for predicitions. - BOOST_REQUIRE_EQUAL( - IO::GetParam>("predictions").n_rows, 1); - BOOST_REQUIRE_EQUAL(IO::GetParam("probabilities").n_rows, 6); + REQUIRE(IO::GetParam>("predictions").n_rows == 1); + REQUIRE(IO::GetParam("probabilities").n_rows == 6); // Check that initial predictions and predictions using saved model are same. CheckMatrices(predictions, IO::GetParam>("predictions")); @@ -467,23 +463,24 @@ BOOST_AUTO_TEST_CASE(DecisionModelCategoricalReuseTest) /** * Check that different maximum depths give different results. */ -BOOST_AUTO_TEST_CASE(DecisionTreeMaximumDepthTest) +TEST_CASE_METHOD(DecisionTreeTestFixture, "DecisionTreeMaximumDepthTest", + "[DecisionTreeMainTest][BindingTests]") { 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 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"); // Initialize an all-ones weight matrix. arma::mat weights(1, labels.n_cols, arma::fill::ones); 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)); @@ -516,5 +513,3 @@ BOOST_AUTO_TEST_CASE(DecisionTreeMaximumDepthTest) CheckMatricesNotEqual(predictions, IO::GetParam>("predictions")); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/kfn_test.cpp b/src/mlpack/tests/main_tests/kfn_test.cpp index 3d6999f4b0..2446c85fce 100644 --- a/src/mlpack/tests/main_tests/kfn_test.cpp +++ b/src/mlpack/tests/main_tests/kfn_test.cpp @@ -20,8 +20,8 @@ static const std::string testName = "K-FurthestNeighborsSearch"; #include "test_helper.hpp" #include -#include -#include "../test_tools.hpp" +#include "../test_catch_tools.hpp" +#include "../catch.hpp" using namespace mlpack; @@ -42,13 +42,12 @@ struct KFNTestFixture } }; -BOOST_FIXTURE_TEST_SUITE(KFNMainTest, KFNTestFixture); - /* * Check that we can't provide reference and query matrices * with different dimensions. */ -BOOST_AUTO_TEST_CASE(KFNEqualDimensionTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNEqualDimensionTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -65,7 +64,7 @@ BOOST_AUTO_TEST_CASE(KFNEqualDimensionTest) SetInputParam("k", (int) 10); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -73,7 +72,8 @@ BOOST_AUTO_TEST_CASE(KFNEqualDimensionTest) * Check that we can't specify an invalid k when only reference * matrix is given. */ -BOOST_AUTO_TEST_CASE(KFNInvalidKTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidKTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(KFNInvalidKTest) SetInputParam("k", (int) 101); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); delete IO::GetParam("output_model"); IO::GetParam("output_model") = NULL; @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(KFNInvalidKTest) // SetInputParam("reference", referenceData); // SetInputParam("k", (int) 0); // Invalid. - // BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + // REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); // IO::GetSingleton().Parameters()["reference"].wasPassed = false; // IO::GetSingleton().Parameters()["k"].wasPassed = false; @@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(KFNInvalidKTest) SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) -1); // Invalid. - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -110,7 +110,8 @@ BOOST_AUTO_TEST_CASE(KFNInvalidKTest) * Check that we can't specify an invalid k when both reference * and query matrices are given. */ -BOOST_AUTO_TEST_CASE(KFNInvalidKQueryDataTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidKQueryDataTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -124,14 +125,15 @@ BOOST_AUTO_TEST_CASE(KFNInvalidKQueryDataTest) SetInputParam("k", (int) 101); 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 can't specify a negative leaf size. */ -BOOST_AUTO_TEST_CASE(KFNLeafSizeTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNLeafSizeTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -141,14 +143,15 @@ BOOST_AUTO_TEST_CASE(KFNLeafSizeTest) SetInputParam("leaf_size", (int) -1); // Invalid. 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 can't pass both input_model and reference matrix. */ -BOOST_AUTO_TEST_CASE(KFNRefModelTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNRefModelTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -164,14 +167,15 @@ BOOST_AUTO_TEST_CASE(KFNRefModelTest) std::move(IO::GetParam("output_model"))); 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 can't pass an invalid tree type. */ -BOOST_AUTO_TEST_CASE(KFNInvalidTreeTypeTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidTreeTypeTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -182,14 +186,15 @@ BOOST_AUTO_TEST_CASE(KFNInvalidTreeTypeTest) SetInputParam("tree_type", (string) "min-rp"); // Invalid. 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 can't pass an invalid algorithm. */ -BOOST_AUTO_TEST_CASE(KFNInvalidAlgoTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidAlgoTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -200,14 +205,15 @@ BOOST_AUTO_TEST_CASE(KFNInvalidAlgoTest) SetInputParam("algorithm", (string) "triple_tree"); // Invalid. 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 can't pass an invalid value of epsilon. */ -BOOST_AUTO_TEST_CASE(KFNInvalidEpsilonTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidEpsilonTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -218,7 +224,7 @@ BOOST_AUTO_TEST_CASE(KFNInvalidEpsilonTest) SetInputParam("epsilon", (double) -1); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); IO::GetSingleton().Parameters()["reference"].wasPassed = false; IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; @@ -226,7 +232,7 @@ BOOST_AUTO_TEST_CASE(KFNInvalidEpsilonTest) SetInputParam("reference", std::move(referenceData)); SetInputParam("epsilon", (double) 2); // Invalid. - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); IO::GetSingleton().Parameters()["reference"].wasPassed = false; IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; @@ -234,14 +240,15 @@ BOOST_AUTO_TEST_CASE(KFNInvalidEpsilonTest) SetInputParam("reference", std::move(referenceData)); SetInputParam("epsilon", (double) 1); // Invalid. - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } /* * Check that we can't pass an invalid value of percentage. */ -BOOST_AUTO_TEST_CASE(KFNInvalidPercentageTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNInvalidPercentageTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -252,7 +259,7 @@ BOOST_AUTO_TEST_CASE(KFNInvalidPercentageTest) SetInputParam("percentage", (double) -1); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); IO::GetSingleton().Parameters()["reference"].wasPassed = false; IO::GetSingleton().Parameters()["percentage"].wasPassed = false; @@ -260,7 +267,7 @@ BOOST_AUTO_TEST_CASE(KFNInvalidPercentageTest) SetInputParam("reference", std::move(referenceData)); SetInputParam("percentage", (double) 0); // Invalid. - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); IO::GetSingleton().Parameters()["reference"].wasPassed = false; IO::GetSingleton().Parameters()["epsilon"].wasPassed = false; @@ -268,7 +275,7 @@ BOOST_AUTO_TEST_CASE(KFNInvalidPercentageTest) SetInputParam("reference", std::move(referenceData)); SetInputParam("percentage", (double) 2); // Invalid. - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -276,7 +283,8 @@ BOOST_AUTO_TEST_CASE(KFNInvalidPercentageTest) * Make sure that dimensions of the neighbors and distances * matrices are correct given a value of k. */ -BOOST_AUTO_TEST_CASE(KFNOutputDimensionTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNOutputDimensionTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -288,20 +296,19 @@ BOOST_AUTO_TEST_CASE(KFNOutputDimensionTest) mlpackMain(); // Check the neighbors matrix has 4 points for each input point. - BOOST_REQUIRE_EQUAL(IO::GetParam> - ("neighbors").n_rows, 10); - BOOST_REQUIRE_EQUAL(IO::GetParam> - ("neighbors").n_cols, 100); + REQUIRE(IO::GetParam>("neighbors").n_rows == 10); + REQUIRE(IO::GetParam>("neighbors").n_cols == 100); // Check the distances matrix has 4 points for each input point. - BOOST_REQUIRE_EQUAL(IO::GetParam("distances").n_rows, 10); - BOOST_REQUIRE_EQUAL(IO::GetParam("distances").n_cols, 100); + REQUIRE(IO::GetParam("distances").n_rows == 10); + REQUIRE(IO::GetParam("distances").n_cols == 100); } /** * Ensure that saved model can be used again. */ -BOOST_AUTO_TEST_CASE(KFNModelReuseTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNModelReuseTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -344,7 +351,8 @@ BOOST_AUTO_TEST_CASE(KFNModelReuseTest) * Ensure that changing the value of epsilon gives us different * approximate KFN results. */ -BOOST_AUTO_TEST_CASE(KFNDifferentEpsilonTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNDifferentEpsilonTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 1000); // 1000 points in 3 dimensions. @@ -381,7 +389,8 @@ BOOST_AUTO_TEST_CASE(KFNDifferentEpsilonTest) * Ensure that changing the value of percentage gives us different * approximate KFN results. */ -BOOST_AUTO_TEST_CASE(KFNDifferentPercentageTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNDifferentPercentageTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 1000); // 1000 points in 3 dimensions. @@ -418,7 +427,8 @@ BOOST_AUTO_TEST_CASE(KFNDifferentPercentageTest) * Ensure that we get different results on running twice in greedy * search mode when random_basis is specified. */ -BOOST_AUTO_TEST_CASE(KFNRandomBasisTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNRandomBasisTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 1000); // 1000 points in 3 dimensions. @@ -434,8 +444,7 @@ BOOST_AUTO_TEST_CASE(KFNRandomBasisTest) arma::mat distances; neighbors = std::move(IO::GetParam>("neighbors")); distances = std::move(IO::GetParam("distances")); - BOOST_REQUIRE_EQUAL(IO::GetParam("output_model")->RandomBasis(), - true); + REQUIRE(IO::GetParam("output_model")->RandomBasis() == true); bindings::tests::CleanMemory(); @@ -448,15 +457,15 @@ BOOST_AUTO_TEST_CASE(KFNRandomBasisTest) CheckMatrices(neighbors, IO::GetParam>("neighbors")); CheckMatrices(distances, IO::GetParam("distances")); - BOOST_REQUIRE_EQUAL(IO::GetParam("output_model")->RandomBasis(), - false); + REQUIRE(IO::GetParam("output_model")->RandomBasis() == false); } /* * Ensure that the program runs successfully when we pass true_neighbors * and/or true_distances and fails when those matrices have the wrong shape. */ -BOOST_AUTO_TEST_CASE(KFNTrueNeighborDistanceTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNTrueNeighborDistanceTest", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -480,7 +489,7 @@ BOOST_AUTO_TEST_CASE(KFNTrueNeighborDistanceTest) SetInputParam("true_distances", distances); SetInputParam("epsilon", (double) 0.5); - BOOST_REQUIRE_NO_THROW(mlpackMain()); + REQUIRE_NOTHROW(mlpackMain()); // True output matrices have incorrect shape. arma::Mat dummyNeighbors; @@ -500,7 +509,7 @@ BOOST_AUTO_TEST_CASE(KFNTrueNeighborDistanceTest) SetInputParam("true_distances", std::move(dummyDistances)); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -508,7 +517,8 @@ BOOST_AUTO_TEST_CASE(KFNTrueNeighborDistanceTest) * Ensure that different search algorithms give same result. * We do not consider greedy because it is an approximate algorithm. */ -BOOST_AUTO_TEST_CASE(KFNAllAlgorithmsTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNAllAlgorithmsTest", + "[KFNMainTest][BindingTests]") { string algorithms[] = {"dual_tree", "naive", "single_tree"}; const int nofalgorithms = 3; @@ -566,7 +576,8 @@ BOOST_AUTO_TEST_CASE(KFNAllAlgorithmsTest) /* * Ensure that different tree types give same result. */ -BOOST_AUTO_TEST_CASE(KFNAllTreeTypesTest) +TEST_CASE_METHOD(KFNTestFixture, "KFNAllTreeTypesTest", + "[KFNMainTest][BindingTests]") { string treetypes[] = {"kd", "vp", "rp", "max-rp", "ub", "cover", "r", "r-star", "x", "ball", "hilbert-r", "r-plus", "r-plus-plus", @@ -626,7 +637,8 @@ BOOST_AUTO_TEST_CASE(KFNAllTreeTypesTest) /** * Ensure that different leaf sizes give different results. */ -BOOST_AUTO_TEST_CASE(KFNDifferentLeafSizes) +TEST_CASE_METHOD(KFNTestFixture, "KFNDifferentLeafSizes", + "[KFNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -638,8 +650,7 @@ BOOST_AUTO_TEST_CASE(KFNDifferentLeafSizes) mlpackMain(); - BOOST_CHECK_EQUAL(IO::GetParam("output_model")->LeafSize(), - (int) 1); + REQUIRE(IO::GetParam("output_model")->LeafSize() == (int) 1); bindings::tests::CleanMemory(); @@ -655,8 +666,5 @@ BOOST_AUTO_TEST_CASE(KFNDifferentLeafSizes) // Check that initial output matrices and the output matrices using // saved model are equal. - BOOST_CHECK_EQUAL(IO::GetParam("output_model")->LeafSize(), - (int) 10); + REQUIRE(IO::GetParam("output_model")->LeafSize() == (int) 10); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/main_tests/knn_test.cpp b/src/mlpack/tests/main_tests/knn_test.cpp index 522f96aa44..f6096b2d80 100644 --- a/src/mlpack/tests/main_tests/knn_test.cpp +++ b/src/mlpack/tests/main_tests/knn_test.cpp @@ -20,8 +20,8 @@ static const std::string testName = "K-NearestNeighborsSearch"; #include "test_helper.hpp" #include -#include -#include "../test_tools.hpp" +#include "../test_catch_tools.hpp" +#include "../catch.hpp" using namespace mlpack; @@ -42,13 +42,12 @@ struct KNNTestFixture } }; -BOOST_FIXTURE_TEST_SUITE(KNNMainTest, KNNTestFixture); - /* * Check that we can't provide reference and query matrices * with different dimensions. */ -BOOST_AUTO_TEST_CASE(KNNEqualDimensionTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNEqualDimensionTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -65,7 +64,7 @@ BOOST_AUTO_TEST_CASE(KNNEqualDimensionTest) SetInputParam("k", (int) 10); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -73,7 +72,8 @@ BOOST_AUTO_TEST_CASE(KNNEqualDimensionTest) * Check that we can't specify an invalid k when only reference * matrix is given. */ -BOOST_AUTO_TEST_CASE(KNNInvalidKTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidKTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(KNNInvalidKTest) SetInputParam("k", (int) 101); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); IO::GetSingleton().Parameters()["reference"].wasPassed = false; IO::GetSingleton().Parameters()["k"].wasPassed = false; @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(KNNInvalidKTest) SetInputParam("reference", std::move(referenceData)); SetInputParam("k", (int) -1); // Invalid. - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -99,7 +99,8 @@ BOOST_AUTO_TEST_CASE(KNNInvalidKTest) * Check that we can't specify an invalid k when both reference * and query matrices are given. */ -BOOST_AUTO_TEST_CASE(KNNInvalidKQueryDataTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidKQueryDataTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -113,14 +114,15 @@ BOOST_AUTO_TEST_CASE(KNNInvalidKQueryDataTest) SetInputParam("k", (int) 101); 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 can't specify a negative leaf size. */ -BOOST_AUTO_TEST_CASE(KNNLeafSizeTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNLeafSizeTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -130,14 +132,15 @@ BOOST_AUTO_TEST_CASE(KNNLeafSizeTest) SetInputParam("leaf_size", (int) -1); // Invalid. 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 can't pass both input_model and reference matrix. */ -BOOST_AUTO_TEST_CASE(KNNRefModelTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNRefModelTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -153,14 +156,15 @@ BOOST_AUTO_TEST_CASE(KNNRefModelTest) std::move(IO::GetParam("output_model"))); 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 can't pass an invalid tree type. */ -BOOST_AUTO_TEST_CASE(KNNInvalidTreeTypeTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidTreeTypeTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -171,14 +175,15 @@ BOOST_AUTO_TEST_CASE(KNNInvalidTreeTypeTest) SetInputParam("tree_type", (string) "min-rp"); // Invalid. 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 can't pass an invalid algorithm. */ -BOOST_AUTO_TEST_CASE(KNNInvalidAlgoTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidAlgoTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -189,14 +194,15 @@ BOOST_AUTO_TEST_CASE(KNNInvalidAlgoTest) SetInputParam("algorithm", (string) "triple_tree"); // Invalid. 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 can't pass an invalid value of epsilon. */ -BOOST_AUTO_TEST_CASE(KNNInvalidEpsilonTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidEpsilonTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -207,14 +213,15 @@ BOOST_AUTO_TEST_CASE(KNNInvalidEpsilonTest) SetInputParam("epsilon", (double) -1); // Invalid. 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 can't pass an invalid value of tau. */ -BOOST_AUTO_TEST_CASE(KNNInvalidTauTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidTauTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -225,14 +232,15 @@ BOOST_AUTO_TEST_CASE(KNNInvalidTauTest) SetInputParam("tau", (double) -1); // Invalid. 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 can't pass an invalid value of rho. */ -BOOST_AUTO_TEST_CASE(KNNInvalidRhoTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNInvalidRhoTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -245,7 +253,7 @@ BOOST_AUTO_TEST_CASE(KNNInvalidRhoTest) SetInputParam("rho", (double) -1); // Invalid. Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); // Reset passed parameters. IO::GetSingleton().Parameters()["reference"].wasPassed = false; @@ -254,7 +262,7 @@ BOOST_AUTO_TEST_CASE(KNNInvalidRhoTest) SetInputParam("reference", std::move(referenceData)); SetInputParam("rho", (double) 1.5); // Invalid. - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -262,7 +270,8 @@ BOOST_AUTO_TEST_CASE(KNNInvalidRhoTest) * Make sure that dimensions of the neighbors and distances matrices are correct * given a value of k. */ -BOOST_AUTO_TEST_CASE(KNNOutputDimensionTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNOutputDimensionTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -274,20 +283,19 @@ BOOST_AUTO_TEST_CASE(KNNOutputDimensionTest) mlpackMain(); // Check the neighbors matrix has 10 points for each input point. - BOOST_REQUIRE_EQUAL(IO::GetParam> - ("neighbors").n_rows, 10); - BOOST_REQUIRE_EQUAL(IO::GetParam> - ("neighbors").n_cols, 100); + REQUIRE(IO::GetParam>("neighbors").n_rows == 10); + REQUIRE(IO::GetParam>("neighbors").n_cols == 100); // Check the distances matrix has 10 points for each input point. - BOOST_REQUIRE_EQUAL(IO::GetParam("distances").n_rows, 10); - BOOST_REQUIRE_EQUAL(IO::GetParam("distances").n_cols, 100); + REQUIRE(IO::GetParam("distances").n_rows == 10); + REQUIRE(IO::GetParam("distances").n_cols == 100); } /** * Ensure that saved model can be used again. */ -BOOST_AUTO_TEST_CASE(KNNModelReuseTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNModelReuseTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -329,7 +337,8 @@ BOOST_AUTO_TEST_CASE(KNNModelReuseTest) * Ensure that changing the value of tau gives us different greedy * spill tree results. */ -BOOST_AUTO_TEST_CASE(KNNDifferentTauTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNDifferentTauTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(6, 1000); // 1000 points in 6 dimensions. @@ -368,7 +377,8 @@ BOOST_AUTO_TEST_CASE(KNNDifferentTauTest) * Ensure that changing the value of rho gives us different greedy * spill tree results. */ -BOOST_AUTO_TEST_CASE(KNNDifferentRhoTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNDifferentRhoTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 1000); // 1000 points in 3 dimensions. @@ -408,7 +418,8 @@ BOOST_AUTO_TEST_CASE(KNNDifferentRhoTest) * Ensure that changing the value of epslion gives us different * approximate KNN results. */ -BOOST_AUTO_TEST_CASE(KNNDifferentEpsilonTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNDifferentEpsilonTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 1000); // 1000 points in 3 dimensions. @@ -445,7 +456,8 @@ BOOST_AUTO_TEST_CASE(KNNDifferentEpsilonTest) * Ensure that we get same results on running twice in dual-tree mode * search mode when random_basis is specified. */ -BOOST_AUTO_TEST_CASE(KNNRandomBasisTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNRandomBasisTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 1000); // 1000 points in 3 dimensions. @@ -462,8 +474,7 @@ BOOST_AUTO_TEST_CASE(KNNRandomBasisTest) arma::mat distances; neighbors = std::move(IO::GetParam>("neighbors")); distances = std::move(IO::GetParam("distances")); - BOOST_REQUIRE_EQUAL(IO::GetParam("output_model")->RandomBasis(), - true); + REQUIRE(IO::GetParam("output_model")->RandomBasis() == true); bindings::tests::CleanMemory(); @@ -476,15 +487,15 @@ BOOST_AUTO_TEST_CASE(KNNRandomBasisTest) CheckMatrices(neighbors, IO::GetParam>("neighbors")); CheckMatrices(distances, IO::GetParam("distances")); - BOOST_REQUIRE_EQUAL(IO::GetParam("output_model")->RandomBasis(), - false); + REQUIRE(IO::GetParam("output_model")->RandomBasis() == false); } /* * Ensure that the program runs successfully when we pass true_neighbors * and/or true_distances and fails when those matrices have the wrong shape. */ -BOOST_AUTO_TEST_CASE(KNNTrueNeighborDistanceTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNTrueNeighborDistanceTest", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -509,7 +520,7 @@ BOOST_AUTO_TEST_CASE(KNNTrueNeighborDistanceTest) SetInputParam("true_distances", distances); SetInputParam("epsilon", (double) 0.5); - BOOST_REQUIRE_NO_THROW(mlpackMain()); + REQUIRE_NOTHROW(mlpackMain()); // True output matrices have incorrect shape. arma::Mat dummyNeighbors; @@ -526,7 +537,7 @@ BOOST_AUTO_TEST_CASE(KNNTrueNeighborDistanceTest) SetInputParam("true_distances", std::move(dummyDistances)); Log::Fatal.ignoreInput = true; - BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error); + REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error); Log::Fatal.ignoreInput = false; } @@ -534,7 +545,8 @@ BOOST_AUTO_TEST_CASE(KNNTrueNeighborDistanceTest) * Ensure that different search algorithms give same result. * We do not consider greedy because it is an approximate algorithm. */ -BOOST_AUTO_TEST_CASE(KNNAllAlgorithmsTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNAllAlgorithmsTest", + "[KNNMainTest][BindingTests]") { string algorithms[] = {"dual_tree", "naive", "single_tree"}; const int nofalgorithms = 3; @@ -592,7 +604,8 @@ BOOST_AUTO_TEST_CASE(KNNAllAlgorithmsTest) /* * Ensure that different tree types give same result. */ -BOOST_AUTO_TEST_CASE(KNNAllTreeTypesTest) +TEST_CASE_METHOD(KNNTestFixture, "KNNAllTreeTypesTest", + "[KNNMainTest][BindingTests]") { // Not including spill for now. string treetypes[] = {"kd", "vp", "rp", "max-rp", "ub", "cover", "r", @@ -653,7 +666,8 @@ BOOST_AUTO_TEST_CASE(KNNAllTreeTypesTest) /** * Ensure that different leaf sizes give different results. */ -BOOST_AUTO_TEST_CASE(KNNDifferentLeafSizes) +TEST_CASE_METHOD(KNNTestFixture, "KNNDifferentLeafSizes", + "[KNNMainTest][BindingTests]") { arma::mat referenceData; referenceData.randu(3, 100); // 100 points in 3 dimensions. @@ -680,10 +694,7 @@ BOOST_AUTO_TEST_CASE(KNNDifferentLeafSizes) // Check that initial output matrices and the output matrices using // saved model are equal. - BOOST_CHECK_EQUAL(output_model->LeafSize(), (int) 1); - BOOST_CHECK_EQUAL(IO::GetParam("output_model")->LeafSize(), - (int) 10); + REQUIRE(output_model->LeafSize() == (int) 1); + REQUIRE(IO::GetParam("output_model")->LeafSize() == (int) 10); delete output_model; } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/metric_test.cpp b/src/mlpack/tests/metric_test.cpp index 92e6834bc3..dffe3211fc 100644 --- a/src/mlpack/tests/metric_test.cpp +++ b/src/mlpack/tests/metric_test.cpp @@ -13,12 +13,13 @@ #include #include #include +#include #include "test_tools.hpp" using namespace std; using namespace mlpack::metric; -BOOST_AUTO_TEST_SUITE(LMetricTest); +BOOST_AUTO_TEST_SUITE(MetricTest); /** * Simple test for L-1 metric. @@ -301,4 +302,62 @@ BOOST_AUTO_TEST_CASE(NMSMetricTest) CheckMatrices(desiredBoundingBox, selectedBoundingBox); } +/** + * + */ +BOOST_AUTO_TEST_CASE(BLEUScoreTest) +{ + typedef typename std::vector WordVector; + std::vector> referenceCorpus + = {{{"this", "is", "my", "house"}, + {"this", "is", "my", "car"}, + {"this", "is", "my", "bike"}}, + + {{"this", "is", "my", "table"}, + {"this", "is", "my", "chair"}, + {"this", "is", "my", "laptop"}}, + + {{"this", "is", "my", "table"}, + {"this", "is", "your", "car"}, + {"this", "is", "my", "notebook"}}}; + + std::vector translationCorpus + = {{"this", "is", "my", "book"}, + {"this", "is", "your", "car"}, + {"this", "is", "my", "watch"}}; + + BLEU<> bleu(4); + + //! 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); + + std::vector 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); + } + + //! 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); + + 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); + } +} + BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/quic_svd_test.cpp b/src/mlpack/tests/quic_svd_test.cpp index 284a42c978..9ae2e33a79 100644 --- a/src/mlpack/tests/quic_svd_test.cpp +++ b/src/mlpack/tests/quic_svd_test.cpp @@ -13,17 +13,14 @@ #include #include -#include -#include "test_tools.hpp" - -BOOST_AUTO_TEST_SUITE(QUICSVDTest); +#include "catch.hpp" using namespace mlpack; /** * The reconstruction error of the obtained SVD should be small. */ -BOOST_AUTO_TEST_CASE(QUICSVDReconstructionError) +TEST_CASE("QUICSVDReconstructionError", "[QUICSVDTest]") { // Load the dataset. arma::mat dataset; @@ -49,13 +46,13 @@ BOOST_AUTO_TEST_CASE(QUICSVDReconstructionError) ++successes; } - BOOST_REQUIRE_GT(successes, 0); + REQUIRE(successes > 0); } /** * The singular value error of the obtained SVD should be small. */ -BOOST_AUTO_TEST_CASE(QUICSVDSingularValueError) +TEST_CASE("QUICSVDSingularValueError", "[QUICSVDTest]") { arma::mat U = arma::randn(3, 20); arma::mat V = arma::randn(10, 3); @@ -80,10 +77,10 @@ BOOST_AUTO_TEST_CASE(QUICSVDSingularValueError) // The sigular value error should be small. double error = arma::norm(s1 - s3); - BOOST_REQUIRE_SMALL(error, 0.1); + REQUIRE(error == Approx(0.0).margin(0.1)); } -BOOST_AUTO_TEST_CASE(QUICSVDSameDimensionTest) +TEST_CASE("QUICSVDSameDimensionTest", "[QUICSVDTest]") { arma::mat dataset = arma::randn(10, 10); @@ -91,5 +88,3 @@ BOOST_AUTO_TEST_CASE(QUICSVDSameDimensionTest) arma::mat u, v, sigma; svd::QUIC_SVD quicsvd(dataset, u, v, sigma); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/randomized_svd_test.cpp b/src/mlpack/tests/randomized_svd_test.cpp index 07371842bf..377a04918a 100644 --- a/src/mlpack/tests/randomized_svd_test.cpp +++ b/src/mlpack/tests/randomized_svd_test.cpp @@ -13,10 +13,7 @@ #include #include -#include -#include "test_tools.hpp" - -BOOST_AUTO_TEST_SUITE(RandomizedSVDTest); +#include "catch.hpp" using namespace mlpack; @@ -24,7 +21,7 @@ using namespace mlpack; * The reconstruction and sigular value error of the obtained SVD should be * small. */ -BOOST_AUTO_TEST_CASE(RandomizedSVDReconstructionError) +TEST_CASE("RandomizedSVDReconstructionError", "[RandomizedSVDTest]") { arma::mat U = arma::randn(3, 20); arma::mat V = arma::randn(10, 3); @@ -54,14 +51,12 @@ BOOST_AUTO_TEST_CASE(RandomizedSVDReconstructionError) // The sigular value error should be small. double error = arma::norm(s2 - s3, "frob") / arma::norm(s2, "frob"); - BOOST_REQUIRE_SMALL(error, 1e-5); + REQUIRE(error == Approx(0.0).margin(1e-5)); arma::mat reconstruct = U2 * arma::diagmat(s2) * V2.t(); // The relative reconstruction error should be small. error = arma::norm(centeredData - reconstruct, "frob") / arma::norm(centeredData, "frob"); - BOOST_REQUIRE_SMALL(error, 1e-5); + REQUIRE(error == Approx(0.0).margin(1e-5)); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/regularized_svd_test.cpp b/src/mlpack/tests/regularized_svd_test.cpp index 32b438b69b..eb412dcd26 100644 --- a/src/mlpack/tests/regularized_svd_test.cpp +++ b/src/mlpack/tests/regularized_svd_test.cpp @@ -14,16 +14,13 @@ #include -#include -#include "test_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::svd; using namespace ens; -BOOST_AUTO_TEST_SUITE(RegularizedSVDTest); - -BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionRandomEvaluate) +TEST_CASE("RegularizedSVDFunctionRandomEvaluate", "[RegularizedSVDTest]") { // Define useful constants. const size_t numUsers = 100; @@ -66,11 +63,12 @@ BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionRandomEvaluate) } // Compare calculated cost and value obtained using Evaluate(). - BOOST_REQUIRE_CLOSE(cost, rSVDFunc.Evaluate(parameters), 1e-5); + REQUIRE(cost == Approx(rSVDFunc.Evaluate(parameters)).epsilon(1e-7)); } } -BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionRegularizationEvaluate) +TEST_CASE("RegularizedSVDFunctionRegularizationEvaluate", + "[RegularizedSVDTest]") { // Define useful constants. const size_t numUsers = 100; @@ -119,14 +117,14 @@ BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionRegularizationEvaluate) // Cost with regularization should be close to the sum of cost without // regularization and the regularization terms. - BOOST_REQUIRE_CLOSE(rSVDFuncNoReg.Evaluate(parameters) + smallRegTerm, - rSVDFuncSmallReg.Evaluate(parameters), 1e-5); - BOOST_REQUIRE_CLOSE(rSVDFuncNoReg.Evaluate(parameters) + bigRegTerm, - rSVDFuncBigReg.Evaluate(parameters), 1e-5); + REQUIRE(rSVDFuncNoReg.Evaluate(parameters) + smallRegTerm == + Approx(rSVDFuncSmallReg.Evaluate(parameters)).epsilon(1e-7)); + REQUIRE(rSVDFuncNoReg.Evaluate(parameters) + bigRegTerm == + Approx(rSVDFuncBigReg.Evaluate(parameters)).epsilon(1e-7)); } } -BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionGradient) +TEST_CASE("RegularizedSVDFunctionGradient", "[RegularizedSVDTest]") { // Define useful constants. const size_t numUsers = 50; @@ -185,19 +183,19 @@ BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionGradient) // Compare numerical and backpropagation gradient values. if (std::abs(gradient1(i, j)) <= 1e-6) - BOOST_REQUIRE_SMALL(numGradient1, 1e-5); + REQUIRE(numGradient1 == Approx(0.0).margin(1e-5)); else - BOOST_REQUIRE_CLOSE(numGradient1, gradient1(i, j), 0.02); + REQUIRE(numGradient1 == Approx(gradient1(i, j)).epsilon(0.0002)); if (std::abs(gradient2(i, j)) <= 1e-6) - BOOST_REQUIRE_SMALL(numGradient2, 1e-5); + REQUIRE(numGradient2 == Approx(0.0).margin(1e-5)); else - BOOST_REQUIRE_CLOSE(numGradient2, gradient2(i, j), 0.02); + REQUIRE(numGradient2 == Approx(gradient2(i, j)).epsilon(0.0002)); } } } -BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionOptimize) +TEST_CASE("RegularizedSVDFunctionOptimize", "[RegularizedSVDTest]") { // Define useful constants. const size_t numUsers = 50; @@ -248,7 +246,7 @@ BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionOptimize) arma::norm(data, "frob"); // Relative error should be small. - BOOST_REQUIRE_SMALL(relativeError, 1e-2); + REQUIRE(relativeError == Approx(0.0).margin(1e-2)); } // The test is only compiled if the user has specified OpenMP to be @@ -256,7 +254,7 @@ BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionOptimize) #ifdef HAS_OPENMP // Test Regularized SVD with parallel SGD. -BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionOptimizeHOGWILD) +TEST_CASE("RegularizedSVDFunctionOptimizeHOGWILD", "[RegularizedSVDTest]") { // Define useful constants. const size_t numUsers = 50; @@ -313,9 +311,7 @@ BOOST_AUTO_TEST_CASE(RegularizedSVDFunctionOptimizeHOGWILD) arma::norm(data, "frob"); // Relative error should be small. - BOOST_REQUIRE_SMALL(relativeError, 1e-2); + REQUIRE(relativeError == Approx(0.0).margin(1e-2)); } #endif - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/serialization_test.cpp b/src/mlpack/tests/serialization_test.cpp index e30fcc4dc9..327786e81c 100644 --- a/src/mlpack/tests/serialization_test.cpp +++ b/src/mlpack/tests/serialization_test.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -1602,4 +1603,34 @@ BOOST_AUTO_TEST_CASE(ssRBMTest) CheckMatrices(Rbm.Weight(), RbmBinary.Weight()); } +// Make sure serialization works for BayesianLinearRegression. +BOOST_AUTO_TEST_CASE(BayesianLinearRegressionTest) +{ + using namespace mlpack::regression; + + // Create a dataset. + arma::mat matX = arma::randn(75, 250); + arma::vec omega = arma::randn(75, 1); + arma::rowvec y = omega.t() * matX; + + BayesianLinearRegression blr(false, false); + blr.Train(matX, y); + arma::vec omegaOpt = blr.Omega(); + + // Now, serialize. + BayesianLinearRegression xmlBlr(false, false), binaryBlr(false, false), + textBlr(false, false); + + SerializeObjectAll(blr, xmlBlr, binaryBlr, textBlr); + + // Now, check that predictions are the same. + arma::rowvec pred, xmlPred, textPred, binaryPred; + blr.Predict(matX, pred); + xmlBlr.Predict(matX, xmlPred); + textBlr.Predict(matX, textPred); + binaryBlr.Predict(matX, binaryPred); + + CheckMatrices(pred, xmlPred, textPred, binaryPred); +} + BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/svd_batch_test.cpp b/src/mlpack/tests/svd_batch_test.cpp index bccea66a88..bac6df4917 100644 --- a/src/mlpack/tests/svd_batch_test.cpp +++ b/src/mlpack/tests/svd_batch_test.cpp @@ -17,10 +17,7 @@ #include #include -#include -#include "test_tools.hpp" - -BOOST_AUTO_TEST_SUITE(SVDBatchTest); +#include "catch.hpp" using namespace std; using namespace mlpack; @@ -30,7 +27,7 @@ using namespace arma; /** * Make sure the SVD Batch lerning is converging. */ -BOOST_AUTO_TEST_CASE(SVDBatchConvergenceElementTest) +TEST_CASE("SVDBatchConvergenceElementTest", "[SVDBatchTest]") { sp_mat data; data.sprandn(100, 100, 0.2); @@ -40,8 +37,8 @@ BOOST_AUTO_TEST_CASE(SVDBatchConvergenceElementTest) mat m1, m2; amf.Apply(data, 2, m1, m2); - BOOST_REQUIRE_NE(amf.TerminationPolicy().Iteration(), - amf.TerminationPolicy().MaxIterations()); + REQUIRE(amf.TerminationPolicy().Iteration() != + amf.TerminationPolicy().MaxIterations()); } //! This is used to ensure we start from the same initial point. @@ -70,7 +67,7 @@ class SpecificRandomInitialization /** * Make sure the momentum is working okay. */ -BOOST_AUTO_TEST_CASE(SVDBatchMomentumTest) +TEST_CASE("SVDBatchMomentumTest", "[SVDBatchTest]") { mat dataset; data::Load("GroupLensSmall.csv", dataset); @@ -111,13 +108,13 @@ BOOST_AUTO_TEST_CASE(SVDBatchMomentumTest) const double momentumRMSE = amf2.Apply(cleanedData, 2, m1, m2); - BOOST_REQUIRE_LE(momentumRMSE, regularRMSE + 0.1); + REQUIRE(momentumRMSE <= regularRMSE + 0.1); } /** * Make sure the regularization is working okay. */ -BOOST_AUTO_TEST_CASE(SVDBatchRegularizationTest) +TEST_CASE("SVDBatchRegularizationTest", "[SVDBatchTest]") { mat dataset; data::Load("GroupLensSmall.csv", dataset); @@ -158,13 +155,13 @@ BOOST_AUTO_TEST_CASE(SVDBatchRegularizationTest) double momentumRMSE = amf2.Apply(cleanedData, 2, m1, m2); - BOOST_REQUIRE_LE(momentumRMSE, regularRMSE + 0.05); + REQUIRE(momentumRMSE <= regularRMSE + 0.05); } /** * Make sure the SVD can factorize matrices with negative entries. */ -BOOST_AUTO_TEST_CASE(SVDBatchNegativeElementTest) +TEST_CASE("SVDBatchNegativeElementTest", "[SVDBatchTest]") { // Create two 5x3 matrices that we should be able to recover. mat testLeft; @@ -189,7 +186,6 @@ BOOST_AUTO_TEST_CASE(SVDBatchNegativeElementTest) arma::mat result = m1 * m2; // 6.5% tolerance on the norm. - BOOST_REQUIRE_CLOSE(arma::norm(test, "fro"), arma::norm(result, "fro"), 9.0); + REQUIRE(arma::norm(test, "fro") == + Approx(arma::norm(result, "fro")).epsilon(0.09)); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/svd_incremental_test.cpp b/src/mlpack/tests/svd_incremental_test.cpp index 50558c6d1e..433a86755f 100644 --- a/src/mlpack/tests/svd_incremental_test.cpp +++ b/src/mlpack/tests/svd_incremental_test.cpp @@ -20,10 +20,7 @@ #include #include -#include -#include "test_tools.hpp" - -BOOST_AUTO_TEST_SUITE(SVDIncrementalTest); +#include "catch.hpp" using namespace std; using namespace mlpack; @@ -33,7 +30,7 @@ using namespace arma; /** * Test for convergence of incomplete incremenal learning. */ -BOOST_AUTO_TEST_CASE(SVDIncompleteIncrementalConvergenceTest) +TEST_CASE("SVDIncompleteIncrementalConvergenceTest", "[SVDIncrementalTest]") { sp_mat data; data.sprandn(100, 100, 0.2); @@ -48,14 +45,14 @@ BOOST_AUTO_TEST_CASE(SVDIncompleteIncrementalConvergenceTest) mat m1, m2; amf.Apply(data, 2, m1, m2); - BOOST_REQUIRE_NE(amf.TerminationPolicy().Iteration(), - amf.TerminationPolicy().MaxIterations()); + REQUIRE(amf.TerminationPolicy().Iteration() != + amf.TerminationPolicy().MaxIterations()); } /** * Test for convergence of complete incremenal learning */ -BOOST_AUTO_TEST_CASE(SVDCompleteIncrementalConvergenceTest) +TEST_CASE("SVDCompleteIncrementalConvergenceTest", "[SVDIncrementalTest]") { sp_mat data; data.sprandn(100, 100, 0.2); @@ -71,8 +68,8 @@ BOOST_AUTO_TEST_CASE(SVDCompleteIncrementalConvergenceTest) mat m1, m2; amf.Apply(data, 2, m1, m2); - BOOST_REQUIRE_NE(amf.TerminationPolicy().Iteration(), - amf.TerminationPolicy().MaxIterations()); + REQUIRE(amf.TerminationPolicy().Iteration() != + amf.TerminationPolicy().MaxIterations()); } //! This is used to ensure we start from the same initial point. @@ -98,7 +95,7 @@ class SpecificRandomInitialization arma::mat H; }; -BOOST_AUTO_TEST_CASE(SVDIncompleteIncrementalRegularizationTest) +TEST_CASE("SVDIncompleteIncrementalRegularizationTest", "[SVDIncrementalTest]") { mat dataset; data::Load("GroupLensSmall.csv", dataset); @@ -143,7 +140,5 @@ BOOST_AUTO_TEST_CASE(SVDIncompleteIncrementalRegularizationTest) mat m3, m4; double regularizedRMSE = amf2.Apply(cleanedData2, 2, m3, m4); - BOOST_REQUIRE_LT(regularizedRMSE, regularRMSE + 0.105); + REQUIRE(regularizedRMSE < regularRMSE + 0.105); } - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/svdplusplus_test.cpp b/src/mlpack/tests/svdplusplus_test.cpp index a7918a259c..dbf1417397 100644 --- a/src/mlpack/tests/svdplusplus_test.cpp +++ b/src/mlpack/tests/svdplusplus_test.cpp @@ -15,15 +15,12 @@ #include -#include -#include "test_tools.hpp" +#include "catch.hpp" using namespace mlpack; using namespace mlpack::svd; -BOOST_AUTO_TEST_SUITE(SVDPlusPlusTest); - -BOOST_AUTO_TEST_CASE(SVDPlusPlusEvaluate) +TEST_CASE("SVDPlusPlusEvaluate", "[SVDPlusPlusTest]") { // Define useful constants. const size_t numUsers = 100; @@ -89,11 +86,11 @@ BOOST_AUTO_TEST_CASE(SVDPlusPlusEvaluate) } // Compare calculated cost and value obtained using Evaluate(). - BOOST_REQUIRE_CLOSE(cost, svdPPFunc.Evaluate(parameters), 1e-5); + REQUIRE(cost == Approx(svdPPFunc.Evaluate(parameters)).epsilon(1e-7)); } } -BOOST_AUTO_TEST_CASE(SVDPlusPlusFunctionRegularizationEvaluate) +TEST_CASE("SVDPlusPlusFunctionRegularizationEvaluate", "[SVDPlusPlusTest]") { // Define useful constants. const size_t numUsers = 100; @@ -173,14 +170,14 @@ BOOST_AUTO_TEST_CASE(SVDPlusPlusFunctionRegularizationEvaluate) // Cost with regularization should be close to the sum of cost without // regularization and the regularization terms. - BOOST_REQUIRE_CLOSE(svdPPFuncNoReg.Evaluate(parameters) + smallRegTerm, - svdPPFuncSmallReg.Evaluate(parameters), 1e-5); - BOOST_REQUIRE_CLOSE(svdPPFuncNoReg.Evaluate(parameters) + bigRegTerm, - svdPPFuncBigReg.Evaluate(parameters), 1e-5); + REQUIRE(svdPPFuncNoReg.Evaluate(parameters) + smallRegTerm == + Approx(svdPPFuncSmallReg.Evaluate(parameters)).epsilon(1e-7)); + REQUIRE(svdPPFuncNoReg.Evaluate(parameters) + bigRegTerm == + Approx(svdPPFuncBigReg.Evaluate(parameters)).epsilon(1e-7)); } } -BOOST_AUTO_TEST_CASE(SVDPlusPlusFunctionGradient) +TEST_CASE("SVDPlusPlusFunctionGradient", "[SVDPlusPlusTest]") { // Define useful constants. const size_t numUsers = 100; @@ -242,19 +239,19 @@ BOOST_AUTO_TEST_CASE(SVDPlusPlusFunctionGradient) // Compare numerical and backpropagation gradient values. if (std::abs(gradient1(i, j)) <= 1e-6) - BOOST_REQUIRE_SMALL(numGradient1, 1e-5); + REQUIRE(numGradient1 == Approx(0.0).margin(1e-5)); else - BOOST_REQUIRE_CLOSE(numGradient1, gradient1(i, j), 0.02); + REQUIRE(numGradient1 == Approx(gradient1(i, j)).epsilon(0.0002)); if (std::abs(gradient2(i, j)) <= 1e-6) - BOOST_REQUIRE_SMALL(numGradient2, 1e-5); + REQUIRE(numGradient2 == Approx(0.0).margin(1e-5)); else - BOOST_REQUIRE_CLOSE(numGradient2, gradient2(i, j), 0.02); + REQUIRE(numGradient2 == Approx(gradient2(i, j)).epsilon(0.0002)); } } } -BOOST_AUTO_TEST_CASE(SVDplusPlusOutputSizeTest) +TEST_CASE("SVDplusPlusOutputSizeTest", "[SVDPlusPlusTest]") { // Load small GroupLens dataset. arma::mat data; @@ -277,17 +274,17 @@ BOOST_AUTO_TEST_CASE(SVDplusPlusOutputSizeTest) itemImplicit); // Check the size of outputs. - BOOST_REQUIRE_EQUAL(itemLatent.n_rows, numItems); - BOOST_REQUIRE_EQUAL(itemLatent.n_cols, rank); - BOOST_REQUIRE_EQUAL(userLatent.n_rows, rank); - BOOST_REQUIRE_EQUAL(userLatent.n_cols, numUsers); - BOOST_REQUIRE_EQUAL(itemBias.n_elem, numItems); - BOOST_REQUIRE_EQUAL(userBias.n_elem, numUsers); - BOOST_REQUIRE_EQUAL(itemImplicit.n_rows, rank); - BOOST_REQUIRE_EQUAL(itemImplicit.n_cols, numItems); + REQUIRE(itemLatent.n_rows == numItems); + REQUIRE(itemLatent.n_cols == rank); + REQUIRE(userLatent.n_rows == rank); + REQUIRE(userLatent.n_cols == numUsers); + REQUIRE(itemBias.n_elem == numItems); + REQUIRE(userBias.n_elem == numUsers); + REQUIRE(itemImplicit.n_rows == rank); + REQUIRE(itemImplicit.n_cols == numItems); } -BOOST_AUTO_TEST_CASE(SVDPlusPlusCleanDataTest) +TEST_CASE("SVDPlusPlusCleanDataTest", "[SVDPlusPlusTest]") { // Load small GroupLens dataset. arma::mat data; @@ -320,21 +317,21 @@ BOOST_AUTO_TEST_CASE(SVDPlusPlusCleanDataTest) SVDPlusPlus<>::CleanData(implicitData, cleanedData, data); // Make sure cleanedData has correct size. - BOOST_REQUIRE_EQUAL(cleanedData.n_rows, numItems); - BOOST_REQUIRE_EQUAL(cleanedData.n_cols, numUsers); + REQUIRE(cleanedData.n_rows == numItems); + REQUIRE(cleanedData.n_cols == numUsers); // Make sure cleanedData has correct number of implicit data. - BOOST_REQUIRE_EQUAL(cleanedData.n_nonzero, implicitData.n_cols); + REQUIRE(cleanedData.n_nonzero == implicitData.n_cols); // Make sure all implicitData are in cleanedData. for (size_t i = 0; i < implicitData.n_cols; ++i) { double value = cleanedData(implicitData(1, i), implicitData(0, i)); - BOOST_REQUIRE_GT(std::fabs(value), 0); + REQUIRE(std::fabs(value) > 0); } } -BOOST_AUTO_TEST_CASE(SVDPlusPlusFunctionOptimize) +TEST_CASE("SVDPlusPlusFunctionOptimize", "[SVDPlusPlusTest]") { // Define useful constants. const size_t numUsers = 100; @@ -433,7 +430,7 @@ BOOST_AUTO_TEST_CASE(SVDPlusPlusFunctionOptimize) arma::norm(data, "frob"); // Relative error should be small. - BOOST_REQUIRE_SMALL(relativeError, 1e-2); + REQUIRE(relativeError == Approx(0.0).margin(1e-2)); } // The test is only compiled if the user has specified OpenMP to be @@ -441,7 +438,7 @@ BOOST_AUTO_TEST_CASE(SVDPlusPlusFunctionOptimize) #ifdef HAS_OPENMP // Test SVDPlusPlus with parallel SGD. -BOOST_AUTO_TEST_CASE(SVDPlusPlusFunctionParallelOptimize) +TEST_CASE("SVDPlusPlusFunctionParallelOptimize", "[SVDPlusPlusTest]") { // Define useful constants. const size_t numUsers = 100; @@ -547,9 +544,7 @@ BOOST_AUTO_TEST_CASE(SVDPlusPlusFunctionParallelOptimize) arma::norm(data, "frob"); // Relative error should be small. - BOOST_REQUIRE_SMALL(relativeError, 1e-2); + REQUIRE(relativeError == Approx(0.0).margin(1e-2)); } #endif - -BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/test_catch_tools.hpp b/src/mlpack/tests/test_catch_tools.hpp index 34396e3cf9..1bac310ddc 100644 --- a/src/mlpack/tests/test_catch_tools.hpp +++ b/src/mlpack/tests/test_catch_tools.hpp @@ -33,7 +33,7 @@ inline void CheckMatrices(const arma::mat& a, for (size_t i = 0; i < a.n_elem; ++i) { if (std::abs(a[i]) < tolerance / 2) - REQUIRE(b[i] == Approx(0.0).margin(tolerance / 200)); + REQUIRE(b[i] == Approx(0.0).margin(tolerance / 2)); else REQUIRE(a[i] == Approx(b[i]).epsilon(tolerance / 100)); } @@ -62,7 +62,7 @@ inline void CheckMatrices(const arma::cube& a, for (size_t i = 0; i < a.n_elem; ++i) { if (std::abs(a[i]) < tolerance / 2) - REQUIRE(b[i] == Approx(0.0).margin(tolerance / 200)); + REQUIRE(b[i] == Approx(0.0).margin(tolerance / 2)); else REQUIRE(a[i] == Approx(b[i]).epsilon(tolerance / 100)); }