diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bbc9ebe6dd3308caf03968ee03c17f709f916a1..7707815e5ee5d12b21a586e367d4ad39ba8db50e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.10) include( ExternalProject ) # set the project name -project(sisso++ VERSION 0.1 LANGUAGES CXX) +project(sisso++ VERSION 0.1 LANGUAGES CXX C) # Cmake modules/macros are in a subdirectory to keep this file cleaner set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) @@ -347,5 +347,28 @@ ExternalProject_Add_StepDependencies(external_Clp CoinUtils) set(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARY_DIRS}/libClp.so;${COIN_CLP_LIBRARY_DIRS}/libCoinUtils.so") include_directories(${COIN_CLP_INCLUDE_DIRS}) +find_package(GTest) +if(NOT GTEST_FOUND) + set(GTEST_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/gtest/build/") + set(GTEST_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/gtest/bin/") + set(GTEST_INCLUDE_DIRS "${GTEST_INSTALL_DIR}/include") + set(GTEST_LIBRARY_DIRS "${GTEST_INSTALL_DIR}/lib") + + ExternalProject_Add( + external_gtest + PREFIX "external/gtest" + GIT_REPOSITORY "https://github.com/google/googletest.git" + GIT_TAG "v1.10.x" + CMAKE_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER};-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER};-DCMAKE_INSTALL_PREFIX=${GTEST_INSTALL_DIR};-DCMAKE_INSTALL_LIBDIR=${GTEST_LIBRARY_DIRS};-DBUILD_SHARED_LIBS=ON;" + BINARY_DIR "${GTEST_BUILD_DIR}" + INSTALL_DIR "${GTEST_INSTALL_DIR}" + ) + set(GTEST_BOTH_LIBRARIES "${GTEST_LIBRARY_DIRS}/libgtest.so;${GTEST_LIBRARY_DIRS}/libgtest_main.so;${GTEST_LIBRARY_DIRS}/libgmock.so;${GTEST_LIBRARY_DIRS}/libgmock_main.so") +endif() + +include_directories(${GTEST_INCLUDE_DIRS}) + include_directories(${CMAKE_CURRENT_LIST_DIR}/src) + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/src) +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/tests/googletest/) diff --git a/src/descriptor_identifier/Model/Model.hpp b/src/descriptor_identifier/Model/Model.hpp index 6dfca9d39141b725770a8f1aa708dc17e9cc6150..b9fcf0f935fc5345de93e5ab92788a83d715fe7a 100644 --- a/src/descriptor_identifier/Model/Model.hpp +++ b/src/descriptor_identifier/Model/Model.hpp @@ -150,13 +150,19 @@ public: */ inline bool fix_intercept(){return _fix_intercept;} + /** + * @brief Accessor to the coefficients for the model + * @return The coefficients for the model for each task + */ + inline std::vector<std::vector<double>> coefs(){return _coefs;} + #ifdef PY_BINDINGS // DocString: model_coefs /** * @brief The coefficient array for the model * @return The coefficients as a python list */ - inline py::list coefs() + inline py::list coefs_py() { py::list coef_lst; for(auto& task_coefs : _coefs) diff --git a/src/descriptor_identifier/Model/ModelClassifier.cpp b/src/descriptor_identifier/Model/ModelClassifier.cpp index 3f41f0e247a748fd63fbea408854b872b65430a2..3784e5033b229c1f491c853b9a0091b9a295d649 100644 --- a/src/descriptor_identifier/Model/ModelClassifier.cpp +++ b/src/descriptor_identifier/Model/ModelClassifier.cpp @@ -444,7 +444,9 @@ std::ostream& operator<< (std::ostream& outStream, const ModelClassifier& model) void ModelClassifier::to_file(std::string filename, bool train, std::vector<int> test_inds) { boost::filesystem::path p(filename.c_str()); - boost::filesystem::create_directories(p.remove_filename()); + boost::filesystem::path parent = p.remove_filename(); + if(parent.string().size() > 0) + boost::filesystem::create_directories(parent); std::ofstream out_file_stream = std::ofstream(); out_file_stream.open(filename); diff --git a/src/descriptor_identifier/Model/ModelLogRegressor.cpp b/src/descriptor_identifier/Model/ModelLogRegressor.cpp index 7a86f6f260d1cb964d65270077017dbee2aaf8c2..76064e7faff8dc3a5843fc70139f99469aedf1a3 100644 --- a/src/descriptor_identifier/Model/ModelLogRegressor.cpp +++ b/src/descriptor_identifier/Model/ModelLogRegressor.cpp @@ -1,18 +1,20 @@ #include <descriptor_identifier/Model/ModelLogRegressor.hpp> +ModelLogRegressor::ModelLogRegressor() +{} + ModelLogRegressor::ModelLogRegressor(std::string prop_label, Unit prop_unit, std::vector<double> prop_train, std::vector<double> prop_test, std::vector<model_node_ptr> feats, std::vector<int> task_sizes_train, std::vector<int> task_sizes_test, bool fix_intercept) : - ModelRegressor(prop_label, prop_unit, prop_train, prop_test, feats, task_sizes_train, task_sizes_test, fix_intercept), + ModelRegressor(prop_label, prop_unit, prop_train, prop_test, feats, task_sizes_train, task_sizes_test, fix_intercept, false), _log_prop_train(_n_samp_train, 0.0), _log_prop_test(_n_samp_test, 0.0), _log_prop_train_est(_n_samp_train, 0.0), _log_prop_test_est(_n_samp_test, 0.0), - _log_train_error(_n_samp_train), - _log_test_error(_n_samp_test) + _log_train_error(_n_samp_train, 0.0), + _log_test_error(_n_samp_test, 0.0) { std::transform(_prop_train.begin(), _prop_train.end(), _log_prop_train.begin(),[](double p){return std::log(p);}); std::transform(_prop_test.begin(), _prop_test.end(), _log_prop_test.begin(),[](double p){return std::log(p);}); - _log_prop_train.reserve(_n_samp_train); _log_prop_test.reserve(_n_samp_test); @@ -38,6 +40,7 @@ ModelLogRegressor::ModelLogRegressor(std::string prop_label, Unit prop_unit, std dgels_('N', sz, _n_dim + 1 - _fix_intercept, 1, a.data(), sz, _log_prop_train.data() + start, sz, work.data(), work.size(), &info); + _coefs.push_back(std::vector<double>(_n_dim + (!fix_intercept), 0.0)); std::copy_n(_log_prop_train.begin() + start, _n_dim + 1 - _fix_intercept, _coefs[tt].data()); std::transform(_prop_train.begin() + start, _prop_train.begin() + start + sz, _log_prop_train.begin() + start, [](double p){return std::log(p);}); @@ -53,10 +56,10 @@ ModelLogRegressor::ModelLogRegressor(std::string prop_label, Unit prop_unit, std { if(sz > 0) { + std::fill_n(_D_test.data(), _D_test.size(), 1.0); for(int ff = 0; ff < feats.size(); ++ff) std::transform(feats[ff]->test_value_ptr() + start, feats[ff]->test_value_ptr() + start + sz, _D_test.data() + ff * sz, [](double fv){return std::log(fv);}); - std::fill_n(_D_test.data() + feats.size() * sz, sz, 1.0); dgemv_('N', sz, _n_dim + 1 - _fix_intercept, 1.0, _D_test.data(), sz, _coefs[ii].data(), 1, 0.0, _log_prop_test_est.data() + start, 1); std::transform(_log_prop_test_est.begin() + start, _log_prop_test_est.begin() + start + sz, _log_prop_test.data() + start, _log_test_error.data() + start, std::minus<double>()); } @@ -72,7 +75,13 @@ ModelLogRegressor::ModelLogRegressor(std::string prop_label, Unit prop_unit, std } ModelLogRegressor::ModelLogRegressor(std::string train_file) : - ModelRegressor(train_file) + ModelRegressor(train_file), + _log_prop_train(_n_samp_train, 0.0), + _log_prop_test(_n_samp_test, 0.0), + _log_prop_train_est(_n_samp_train, 0.0), + _log_prop_test_est(_n_samp_test, 0.0), + _log_train_error(_n_samp_train), + _log_test_error(_n_samp_test) { std::transform(_D_train.begin(), _D_train.begin() + _n_samp_train, _D_train.begin(), [](double dt){return std::log(dt);}); std::transform(_prop_train.begin(), _prop_train.end(), _log_prop_train.begin(), [](double pt){return std::log(pt);}); @@ -82,7 +91,13 @@ ModelLogRegressor::ModelLogRegressor(std::string train_file) : } ModelLogRegressor::ModelLogRegressor(std::string train_file, std::string test_file) : - ModelRegressor(train_file, test_file) + ModelRegressor(train_file, test_file), + _log_prop_train(_n_samp_train, 0.0), + _log_prop_test(_n_samp_test, 0.0), + _log_prop_train_est(_n_samp_train, 0.0), + _log_prop_test_est(_n_samp_test, 0.0), + _log_train_error(_n_samp_train), + _log_test_error(_n_samp_test) { std::transform(_D_train.begin(), _D_train.begin() + _n_samp_train, _D_train.begin(), [](double dt){return std::log(dt);}); std::transform(_D_test.begin(), _D_test.begin() + _n_samp_test, _D_test.begin(), [](double dt){return std::log(dt);}); @@ -103,19 +118,38 @@ ModelLogRegressor::ModelLogRegressor(std::string train_file, std::string test_fi std::string ModelLogRegressor::toString() const { std::stringstream unit_rep; - unit_rep << "c0"; - for(int ff = 0; ff < _feats.size(); ++ff) - unit_rep << " * (" << _feats[ff]->expr() << ")^a" << ff; + if(_fix_intercept) + { + unit_rep << "(" << _feats[0]->expr() << ")^a0"; + for(int ff = 1; ff < _feats.size(); ++ff) + unit_rep << " * (" << _feats[ff]->expr() << ")^a" << ff; + } + else + { + unit_rep << "exp(c0)"; + for(int ff = 0; ff < _feats.size(); ++ff) + unit_rep << " * (" << _feats[ff]->expr() << ")^a" << ff; + } return unit_rep.str(); } std::string ModelLogRegressor::toLatexString() const { std::stringstream unit_rep; - unit_rep << "$c_0"; - for(int ff = 0; ff < _feats.size(); ++ff) - unit_rep << "\\left(" << _feats[ff]->get_latex_expr("") << "\\right)^{a_" << ff << "}"; - unit_rep << "$"; + if(_fix_intercept) + { + unit_rep << "$\\left(" << _feats[0]->get_latex_expr("") << "\\right)^{a_0}" << std::endl; + for(int ff = 1; ff < _feats.size(); ++ff) + unit_rep << "\\left(" << _feats[ff]->get_latex_expr("") << "\\right)^{a_" << ff << "}"; + unit_rep << "$"; + } + else + { + unit_rep << "$c_0"; + for(int ff = 0; ff < _feats.size(); ++ff) + unit_rep << "\\left(" << _feats[ff]->get_latex_expr("") << "\\right)^{a_" << ff << "}"; + unit_rep << "$"; + } return unit_rep.str(); } diff --git a/src/descriptor_identifier/Model/ModelLogRegressor.hpp b/src/descriptor_identifier/Model/ModelLogRegressor.hpp index 73be5d6b372148f4158b70e18802e83e1a2feb1c..62255b0a23edd25c7a35dc3fadd93426d5edbf01 100644 --- a/src/descriptor_identifier/Model/ModelLogRegressor.hpp +++ b/src/descriptor_identifier/Model/ModelLogRegressor.hpp @@ -26,6 +26,7 @@ typedef std::shared_ptr<ModelNode> model_node_ptr; */ class ModelLogRegressor : public ModelRegressor { +protected: std::vector<double> _log_prop_train; //!< The log of the real Property std::vector<double> _log_prop_test; //!< The log of the real Property @@ -36,6 +37,11 @@ class ModelLogRegressor : public ModelRegressor std::vector<double> _log_test_error; //!< The error of the model (testing) public: + /** + * @brief Default constructor] + */ + ModelLogRegressor(); + /** * @brief Constructor for the model * diff --git a/src/descriptor_identifier/Model/ModelRegressor.cpp b/src/descriptor_identifier/Model/ModelRegressor.cpp index 8926c5cd96715387558077ecf565d81fea4a3e27..ca2b33095adfe5752c81674896ee10b5d369a438 100644 --- a/src/descriptor_identifier/Model/ModelRegressor.cpp +++ b/src/descriptor_identifier/Model/ModelRegressor.cpp @@ -1,6 +1,9 @@ #include <descriptor_identifier/Model/ModelRegressor.hpp> -ModelRegressor::ModelRegressor(std::string prop_label, Unit prop_unit, std::vector<double> prop_train, std::vector<double> prop_test, std::vector<model_node_ptr> feats, std::vector<int> task_sizes_train, std::vector<int> task_sizes_test, bool fix_intercept) : +ModelRegressor::ModelRegressor() +{} + +ModelRegressor::ModelRegressor(std::string prop_label, Unit prop_unit, std::vector<double> prop_train, std::vector<double> prop_test, std::vector<model_node_ptr> feats, std::vector<int> task_sizes_train, std::vector<int> task_sizes_test, bool fix_intercept, bool fill_vecs) : Model(prop_label, prop_unit, prop_train, prop_test, feats, task_sizes_train, task_sizes_test, fix_intercept), _prop_train_est(_n_samp_train, 0.0), _prop_test_est(_n_samp_test, 0.0), @@ -9,51 +12,53 @@ ModelRegressor::ModelRegressor(std::string prop_label, Unit prop_unit, std::vect { _prop_train_est.reserve(_n_samp_train); _prop_test_est.reserve(_n_samp_test); - - std::vector<double> a(_D_train.size(), 1.0); - std::vector<double> work(_D_train.size(), 0.0); - - int info; - int start = 0; - - std::copy_n(_D_train.begin(), _D_train.size(), a.begin()); - for(auto& sz : _task_sizes_train) + if(fill_vecs) { - std::fill_n(a.data(), a.size(), 1.0); - std::fill_n(_D_train.data(), _D_train.size(), 1.0); + std::vector<double> a(_D_train.size(), 1.0); + std::vector<double> work(_D_train.size(), 0.0); - for(int ff = 0; ff < feats.size(); ++ff) + int info; + int start = 0; + + std::copy_n(_D_train.begin(), _D_train.size(), a.begin()); + for(auto& sz : _task_sizes_train) { - std::copy_n(feats[ff]->value_ptr() + start, sz, _D_train.data() + ff * sz); - std::copy_n(feats[ff]->value_ptr() + start, sz, a.data() + ff * sz); - } + std::fill_n(a.data(), a.size(), 1.0); + std::fill_n(_D_train.data(), _D_train.size(), 1.0); - dgels_('N', sz, _n_dim + 1 - _fix_intercept, 1, a.data(), sz, prop_train.data() + start, sz, work.data(), work.size(), &info); + for(int ff = 0; ff < feats.size(); ++ff) + { + std::copy_n(feats[ff]->value_ptr() + start, sz, _D_train.data() + ff * sz); + std::copy_n(feats[ff]->value_ptr() + start, sz, a.data() + ff * sz); + } - _coefs.push_back(std::vector<double>(_n_dim + (!fix_intercept), 0.0)); + dgels_('N', sz, _n_dim + 1 - _fix_intercept, 1, a.data(), sz, prop_train.data() + start, sz, work.data(), work.size(), &info); - std::copy_n(prop_train.begin() + start, _n_dim + 1 - _fix_intercept, _coefs.back().data()); - dgemv_('N', sz, _n_dim + 1 - _fix_intercept, 1.0, _D_train.data(), sz, _coefs.back().data(), 1, 0.0, _prop_train_est.data() + start, 1); - std::transform(_prop_train_est.begin() + start, _prop_train_est.begin() + start + sz, _prop_train.data() + start, _train_error.data() + start, std::minus<double>()); + _coefs.push_back(std::vector<double>(_n_dim + (!fix_intercept), 0.0)); - start += sz; - } + std::copy_n(prop_train.begin() + start, _n_dim + 1 - _fix_intercept, _coefs.back().data()); + dgemv_('N', sz, _n_dim + 1 - _fix_intercept, 1.0, _D_train.data(), sz, _coefs.back().data(), 1, 0.0, _prop_train_est.data() + start, 1); + std::transform(_prop_train_est.begin() + start, _prop_train_est.begin() + start + sz, _prop_train.data() + start, _train_error.data() + start, std::minus<double>()); - start = 0; - int ii = 0; - for(auto& sz : _task_sizes_test) - { - if(sz > 0) - { - for(int ff = 0; ff < feats.size(); ++ff) - std::copy_n(feats[ff]->test_value().data() + start, sz, _D_test.data() + ff * sz); + start += sz; + } - std::fill_n(_D_test.data() + feats.size() * sz, sz, 1.0); - dgemv_('N', sz, _n_dim + 1 - _fix_intercept, 1.0, _D_test.data(), sz, _coefs[ii].data(), 1, 0.0, _prop_test_est.data() + start, 1); - std::transform(_prop_test_est.begin() + start, _prop_test_est.begin() + start + sz, _prop_test.data() + start, _test_error.data() + start, std::minus<double>()); + start = 0; + int ii = 0; + for(auto& sz : _task_sizes_test) + { + if(sz > 0) + { + std::fill_n(_D_test.data(), _D_test.size(), 1.0); + for(int ff = 0; ff < feats.size(); ++ff) + std::copy_n(feats[ff]->test_value().data() + start, sz, _D_test.data() + ff * sz); + + dgemv_('N', sz, _n_dim + 1 - _fix_intercept, 1.0, _D_test.data(), sz, _coefs[ii].data(), 1, 0.0, _prop_test_est.data() + start, 1); + std::transform(_prop_test_est.begin() + start, _prop_test_est.begin() + start + sz, _prop_test.data() + start, _test_error.data() + start, std::minus<double>()); + } + ++ii; + start += sz; } - ++ii; - start += sz; } } @@ -125,6 +130,8 @@ std::vector<std::string> ModelRegressor::populate_model(std::string filename, bo std::string model_line; std::getline(file_stream, model_line); + _fix_intercept = (model_line.substr(0, 4).compare("# c0") != 0) && (model_line.substr(0, 9).compare("# exp(c0)") != 0); + // Get the property unit and error std::string unit_line; std::string error_line; @@ -173,20 +180,14 @@ std::vector<std::string> ModelRegressor::populate_model(std::string filename, bo if(train) { _coefs.push_back(std::vector<double>(n_dim + 1, 0.0)); - std::transform(split_line.begin() + 1, split_line.end()-1, _coefs.back().data(), [](std::string s){return std::stod(s);}); + std::transform(split_line.begin() + 1, split_line.end()-1, _coefs.back().data(), [](std::string s){return std::stod(s);}); } std::getline(file_stream, line); } while(line.substr(0, 14).compare("# Feature Rung") != 0); - if(_coefs.back().back() == 0.0) - _fix_intercept = true; - else - _fix_intercept = false; - - _n_dim = n_dim; - + _n_dim = n_dim + _fix_intercept; std::getline(file_stream, line); - for(int ff = 0; ff < n_dim; ++ff) + for(int ff = 0; ff < _n_dim; ++ff) { feature_expr.push_back(line.substr(6)); std::getline(file_stream, line); @@ -270,19 +271,38 @@ std::vector<std::string> ModelRegressor::populate_model(std::string filename, bo std::string ModelRegressor::toString() const { std::stringstream unit_rep; - unit_rep << "c0"; - for(int ff = 0; ff < _feats.size(); ++ff) - unit_rep << " + a" << std::to_string(ff) << " * " << _feats[ff]->expr(); + if(!_fix_intercept) + { + unit_rep << "c0"; + for(int ff = 0; ff < _feats.size(); ++ff) + unit_rep << " + a" << std::to_string(ff) << " * " << _feats[ff]->expr(); + } + else + { + unit_rep << "a0 * " << _feats[0]->expr(); + for(int ff = 1; ff < _feats.size(); ++ff) + unit_rep << " + a" << std::to_string(ff) << " * " << _feats[ff]->expr(); + } return unit_rep.str(); } std::string ModelRegressor::toLatexString() const { std::stringstream unit_rep; - unit_rep << "$c_0"; - for(int ff = 0; ff < _feats.size(); ++ff) - unit_rep << " + a_" << std::to_string(ff) << _feats[ff]->get_latex_expr(""); - unit_rep << "$"; + if(_fix_intercept) + { + unit_rep << "$a_0" << _feats[0]->get_latex_expr(""); + for(int ff = 1; ff < _feats.size(); ++ff) + unit_rep << " + a_" << std::to_string(ff) << _feats[ff]->get_latex_expr(""); + unit_rep << "$"; + } + else + { + unit_rep << "$c_0"; + for(int ff = 0; ff < _feats.size(); ++ff) + unit_rep << " + a_" << std::to_string(ff) << _feats[ff]->get_latex_expr(""); + unit_rep << "$"; + } return unit_rep.str(); } @@ -295,7 +315,9 @@ std::ostream& operator<< (std::ostream& outStream, const ModelRegressor& model) void ModelRegressor::to_file(std::string filename, bool train, std::vector<int> test_inds) { boost::filesystem::path p(filename.c_str()); - boost::filesystem::create_directories(p.remove_filename()); + boost::filesystem::path parent = p.remove_filename(); + if(parent.string().size() > 0) + boost::filesystem::create_directories(parent); std::ofstream out_file_stream = std::ofstream(); out_file_stream.open(filename); @@ -310,7 +332,7 @@ void ModelRegressor::to_file(std::string filename, bool train, std::vector<int> out_file_stream << "# Coefficients" << std::endl; out_file_stream << std::setw(10) << std::left << "# Task"; - for(int cc = 0; cc < _coefs[0].size() - (1 - _fix_intercept); ++cc) + for(int cc = 0; cc < _coefs[0].size() - (!_fix_intercept); ++cc) out_file_stream << std::setw(24) << " a" + std::to_string(cc); if(!_fix_intercept) diff --git a/src/descriptor_identifier/Model/ModelRegressor.hpp b/src/descriptor_identifier/Model/ModelRegressor.hpp index a12973fa59f44df977e475dd3fd85b3a15a6cd74..9f21ca7826db5809d1d7fbfc4d70c30a9ac3ff28 100644 --- a/src/descriptor_identifier/Model/ModelRegressor.hpp +++ b/src/descriptor_identifier/Model/ModelRegressor.hpp @@ -44,6 +44,11 @@ protected: std::vector<double> _test_error; //!< The error of the model (testing) public: + /** + * @brief Default Constructor + */ + ModelRegressor(); + /** * @brief Constructor for the model * @@ -54,7 +59,7 @@ public: * @param task_sizes_train Number of samples per task in the training data * @param task_sizes_test Number of samples per task in the test data */ - ModelRegressor(std::string prop_label, Unit prop_unit, std::vector<double> prop_train, std::vector<double> prop_test, std::vector<model_node_ptr> feats, std::vector<int> task_sizes_train, std::vector<int> task_sizes_test, bool fix_intercept); + ModelRegressor(std::string prop_label, Unit prop_unit, std::vector<double> prop_train, std::vector<double> prop_test, std::vector<model_node_ptr> feats, std::vector<int> task_sizes_train, std::vector<int> task_sizes_test, bool fix_intercept, bool fill_vecs=true); // DocString: model_reg_init_str /** diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.cpp index 58522a9ea4f5c15bde03c3fac6f796566c8f45c7..1147614ef5427df3b6cc63b9afdf9c9caf2eb40f 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.cpp @@ -6,8 +6,12 @@ void generateAbsNode(std::vector<node_ptr>& feat_list, node_ptr feat, int& feat_ if((feat->type() == NODE_TYPE::ABS) || (feat->type() == NODE_TYPE::ABS_DIFF)) return; + double* val_ptr = feat->value_ptr(feat->rung() + 1); + if(*std::min_element(val_ptr, val_ptr + feat->n_samp()) > 0.0) + return; + int offset = feat->rung() + 1; - double* val_ptr = node_value_arrs::get_value_ptr(feat_ind, feat_ind, offset); + val_ptr = node_value_arrs::get_value_ptr(feat_ind, feat_ind, offset); allowed_op_funcs::abs(feat->n_samp(), feat->value_ptr(offset + 2), val_ptr); if((util_funcs::stand_dev(val_ptr, feat->n_samp()) < 1.0e-13) || std::any_of(val_ptr, val_ptr + feat->n_samp(), [&u_bound](double d){return !std::isfinite(d) || (std::abs(d) > u_bound);}) || (util_funcs::max_abs_val<double>(val_ptr, feat->n_samp()) < l_bound)) @@ -28,6 +32,11 @@ AbsNode::AbsNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): { if((feat->type() == NODE_TYPE::ABS) || (feat->type() == NODE_TYPE::ABS_DIFF)) throw InvalidFeatureException(); + + double* val_ptr = feat->value_ptr(rung() + 2); + if(*std::min_element(val_ptr, val_ptr + _n_samp) > 0.0) + throw InvalidFeatureException(); + set_value(); if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) throw InvalidFeatureException(); diff --git a/src/feature_creation/node/value_storage/nodes_value_containers.cpp b/src/feature_creation/node/value_storage/nodes_value_containers.cpp index e0dc8bb47786f37f9915433f7e170c867a417122..cd6d214f2047f64bfde758a58b008f1229adc0ee 100644 --- a/src/feature_creation/node/value_storage/nodes_value_containers.cpp +++ b/src/feature_creation/node/value_storage/nodes_value_containers.cpp @@ -64,6 +64,8 @@ void node_value_arrs::resize_values_arr(int n_dims, int n_feat, bool use_temp) { TEMP_STORAGE_ARR = {}; TEMP_STORAGE_REG = {}; + TEMP_STORAGE_TEST_ARR = {}; + TEMP_STORAGE_TEST_REG = {}; } } diff --git a/src/feature_creation/units/Unit.cpp b/src/feature_creation/units/Unit.cpp index f96e5bd78feff445dd5f91768317075b2640e0e3..15a0726698719443d1d23f9eccedc9c55d6fb116 100644 --- a/src/feature_creation/units/Unit.cpp +++ b/src/feature_creation/units/Unit.cpp @@ -11,6 +11,7 @@ Unit::Unit(std::string unit_str) : _dct() { boost::ireplace_all(unit_str, " ", ""); + boost::ireplace_all(unit_str, "Unitless", ""); std::vector<std::string> split_unit; boost::algorithm::split(split_unit, unit_str, boost::algorithm::is_any_of("*/")); @@ -42,12 +43,13 @@ Unit::Unit(std::string unit_str) : for(int oo = 0; oo < ops.size(); ++oo) { - std::vector<std::string> get_power; - boost::algorithm::split(get_power, split_unit[oo], boost::algorithm::is_any_of("^")); + std::vector<std::string> get_power = str_utils::split_string_trim(split_unit[oo], "^"); + if(get_power[0][0] == '1') + continue; if(get_power.size() > 1) - _dct[get_power[0]] = ops[oo] * std::stod(get_power[1]); + _dct[get_power[0]] += ops[oo] * std::stod(get_power[1]); else - _dct[get_power[0]] = ops[oo]; + _dct[get_power[0]] += ops[oo]; } } @@ -180,14 +182,12 @@ Unit Unit::inverse() return Unit(to_out); } -bool Unit::equal(Unit unit_2) +bool Unit::equal(Unit unit_2) const { for(auto& el : unit_2.dct()) { if((_dct.count(el.first) == 0) && (el.second != 0)) return false; - else if(_dct[el.first] != el.second) - return false; } for(auto& el : _dct) diff --git a/src/feature_creation/units/Unit.hpp b/src/feature_creation/units/Unit.hpp index 9dcf29d34b950a33193b2c89807d8152fbca146e..1414adc83d93fd6e7e01ebf14f079d5e43d4b17e 100644 --- a/src/feature_creation/units/Unit.hpp +++ b/src/feature_creation/units/Unit.hpp @@ -22,6 +22,8 @@ #include <boost/serialization/map.hpp> #include <boost/serialization/string.hpp> +#include <utils/string_utils.hpp> + using StringRange = boost::iterator_range<std::string::const_iterator>; // DocString: cls_unit @@ -146,7 +148,7 @@ public: * @param unit_2 The unit to compare against * @return True if unit_2 equals this unit */ - bool equal(Unit unit_2); + bool equal(Unit unit_2) const; // DocString: unit_eq /** @@ -155,7 +157,7 @@ public: * @param unit_2 The unit to compare against * @return True if unit_2 equals this unit */ - inline bool operator== (Unit unit_2){return equal(unit_2);} + inline bool operator== (Unit unit_2) const {return equal(unit_2);} // DocString: unit_neq /** @@ -164,7 +166,7 @@ public: * @param unit_2 The unit to compare against * @return False if unit_2 equals this unit */ - inline bool operator!= (Unit unit_2){return !equal(unit_2);} + inline bool operator!= (Unit unit_2) const {return !equal(unit_2);} /** * @brief The dictionary @@ -181,4 +183,8 @@ public: */ std::ostream& operator<< (std::ostream& outStream, const Unit& unit); +// inline bool operator==(const Unit& u1, const Unit& u2) +// { +// return u1.equal(u2); +// } #endif diff --git a/src/python/bindings_docstring_keyed.cpp b/src/python/bindings_docstring_keyed.cpp index bbbc86c3c83370c0e9af6f763e35c2a1befe8728..10e6f5960888de14a782b216093f4c09c85af286 100644 --- a/src/python/bindings_docstring_keyed.cpp +++ b/src/python/bindings_docstring_keyed.cpp @@ -357,7 +357,7 @@ void sisso::descriptor_identifier::registerModel() .add_property("prop_train", &Model::prop_train, "@DocString_model_prop_train@") .add_property("prop_test", &Model::prop_test, "@DocString_model_prop_test@") .add_property("feats", &Model::feats, "@DocString_model_feats@") - .add_property("coefs", &Model::coefs, "@DocString_model_coefs@") + .add_property("coefs", &Model::coefs_py, "@DocString_model_coefs@") .add_property("prop_unit", &Model::prop_unit, "@DocString_model_prop_unit@") .add_property("prop_label", &Model::prop_label, "@DocString_model_prop_label@") .add_property("task_size_train", &Model::task_sizes_train, "@DocString_model_task_sizes_train") diff --git a/src/python/postprocess/utils.py b/src/python/postprocess/utils.py index c08b7e431bdfd9460a56ced5f1e54f29f3a23667..f0e8876da55bd592a70b3a2536fc44e7c5407c48 100644 --- a/src/python/postprocess/utils.py +++ b/src/python/postprocess/utils.py @@ -36,7 +36,7 @@ def load_model(train_file, test_file=None): return ModelRegressor(train_file, test_file) else: return ModelRegressor(train_file) - elif model_line[:4] == "c0 *": + elif model_line[:9] == "exp(c0) *": if test_file: return ModelLogRegressor(train_file, test_file) else: diff --git a/tests/googletest/CMakeLists.txt b/tests/googletest/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a1675e225c43a6c63b76ba6e93154379cbe169c7 --- /dev/null +++ b/tests/googletest/CMakeLists.txt @@ -0,0 +1,16 @@ +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations") +set(CMAKE_INSTALL_RPATH ${Boost_LIBRARY_DIRS};${LAPACK_DIR};${MPI_DIR};${COIN_CLP_LIBRARY_DIRS};${COIN_UTILS_LIBRARY_DIRS};${GTEST_LIBRARY_DIRS};${NLOPT_LIBRARY_DIRS};${FMT_LIBRARY_DIRS};${CMAKE_CURRENT_LIST_DIR}/../../lib/) + +file(GLOB_RECURSE SISSO_TEST_SOURCES *.cc) +add_executable(sisso_test ${SISSO_TEST_SOURCES}) + +set_target_properties(sisso_test + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" +) + +target_link_libraries(sisso_test libsisso ${LAPACK_LIBRARIES} ${MPI_LIBRARIES} -Wl,--rpath=${GTEST_LIBRARY_DIRS} -Wl,--rpath=${Boost_LIB_DIR} -Wl,--rpath=${LAPACK_DIR} ${Boost_LIBRARIES} ${COIN_CLP_LIBRARIES} ${OPENMP_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ${FMT_LIBRARIES} ${NLOPT_LIBRARIES}) +message(STATUS "${LAPACK_LIBRARIES} ${MPI_LIBRARIES} -Wl,--rpath=${GTEST_LIBRARY_DIRS} -Wl,--rpath=${Boost_LIB_DIR} -Wl,--rpath=${LAPACK_DIR} ${Boost_LIBRARIES} ${COIN_CLP_LIBRARIES} ${OPENMP_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ${FMT_LIBRARIES}") +install(TARGETS sisso_test DESTINATION ${CMAKE_CURRENT_LIST_DIR}) diff --git a/tests/googletest/descriptor_identification/model/test_model_classifier.cc b/tests/googletest/descriptor_identification/model/test_model_classifier.cc new file mode 100644 index 0000000000000000000000000000000000000000..927d60db068bc90021e2dc6a229a3b2ccd73e5a3 --- /dev/null +++ b/tests/googletest/descriptor_identification/model/test_model_classifier.cc @@ -0,0 +1,82 @@ +#include <descriptor_identifier/Model/ModelClassifier.hpp> +#include <boost/filesystem.hpp> +#include "gtest/gtest.h" + +namespace +{ + class ModelClassifierTests : public ::testing::Test + { + protected: + void SetUp() override + { + _task_sizes_train = {12}; + _task_sizes_test = {2}; + + std::vector<double> value_1 = {1.0, -2.0, 3.0, -4.0, 5.0, -6.0, 7.0, -8.0, 9.0, -10.0, 0.1, -0.1}; + std::vector<double> test_value_1 = {10.0, -7.0}; + + model_node_ptr feat_1 = std::make_shared<ModelNode>(0, 0, "A", "$A$", "0", value_1, test_value_1, Unit("m")); + + _features = {feat_1}; + + _prop = {0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0}; + _prop_test = {0.0, 1.0}; + } + std::vector<int> _task_sizes_train; + std::vector<int> _task_sizes_test; + + std::vector<double> _prop; + std::vector<double> _prop_test; + + std::vector<model_node_ptr> _features; + }; + + TEST_F(ModelClassifierTests, NodesTest) + { + ModelClassifier model( + "Property", + Unit("m"), + _prop, + _prop_test, + _features, + _task_sizes_train, + _task_sizes_test, + false + ); + EXPECT_STREQ(model.toString().c_str(), "[A]"); + EXPECT_EQ(model.n_convex_overlap_train(), 0); + EXPECT_EQ(model.n_convex_overlap_test(), 0); + EXPECT_EQ(model.n_svm_misclassified_train(), 0); + EXPECT_EQ(model.n_svm_misclassified_test(), 0); + EXPECT_LT(model.percent_train_error(), 1.0e-10); + EXPECT_LT(model.percent_test_error(), 1.0e-10); + + EXPECT_EQ(model.n_samp_train(), 12); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 1); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + model.to_file("train_class_mods.dat", true, {5, 11}); + model.to_file("test_class_mods.dat", false, {5, 11}); + } + + TEST_F(ModelClassifierTests, FileTest) + { + ModelClassifier model("train_class_mods.dat", "test_class_mods.dat"); + EXPECT_STREQ(model.toString().c_str(), "[A]"); + EXPECT_EQ(model.n_convex_overlap_train(), 0); + EXPECT_EQ(model.n_convex_overlap_test(), 0); + EXPECT_EQ(model.n_svm_misclassified_train(), 0); + EXPECT_EQ(model.n_svm_misclassified_test(), 0); + EXPECT_LT(model.percent_train_error(), 1.0e-10); + EXPECT_LT(model.percent_test_error(), 1.0e-10); + + EXPECT_EQ(model.n_samp_train(), 12); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 1); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + boost::filesystem::remove("train_class_mods.dat"); + boost::filesystem::remove("test_class_mods.dat"); + } +} diff --git a/tests/googletest/descriptor_identification/model/test_model_log_regressor.cc b/tests/googletest/descriptor_identification/model/test_model_log_regressor.cc new file mode 100644 index 0000000000000000000000000000000000000000..b4ab2054a88729d20584a9f2cc4a92cf7d3242f7 --- /dev/null +++ b/tests/googletest/descriptor_identification/model/test_model_log_regressor.cc @@ -0,0 +1,196 @@ +#include <descriptor_identifier/Model/ModelLogRegressor.hpp> +#include <boost/filesystem.hpp> +#include "gtest/gtest.h" + +namespace +{ + class ModelLogRegssorTests : public ::testing::Test + { + protected: + void SetUp() override + { + _task_sizes_train = {10}; + _task_sizes_test = {2}; + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}; + std::vector<double> test_value_1 = {1.0, 7.0}; + + std::vector<double> value_2 = {1.10, 2.20, 3.10, 4.20, 5.10, 6.20, 7.10, 8.20, 9.10, 10.20}; + std::vector<double> test_value_2 = {2.10, 4.80}; + + model_node_ptr feat_1 = std::make_shared<ModelNode>(0, 0, "A", "$A$", "0", value_1, test_value_1, Unit("m")); + model_node_ptr feat_2 = std::make_shared<ModelNode>(1, 0, "B", "$B$", "1", value_2, test_value_2, Unit("m")); + + _features = {feat_1, feat_2}; + + _prop = std::vector<double>(10, 0.0); + _prop_test = std::vector<double>(2, 0.0); + + std::transform(value_1.begin(), value_1.end(), value_2.begin(), _prop.begin(), [](double v1, double v2){return 0.001 * std::pow(v1, 0.1) * std::pow(v2, -2.1);}); + std::transform(test_value_1.begin(), test_value_1.end(), test_value_2.begin(), _prop_test.begin(), [](double v1, double v2){return 0.001 * std::pow(v1, 0.1) * std::pow(v2, -2.1);}); + } + std::vector<int> _task_sizes_train; + std::vector<int> _task_sizes_test; + + std::vector<double> _prop; + std::vector<double> _prop_test; + + std::vector<model_node_ptr> _features; + }; + + TEST_F(ModelLogRegssorTests, FixInterceptFalseTest) + { + ModelLogRegressor model( + "Property", + Unit("m"), + _prop, + _prop_test, + _features, + _task_sizes_train, + _task_sizes_test, + false + ); + EXPECT_STREQ(model.toString().c_str(), "exp(c0) * (A)^a0 * (B)^a1"); + EXPECT_LT(model.rmse(), 1e-10); + EXPECT_LT(model.test_rmse(), 1e-10); + EXPECT_LT(model.max_ae(), 1e-10); + EXPECT_LT(model.test_max_ae(), 1e-10); + EXPECT_LT(model.mae(), 1e-10); + EXPECT_LT(model.test_mae(), 1e-10); + EXPECT_LT(model.mape(), 1e-10); + EXPECT_LT(model.test_mape(), 1e-10); + EXPECT_LT(model.percentile_25_ae(), 1e-10); + EXPECT_LT(model.percentile_25_test_ae(), 1e-10); + EXPECT_LT(model.percentile_50_ae(), 1e-10); + EXPECT_LT(model.percentile_50_test_ae(), 1e-10); + EXPECT_LT(model.percentile_75_ae(), 1e-10); + EXPECT_LT(model.percentile_75_test_ae(), 1e-10); + EXPECT_LT(model.percentile_95_ae(), 1e-10); + EXPECT_LT(model.percentile_95_test_ae(), 1e-10); + + EXPECT_EQ(model.n_samp_train(), 10); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 2); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + EXPECT_LT(std::abs(model.coefs()[0][0] - 0.1), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][1] + 2.1), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][2] - std::log(0.001)), 1e-10); + + model.to_file("train_false.dat", true, {5, 11}); + model.to_file("test_false.dat", false, {5, 11}); + } + + TEST_F(ModelLogRegssorTests, FixInterceptFalseFileTest) + { + ModelLogRegressor model("train_false.dat", "test_false.dat"); + EXPECT_STREQ(model.toString().c_str(), "exp(c0) * (A)^a0 * (B)^a1"); + EXPECT_LT(model.rmse(), 1e-10); + EXPECT_LT(model.test_rmse(), 1e-10); + EXPECT_LT(model.max_ae(), 1e-10); + EXPECT_LT(model.test_max_ae(), 1e-10); + EXPECT_LT(model.mae(), 1e-10); + EXPECT_LT(model.test_mae(), 1e-10); + EXPECT_LT(model.mape(), 1e-10); + EXPECT_LT(model.test_mape(), 1e-10); + EXPECT_LT(model.percentile_25_ae(), 1e-10); + EXPECT_LT(model.percentile_25_test_ae(), 1e-10); + EXPECT_LT(model.percentile_50_ae(), 1e-10); + EXPECT_LT(model.percentile_50_test_ae(), 1e-10); + EXPECT_LT(model.percentile_75_ae(), 1e-10); + EXPECT_LT(model.percentile_75_test_ae(), 1e-10); + EXPECT_LT(model.percentile_95_ae(), 1e-10); + EXPECT_LT(model.percentile_95_test_ae(), 1e-10); + + EXPECT_EQ(model.n_samp_train(), 10); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 2); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + EXPECT_LT(std::abs(model.coefs()[0][0] - 0.1), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][1] + 2.1), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][2] - std::log(0.001)), 1e-10); + + boost::filesystem::remove("train_false.dat"); + boost::filesystem::remove("test_false.dat"); + } + + TEST_F(ModelLogRegssorTests, FixInterceptTrueTest) + { + std::transform(_features[0]->value_ptr(), _features[0]->value_ptr() + 10, _features[1]->value_ptr(), _prop.begin(), [](double v1, double v2){return std::pow(v1, 0.1) * std::pow(v2, -2.1);}); + std::transform(_features[0]->test_value_ptr(), _features[0]->test_value_ptr() + 2, _features[1]->test_value_ptr(), _prop_test.begin(), [](double v1, double v2){return std::pow(v1, 0.1) * std::pow(v2, -2.1);}); + + ModelLogRegressor model( + "Property", + Unit("m"), + _prop, + _prop_test, + _features, + _task_sizes_train, + _task_sizes_test, + true + ); + EXPECT_STREQ(model.toString().c_str(), "(A)^a0 * (B)^a1"); + + EXPECT_LT(model.rmse(), 1e-10); + EXPECT_LT(model.test_rmse(), 1e-10); + EXPECT_LT(model.max_ae(), 1e-10); + EXPECT_LT(model.test_max_ae(), 1e-10); + EXPECT_LT(model.mae(), 1e-10); + EXPECT_LT(model.test_mae(), 1e-10); + EXPECT_LT(model.mape(), 1e-10); + EXPECT_LT(model.test_mape(), 1e-10); + EXPECT_LT(model.percentile_25_ae(), 1e-10); + EXPECT_LT(model.percentile_25_test_ae(), 1e-10); + EXPECT_LT(model.percentile_50_ae(), 1e-10); + EXPECT_LT(model.percentile_50_test_ae(), 1e-10); + EXPECT_LT(model.percentile_75_ae(), 1e-10); + EXPECT_LT(model.percentile_75_test_ae(), 1e-10); + EXPECT_LT(model.percentile_95_ae(), 1e-10); + EXPECT_LT(model.percentile_95_test_ae(), 1e-10); + + EXPECT_EQ(model.n_samp_train(), 10); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 2); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + EXPECT_LT(std::abs(model.coefs()[0][0] - 0.1), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][1] + 2.1), 1e-10); + + model.to_file("train_true.dat", true, {5, 11}); + model.to_file("test_true.dat", false, {5, 11}); + } + + TEST_F(ModelLogRegssorTests, FixInterceptTrueFileTest) + { + ModelLogRegressor model("train_true.dat", "test_true.dat"); + EXPECT_STREQ(model.toString().c_str(), "(A)^a0 * (B)^a1"); + EXPECT_LT(model.rmse(), 1e-10); + EXPECT_LT(model.test_rmse(), 1e-10); + EXPECT_LT(model.max_ae(), 1e-10); + EXPECT_LT(model.test_max_ae(), 1e-10); + EXPECT_LT(model.mae(), 1e-10); + EXPECT_LT(model.test_mae(), 1e-10); + EXPECT_LT(model.mape(), 1e-10); + EXPECT_LT(model.test_mape(), 1e-10); + EXPECT_LT(model.percentile_25_ae(), 1e-10); + EXPECT_LT(model.percentile_25_test_ae(), 1e-10); + EXPECT_LT(model.percentile_50_ae(), 1e-10); + EXPECT_LT(model.percentile_50_test_ae(), 1e-10); + EXPECT_LT(model.percentile_75_ae(), 1e-10); + EXPECT_LT(model.percentile_75_test_ae(), 1e-10); + EXPECT_LT(model.percentile_95_ae(), 1e-10); + EXPECT_LT(model.percentile_95_test_ae(), 1e-10); + + EXPECT_EQ(model.n_samp_train(), 10); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 2); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + EXPECT_LT(std::abs(model.coefs()[0][0] - 0.1), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][1] + 2.1), 1e-10); + + // boost::filesystem::remove("train_true.dat"); + // boost::filesystem::remove("test_true.dat"); + } +} diff --git a/tests/googletest/descriptor_identification/model/test_model_regressor.cc b/tests/googletest/descriptor_identification/model/test_model_regressor.cc new file mode 100644 index 0000000000000000000000000000000000000000..f76fc5bafe7106f85c095ef1ba17c72f77cab60e --- /dev/null +++ b/tests/googletest/descriptor_identification/model/test_model_regressor.cc @@ -0,0 +1,211 @@ +#include <descriptor_identifier/Model/ModelRegressor.hpp> +#include <boost/filesystem.hpp> +#include "gtest/gtest.h" + +namespace +{ + class ModelRegssorTests : public ::testing::Test + { + protected: + void SetUp() override + { + _task_sizes_train = {5, 5}; + _task_sizes_test = {1, 1}; + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}; + std::vector<double> test_value_1 = {1.0, 7.0}; + + std::vector<double> value_2 = {1.10, 2.20, 3.10, 4.20, 5.10, 6.20, 7.10, 8.20, 9.10, 10.20}; + std::vector<double> test_value_2 = {2.10, 4.80}; + + model_node_ptr feat_1 = std::make_shared<ModelNode>(0, 0, "A", "$A$", "0", value_1, test_value_1, Unit("m")); + model_node_ptr feat_2 = std::make_shared<ModelNode>(1, 0, "B", "$B$", "1", value_2, test_value_2, Unit("m")); + + _features = {feat_1, feat_2}; + + _prop = std::vector<double>(10, 0.0); + _prop_test = std::vector<double>(2, 0.0); + + std::transform(value_1.begin(), value_1.begin() + 5, value_2.begin(), _prop.begin(), [](double v1, double v2){return 0.001 + v1 + v2;}); + std::transform(value_1.begin() + 5, value_1.end(), value_2.begin() + 5, _prop.begin() + 5, [](double v1, double v2){return -6.5 + 1.25 * v1 - 0.4 * v2;}); + + std::transform(test_value_1.begin(), test_value_1.begin() + 1, test_value_2.begin(), _prop_test.begin(), [](double v1, double v2){return 0.001 + v1 + v2;}); + std::transform(test_value_1.begin() + 1, test_value_1.end(), test_value_2.begin() + 1, _prop_test.begin() + 1, [](double v1, double v2){return -6.5 + 1.25 * v1 - 0.4 * v2;}); + } + std::vector<int> _task_sizes_train; + std::vector<int> _task_sizes_test; + + std::vector<double> _prop; + std::vector<double> _prop_test; + + std::vector<model_node_ptr> _features; + }; + + TEST_F(ModelRegssorTests, FixInterceptFalseTest) + { + ModelRegressor model( + "Property", + Unit("m"), + _prop, + _prop_test, + _features, + _task_sizes_train, + _task_sizes_test, + false + ); + EXPECT_STREQ(model.toString().c_str(), "c0 + a0 * A + a1 * B"); + EXPECT_LT(model.rmse(), 1e-10); + EXPECT_LT(model.test_rmse(), 1e-10); + EXPECT_LT(model.max_ae(), 1e-10); + EXPECT_LT(model.test_max_ae(), 1e-10); + EXPECT_LT(model.mae(), 1e-10); + EXPECT_LT(model.test_mae(), 1e-10); + EXPECT_LT(model.mape(), 1e-10); + EXPECT_LT(model.test_mape(), 1e-10); + EXPECT_LT(model.percentile_25_ae(), 1e-10); + EXPECT_LT(model.percentile_25_test_ae(), 1e-10); + EXPECT_LT(model.percentile_50_ae(), 1e-10); + EXPECT_LT(model.percentile_50_test_ae(), 1e-10); + EXPECT_LT(model.percentile_75_ae(), 1e-10); + EXPECT_LT(model.percentile_75_test_ae(), 1e-10); + EXPECT_LT(model.percentile_95_ae(), 1e-10); + EXPECT_LT(model.percentile_95_test_ae(), 1e-10); + + EXPECT_EQ(model.n_samp_train(), 10); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 2); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + EXPECT_LT(std::abs(model.coefs()[0][0] - 1.0), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][1] - 1.0), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][2] - 0.001), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][0] - 1.25), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][1] + 0.4), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][2] + 6.5), 1e-10); + + model.to_file("train_false.dat", true, {5, 11}); + model.to_file("test_false.dat", false, {5, 11}); + } + + TEST_F(ModelRegssorTests, FixInterceptFalseFileTest) + { + ModelRegressor model("train_false.dat", "test_false.dat"); + EXPECT_STREQ(model.toString().c_str(), "c0 + a0 * A + a1 * B"); + EXPECT_LT(model.rmse(), 1e-10); + EXPECT_LT(model.test_rmse(), 1e-10); + EXPECT_LT(model.max_ae(), 1e-10); + EXPECT_LT(model.test_max_ae(), 1e-10); + EXPECT_LT(model.mae(), 1e-10); + EXPECT_LT(model.test_mae(), 1e-10); + EXPECT_LT(model.mape(), 1e-10); + EXPECT_LT(model.test_mape(), 1e-10); + EXPECT_LT(model.percentile_25_ae(), 1e-10); + EXPECT_LT(model.percentile_25_test_ae(), 1e-10); + EXPECT_LT(model.percentile_50_ae(), 1e-10); + EXPECT_LT(model.percentile_50_test_ae(), 1e-10); + EXPECT_LT(model.percentile_75_ae(), 1e-10); + EXPECT_LT(model.percentile_75_test_ae(), 1e-10); + EXPECT_LT(model.percentile_95_ae(), 1e-10); + EXPECT_LT(model.percentile_95_test_ae(), 1e-10); + + EXPECT_EQ(model.n_samp_train(), 10); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 2); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + EXPECT_LT(std::abs(model.coefs()[0][0] - 1.0), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][1] - 1.0), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][2] - 0.001), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][0] - 1.25), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][1] + 0.4), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][2] + 6.5), 1e-10); + + boost::filesystem::remove("train_false.dat"); + boost::filesystem::remove("test_false.dat"); + } + + TEST_F(ModelRegssorTests, FixInterceptTrueTest) + { + std::transform(_features[0]->value_ptr(), _features[0]->value_ptr() + 5, _features[1]->value_ptr(), _prop.begin(), [](double v1, double v2){return v1 + v2;}); + std::transform(_features[0]->value_ptr() + 5, _features[0]->value_ptr() + 10, _features[1]->value_ptr() + 5, _prop.begin() + 5, [](double v1, double v2){return 1.25 * v1 - 0.4 * v2;}); + + std::transform(_features[0]->test_value_ptr(), _features[0]->test_value_ptr() + 1, _features[1]->test_value_ptr(), _prop_test.begin(), [](double v1, double v2){return v1 + v2;}); + std::transform(_features[0]->test_value_ptr() + 1, _features[0]->test_value_ptr() + 2, _features[1]->test_value_ptr() + 1, _prop_test.begin() + 1, [](double v1, double v2){return 1.25 * v1 - 0.4 * v2;}); + + ModelRegressor model( + "Property", + Unit("m"), + _prop, + _prop_test, + _features, + _task_sizes_train, + _task_sizes_test, + true + ); + EXPECT_STREQ(model.toString().c_str(), "a0 * A + a1 * B"); + EXPECT_LT(model.rmse(), 1e-10); + EXPECT_LT(model.test_rmse(), 1e-10); + EXPECT_LT(model.max_ae(), 1e-10); + EXPECT_LT(model.test_max_ae(), 1e-10); + EXPECT_LT(model.mae(), 1e-10); + EXPECT_LT(model.test_mae(), 1e-10); + EXPECT_LT(model.mape(), 1e-10); + EXPECT_LT(model.test_mape(), 1e-10); + EXPECT_LT(model.percentile_25_ae(), 1e-10); + EXPECT_LT(model.percentile_25_test_ae(), 1e-10); + EXPECT_LT(model.percentile_50_ae(), 1e-10); + EXPECT_LT(model.percentile_50_test_ae(), 1e-10); + EXPECT_LT(model.percentile_75_ae(), 1e-10); + EXPECT_LT(model.percentile_75_test_ae(), 1e-10); + EXPECT_LT(model.percentile_95_ae(), 1e-10); + EXPECT_LT(model.percentile_95_test_ae(), 1e-10); + + EXPECT_EQ(model.n_samp_train(), 10); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 2); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + EXPECT_LT(std::abs(model.coefs()[0][0] - 1.0), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][1] - 1.0), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][0] - 1.25), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][1] + 0.4), 1e-10); + + model.to_file("train_true.dat", true, {5, 11}); + model.to_file("test_true.dat", false, {5, 11}); + } + + TEST_F(ModelRegssorTests, FixInterceptTrueFileTest) + { + ModelRegressor model("train_true.dat", "test_true.dat"); + EXPECT_STREQ(model.toString().c_str(), "a0 * A + a1 * B"); + EXPECT_LT(model.rmse(), 1e-10); + EXPECT_LT(model.test_rmse(), 1e-10); + EXPECT_LT(model.max_ae(), 1e-10); + EXPECT_LT(model.test_max_ae(), 1e-10); + EXPECT_LT(model.mae(), 1e-10); + EXPECT_LT(model.test_mae(), 1e-10); + EXPECT_LT(model.mape(), 1e-10); + EXPECT_LT(model.test_mape(), 1e-10); + EXPECT_LT(model.percentile_25_ae(), 1e-10); + EXPECT_LT(model.percentile_25_test_ae(), 1e-10); + EXPECT_LT(model.percentile_50_ae(), 1e-10); + EXPECT_LT(model.percentile_50_test_ae(), 1e-10); + EXPECT_LT(model.percentile_75_ae(), 1e-10); + EXPECT_LT(model.percentile_75_test_ae(), 1e-10); + EXPECT_LT(model.percentile_95_ae(), 1e-10); + EXPECT_LT(model.percentile_95_test_ae(), 1e-10); + + EXPECT_EQ(model.n_samp_train(), 10); + EXPECT_EQ(model.n_samp_test(), 2); + EXPECT_EQ(model.n_dim(), 2); + EXPECT_EQ(model.prop_unit(), Unit("m")); + + EXPECT_LT(std::abs(model.coefs()[0][0] - 1.0), 1e-10); + EXPECT_LT(std::abs(model.coefs()[0][1] - 1.0), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][0] - 1.25), 1e-10); + EXPECT_LT(std::abs(model.coefs()[1][1] + 0.4), 1e-10); + + boost::filesystem::remove("train_true.dat"); + boost::filesystem::remove("test_true.dat"); + } +} diff --git a/tests/googletest/descriptor_identification/sisso_regressor/test_sisso_classifier.cc b/tests/googletest/descriptor_identification/sisso_regressor/test_sisso_classifier.cc new file mode 100644 index 0000000000000000000000000000000000000000..62a777ce45cd2321cf27db81fb72ff7e52277044 --- /dev/null +++ b/tests/googletest/descriptor_identification/sisso_regressor/test_sisso_classifier.cc @@ -0,0 +1,189 @@ +#include <descriptor_identifier/SISSO_DI/SISSOClassifier.hpp> +#include <boost/filesystem.hpp> +#include "gtest/gtest.h" +#include <random> + +namespace +{ + class SISSOClassifierTests : public ::testing::Test + { + protected: + void SetUp() override + { + allowed_op_maps::set_node_maps(); + node_value_arrs::initialize_d_matrix_arr(); + mpi_setup::init_mpi_env(); + + node_value_arrs::initialize_values_arr(80, 20, 3); + + _task_sizes_train = {80}; + _task_sizes_test = {20}; + _leave_out_inds = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + std::vector<double> value_1(80, 0.0); + std::vector<double> value_2(80, 0.0); + std::vector<double> value_3(80, 0.0); + + std::vector<double> test_value_1(20, 0.0); + std::vector<double> test_value_2(20, 0.0); + std::vector<double> test_value_3(20, 0.0); + + std::default_random_engine generator; + std::uniform_real_distribution<double> distribution_3(-1.0, 1.0); + std::uniform_real_distribution<double> distribution_12_pos(0.1, 1.0); + std::uniform_real_distribution<double> distribution_12_neg(-1.0, -0.1); + + + for(int ii = 0; ii < 20; ++ii) + { + value_1[ii] = distribution_12_neg(generator); + value_2[ii] = distribution_12_neg(generator); + value_3[ii] = distribution_3(generator); + } + for(int ii = 20; ii < 40; ++ii) + { + value_1[ii] = distribution_12_pos(generator); + value_2[ii] = distribution_12_pos(generator); + value_3[ii] = distribution_3(generator); + } + for(int ii = 40; ii < 60; ++ii) + { + value_1[ii] = distribution_12_neg(generator); + value_2[ii] = distribution_12_pos(generator); + value_3[ii] = distribution_3(generator); + } + for(int ii = 60; ii < 80; ++ii) + { + value_1[ii] = distribution_12_pos(generator); + value_2[ii] = distribution_12_neg(generator); + value_3[ii] = distribution_3(generator); + } + + value_1[0] = 0.1; + value_1[20] = -0.1; + value_1[40] = 0.1; + value_1[60] = -0.1; + + value_2[0] = -0.1; + value_2[20] = 0.1; + value_2[40] = 0.1; + value_2[60] = -0.1; + + for(int ii = 0; ii < 5; ++ii) + { + test_value_1[ii] = distribution_12_neg(generator); + test_value_2[ii] = distribution_12_neg(generator); + test_value_3[ii] = distribution_3(generator); + } + for(int ii = 5; ii < 10; ++ii) + { + test_value_1[ii] = distribution_12_pos(generator); + test_value_2[ii] = distribution_12_pos(generator); + test_value_3[ii] = distribution_3(generator); + } + for(int ii = 10; ii < 15; ++ii) + { + test_value_1[ii] = distribution_12_neg(generator); + test_value_2[ii] = distribution_12_pos(generator); + test_value_3[ii] = distribution_3(generator); + } + for(int ii = 15; ii < 20; ++ii) + { + test_value_1[ii] = distribution_12_pos(generator); + test_value_2[ii] = distribution_12_neg(generator); + test_value_3[ii] = distribution_3(generator); + } + + + test_value_1[0] = 0.1; + test_value_1[5] = -0.1; + test_value_1[10] = 0.1; + test_value_1[15] = -0.1; + + test_value_2[0] = -0.1; + test_value_2[5] = 0.1; + test_value_2[10] = 0.1; + test_value_2[15] = -0.1; + + node_ptr feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + node_ptr feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit("m")); + node_ptr feat_3 = std::make_shared<FeatureNode>(2, "C", value_3, test_value_3, Unit("s")); + + _prop = std::vector<double>(80, 0.0); + _prop_test = std::vector<double>(20, 0.0); + std::fill_n(_prop.begin() + 40, 40, 1.0); + std::fill_n(_prop_test.begin() + 10, 10, 1.0); + + _phi_0 ={feat_1, feat_2, feat_3}; + + _allowed_ops = {"add", "sub", "mult", "sq", "cb", "sqrt", "cbrt"}; + + } + std::vector<std::string> _allowed_ops; + std::vector<node_ptr> _phi_0; + + std::vector<double> _prop; + std::vector<double> _prop_test; + + std::vector<int> _task_sizes_train; + std::vector<int> _task_sizes_test; + std::vector<int> _leave_out_inds; + }; + + TEST_F(SISSOClassifierTests, FixInterceptFalseTest) + { + std::shared_ptr<FeatureSpace> feat_space = std::make_shared<FeatureSpace>( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop, + _task_sizes_train, + "classification", + 2, + 10, + 1, + 0, + 1.0, + 1e-50, + 1e50 + ); + SISSOClassifier sisso( + feat_space, + "Property", + Unit("m"), + _prop, + _prop_test, + _task_sizes_train, + _task_sizes_test, + _leave_out_inds, + 2, + 2, + 3 + ); + std::vector<double> prop_comp(80, 0.0); + std::transform(_prop.begin(), _prop.end(), sisso.prop().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(p1 - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.end(), [](double p){return p > 1e-10;})); + + std::transform(_prop_test.begin(), _prop_test.begin() + 10, sisso.prop_test().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(p1 - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.begin() + 10, [](double p){return p > 1e-10;})); + + EXPECT_EQ(sisso.n_samp(), 80); + EXPECT_EQ(sisso.n_dim(), 2); + EXPECT_EQ(sisso.n_residual(), 2); + EXPECT_EQ(sisso.n_models_store(), 3); + + sisso.fit(); + + EXPECT_EQ(sisso.models().size(), 2); + EXPECT_EQ(sisso.models()[0].size(), 3); + + EXPECT_EQ(sisso.models()[0][0].n_convex_overlap_train(), 4); + EXPECT_EQ(sisso.models().back()[0].n_convex_overlap_train(), 0); + + EXPECT_EQ(sisso.models()[0][0].n_convex_overlap_test(), 4); + EXPECT_EQ(sisso.models().back()[0].n_convex_overlap_test(), 0); + + boost::filesystem::remove_all("feature_space/"); + boost::filesystem::remove_all("models/"); + } +} diff --git a/tests/googletest/descriptor_identification/sisso_regressor/test_sisso_log_regressor.cc b/tests/googletest/descriptor_identification/sisso_regressor/test_sisso_log_regressor.cc new file mode 100644 index 0000000000000000000000000000000000000000..efa7555519298c092489ea83587f68b7d417e66e --- /dev/null +++ b/tests/googletest/descriptor_identification/sisso_regressor/test_sisso_log_regressor.cc @@ -0,0 +1,199 @@ +#include <descriptor_identifier/SISSO_DI/SISSOLogRegressor.hpp> +#include <boost/filesystem.hpp> +#include "gtest/gtest.h" +#include <random> + +namespace +{ + class SISSOLogRegressorTests : public ::testing::Test + { + protected: + void SetUp() override + { + allowed_op_maps::set_node_maps(); + node_value_arrs::initialize_d_matrix_arr(); + mpi_setup::init_mpi_env(); + + node_value_arrs::initialize_values_arr(90, 10, 3); + + _task_sizes_train = {90}; + _task_sizes_test = {10}; + _leave_out_inds = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + std::vector<double> value_1(90, 0.0); + std::vector<double> value_2(90, 0.0); + std::vector<double> value_3(90, 0.0); + + std::vector<double> test_value_1(10, 0.0); + std::vector<double> test_value_2(10, 0.0); + std::vector<double> test_value_3(10, 0.0); + + std::default_random_engine generator; + std::uniform_real_distribution<double> distribution_feats(0.01, 100.0); + std::uniform_real_distribution<double> distribution_params(0.9, 1.1); + + for(int ii = 0; ii < 90; ++ii) + { + value_1[ii] = distribution_feats(generator); + value_2[ii] = distribution_feats(generator); + value_3[ii] = distribution_feats(generator); + } + + for(int ii = 0; ii < 10; ++ii) + { + test_value_1[ii] = distribution_feats(generator); + test_value_2[ii] = distribution_feats(generator); + test_value_3[ii] = distribution_feats(generator); + } + + node_ptr feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + node_ptr feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit("m")); + node_ptr feat_3 = std::make_shared<FeatureNode>(2, "C", value_3, test_value_3, Unit("s")); + + _phi_0 ={feat_1, feat_2, feat_3}; + + double a00 = distribution_params(generator); + double a10 = distribution_params(generator); + double c00 = distribution_feats(generator); + + _prop = std::vector<double>(90, 0.0); + std::transform(value_1.begin(), value_1.end(), value_2.begin(), _prop.begin(), [&c00, &a00, &a10](double v1, double v2){return c00 * std::pow(v1 * v1, a00) * std::pow(v2, a10);}); + + _prop_test = std::vector<double>(10, 0.0); + std::transform(test_value_1.begin(), test_value_1.end(), test_value_2.begin(), _prop_test.begin(), [&c00, &a00, &a10](double v1, double v2){return c00 * std::pow(v1 * v1, a00) * std::pow(v2, a10);}); + + _prop_zero_int = std::vector<double>(90, 0.0); + std::transform(value_1.begin(), value_1.end(), value_2.begin(), _prop_zero_int.begin(), [&a00, &a10](double v1, double v2){return std::pow(v1 * v1, a00) * std::pow(v2, a10);}); + + _prop_test_zero_int = std::vector<double>(10, 0.0); + std::transform(test_value_1.begin(), test_value_1.end(), test_value_2.begin(), _prop_test_zero_int.begin(), [&a00, &a10](double v1, double v2){return std::pow(v1 * v1, a00) * std::pow(v2, a10);}); + + _allowed_ops = {"div", "add", "mult", "sub"}; + + } + std::vector<std::string> _allowed_ops; + std::vector<node_ptr> _phi_0; + + std::vector<double> _prop; + std::vector<double> _prop_test; + + std::vector<double> _prop_zero_int; + std::vector<double> _prop_test_zero_int; + + std::vector<int> _task_sizes_train; + std::vector<int> _task_sizes_test; + std::vector<int> _leave_out_inds; + }; + + TEST_F(SISSOLogRegressorTests, FixInterceptFalseTest) + { + std::shared_ptr<FeatureSpace> feat_space = std::make_shared<FeatureSpace>( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop, + _task_sizes_train, + "log_regression", + 2, + 10, + 1, + 0, + 1.0, + 1e-50, + 1e50 + ); + SISSOLogRegressor sisso( + feat_space, + "Property", + Unit("m"), + _prop, + _prop_test, + _task_sizes_train, + _task_sizes_test, + _leave_out_inds, + 2, + 2, + 3, + false + ); + std::vector<double> prop_comp(90, 0.0); + std::transform(_prop.begin(), _prop.end(), sisso.prop().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(std::log(p1) - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.end(), [](double p){return p > 1e-10;})); + + std::transform(_prop_test.begin(), _prop_test.begin() + 10, sisso.prop_test().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(p1 - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.begin() + 10, [](double p){return p > 1e-10;})); + + EXPECT_EQ(sisso.n_samp(), 90); + EXPECT_EQ(sisso.n_dim(), 2); + EXPECT_EQ(sisso.n_residual(), 2); + EXPECT_EQ(sisso.n_models_store(), 3); + + sisso.fit(); + + EXPECT_EQ(sisso.models().size(), 2); + EXPECT_EQ(sisso.models()[0].size(), 3); + + EXPECT_LT(sisso.models().back()[0].rmse(), 1e-7); + EXPECT_LT(sisso.models().back()[0].test_rmse(), 1e-7); + + boost::filesystem::remove_all("feature_space/"); + boost::filesystem::remove_all("models/"); + } + + TEST_F(SISSOLogRegressorTests, FixInterceptTrueTest) + { + std::shared_ptr<FeatureSpace> feat_space = std::make_shared<FeatureSpace>( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop_zero_int, + _task_sizes_train, + "log_regression", + 2, + 10, + 1, + 0, + 1.0, + 1e-50, + 1e50 + ); + + SISSOLogRegressor sisso( + feat_space, + "Property", + Unit("m"), + _prop_zero_int, + _prop_test_zero_int, + _task_sizes_train, + _task_sizes_test, + _leave_out_inds, + 2, + 2, + 3, + true + ); + + std::vector<double> prop_comp(90, 0.0); + std::transform(_prop_zero_int.begin(), _prop_zero_int.end(), sisso.prop().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(std::log(p1) - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.end(), [](double p){return p > 1e-10;})); + + std::transform(_prop_test_zero_int.begin(), _prop_test_zero_int.begin() + 10, sisso.prop_test().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(p1 - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.begin() + 10, [](double p){return p > 1e-10;})); + + EXPECT_EQ(sisso.n_samp(), 90); + EXPECT_EQ(sisso.n_dim(), 2); + EXPECT_EQ(sisso.n_residual(), 2); + EXPECT_EQ(sisso.n_models_store(), 3); + + sisso.fit(); + + EXPECT_EQ(sisso.models().size(), 2); + EXPECT_EQ(sisso.models()[0].size(), 3); + + EXPECT_LT(sisso.models().back()[0].rmse(), 1e-7); + EXPECT_LT(sisso.models().back()[0].test_rmse(), 1e-7); + + boost::filesystem::remove_all("feature_space/"); + boost::filesystem::remove_all("models/"); + } +} diff --git a/tests/googletest/descriptor_identification/sisso_regressor/test_sisso_regressor.cc b/tests/googletest/descriptor_identification/sisso_regressor/test_sisso_regressor.cc new file mode 100644 index 0000000000000000000000000000000000000000..54c006789cc10d2844a7529d7ff57a6c83d3a8af --- /dev/null +++ b/tests/googletest/descriptor_identification/sisso_regressor/test_sisso_regressor.cc @@ -0,0 +1,220 @@ +#include <descriptor_identifier/SISSO_DI/SISSORegressor.hpp> +#include <boost/filesystem.hpp> +#include "gtest/gtest.h" +#include <random> + +namespace +{ + class SISSORegressorTests : public ::testing::Test + { + protected: + void SetUp() override + { + allowed_op_maps::set_node_maps(); + node_value_arrs::initialize_d_matrix_arr(); + mpi_setup::init_mpi_env(); + + node_value_arrs::initialize_values_arr(90, 10, 3); + + _task_sizes_train = {36, 54}; + _task_sizes_test = {4, 6}; + _leave_out_inds = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + std::vector<double> value_1(90, 0.0); + std::vector<double> value_2(90, 0.0); + std::vector<double> value_3(90, 0.0); + + std::vector<double> test_value_1(10, 0.0); + std::vector<double> test_value_2(10, 0.0); + std::vector<double> test_value_3(10, 0.0); + + std::default_random_engine generator; + std::uniform_real_distribution<double> distribution_feats(-50.0, 50.0); + std::uniform_real_distribution<double> distribution_params(-2.50, 2.50); + + for(int ii = 0; ii < 90; ++ii) + { + value_1[ii] = distribution_feats(generator); + value_2[ii] = distribution_feats(generator); + value_3[ii] = distribution_feats(generator); + } + + for(int ii = 0; ii < 10; ++ii) + { + test_value_1[ii] = distribution_feats(generator); + test_value_2[ii] = distribution_feats(generator); + test_value_3[ii] = distribution_feats(generator); + } + + node_ptr feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + node_ptr feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit("m")); + node_ptr feat_3 = std::make_shared<FeatureNode>(2, "C", value_3, test_value_3, Unit("s")); + + _phi_0 ={feat_1, feat_2, feat_3}; + + double a00 = distribution_params(generator); + double a01 = distribution_params(generator); + + double a10 = distribution_params(generator); + double a11 = distribution_params(generator); + + double c00 = distribution_params(generator); + double c01 = distribution_params(generator); + + _prop = std::vector<double>(90, 0.0); + std::transform(value_1.begin(), value_1.begin() + _task_sizes_train[0], value_2.begin(), _prop.begin(), [&c00, &a00](double v1, double v2){return c00 + a00 * (v1 - v2) * (v1 - v2);}); + std::transform(value_1.begin() + _task_sizes_train[0], value_1.end(), value_2.begin() + _task_sizes_train[0], _prop.begin() + _task_sizes_train[0], [&c01, &a01](double v1, double v2){return c01 + a01 * (v1 - v2) * (v1 - v2);}); + + std::transform(value_3.begin(), value_3.begin() + _task_sizes_train[0], _prop.begin(), _prop.begin(), [&a10](double v3, double p){return p + a10 * v3;}); + std::transform(value_3.begin() + _task_sizes_train[0], value_3.end(), _prop.begin() + _task_sizes_train[0], _prop.begin() + _task_sizes_train[0], [&a11](double v3, double p){return p + a11 * v3;}); + + _prop_test = std::vector<double>(10, 0.0); + std::transform(test_value_1.begin(), test_value_1.begin() + _task_sizes_test[0], test_value_2.begin(), _prop_test.begin(), [&c00, &a00](double v1, double v2){return c00 + a00 * (v1 - v2) * (v1 - v2);}); + std::transform(test_value_1.begin() + _task_sizes_test[0], test_value_1.end(), test_value_2.begin() + _task_sizes_test[0], _prop_test.begin() + _task_sizes_test[0], [&c01, &a01](double v1, double v2){return c01 + a01 * (v1 - v2) * (v1 - v2);}); + + std::transform(test_value_3.begin(), test_value_3.begin() + _task_sizes_test[0], _prop_test.begin(), _prop_test.begin(), [&a10](double v3, double p){return p + a10 * v3;}); + std::transform(test_value_3.begin() + _task_sizes_test[0], test_value_3.end(), _prop_test.begin() + _task_sizes_test[0], _prop_test.begin() + _task_sizes_test[0], [&a11](double v3, double p){return p + a11 * v3;}); + + _prop_zero_int = std::vector<double>(90, 0.0); + std::transform(value_1.begin(), value_1.begin() + _task_sizes_train[0], value_2.begin(), _prop_zero_int.begin(), [&a00](double v1, double v2){return a00 * (v1 - v2) * (v1 - v2);}); + std::transform(value_1.begin() + _task_sizes_train[0], value_1.end(), value_2.begin() + _task_sizes_train[0], _prop_zero_int.begin() + _task_sizes_train[0], [&a01](double v1, double v2){return a01 * (v1 - v2) * (v1 - v2);}); + + std::transform(value_3.begin(), value_3.begin() + _task_sizes_train[0], _prop_zero_int.begin(), _prop_zero_int.begin(), [&a10](double v3, double p){return p + a10 * v3;}); + std::transform(value_3.begin() + _task_sizes_train[0], value_3.end(), _prop_zero_int.begin() + _task_sizes_train[0], _prop_zero_int.begin() + _task_sizes_train[0], [&a11](double v3, double p){return p + a11 * v3;}); + + _prop_test_zero_int = std::vector<double>(10, 0.0); + std::transform(test_value_1.begin(), test_value_1.begin() + _task_sizes_test[0], test_value_2.begin(), _prop_test_zero_int.begin(), [&a00](double v1, double v2){return a00 * (v1 - v2) * (v1 - v2);}); + std::transform(test_value_1.begin() + _task_sizes_test[0], test_value_1.end(), test_value_2.begin() + _task_sizes_test[0], _prop_test_zero_int.begin() + _task_sizes_test[0], [&a01](double v1, double v2){return a01 * (v1 - v2) * (v1 - v2);}); + + std::transform(test_value_3.begin(), test_value_3.begin() + _task_sizes_test[0], _prop_test_zero_int.begin(), _prop_test_zero_int.begin(), [&a10](double v3, double p){return p + a10 * v3;}); + std::transform(test_value_3.begin() + _task_sizes_test[0], test_value_3.end(), _prop_test_zero_int.begin() + _task_sizes_test[0], _prop_test_zero_int.begin() + _task_sizes_test[0], [&a11](double v3, double p){return p + a11 * v3;}); + + + _allowed_ops = {"div", "sq", "cb", "sub"}; + } + std::vector<std::string> _allowed_ops; + std::vector<node_ptr> _phi_0; + + std::vector<double> _prop; + std::vector<double> _prop_test; + + std::vector<double> _prop_zero_int; + std::vector<double> _prop_test_zero_int; + + std::vector<int> _task_sizes_train; + std::vector<int> _task_sizes_test; + std::vector<int> _leave_out_inds; + }; + + TEST_F(SISSORegressorTests, FixInterceptFalseTest) + { + std::shared_ptr<FeatureSpace> feat_space = std::make_shared<FeatureSpace>( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop, + _task_sizes_train, + "regression", + 2, + 10, + 1, + 0, + 1.0, + 1e-50, + 1e50 + ); + SISSORegressor sisso( + feat_space, + "Property", + Unit("m"), + _prop, + _prop_test, + _task_sizes_train, + _task_sizes_test, + _leave_out_inds, + 2, + 2, + 3, + false + ); + std::vector<double> prop_comp(90, 0.0); + std::transform(_prop.begin(), _prop.end(), sisso.prop().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(p1 - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.end(), [](double p){return p > 1e-10;})); + + std::transform(_prop_test.begin(), _prop_test.begin() + 2, sisso.prop_test().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(p1 - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.begin() + 2, [](double p){return p > 1e-10;})); + + EXPECT_EQ(sisso.n_samp(), 90); + EXPECT_EQ(sisso.n_dim(), 2); + EXPECT_EQ(sisso.n_residual(), 2); + EXPECT_EQ(sisso.n_models_store(), 3); + + sisso.fit(); + + EXPECT_EQ(sisso.models().size(), 2); + EXPECT_EQ(sisso.models()[0].size(), 3); + + EXPECT_LT(sisso.models().back()[0].rmse(), 1e-10); + EXPECT_LT(sisso.models().back()[0].test_rmse(), 1e-10); + + boost::filesystem::remove_all("feature_space/"); + boost::filesystem::remove_all("models/"); + } + + TEST_F(SISSORegressorTests, FixInterceptTrueTest) + { + std::shared_ptr<FeatureSpace> feat_space = std::make_shared<FeatureSpace>( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop_zero_int, + _task_sizes_train, + "regression", + 2, + 10, + 1, + 0, + 1.0, + 1e-50, + 1e50 + ); + + SISSORegressor sisso( + feat_space, + "Property", + Unit("m"), + _prop_zero_int, + _prop_test_zero_int, + _task_sizes_train, + _task_sizes_test, + _leave_out_inds, + 2, + 2, + 3, + true + ); + + std::vector<double> prop_comp(90, 0.0); + std::transform(_prop_zero_int.begin(), _prop_zero_int.end(), sisso.prop().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(p1 - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.end(), [](double p){return p > 1e-10;})); + + std::transform(_prop_test_zero_int.begin(), _prop_test_zero_int.begin() + 2, sisso.prop_test().begin(), prop_comp.begin(), [](double p1, double p2){return std::abs(p1 - p2);}); + EXPECT_FALSE(std::any_of(prop_comp.begin(), prop_comp.begin() + 2, [](double p){return p > 1e-10;})); + + EXPECT_EQ(sisso.n_samp(), 90); + EXPECT_EQ(sisso.n_dim(), 2); + EXPECT_EQ(sisso.n_residual(), 2); + EXPECT_EQ(sisso.n_models_store(), 3); + + sisso.fit(); + + EXPECT_EQ(sisso.models().size(), 2); + EXPECT_EQ(sisso.models()[0].size(), 3); + + EXPECT_LT(sisso.models().back()[0].rmse(), 1e-10); + EXPECT_LT(sisso.models().back()[0].test_rmse(), 1e-10); + + boost::filesystem::remove_all("feature_space/"); + boost::filesystem::remove_all("models/"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_abs_diff_node.cc b/tests/googletest/feature_creation/feature_generation/test_abs_diff_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..95339a08109f196c0824f02ef5426d9327fb708b --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_abs_diff_node.cc @@ -0,0 +1,161 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" + +namespace +{ + class AbsDiffNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {5.0}; + + std::vector<double> value_2 = {10.0, 20.0, 30.0, 40.0}; + std::vector<double> test_value_2 = {50.0}; + + std::vector<double> value_3 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_3 = {5.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("s")); + _feat_4 = std::make_shared<FeatureNode>(3, "C", value_3, test_value_3, Unit("s")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<AddNode>(_feat_1, _feat_2, 4, -1e-50, 1e50)); + _phi.push_back(std::make_shared<SubNode>(_feat_1, _feat_2, 4, -1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + node_ptr _abs_diff_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(AbsDiffNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateAbsDiffNode(_phi, _phi[0], _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (AbsDiffNode created when units do not match.)"; + + generateAbsDiffNode(_phi, _phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (Creation of AbsDiffNode led to a feature with a constant value)"; + + generateAbsDiffNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1.0); + EXPECT_EQ(_phi.size(), 6) << " (AbsDiffNode created with an absolute value above the upper bound)"; + + generateAbsDiffNode(_phi, _phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (AbsDiffNode created with an absolute value below the lower bound)"; + + generateAbsDiffNode(_phi, _phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (AbsDiffNode created with only one primary feature present)"; + + generateAbsDiffNode(_phi, _phi[4], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (AbsDiffNode created when some terms cancel out)"; + + generateAbsDiffNode(_phi, _phi[5], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (AbsDiffNode created that is a duplicate of a second feature)"; + + generateAbsDiffNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (Failure to create a valid feature)"; + } + + TEST_F(AbsDiffNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _abs_diff_test = std::make_shared<AbsDiffNode>(_phi[0], _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AbsDiffNode created when units do not match.)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_diff_test = std::make_shared<AbsDiffNode>(_phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (Creation of AbsDiffNode led to a feature with a constant value)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_diff_test = std::make_shared<AbsDiffNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1.0); + EXPECT_TRUE(false) << " (AbsDiffNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_diff_test = std::make_shared<AbsDiffNode>(_phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (AbsDiffNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_diff_test = std::make_shared<AbsDiffNode>(_phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AbsDiffNode created with only one primary feature present)"; + } + catch(const InvalidFeatureException& e) + {} + try + { + _abs_diff_test = std::make_shared<AbsDiffNode>(_phi[1], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AbsDiffNode created when some terms cancel out)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_diff_test = std::make_shared<AbsDiffNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + try + { + _abs_diff_test = std::make_shared<AbsDiffNode>(_phi[5], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AbsDiffNode created that is a duplicate of a second feature)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(AbsDiffNodeTest, AttributesTest) + { + _abs_diff_test = std::make_shared<AbsDiffNode>(_phi[0], _phi[1], 5, 1e-50, 1e50); + _abs_diff_test = std::make_shared<AbsDiffNode>(_abs_diff_test, _phi[1], 6, 1e-50, 1e50); + + EXPECT_EQ(_abs_diff_test->rung(), 2); + + EXPECT_EQ(_abs_diff_test->value_ptr()[0], 1.0); + EXPECT_EQ(_abs_diff_test->test_value_ptr()[0], 5.0); + + EXPECT_EQ(_abs_diff_test->value()[0], 1.0); + EXPECT_EQ(_abs_diff_test->test_value()[0], 5.0); + + EXPECT_STREQ(_abs_diff_test->unit().toString().c_str(), "m"); + + EXPECT_STREQ(_abs_diff_test->expr().c_str(), "||A - (B)| - (B)|"); + EXPECT_STREQ(_abs_diff_test->postfix_expr().c_str(), "0|1|abd|1|abd"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_abs_node.cc b/tests/googletest/feature_creation/feature_generation/test_abs_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..97910a20fdc3cdf177c57df3dbe2a0e590cdb8fc --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_abs_node.cc @@ -0,0 +1,149 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" + +namespace +{ + class AbsNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {-1.0, -2.0, -3.0, -4.0}; + std::vector<double> test_value_1 = {50.0}; + + std::vector<double> value_2 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_2 = {5.0}; + + std::vector<double> value_3 = {1.0, -1.0, 1.0, -1.0}; + std::vector<double> test_value_3 = {1.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_3, test_value_3, Unit("m")); + + _phi = {_feat_1, _feat_2, _feat_3}; + _phi.push_back(std::make_shared<AbsDiffNode>(_feat_1, _feat_3, 3, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + + node_ptr _abs_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(AbsNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateAbsNode(_phi, _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 4) << " (Creation of AbsNode led to a feature with a constant value)"; + + generateAbsNode(_phi, _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 4) << "(AbsNode created with a feature that only has positive values)"; + + generateAbsNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), 4) << " (AbsNode created with an absolute value above the upper bound)"; + + generateAbsNode(_phi, _phi[0], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 4) << " (AbsNode created with an absolute value below the lower bound)"; + + generateAbsNode(_phi, _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 4) << " (AbsfNode created from another an AbsDiffNode)"; + + generateAbsNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (Failure to create a valid feature)"; + + generateAbsNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (AbsNode created from another AbsNode)"; + + } + + TEST_F(AbsNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _abs_test = std::make_shared<AbsNode>(_phi[2], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (Creation of AbsNode led to a feature with a constant value)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_test = std::make_shared<AbsNode>(_phi[1], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AbsNode created with a feature that only has positive values)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_test = std::make_shared<AbsNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (AbsNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_test = std::make_shared<AbsNode>(_phi[0], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (AbsNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_test = std::make_shared<AbsNode>(_phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AbsfNode created from another an AbsDiffNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _abs_test = std::make_shared<AbsNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + + try + { + _abs_test = std::make_shared<AbsNode>(_abs_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AbsNode created from another AbsNode)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(AbsNodeTest, AttributesTest) + { + _abs_test = std::make_shared<AbsNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_abs_test->rung(), 1); + + EXPECT_EQ(_abs_test->value_ptr()[0], 1.0); + EXPECT_EQ(_abs_test->test_value_ptr()[0], 50.0); + + EXPECT_EQ(_abs_test->value()[0], 1.0); + EXPECT_EQ(_abs_test->test_value()[0], 50.0); + + EXPECT_STREQ(_abs_test->unit().toString().c_str(), "m"); + + EXPECT_STREQ(_abs_test->expr().c_str(), "|A|"); + EXPECT_STREQ(_abs_test->postfix_expr().c_str(), "0|abs"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_add_node.cc b/tests/googletest/feature_creation/feature_generation/test_add_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..b93800539d0fd067f710bec38e8f317f5fa570f7 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_add_node.cc @@ -0,0 +1,159 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" + +namespace +{ + class AddNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {5.0}; + + std::vector<double> value_2 = {10.0, 20.0, 30.0, 40.0}; + std::vector<double> test_value_2 = {50.0}; + + std::vector<double> value_3 = {-1.0, -2.0, -3.0, -4.0}; + std::vector<double> test_value_3 = {-5.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("s")); + _feat_4 = std::make_shared<FeatureNode>(3, "C", value_3, test_value_3, Unit("s")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<SubNode>(_feat_1, _feat_2, 4, -1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + node_ptr _add_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(AddNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateAddNode(_phi, _phi[0], _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (AddNode created when units do not match.)"; + + generateAddNode(_phi, _phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (Creation of AddNode led to a feature with a constant value)"; + + generateAddNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1.0); + EXPECT_EQ(_phi.size(), 5) << " (AddNode created with an absolute value above the upper bound)"; + + generateAddNode(_phi, _phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (AddNode created with an absolute value below the lower bound)"; + + generateAddNode(_phi, _phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (AddNode created with only one primary feature present)"; + + generateAddNode(_phi, _phi[4], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (AddNode created when some terms cancel out)"; + + generateAddNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (Failure to create a valid feature)"; + + generateAddNode(_phi, _phi[5], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (AddNode created that is a duplicate of a second feature)"; + } + + TEST_F(AddNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _add_test = std::make_shared<AddNode>(_phi[0], _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AddNode created when units do not match.)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _add_test = std::make_shared<AddNode>(_phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (Creation of AddNode led to a feature with a constant value)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _add_test = std::make_shared<AddNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1.0); + EXPECT_TRUE(false) << " (AddNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _add_test = std::make_shared<AddNode>(_phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (AddNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _add_test = std::make_shared<AddNode>(_phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AddNode created with only one primary feature present)"; + } + catch(const InvalidFeatureException& e) + {} + try + { + _add_test = std::make_shared<AddNode>(_phi[1], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AddNode created when some terms cancel out)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _add_test = std::make_shared<AddNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + try + { + _add_test = std::make_shared<AddNode>(_add_test, _add_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (AddNode created that is a duplicate of a second feature)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(AddNodeTest, AttributesTest) + { + _add_test = std::make_shared<AddNode>(_phi[0], _phi[1], 5, 1e-50, 1e50); + _add_test = std::make_shared<AddNode>(_add_test, _phi[1], 6, 1e-50, 1e50); + + EXPECT_EQ(_add_test->rung(), 2); + + EXPECT_EQ(_add_test->value_ptr()[0], 21.0); + EXPECT_EQ(_add_test->test_value_ptr()[0], 105.0); + + EXPECT_EQ(_add_test->value()[0], 21.0); + EXPECT_EQ(_add_test->test_value()[0], 105.0); + + EXPECT_STREQ(_add_test->unit().toString().c_str(), "m"); + + EXPECT_STREQ(_add_test->expr().c_str(), "((A + B) + B)"); + EXPECT_STREQ(_add_test->postfix_expr().c_str(), "0|1|add|1|add"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_cb_node.cc b/tests/googletest/feature_creation/feature_generation/test_cb_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..6099b8e5e2dd795e09335f97248a8923ed74baa2 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_cb_node.cc @@ -0,0 +1,146 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp> + +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class CbNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 8.0}; + std::vector<double> test_value_1 = {2.0}; + + std::vector<double> value_2 = {1.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + std::vector<double> value_3 = {-1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_3 = {0.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("m")); + _feat_4 = std::make_shared<FeatureNode>(3, "D", value_3, test_value_3, Unit("m")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<InvNode>(_feat_1, 6, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SqNode>(_feat_1, 11, 1e-50, 1e50)); + _phi.push_back(std::make_shared<CbrtNode>(_feat_1, 11, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + + node_ptr _cb_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(CbNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + int phi_sz = _phi.size(); + + generateCbNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbNode created with an absolute value above the upper bound)"; + + generateCbNode(_phi, _phi[0], feat_ind, 1e10, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbNode created with an absolute value below the lower bound)"; + + generateCbNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbNode created from a InvNode)"; + + generateCbNode(_phi, _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbNode created from a SqNode)"; + + generateCbNode(_phi, _phi[6], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbNode created from a CbrtNode)"; + + generateCbNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + ++phi_sz; + EXPECT_EQ(_phi.size(), phi_sz) << " (Failure to create a valid feature)"; + } + + TEST_F(CbNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + try + { + _cb_test = std::make_shared<CbNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (CbNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cb_test = std::make_shared<CbNode>(_phi[0], feat_ind, 1e10, 1e50); + EXPECT_TRUE(false) << " (CbNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cb_test = std::make_shared<CbNode>(_phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (CbNode created from a InvNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cb_test = std::make_shared<CbNode>(_phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (CbNode created from a SqNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cb_test = std::make_shared<CbNode>(_phi[6], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (CbNode created from a CbrtNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cb_test = std::make_shared<CbNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + } + + TEST_F(CbNodeTest, AttributesTest) + { + _cb_test = std::make_shared<CbNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_cb_test->rung(), 1); + + EXPECT_EQ(_cb_test->value_ptr()[1], 8.0); + EXPECT_EQ(_cb_test->test_value_ptr()[0], 8.0); + + EXPECT_EQ(_cb_test->value()[1], 8.0); + EXPECT_EQ(_cb_test->test_value()[0], 8.0); + + EXPECT_STREQ(_cb_test->unit().toString().c_str(), "m^3"); + + EXPECT_STREQ(_cb_test->expr().c_str(), "(A)^3"); + EXPECT_STREQ(_cb_test->postfix_expr().c_str(), "0|cb"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_cbrt_node.cc b/tests/googletest/feature_creation/feature_generation/test_cbrt_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..5760cb80981973efba51448fa005ca2a5afc0e34 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_cbrt_node.cc @@ -0,0 +1,171 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sp/sixth_power.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp> + +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class CbrtNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 8.0}; + std::vector<double> test_value_1 = {8.0}; + + std::vector<double> value_2 = {1.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + std::vector<double> value_3 = {-1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_3 = {0.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("m")); + _feat_4 = std::make_shared<FeatureNode>(3, "D", value_3, test_value_3, Unit("m")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<InvNode>(_feat_1, 6, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SqNode>(_feat_1, 11, 1e-50, 1e50)); + _phi.push_back(std::make_shared<CbNode>(_feat_1, 12, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SixPowNode>(_feat_1, 12, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + + node_ptr _cbrt_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(CbrtNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + int phi_sz = _phi.size(); + + generateCbrtNode(_phi, _phi[3], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbrtNode created with a feature that has a value < 0.0)"; + + generateCbrtNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbrtNode created with an absolute value above the upper bound)"; + + generateCbrtNode(_phi, _phi[0], feat_ind, 1e10, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbrtNode created with an absolute value below the lower bound)"; + + generateCbrtNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbrtNode created from a InvNode)"; + + generateCbrtNode(_phi, _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbrtNode created from a SqNode)"; + + generateCbrtNode(_phi, _phi[6], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbrtNode created from a CbNode)"; + + generateCbrtNode(_phi, _phi[7], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (CbrtNode created from a SixPowNode)"; + + generateCbrtNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + ++phi_sz; + EXPECT_EQ(_phi.size(), phi_sz) << " (Failure to create a valid feature)"; + } + + TEST_F(CbrtNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _cbrt_test = std::make_shared<CbrtNode>(_phi[3], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (CbrtNode created with a feature that has a value < 0.0)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cbrt_test = std::make_shared<CbrtNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (CbrtNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cbrt_test = std::make_shared<CbrtNode>(_phi[0], feat_ind, 1e10, 1e50); + EXPECT_TRUE(false) << " (CbrtNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cbrt_test = std::make_shared<CbrtNode>(_phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (CbrtNode created from a InvNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cbrt_test = std::make_shared<CbrtNode>(_phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (CbrtNode created from a SqNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cbrt_test = std::make_shared<CbrtNode>(_phi[6], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (CbrtNode created from a CbNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cbrt_test = std::make_shared<CbrtNode>(_phi[7], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (CbrtNode created from a SixPowNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cbrt_test = std::make_shared<CbrtNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + } + + TEST_F(CbrtNodeTest, AttributesTest) + { + _cbrt_test = std::make_shared<CbrtNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_cbrt_test->rung(), 1); + + EXPECT_EQ(_cbrt_test->value_ptr()[3], 2.0); + EXPECT_EQ(_cbrt_test->test_value_ptr()[0], 2.0); + + EXPECT_EQ(_cbrt_test->value()[3], 2.0); + EXPECT_EQ(_cbrt_test->test_value()[0], 2.0); + + EXPECT_STREQ(_cbrt_test->unit().toString().c_str(), "m^0.333333"); + + EXPECT_STREQ(_cbrt_test->expr().c_str(), "cbrt(A)"); + EXPECT_STREQ(_cbrt_test->postfix_expr().c_str(), "0|cbrt"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_cos_node.cc b/tests/googletest/feature_creation/feature_generation/test_cos_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..9b4f270a78e6e80738c63fb95b71f1a3cb8110cd --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_cos_node.cc @@ -0,0 +1,147 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class CosNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {0.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {0.0}; + + std::vector<double> value_2 = {0.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit()); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit()); + + _phi = {_feat_1, _feat_2, _feat_3}; + _phi.push_back(std::make_shared<SinNode>(_feat_1, 3, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + + node_ptr _cos_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(CosNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateCosNode(_phi, _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 4) << " (Creation of CosNode led to a feature with a constant value)"; + + generateCosNode(_phi, _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 4) << "(CosNode created with a feature that is not unitless)"; + + generateCosNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), 4) << " (CosNode created with an absolute value above the upper bound)"; + + generateCosNode(_phi, _phi[0], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 4) << " (CosNode created with an absolute value below the lower bound)"; + + generateCosNode(_phi, _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 4) << " (CosNode created from another a SinNode)"; + + generateCosNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (Failure to create a valid feature)"; + + generateCosNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (CosNode created from another CosNode)"; + + } + + TEST_F(CosNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _cos_test = std::make_shared<CosNode>(_phi[2], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (Creation of CosNode led to a feature with a constant value)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cos_test = std::make_shared<CosNode>(_phi[1], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << "(CosNode created with a feature that is not unitless)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cos_test = std::make_shared<CosNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (CosNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cos_test = std::make_shared<CosNode>(_phi[0], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (CosNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cos_test = std::make_shared<CosNode>(_phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (CosNode created from another a SinNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _cos_test = std::make_shared<CosNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + + try + { + _cos_test = std::make_shared<CosNode>(_cos_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (CosNode created from another CosNode)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(CosNodeTest, AttributesTest) + { + _cos_test = std::make_shared<CosNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_cos_test->rung(), 1); + + EXPECT_EQ(_cos_test->value_ptr()[0], 1.0); + EXPECT_EQ(_cos_test->test_value_ptr()[0], 1.0); + + EXPECT_EQ(_cos_test->value()[0], 1.0); + EXPECT_EQ(_cos_test->test_value()[0], 1.0); + + EXPECT_STREQ(_cos_test->unit().toString().c_str(), "Unitless"); + + EXPECT_STREQ(_cos_test->expr().c_str(), "cos(A)"); + EXPECT_STREQ(_cos_test->postfix_expr().c_str(), "0|cos"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_div_node.cc b/tests/googletest/feature_creation/feature_generation/test_div_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..42cd9c6d8d596d8d55cdf9f5b3e69d4524bdc12a --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_div_node.cc @@ -0,0 +1,209 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" + +namespace +{ + class DivNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {5.0}; + + std::vector<double> value_2 = {10.0, 25.0, 30.0, 40.0}; + std::vector<double> test_value_2 = {50.0}; + + std::vector<double> value_3 = {0.5, 1.0, 1.5, 2.0}; + std::vector<double> test_value_3 = {-5.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("s")); + _feat_4 = std::make_shared<FeatureNode>(3, "D", value_3, test_value_3, Unit("s")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<MultNode>(_feat_1, _feat_2, 4, -1e-50, 1e50)); + _phi.push_back(std::make_shared<InvNode>(_feat_2, 5, -1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + node_ptr _div_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(DivNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateDivNode(_phi, _phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (Creation of DivNode led to a feature with a constant value)"; + + generateDivNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), 6) << " (DivNode created with an absolute value above the upper bound)"; + + generateDivNode(_phi, _phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (DivNode created with an absolute value below the lower bound)"; + + generateDivNode(_phi, _phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (DivNode created with only one primary feature present)"; + + generateDivNode(_phi, _phi[4], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (DivNode created when some terms cancel out)"; + + generateDivNode(_phi, _phi[0], _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (DivNode created when one of the input features is an InvNode)"; + + generateDivNode(_phi, _phi[5], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (DivNode created when one of the input features is an InvNode)"; + + generateDivNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (Failure to create a valid feature)"; + + generateDivNode(_phi, _phi[6], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (DivNode created that is a duplicate of a second feature)"; + + generateDivNode(_phi, _phi[2], _phi[6], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (DivNode created when the second input feature is a DivvNode)"; + + generateDivNode(_phi, _phi[0], _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 8) << " (Failure to create valid feature.)"; + + generateDivNode(_phi, _phi[6], _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 9) << " (Failure to create valid feature.)"; + } + + TEST_F(DivNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _div_test = std::make_shared<DivNode>(_phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (Creation of DivNode led to a feature with a constant value)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _div_test = std::make_shared<DivNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (DivNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _div_test = std::make_shared<DivNode>(_phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (DivNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _div_test = std::make_shared<DivNode>(_phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (DivNode created with only one primary feature present)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _div_test = std::make_shared<DivNode>(_phi[4], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (DivNode created when some terms cancel out)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _div_test = std::make_shared<DivNode>(_phi[0], _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (DivNode created when one of the input features is an InvNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _div_test = std::make_shared<DivNode>(_phi[5], _phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + EXPECT_TRUE(false) << " (DivNode created when one of the input features is an InvNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _div_test = std::make_shared<DivNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1e50); + } + catch(const InvalidFeatureException& e) + { + EXPECT_TRUE(false) << " (Failure to create a valid feature)"; + } + + try + { + _div_test = std::make_shared<DivNode>(_div_test, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (DivNode created that is a duplicate of a second feature)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _div_test = std::make_shared<DivNode>(_phi[2], _div_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (DivNode created when the second input feature is a DivNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _div_test = std::make_shared<DivNode>(_phi[0], _phi[2], feat_ind, 1e-50, 1e50); + } + catch(const InvalidFeatureException& e) + { + EXPECT_TRUE(false) << " (Failure to create valid feature.)"; + } + + try + { + _div_test = std::make_shared<DivNode>(_div_test, _phi[2], feat_ind, 1e-50, 1e50); + } + catch(const InvalidFeatureException& e) + { + EXPECT_TRUE(false) << " (Failure to create valid feature.)"; + } + } + + TEST_F(DivNodeTest, AttributesTest) + { + _div_test = std::make_shared<DivNode>(_phi[0], _phi[1], 5, 1e-50, 1e50); + _div_test = std::make_shared<DivNode>(_div_test, _phi[1], 6, 1e-50, 1e50); + + EXPECT_EQ(_div_test->rung(), 2); + + EXPECT_EQ(_div_test->value_ptr()[0], 0.01); + EXPECT_EQ(_div_test->test_value_ptr()[0], 0.002); + + EXPECT_EQ(_div_test->value()[0], 0.01); + EXPECT_EQ(_div_test->test_value()[0], 0.002); + + EXPECT_STREQ(_div_test->unit().toString().c_str(), "m^-1"); + + EXPECT_STREQ(_div_test->expr().c_str(), "[([(A) / (B)]) / (B)]"); + EXPECT_STREQ(_div_test->postfix_expr().c_str(), "0|1|div|1|div"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_exp_node.cc b/tests/googletest/feature_creation/feature_generation/test_exp_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..3d15c29a367ea5e8e9d0f0c5f01a4a1133edce83 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_exp_node.cc @@ -0,0 +1,176 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp> + +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class ExpNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 3); + + std::vector<double> value_1 = {0.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {0.0}; + + std::vector<double> value_2 = {1.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit()); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit()); + + _phi = {_feat_1, _feat_2, _feat_3}; + _phi.push_back(std::make_shared<LogNode>(_feat_3, 3, 1e-50, 1e50)); + _phi.push_back(std::make_shared<NegExpNode>(_feat_1, 3, 1e-50, 1e50)); + _phi.push_back(std::make_shared<AddNode>(_feat_1, _feat_3, 3, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SubNode>(_feat_1, _feat_3, 3, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + + node_ptr _exp_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(ExpNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateExpNode(_phi, _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << "(ExpNode created with a feature that is not unitless)"; + + generateExpNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), 7) << " (ExpNode created with an absolute value above the upper bound)"; + + generateExpNode(_phi, _phi[0], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (ExpNode created with an absolute value below the lower bound)"; + + generateExpNode(_phi, _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (ExpNode created from a LogNode)"; + + generateExpNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (ExpNode created from a NegExpNode)"; + + generateExpNode(_phi, _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (ExpNode created from a AddNode)"; + + generateExpNode(_phi, _phi[6], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (ExpNode created from a SubNode)"; + + generateExpNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 8) << " (Failure to create a valid feature)"; + + generateExpNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 8) << " (ExpNode created from another ExpNode)"; + + } + + TEST_F(ExpNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _exp_test = std::make_shared<ExpNode>(_phi[1], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << "(ExpNode created with a feature that is not unitless)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _exp_test = std::make_shared<ExpNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (ExpNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _exp_test = std::make_shared<ExpNode>(_phi[0], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (ExpNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _exp_test = std::make_shared<ExpNode>(_phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (ExpNode created from a LogNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _exp_test = std::make_shared<ExpNode>(_phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (ExpNode created from a NegExpNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _exp_test = std::make_shared<ExpNode>(_phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (ExpNode created from a AddNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _exp_test = std::make_shared<ExpNode>(_phi[6], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (ExpNode created from a SubNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _exp_test = std::make_shared<ExpNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + + try + { + _exp_test = std::make_shared<ExpNode>(_exp_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (ExpNode created from another ExpNode)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(ExpNodeTest, AttributesTest) + { + _exp_test = std::make_shared<ExpNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_exp_test->rung(), 1); + + EXPECT_EQ(_exp_test->value_ptr()[0], 1.0); + EXPECT_EQ(_exp_test->test_value_ptr()[0], 1.0); + + EXPECT_EQ(_exp_test->value()[0], 1.0); + EXPECT_EQ(_exp_test->test_value()[0], 1.0); + + EXPECT_STREQ(_exp_test->unit().toString().c_str(), "Unitless"); + + EXPECT_STREQ(_exp_test->expr().c_str(), "exp(A)"); + EXPECT_STREQ(_exp_test->postfix_expr().c_str(), "0|exp"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_feat_node.cc b/tests/googletest/feature_creation/feature_generation/test_feat_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..75da02f179e6555784993d00eb5bbafb95f5d291 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_feat_node.cc @@ -0,0 +1,74 @@ +#include <feature_creation/node/FeatureNode.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" + +namespace +{ + class FeatNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 3); + + _value_1 = {1.0, 2.0, 3.0, 4.0}; + _test_value_1 = {5.0}; + + _value_2 = {10.0, 10.0, 10.0, 10.0}; + _test_value_2 = {10.0}; + + _value_3 = {1.0, 2.0, 3.0, 1.0/0.0}; + _test_value_3 = {5.0}; + } + + std::vector<double> _value_1; + std::vector<double> _test_value_1; + + std::vector<double> _value_2; + std::vector<double> _test_value_2; + + std::vector<double> _value_3; + std::vector<double> _test_value_3; + }; + + TEST_F(FeatNodeTest, ConstructorTest) + { + node_ptr feat_1 = std::make_shared<FeatureNode>(0, "A", _value_1, _test_value_1, Unit("m")); + node_ptr feat_2 = std::make_shared<FeatureNode>(1, "B", _value_2, _test_value_2, Unit()); + node_ptr feat_3 = std::make_shared<FeatureNode>(2, "C", _value_3, _test_value_3, Unit("m")); + + EXPECT_FALSE(feat_1->is_const()); + EXPECT_FALSE(feat_1->is_nan()); + EXPECT_STREQ(feat_1->unit().toString().c_str(), "m"); + EXPECT_STREQ(feat_1->expr().c_str(), "A"); + EXPECT_STREQ(feat_1->postfix_expr().c_str(), "0"); + EXPECT_EQ(feat_1->value()[0], _value_1[0]); + EXPECT_EQ(feat_1->test_value()[0], _test_value_1[0]); + EXPECT_EQ(feat_1->value_ptr()[0], _value_1[0]); + EXPECT_EQ(feat_1->test_value_ptr()[0], _test_value_1[0]); + EXPECT_EQ(feat_1->n_feats(), 0); + + EXPECT_TRUE(feat_2->is_const()); + EXPECT_FALSE(feat_2->is_nan()); + EXPECT_STREQ(feat_2->unit().toString().c_str(), "Unitless"); + EXPECT_STREQ(feat_2->expr().c_str(), "B"); + EXPECT_STREQ(feat_2->postfix_expr().c_str(), "1"); + EXPECT_EQ(feat_2->value()[0], _value_2[0]); + EXPECT_EQ(feat_2->test_value()[0], _test_value_2[0]); + EXPECT_EQ(feat_2->value_ptr()[0], _value_2[0]); + EXPECT_EQ(feat_2->test_value_ptr()[0], _test_value_2[0]); + EXPECT_EQ(feat_2->n_feats(), 0); + + EXPECT_FALSE(feat_3->is_const()); + EXPECT_TRUE(feat_3->is_nan()); + EXPECT_STREQ(feat_3->unit().toString().c_str(), "m"); + EXPECT_STREQ(feat_3->expr().c_str(), "C"); + EXPECT_STREQ(feat_3->postfix_expr().c_str(), "2"); + EXPECT_EQ(feat_3->value()[0], _value_3[0]); + EXPECT_EQ(feat_3->test_value()[0], _test_value_3[0]); + EXPECT_EQ(feat_3->value_ptr()[0], _value_3[0]); + EXPECT_EQ(feat_3->test_value_ptr()[0], _test_value_3[0]); + EXPECT_EQ(feat_3->n_feats(), 0); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_inv_node.cc b/tests/googletest/feature_creation/feature_generation/test_inv_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..dae10cde8f2efd1793d9b5d074c0dac1abc9601b --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_inv_node.cc @@ -0,0 +1,170 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp> + +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class InvNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 8.0}; + std::vector<double> test_value_1 = {2.0}; + + std::vector<double> value_2 = {1.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + std::vector<double> value_3 = {0.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_3 = {0.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit()); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("m")); + _feat_4 = std::make_shared<FeatureNode>(3, "D", value_3, test_value_3, Unit("m")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<ExpNode>(_feat_2, 6, 1e-50, 1e50)); + _phi.push_back(std::make_shared<NegExpNode>(_feat_2, 10, 1e-50, 1e50)); + _phi.push_back(std::make_shared<DivNode>(_feat_1, _feat_3, 11, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + + node_ptr _inv_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(InvNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + int phi_sz = _phi.size(); + + generateInvNode(_phi, _phi[3], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), phi_sz) << " (InvNode created with a feature that has a value equal 0.0)"; + + generateInvNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), phi_sz) << " (InvNode created with an absolute value above the upper bound)"; + + generateInvNode(_phi, _phi[0], feat_ind, 1e10, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (InvNode created with an absolute value below the lower bound)"; + + generateInvNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (InvNode created from a ExpNode)"; + + generateInvNode(_phi, _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (InvNode created from a NegExpNode)"; + + generateInvNode(_phi, _phi[6], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (InvNode created from a DivNode)"; + + generateInvNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + ++phi_sz; + EXPECT_EQ(_phi.size(), phi_sz) << " (Failure to create a valid feature)"; + + generateInvNode(_phi, _phi[7], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (InvNode created from another InvNode)"; + } + + TEST_F(InvNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _inv_test = std::make_shared<InvNode>(_phi[3], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (InvNode created with a feature that has a value equal to 0.0)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _inv_test = std::make_shared<InvNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (InvNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _inv_test = std::make_shared<InvNode>(_phi[0], feat_ind, 1e10, 1e50); + EXPECT_TRUE(false) << " (InvNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _inv_test = std::make_shared<InvNode>(_phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (InvNode created from a ExpNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _inv_test = std::make_shared<InvNode>(_phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (InvNode created from a NegExpNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _inv_test = std::make_shared<InvNode>(_phi[6], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (InvNode created from a DivNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _inv_test = std::make_shared<InvNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + + try + { + _inv_test = std::make_shared<InvNode>(_inv_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (InvNode created from another InvNode)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(InvNodeTest, AttributesTest) + { + _inv_test = std::make_shared<InvNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_inv_test->rung(), 1); + + EXPECT_EQ(_inv_test->value_ptr()[1], 0.5); + EXPECT_EQ(_inv_test->test_value_ptr()[0], 0.5); + + EXPECT_EQ(_inv_test->value()[1], 0.5); + EXPECT_EQ(_inv_test->test_value()[0], 0.50); + + EXPECT_STREQ(_inv_test->unit().toString().c_str(), "m^-1"); + + EXPECT_STREQ(_inv_test->expr().c_str(), "1.0 / (A)"); + EXPECT_STREQ(_inv_test->postfix_expr().c_str(), "0|inv"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_log_node.cc b/tests/googletest/feature_creation/feature_generation/test_log_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..56ac1bbcc535ac11e4d919b0ef96c481c6f7130b --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_log_node.cc @@ -0,0 +1,270 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sp/sixth_power.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp> + +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class LogNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {1.0}; + + std::vector<double> value_2 = {1.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + std::vector<double> value_3 = {0.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_3 = {0.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit()); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit()); + _feat_4 = std::make_shared<FeatureNode>(3, "D", value_3, test_value_3, Unit()); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<ExpNode>(_feat_1, 4, 1e-50, 1e50)); + _phi.push_back(std::make_shared<NegExpNode>(_feat_1, 5, 1e-50, 1e50)); + _phi.push_back(std::make_shared<InvNode>(_feat_1, 6, 1e-50, 1e50)); + _phi.push_back(std::make_shared<MultNode>(_feat_1, _feat_3, 7, 1e-50, 1e50)); + _phi.push_back(std::make_shared<DivNode>(_feat_1, _feat_3, 8, 1e-50, 1e50)); + _phi.push_back(std::make_shared<CbrtNode>(_feat_1, 9, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SqrtNode>(_feat_1, 10, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SqNode>(_feat_1, 11, 1e-50, 1e50)); + _phi.push_back(std::make_shared<CbNode>(_feat_1, 12, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SixPowNode>(_feat_1, 13, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + + node_ptr _log_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(LogNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateLogNode(_phi, _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << "(LogNode created with a feature that is not unitless)"; + + generateLogNode(_phi, _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << "(LogNode created with a feature that has a non-positive value)"; + + generateLogNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created with an absolute value above the upper bound)"; + + generateLogNode(_phi, _phi[0], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created with an absolute value below the lower bound)"; + + generateLogNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a ExpNode)"; + + generateLogNode(_phi, _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a NegExpNode)"; + + generateLogNode(_phi, _phi[6], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a InvNode)"; + + generateLogNode(_phi, _phi[7], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a MultNode)"; + + generateLogNode(_phi, _phi[8], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a DivNode)"; + + generateLogNode(_phi, _phi[9], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a CbrtNode)"; + + generateLogNode(_phi, _phi[10], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a SqrtNode)"; + + generateLogNode(_phi, _phi[11], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a SqNode)"; + + generateLogNode(_phi, _phi[12], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a CbNode)"; + + generateLogNode(_phi, _phi[13], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 14) << " (LogNode created from a SixPowNode)"; + + generateLogNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 15) << " (Failure to create a valid feature)"; + + generateLogNode(_phi, _phi[14], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 15) << " (LogNode created from another LogNode)"; + + } + + TEST_F(LogNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _log_test = std::make_shared<LogNode>(_phi[1], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << "(LogNode created with a feature that is not unitless)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_feat_4, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << "(LogNode created with a feature that has a non-positive value)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (LogNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[0], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (LogNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a ExpNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a NegExpNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[6], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a InvNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[7], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a MultNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[8], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a DivNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[9], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a CbrtNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[10], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a SqrtNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[11], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a SqNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[12], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a CbNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[13], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from a SixPowNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _log_test = std::make_shared<LogNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + + try + { + _log_test = std::make_shared<LogNode>(_log_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (LogNode created from another LogNode)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(LogNodeTest, AttributesTest) + { + _log_test = std::make_shared<LogNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_log_test->rung(), 1); + + EXPECT_EQ(_log_test->value_ptr()[0], 0.0); + EXPECT_EQ(_log_test->test_value_ptr()[0], 0.0); + + EXPECT_EQ(_log_test->value()[0], 0.0); + EXPECT_EQ(_log_test->test_value()[0], 0.0); + + EXPECT_STREQ(_log_test->unit().toString().c_str(), "Unitless"); + + EXPECT_STREQ(_log_test->expr().c_str(), "log(A)"); + EXPECT_STREQ(_log_test->postfix_expr().c_str(), "0|log"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_model_node.cc b/tests/googletest/feature_creation/feature_generation/test_model_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..277b3de34071b6894818d3ea44d0e5b6af6c2d74 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_model_node.cc @@ -0,0 +1,80 @@ +#include <feature_creation/node/ModelNode.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" + +namespace +{ + class ModelNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 3); + + _value_1 = {1.0, 2.0, 3.0, 4.0}; + _test_value_1 = {5.0}; + + _value_2 = {10.0, 10.0, 10.0, 1.0}; + _test_value_2 = {10.0}; + + _value_3 = {1.0, 2.0, 3.0, 1.0}; + _test_value_3 = {5.0}; + } + + std::vector<double> _value_1; + std::vector<double> _test_value_1; + + std::vector<double> _value_2; + std::vector<double> _test_value_2; + + std::vector<double> _value_3; + std::vector<double> _test_value_3; + }; + + TEST_F(ModelNodeTest, ConstructorTest) + { + node_ptr feat_1 = std::make_shared<ModelNode>(0, 1, "A", "$A$", "0", _value_1, _test_value_1, Unit("m")); + node_ptr feat_2 = std::make_shared<ModelNode>(1, 1, "B", "$B$", "1", _value_2, _test_value_2, Unit()); + node_ptr feat_3 = std::make_shared<ModelNode>(2, 1, "C", "$C$", "2", _value_3, _test_value_3, Unit("m")); + + EXPECT_FALSE(feat_1->is_const()); + EXPECT_FALSE(feat_1->is_nan()); + EXPECT_STREQ(feat_1->unit().toString().c_str(), "m"); + EXPECT_STREQ(feat_1->expr().c_str(), "A"); + EXPECT_STREQ(feat_1->postfix_expr().c_str(), "0"); + EXPECT_EQ(feat_1->value()[0], _value_1[0]); + EXPECT_EQ(feat_1->test_value()[0], _test_value_1[0]); + EXPECT_EQ(feat_1->value_ptr()[0], _value_1[0]); + EXPECT_EQ(feat_1->test_value_ptr()[0], _test_value_1[0]); + EXPECT_EQ(feat_1->rung(), 1); + EXPECT_EQ(feat_1->n_feats(), 0); + EXPECT_EQ(feat_1->n_feats(), 0); + + EXPECT_FALSE(feat_2->is_const()); + EXPECT_FALSE(feat_2->is_nan()); + EXPECT_STREQ(feat_2->unit().toString().c_str(), "Unitless"); + EXPECT_STREQ(feat_2->expr().c_str(), "B"); + EXPECT_STREQ(feat_2->postfix_expr().c_str(), "1"); + EXPECT_EQ(feat_2->value()[0], _value_2[0]); + EXPECT_EQ(feat_2->test_value()[0], _test_value_2[0]); + EXPECT_EQ(feat_2->value_ptr()[0], _value_2[0]); + EXPECT_EQ(feat_2->test_value_ptr()[0], _test_value_2[0]); + EXPECT_EQ(feat_2->rung(), 1); + EXPECT_EQ(feat_2->n_feats(), 0); + EXPECT_EQ(feat_2->n_feats(), 0); + + EXPECT_FALSE(feat_3->is_const()); + EXPECT_FALSE(feat_3->is_nan()); + EXPECT_STREQ(feat_3->unit().toString().c_str(), "m"); + EXPECT_STREQ(feat_3->expr().c_str(), "C"); + EXPECT_STREQ(feat_3->postfix_expr().c_str(), "2"); + EXPECT_EQ(feat_3->value()[0], _value_3[0]); + EXPECT_EQ(feat_3->test_value()[0], _test_value_3[0]); + EXPECT_EQ(feat_3->value_ptr()[0], _value_3[0]); + EXPECT_EQ(feat_3->test_value_ptr()[0], _test_value_3[0]); + EXPECT_EQ(feat_3->rung(), 1); + EXPECT_EQ(feat_3->n_feats(), 0); + EXPECT_EQ(feat_3->n_feats(), 0); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_mult_node.cc b/tests/googletest/feature_creation/feature_generation/test_mult_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..a582390c01c057a774629a32fe19654587a7377d --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_mult_node.cc @@ -0,0 +1,160 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" + +namespace +{ + class MultNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {5.0}; + + std::vector<double> value_2 = {10.0, 25.0, 30.0, 40.0}; + std::vector<double> test_value_2 = {50.0}; + + std::vector<double> value_3 = {1.0, 0.5, 1.0/3.0, 0.25}; + std::vector<double> test_value_3 = {-5.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("s")); + _feat_4 = std::make_shared<FeatureNode>(3, "D", value_3, test_value_3, Unit("s")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<DivNode>(_feat_1, _feat_2, 4, -1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + node_ptr _mult_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(MultNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateMultNode(_phi, _phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (Creation of MultNode led to a feature with a constant value)"; + + generateMultNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1.0); + EXPECT_EQ(_phi.size(), 5) << " (MultNode created with an absolute value above the upper bound)"; + + generateMultNode(_phi, _phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (MultNode created with an absolute value below the lower bound)"; + + generateMultNode(_phi, _phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (MultNode created with only one primary feature present)"; + + generateMultNode(_phi, _phi[4], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (MultNode created when some terms cancel out)"; + + generateMultNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (Failure to create a valid feature)"; + + generateMultNode(_phi, _phi[5], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (MultNode created that is a duplicate of a second feature)"; + + generateMultNode(_phi, _phi[0], _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (MultNode not created when units do not match.)"; + } + + TEST_F(MultNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _mult_test = std::make_shared<MultNode>(_phi[0], _phi[2], feat_ind, 1e-50, 1e50); + } + catch(const InvalidFeatureException& e) + { + EXPECT_TRUE(false) << " (MultNode not created when units do not match.)"; + } + + try + { + _mult_test = std::make_shared<MultNode>(_phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (Creation of MultNode led to a feature with a constant value)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _mult_test = std::make_shared<MultNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1.0); + EXPECT_TRUE(false) << " (MultNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _mult_test = std::make_shared<MultNode>(_phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (MultNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _mult_test = std::make_shared<MultNode>(_phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (MultNode created with only one primary feature present)"; + } + catch(const InvalidFeatureException& e) + {} + try + { + _mult_test = std::make_shared<MultNode>(_phi[1], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (MultNode created when some terms cancel out)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _mult_test = std::make_shared<MultNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + try + { + _mult_test = std::make_shared<MultNode>(_mult_test, _mult_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (MultNode created that is a duplicate of a second feature)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(MultNodeTest, AttributesTest) + { + _mult_test = std::make_shared<MultNode>(_phi[0], _phi[1], 5, 1e-50, 1e50); + _mult_test = std::make_shared<MultNode>(_mult_test, _phi[1], 6, 1e-50, 1e50); + + EXPECT_EQ(_mult_test->rung(), 2); + + EXPECT_EQ(_mult_test->value_ptr()[0], 100.0); + EXPECT_EQ(_mult_test->test_value_ptr()[0], 12500); + + EXPECT_EQ(_mult_test->value()[0], 100.0); + EXPECT_EQ(_mult_test->test_value()[0], 12500.0); + + EXPECT_STREQ(_mult_test->unit().toString().c_str(), "m^3"); + + EXPECT_STREQ(_mult_test->expr().c_str(), "[([(A) * (B)]) * (B)]"); + EXPECT_STREQ(_mult_test->postfix_expr().c_str(), "0|1|mult|1|mult"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_neg_exp_node.cc b/tests/googletest/feature_creation/feature_generation/test_neg_exp_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..205d7a92703b9cab7237d4ddf3bee62e7d6e25d1 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_neg_exp_node.cc @@ -0,0 +1,176 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp> + +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class NegExpNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 3); + + std::vector<double> value_1 = {0.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {0.0}; + + std::vector<double> value_2 = {1.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit()); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit()); + + _phi = {_feat_1, _feat_2, _feat_3}; + _phi.push_back(std::make_shared<LogNode>(_feat_3, 3, 1e-50, 1e50)); + _phi.push_back(std::make_shared<ExpNode>(_feat_1, 3, 1e-50, 1e50)); + _phi.push_back(std::make_shared<AddNode>(_feat_1, _feat_3, 3, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SubNode>(_feat_1, _feat_3, 3, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + + node_ptr _neg_exp_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(NegExpNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateNegExpNode(_phi, _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << "(NegExpNode created with a feature that is not unitless)"; + + generateNegExpNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), 7) << " (NegExpNode created with an absolute value above the upper bound)"; + + generateNegExpNode(_phi, _phi[0], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (NegExpNode created with an absolute value below the lower bound)"; + + generateNegExpNode(_phi, _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (NegExpNode created from a LogNode)"; + + generateNegExpNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (NegExpNode created from a ExpNode)"; + + generateNegExpNode(_phi, _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (NegExpNode created from a AddNode)"; + + generateNegExpNode(_phi, _phi[6], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 7) << " (NegExpNode created from a SubNode)"; + + generateNegExpNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 8) << " (Failure to create a valid feature)"; + + generateNegExpNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 8) << " (NegExpNode created from another NegExpNode)"; + + } + + TEST_F(NegExpNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _neg_exp_test = std::make_shared<NegExpNode>(_phi[1], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << "(NegExpNode created with a feature that is not unitless)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _neg_exp_test = std::make_shared<NegExpNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (NegExpNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _neg_exp_test = std::make_shared<NegExpNode>(_phi[0], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (NegExpNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _neg_exp_test = std::make_shared<NegExpNode>(_phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (NegExpNode created from a LogNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _neg_exp_test = std::make_shared<NegExpNode>(_phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (NegExpNode created from a ExpNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _neg_exp_test = std::make_shared<NegExpNode>(_phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (NegExpNode created from a AddNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _neg_exp_test = std::make_shared<NegExpNode>(_phi[6], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (NegExpNode created from a SubNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _neg_exp_test = std::make_shared<NegExpNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + + try + { + _neg_exp_test = std::make_shared<NegExpNode>(_neg_exp_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (NegExpNode created from another NegExpNode)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(NegExpNodeTest, AttributesTest) + { + _neg_exp_test = std::make_shared<NegExpNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_neg_exp_test->rung(), 1); + + EXPECT_EQ(_neg_exp_test->value_ptr()[0], 1.0); + EXPECT_EQ(_neg_exp_test->test_value_ptr()[0], 1.0); + + EXPECT_EQ(_neg_exp_test->value()[0], 1.0); + EXPECT_EQ(_neg_exp_test->test_value()[0], 1.0); + + EXPECT_STREQ(_neg_exp_test->unit().toString().c_str(), "Unitless"); + + EXPECT_STREQ(_neg_exp_test->expr().c_str(), "exp[-1.0*(A)]"); + EXPECT_STREQ(_neg_exp_test->postfix_expr().c_str(), "0|nexp"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_sin_node.cc b/tests/googletest/feature_creation/feature_generation/test_sin_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..79325c785bd70dd6a195b772ee879df0a5341965 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_sin_node.cc @@ -0,0 +1,147 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class SinNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {0.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {0.0}; + + std::vector<double> value_2 = {0.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit()); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit()); + + _phi = {_feat_1, _feat_2, _feat_3}; + _phi.push_back(std::make_shared<CosNode>(_feat_1, 3, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + + node_ptr _sin_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(SinNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateSinNode(_phi, _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 4) << " (Creation of SinNode led to a feature with a constant value)"; + + generateSinNode(_phi, _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 4) << "(SinNode created with a feature that is not unitless)"; + + generateSinNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), 4) << " (SinNode created with an absolute value above the upper bound)"; + + generateSinNode(_phi, _phi[0], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 4) << " (SinNode created with an absolute value below the lower bound)"; + + generateSinNode(_phi, _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 4) << " (SinNode created from another a CosNode)"; + + generateSinNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (Failure to create a valid feature)"; + + generateSinNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (SinNode created from another SinNode)"; + + } + + TEST_F(SinNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _sin_test = std::make_shared<SinNode>(_phi[2], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (Creation of SinNode led to a feature with a constant value)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sin_test = std::make_shared<SinNode>(_phi[1], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << "(SinNode created with a feature that is not unitless)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sin_test = std::make_shared<SinNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (SinNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sin_test = std::make_shared<SinNode>(_phi[0], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (SinNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sin_test = std::make_shared<SinNode>(_phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SinNode created from another a CosNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sin_test = std::make_shared<SinNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + + try + { + _sin_test = std::make_shared<SinNode>(_sin_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SinNode created from another SinNode)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(SinNodeTest, AttributesTest) + { + _sin_test = std::make_shared<SinNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_sin_test->rung(), 1); + + EXPECT_EQ(_sin_test->value_ptr()[0], 0.0); + EXPECT_EQ(_sin_test->test_value_ptr()[0], 0.0); + + EXPECT_EQ(_sin_test->value()[0], 0.0); + EXPECT_EQ(_sin_test->test_value()[0], 0.0); + + EXPECT_STREQ(_sin_test->unit().toString().c_str(), "Unitless"); + + EXPECT_STREQ(_sin_test->expr().c_str(), "sin(A)"); + EXPECT_STREQ(_sin_test->postfix_expr().c_str(), "0|sin"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_six_pow_node.cc b/tests/googletest/feature_creation/feature_generation/test_six_pow_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..37484d12214a170353c9dcd3acc16bff9831b764 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_six_pow_node.cc @@ -0,0 +1,173 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sp/sixth_power.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp> + +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class SixPowNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {2.0}; + + std::vector<double> value_2 = {1.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + std::vector<double> value_3 = {0.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_3 = {0.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("m")); + _feat_4 = std::make_shared<FeatureNode>(3, "D", value_3, test_value_3, Unit("m")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<InvNode>(_feat_1, 6, 1e-50, 1e50)); + _phi.push_back(std::make_shared<CbrtNode>(_feat_1, 9, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SqrtNode>(_feat_1, 10, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SqNode>(_feat_1, 11, 1e-50, 1e50)); + _phi.push_back(std::make_shared<CbNode>(_feat_1, 12, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + + node_ptr _six_pow_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(SixPowNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + int phi_sz = _phi.size(); + + generateSixPowNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), phi_sz) << " (SixPowNode created with an absolute value above the upper bound)"; + + generateSixPowNode(_phi, _phi[0], feat_ind, 1e10, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SixPowNode created with an absolute value below the lower bound)"; + + generateSixPowNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SixPowNode created from a InvNode)"; + + generateSixPowNode(_phi, _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SixPowNode created from a CbrtNode)"; + + generateSixPowNode(_phi, _phi[6], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SixPowNode created from a SqrtNode)"; + + generateSixPowNode(_phi, _phi[7], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SixPowNode created from a SqNode)"; + + generateSixPowNode(_phi, _phi[8], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SixPowNode created from a CbNode)"; + + generateSixPowNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + ++phi_sz; + EXPECT_EQ(_phi.size(), phi_sz) << " (Failure to create a valid feature)"; + } + + TEST_F(SixPowNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _six_pow_test = std::make_shared<SixPowNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (SixPowNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _six_pow_test = std::make_shared<SixPowNode>(_phi[0], feat_ind, 1e10, 1e50); + EXPECT_TRUE(false) << " (SixPowNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _six_pow_test = std::make_shared<SixPowNode>(_phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SixPowNode created from a InvNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _six_pow_test = std::make_shared<SixPowNode>(_phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SixPowNode created from a CbrtNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _six_pow_test = std::make_shared<SixPowNode>(_phi[6], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SixPowNode created from a SqrtNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _six_pow_test = std::make_shared<SixPowNode>(_phi[7], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SixPowNode created from a SqNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _six_pow_test = std::make_shared<SixPowNode>(_phi[8], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SixPowNode created from a CbNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _six_pow_test = std::make_shared<SixPowNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + } + + TEST_F(SixPowNodeTest, AttributesTest) + { + _six_pow_test = std::make_shared<SixPowNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_six_pow_test->rung(), 1); + + EXPECT_EQ(_six_pow_test->value_ptr()[1], 64.0); + EXPECT_EQ(_six_pow_test->test_value_ptr()[0], 64.0); + + EXPECT_EQ(_six_pow_test->value()[1], 64.0); + EXPECT_EQ(_six_pow_test->test_value()[0], 64.0); + + EXPECT_STREQ(_six_pow_test->unit().toString().c_str(), "m^6"); + + EXPECT_STREQ(_six_pow_test->expr().c_str(), "(A)^6"); + EXPECT_STREQ(_six_pow_test->postfix_expr().c_str(), "0|sp"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_sq_node.cc b/tests/googletest/feature_creation/feature_generation/test_sq_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..8864b39d3f45da20077977c888f5dc846fda7832 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_sq_node.cc @@ -0,0 +1,133 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp> + +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class SqNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 8.0}; + std::vector<double> test_value_1 = {2.0}; + + std::vector<double> value_2 = {1.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + std::vector<double> value_3 = {-1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_3 = {0.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("m")); + _feat_4 = std::make_shared<FeatureNode>(3, "D", value_3, test_value_3, Unit("m")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<InvNode>(_feat_1, 6, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SqrtNode>(_feat_1, 11, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + + node_ptr _sq_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(SqNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + int phi_sz = _phi.size(); + + generateSqNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqNode created with an absolute value above the upper bound)"; + + generateSqNode(_phi, _phi[0], feat_ind, 1e10, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqNode created with an absolute value below the lower bound)"; + + generateSqNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqNode created from a InvNode)"; + + generateSqNode(_phi, _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqNode created from a SqrtNode)"; + + generateSqNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + ++phi_sz; + EXPECT_EQ(_phi.size(), phi_sz) << " (Failure to create a valid feature)"; + } + + TEST_F(SqNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + try + { + _sq_test = std::make_shared<SqNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (SqNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sq_test = std::make_shared<SqNode>(_phi[0], feat_ind, 1e10, 1e50); + EXPECT_TRUE(false) << " (SqNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sq_test = std::make_shared<SqNode>(_phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SqNode created from a InvNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sq_test = std::make_shared<SqNode>(_phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SqNode created from a SqrtNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sq_test = std::make_shared<SqNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + } + + TEST_F(SqNodeTest, AttributesTest) + { + _sq_test = std::make_shared<SqNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_sq_test->rung(), 1); + + EXPECT_EQ(_sq_test->value_ptr()[1], 4.0); + EXPECT_EQ(_sq_test->test_value_ptr()[0], 4.0); + + EXPECT_EQ(_sq_test->value()[1], 4.0); + EXPECT_EQ(_sq_test->test_value()[0], 4.0); + + EXPECT_STREQ(_sq_test->unit().toString().c_str(), "m^2"); + + EXPECT_STREQ(_sq_test->expr().c_str(), "(A)^2"); + EXPECT_STREQ(_sq_test->postfix_expr().c_str(), "0|sq"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_sqrt_node.cc b/tests/googletest/feature_creation/feature_generation/test_sqrt_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..8c02401d04ef7c533a5da6430468a12886d779d0 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_sqrt_node.cc @@ -0,0 +1,184 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sp/sixth_power.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp> + +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" +#include <math.h> + +namespace +{ + class SqrtNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {4.0}; + + std::vector<double> value_2 = {1.0, 2.0 * M_PI, 4.0 * M_PI, 6.0 * M_PI}; + std::vector<double> test_value_2 = {5.0}; + + std::vector<double> value_3 = {-1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_3 = {0.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_1, test_value_1, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("m")); + _feat_4 = std::make_shared<FeatureNode>(3, "D", value_3, test_value_3, Unit("m")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<InvNode>(_feat_1, 6, 1e-50, 1e50)); + _phi.push_back(std::make_shared<CbrtNode>(_feat_1, 9, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SqNode>(_feat_1, 11, 1e-50, 1e50)); + _phi.push_back(std::make_shared<CbNode>(_feat_1, 12, 1e-50, 1e50)); + _phi.push_back(std::make_shared<SixPowNode>(_feat_1, 12, 1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + + node_ptr _sqrt_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(SqrtNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + int phi_sz = _phi.size(); + + generateSqrtNode(_phi, _phi[3], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqrtNode created with a feature that has a value < 0.0)"; + + generateSqrtNode(_phi, _phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqrtNode created with an absolute value above the upper bound)"; + + generateSqrtNode(_phi, _phi[0], feat_ind, 1e10, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqrtNode created with an absolute value below the lower bound)"; + + generateSqrtNode(_phi, _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqrtNode created from a InvNode)"; + + generateSqrtNode(_phi, _phi[5], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqrtNode created from a CbrtNode)"; + + generateSqrtNode(_phi, _phi[6], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqrtNode created from a SqNode)"; + + generateSqrtNode(_phi, _phi[7], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqrtNode created from a CbNode)"; + + generateSqrtNode(_phi, _phi[8], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), phi_sz) << " (SqrtNode created from a SixPowNode)"; + + generateSqrtNode(_phi, _phi[0], feat_ind, 1e-50, 1e50); + ++phi_sz; + EXPECT_EQ(_phi.size(), phi_sz) << " (Failure to create a valid feature)"; + } + + TEST_F(SqrtNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[3], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (SqrtNode created with a feature that has a value < 0.0)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[0], feat_ind, 1e-50, 1e-40); + EXPECT_TRUE(false) << " (SqrtNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[0], feat_ind, 1e10, 1e50); + EXPECT_TRUE(false) << " (SqrtNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SqrtNode created from a InvNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[5], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SqrtNode created from a CbrtNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[6], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SqrtNode created from a SqNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[7], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SqrtNode created from a CbNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[8], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SqrtNode created from a SixPowNode)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[0], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + } + + TEST_F(SqrtNodeTest, AttributesTest) + { + _sqrt_test = std::make_shared<SqrtNode>(_phi[0], 5, 1e-50, 1e50); + + EXPECT_EQ(_sqrt_test->rung(), 1); + + EXPECT_EQ(_sqrt_test->value_ptr()[3], 2.0); + EXPECT_EQ(_sqrt_test->test_value_ptr()[0], 2.0); + + EXPECT_EQ(_sqrt_test->value()[3], 2.0); + EXPECT_EQ(_sqrt_test->test_value()[0], 2.0); + + EXPECT_STREQ(_sqrt_test->unit().toString().c_str(), "m^0.5"); + + EXPECT_STREQ(_sqrt_test->expr().c_str(), "sqrt(A)"); + EXPECT_STREQ(_sqrt_test->postfix_expr().c_str(), "0|sqrt"); + } +} diff --git a/tests/googletest/feature_creation/feature_generation/test_sub_node.cc b/tests/googletest/feature_creation/feature_generation/test_sub_node.cc new file mode 100644 index 0000000000000000000000000000000000000000..1a63cffb61200feedf08832bfac7e4ad4ccf6b48 --- /dev/null +++ b/tests/googletest/feature_creation/feature_generation/test_sub_node.cc @@ -0,0 +1,159 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> +#include <feature_creation/node/FeatureNode.hpp> +#include "gtest/gtest.h" + +namespace +{ + class SubNodeTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 4); + + std::vector<double> value_1 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_1 = {5.0}; + + std::vector<double> value_2 = {10.0, 20.0, 30.0, 40.0}; + std::vector<double> test_value_2 = {50.0}; + + std::vector<double> value_3 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_3 = {5.0}; + + _feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit("m")); + _feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit("m")); + _feat_3 = std::make_shared<FeatureNode>(2, "C", value_2, test_value_2, Unit("s")); + _feat_4 = std::make_shared<FeatureNode>(3, "C", value_3, test_value_3, Unit("s")); + + _phi = {_feat_1, _feat_2, _feat_3, _feat_4}; + _phi.push_back(std::make_shared<AddNode>(_feat_1, _feat_2, 4, -1e-50, 1e50)); + } + + node_ptr _feat_1; + node_ptr _feat_2; + node_ptr _feat_3; + node_ptr _feat_4; + node_ptr _sub_test; + + std::vector<node_ptr> _phi; + }; + + TEST_F(SubNodeTest, GeneratorTest) + { + int feat_ind = _phi.size(); + + generateSubNode(_phi, _phi[0], _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (SubNode created when units do not match.)"; + + generateSubNode(_phi, _phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (Creation of SubNode led to a feature with a constant value)"; + + generateSubNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1.0); + EXPECT_EQ(_phi.size(), 5) << " (SubNode created with an absolute value above the upper bound)"; + + generateSubNode(_phi, _phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (SubNode created with an absolute value below the lower bound)"; + + generateSubNode(_phi, _phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (SubNode created with only one primary feature present)"; + + generateSubNode(_phi, _phi[4], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 5) << " (SubNode created when some terms cancel out)"; + + generateSubNode(_phi, _phi[0], _phi[1], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (Failure to create a valid feature)"; + + generateSubNode(_phi, _phi[5], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_EQ(_phi.size(), 6) << " (SubNode created that is a duplicate of a second feature)"; + } + + TEST_F(SubNodeTest, ConstructorTest) + { + int feat_ind = _phi.size(); + + try + { + _sub_test = std::make_shared<SubNode>(_phi[0], _phi[2], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SubNode created when units do not match.)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sub_test = std::make_shared<SubNode>(_phi[0], _phi[3], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (Creation of SubNode led to a feature with a constant value)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sub_test = std::make_shared<SubNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1.0); + EXPECT_TRUE(false) << " (SubNode created with an absolute value above the upper bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sub_test = std::make_shared<SubNode>(_phi[0], _phi[1], feat_ind, 1e3, 1e50); + EXPECT_TRUE(false) << " (SubNode created with an absolute value below the lower bound)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sub_test = std::make_shared<SubNode>(_phi[0], _phi[0], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SubNode created with only one primary feature present)"; + } + catch(const InvalidFeatureException& e) + {} + try + { + _sub_test = std::make_shared<SubNode>(_phi[1], _phi[4], feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SubNode created when some terms cancel out)"; + } + catch(const InvalidFeatureException& e) + {} + + try + { + _sub_test = std::make_shared<SubNode>(_phi[0], _phi[1], feat_ind, 1e-50, 1e50); + ++feat_ind; + } + catch(const InvalidFeatureException& e) + { + ASSERT_TRUE(false) << " (Failure to create a valid feature)"; + } + try + { + _sub_test = std::make_shared<SubNode>(_sub_test, _sub_test, feat_ind, 1e-50, 1e50); + EXPECT_TRUE(false) << " (SubNode created that is a duplicate of a second feature)"; + } + catch(const InvalidFeatureException& e) + {} + } + + TEST_F(SubNodeTest, AttributesTest) + { + _sub_test = std::make_shared<SubNode>(_phi[0], _phi[1], 5, 1e-50, 1e50); + _sub_test = std::make_shared<SubNode>(_sub_test, _phi[1], 6, 1e-50, 1e50); + + EXPECT_EQ(_sub_test->rung(), 2); + + EXPECT_EQ(_sub_test->value_ptr()[0], -19.0); + EXPECT_EQ(_sub_test->test_value_ptr()[0], -95.0); + + EXPECT_EQ(_sub_test->value()[0], -19.0); + EXPECT_EQ(_sub_test->test_value()[0], -95.0); + + EXPECT_STREQ(_sub_test->unit().toString().c_str(), "m"); + + EXPECT_STREQ(_sub_test->expr().c_str(), "[([(A) - (B)]) - (B)]"); + EXPECT_STREQ(_sub_test->postfix_expr().c_str(), "0|1|sub|1|sub"); + } +} diff --git a/tests/googletest/feature_creation/feature_space/test_feat_space.cc b/tests/googletest/feature_creation/feature_space/test_feat_space.cc new file mode 100644 index 0000000000000000000000000000000000000000..cb92425fe3bb0fd6f4247e187d54b4d1debc9e1f --- /dev/null +++ b/tests/googletest/feature_creation/feature_space/test_feat_space.cc @@ -0,0 +1,230 @@ +#include <feature_creation/feature_space/FeatureSpace.hpp> +#include <boost/filesystem.hpp> +#include "gtest/gtest.h" + +namespace +{ + class FeatSpaceTest : public ::testing::Test + { + protected: + void SetUp() override + { + allowed_op_maps::set_node_maps(); + node_value_arrs::initialize_d_matrix_arr(); + mpi_setup::init_mpi_env(); + + _task_sizes = {5, 5}; + node_value_arrs::initialize_values_arr(10, 0, 3); + + std::vector<double> value_1 = {3.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}; + std::vector<double> value_2 = {1.10, 2.20, 3.10, 4.20, 5.10, 6.20, 7.10, 8.20, 9.10, 10.20}; + std::vector<double> value_3 = {3.0, -3.0, 5.0, -7.0, 9.0, -2.0, 4.0, -6.0, 8.0, -10.0}; + + node_ptr feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, std::vector<double>(), Unit("m")); + node_ptr feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, std::vector<double>(), Unit("m")); + node_ptr feat_3 = std::make_shared<FeatureNode>(2, "C", value_3, std::vector<double>(), Unit("s")); + + _phi_0 = {feat_1, feat_2, feat_3}; + _prop = std::vector<double>(10, 0.0); + _prop_class = {0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0}; + _prop_log_reg = std::vector<double>(10, 0.0); + std::transform(value_2.begin(), value_2.begin() + _task_sizes[0], value_3.begin(), _prop.begin(), [](double v1, double v2){return v1 / (v2 * v2);}); + std::transform(value_2.begin() + _task_sizes[0], value_2.end(), value_3.begin() + _task_sizes[0], _prop.begin() + _task_sizes[0], [](double v1, double v2){return -6.5 + 1.25 * v1 / (v2 * v2);}); + + std::transform(value_2.begin(), value_2.end(), value_3.begin(), _prop_log_reg.begin(), [](double v1, double v2){return v1 / (v2 * v2);}); + + _allowed_ops = {"sq", "cb", "div", "add"}; + } + + std::vector<node_ptr> _phi_0; + std::vector<std::string> _allowed_ops; + std::vector<double> _prop; + std::vector<double> _prop_log_reg; + std::vector<double> _prop_class; + std::vector<int> _task_sizes; + }; + + TEST_F(FeatSpaceTest, RegTest) + { + FeatureSpace feat_space( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop, + _task_sizes, + "regression", + 2, + 10, + 1, + 0, + 1.0, + 1e-50, + 1e50 + ); + feat_space.sis(_prop); + EXPECT_EQ(feat_space.task_sizes()[0], _task_sizes[0]); + EXPECT_STREQ(feat_space.feature_space_file().c_str(), "feature_space/selected_features.txt"); + EXPECT_EQ(feat_space.l_bound(), 1e-50); + EXPECT_EQ(feat_space.u_bound(), 1e50); + EXPECT_EQ(feat_space.max_phi(), 2); + EXPECT_EQ(feat_space.n_sis_select(), 10); + EXPECT_EQ(feat_space.n_samp(), 10); + EXPECT_EQ(feat_space.n_feat(), 154); + EXPECT_EQ(feat_space.n_rung_store(), 1); + EXPECT_EQ(feat_space.n_rung_generate(), 0); + + EXPECT_LT(std::abs(feat_space.phi_selected()[0]->value()[0] - _prop[0]), 1e-10); + EXPECT_LT(std::abs(feat_space.phi0()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-10); + EXPECT_LT(std::abs(feat_space.phi()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-10); + + boost::filesystem::remove_all("feature_space/"); + } + + TEST_F(FeatSpaceTest, ProjectGenTest) + { + FeatureSpace feat_space( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop, + _task_sizes, + "regression", + 2, + 10, + 1, + 1, + 1.0, + 1e-50, + 1e50 + ); + feat_space.sis(_prop); + EXPECT_EQ(feat_space.task_sizes()[0], _task_sizes[0]); + EXPECT_STREQ(feat_space.feature_space_file().c_str(), "feature_space/selected_features.txt"); + EXPECT_EQ(feat_space.l_bound(), 1e-50); + EXPECT_EQ(feat_space.u_bound(), 1e50); + EXPECT_EQ(feat_space.max_phi(), 2); + EXPECT_EQ(feat_space.n_sis_select(), 10); + EXPECT_EQ(feat_space.n_samp(), 10); + EXPECT_EQ(feat_space.n_feat(), 16); + EXPECT_EQ(feat_space.n_rung_store(), 1); + EXPECT_EQ(feat_space.n_rung_generate(), 1); + + EXPECT_LT(std::abs(feat_space.phi_selected()[0]->value()[0] - _prop[0]), 1e-10); + EXPECT_LT(std::abs(feat_space.phi0()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-10); + EXPECT_LT(std::abs(feat_space.phi()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-10); + + boost::filesystem::remove_all("feature_space/"); + } + + TEST_F(FeatSpaceTest, MaxCorrTest) + { + FeatureSpace feat_space( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop, + _task_sizes, + "regression", + 2, + 10, + 1, + 0, + 0.99, + 1e-50, + 1e50 + ); + feat_space.sis(_prop); + EXPECT_EQ(feat_space.task_sizes()[0], _task_sizes[0]); + EXPECT_STREQ(feat_space.feature_space_file().c_str(), "feature_space/selected_features.txt"); + EXPECT_EQ(feat_space.l_bound(), 1e-50); + EXPECT_EQ(feat_space.u_bound(), 1e50); + EXPECT_EQ(feat_space.max_phi(), 2); + EXPECT_EQ(feat_space.n_sis_select(), 10); + EXPECT_EQ(feat_space.n_samp(), 10); + EXPECT_EQ(feat_space.n_feat(), 154); + EXPECT_EQ(feat_space.n_rung_store(), 1); + EXPECT_EQ(feat_space.n_rung_generate(), 0); + + EXPECT_LT(std::abs(feat_space.phi_selected()[0]->value()[0] - _prop[0]), 1e-10); + EXPECT_LT(std::abs(feat_space.phi0()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-10); + EXPECT_LT(std::abs(feat_space.phi()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-10); + + boost::filesystem::remove_all("feature_space/"); + } + + TEST_F(FeatSpaceTest, LogRegTest) + { + FeatureSpace feat_space( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop_log_reg, + {10}, + "log_regression", + 2, + 10, + 1, + 0, + 1.0, + 1e-50, + 1e50 + ); + + std::transform(_prop_log_reg.begin(), _prop_log_reg.end(), _prop_log_reg.begin(), [](double pl){return std::log(pl);}); + feat_space.sis(_prop_log_reg); + + EXPECT_EQ(feat_space.task_sizes()[0], 10); + EXPECT_STREQ(feat_space.feature_space_file().c_str(), "feature_space/selected_features.txt"); + EXPECT_EQ(feat_space.l_bound(), 1e-50); + EXPECT_EQ(feat_space.u_bound(), 1e50); + EXPECT_EQ(feat_space.max_phi(), 2); + EXPECT_EQ(feat_space.n_sis_select(), 10); + EXPECT_EQ(feat_space.n_samp(), 10); + EXPECT_EQ(feat_space.n_feat(), 154); + EXPECT_EQ(feat_space.n_rung_store(), 1); + EXPECT_EQ(feat_space.n_rung_generate(), 0); + + std::vector<double> log_a(10, 0.0); + EXPECT_LT(std::abs(1.0 - util_funcs::log_r2(feat_space.phi_selected()[0]->value_ptr(), _prop_log_reg.data(), log_a.data(), 10)), 1e-8); + EXPECT_LT(std::abs(feat_space.phi0()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-8); + EXPECT_LT(std::abs(feat_space.phi()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-8); + boost::filesystem::remove_all("feature_space/"); + } + + TEST_F(FeatSpaceTest, ClassTest) + { + FeatureSpace feat_space( + mpi_setup::comm, + _phi_0, + _allowed_ops, + _prop_class, + {10}, + "classification", + 0, + 1, + 0, + 0, + 1.0, + 1e-50, + 1e50 + ); + feat_space.sis(_prop_class); + + EXPECT_EQ(feat_space.task_sizes()[0], 10); + EXPECT_STREQ(feat_space.feature_space_file().c_str(), "feature_space/selected_features.txt"); + EXPECT_EQ(feat_space.l_bound(), 1e-50); + EXPECT_EQ(feat_space.u_bound(), 1e50); + EXPECT_EQ(feat_space.max_phi(), 0); + EXPECT_EQ(feat_space.n_sis_select(), 1); + EXPECT_EQ(feat_space.n_samp(), 10); + EXPECT_EQ(feat_space.n_feat(), 3); + EXPECT_EQ(feat_space.n_rung_store(), 0); + EXPECT_EQ(feat_space.n_rung_generate(), 0); + + EXPECT_LT(std::abs(feat_space.phi_selected()[0]->value()[1] + 3.0), 1e-10); + EXPECT_LT(std::abs(feat_space.phi0()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-10); + EXPECT_LT(std::abs(feat_space.phi()[0]->value()[0] - _phi_0[0]->value()[0]), 1e-10); + + boost::filesystem::remove_all("feature_space/"); + } +} diff --git a/tests/googletest/feature_creation/units/test_untis.cc b/tests/googletest/feature_creation/units/test_untis.cc new file mode 100644 index 0000000000000000000000000000000000000000..5ba3d7427480281c9cd5836ab622382513187a0f --- /dev/null +++ b/tests/googletest/feature_creation/units/test_untis.cc @@ -0,0 +1,62 @@ +#include <feature_creation/units/Unit.hpp> +#include "gtest/gtest.h" + +namespace { + + //test unit's str constructor + TEST(Unit, StringConstructor) + { + Unit u_1("m"); + Unit u_2("s"); + + EXPECT_NE(u_1, u_2); + EXPECT_EQ(u_1, Unit(u_1)); + EXPECT_EQ(u_2, Unit(u_2)); + + EXPECT_STREQ(u_1.toString().c_str(), "m"); + EXPECT_STREQ(u_2.toString().c_str(), "s"); + + EXPECT_EQ(u_1 / u_2, Unit("m/s")); + EXPECT_EQ(u_1 / u_1, Unit()); + EXPECT_EQ(u_1 * u_2, Unit("m*s")); + EXPECT_EQ(u_1 * u_1, Unit("m^2.0")); + EXPECT_EQ(u_1 ^ 2.0, Unit("m^2.0")); + EXPECT_EQ(u_1.inverse(), Unit("1 / m")); + + u_2 /= u_1; + EXPECT_EQ(u_2, Unit("s/m")); + u_2 *= u_2; + EXPECT_EQ(u_2, Unit("s * s/m^2")); + } + + //test mean calculations + TEST(Unit, MapConstructor) + { + std::map<std::string, double> dct_1; + std::map<std::string, double> dct_2; + + dct_1["m"] = 1.0; + dct_2["s"] = 1.0; + Unit u_1(dct_1); + Unit u_2(dct_2); + + EXPECT_NE(u_1, u_2); + EXPECT_EQ(u_1, Unit(u_1)); + EXPECT_EQ(u_2, Unit(u_2)); + + EXPECT_STREQ(u_1.toString().c_str(), "m"); + EXPECT_STREQ(u_2.toString().c_str(), "s"); + + EXPECT_EQ(u_1 / u_2, Unit("m/s")); + EXPECT_EQ(u_1 / u_1, Unit()); + EXPECT_EQ(u_1 * u_2, Unit("m*s")); + EXPECT_EQ(u_1 * u_1, Unit("m^2.0")); + EXPECT_EQ(u_1 ^ 2.0, Unit("m^2.0")); + EXPECT_EQ(u_1.inverse(), Unit("1 / m")); + + u_2 /= u_1; + EXPECT_EQ(u_2, Unit("s/m")); + u_2 *= u_2; + EXPECT_EQ(u_2, Unit("s * s/m^2")); + } +} diff --git a/tests/googletest/feature_creation/utils/test_utils.cc b/tests/googletest/feature_creation/utils/test_utils.cc new file mode 100644 index 0000000000000000000000000000000000000000..ef6b4240bed6293330717685df141f59d0d8bb69 --- /dev/null +++ b/tests/googletest/feature_creation/utils/test_utils.cc @@ -0,0 +1,117 @@ +#include <feature_creation/node/utils.hpp> +#include <boost/filesystem.hpp> +#include "gtest/gtest.h" + +namespace +{ + class FeatCreationUtilsTest : public ::testing::Test + { + protected: + void SetUp() override + { + node_value_arrs::initialize_values_arr(4, 1, 3); + + std::vector<double> value_1 = {-1.0, -2.0, -3.0, -4.0}; + std::vector<double> test_value_1 = {50.0}; + + std::vector<double> value_2 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> test_value_2 = {5.0}; + + std::vector<double> value_3 = {1.0, -1.0, 1.0, -1.0}; + std::vector<double> test_value_3 = {1.0}; + + node_ptr feat_1 = std::make_shared<FeatureNode>(0, "A", value_1, test_value_1, Unit()); + node_ptr feat_2 = std::make_shared<FeatureNode>(1, "B", value_2, test_value_2, Unit()); + node_ptr feat_3 = std::make_shared<FeatureNode>(2, "C", value_3, test_value_3, Unit()); + + _phi0 = {feat_1, feat_2, feat_3}; + _feat_ind = 3; + } + + std::vector<node_ptr> _phi0; + int _feat_ind; + }; + + TEST_F(FeatCreationUtilsTest, TestPostfix2Node) + { + node_ptr test = str2node::postfix2node("0|2|div|exp|1|add", _phi0, _feat_ind); + EXPECT_EQ(test->type(), NODE_TYPE::ADD); + EXPECT_EQ(test->rung(), 3); + EXPECT_LT(abs(test->value()[1] - (std::exp(2.0) + 2.0)), 1e-10); + EXPECT_STREQ(test->expr().c_str(), "(exp([(A) / (C)]) + B)"); + } + + TEST_F(FeatCreationUtilsTest, TestPhiSelFromFile) + { + std::ofstream out_file_stream = std::ofstream(); + out_file_stream.open("phi_sel.txt"); + out_file_stream << std::setw(14) <<std::left << "# FEAT_ID" << "Feature Postfix Expression (RPN)" << std::endl; + out_file_stream << std::setw(14) <<std::left << 0 << "0|2|div|exp|1|add" << std::endl; + out_file_stream << std::setw(14) <<std::left << 1 << "0|2|div|nexp|1|add" << std::endl; + out_file_stream << std::setw(14) <<std::left << 2 << "0|2|div|sq|1|add" << std::endl; + out_file_stream << std::setw(14) <<std::left << 3 << "0|2|div|cb|1|add" << std::endl; + out_file_stream << std::setw(14) <<std::left << 4 << "0|2|div|sp|1|add" << std::endl; + out_file_stream << "#"; + for(int dd = 0; dd < 71; ++dd) + out_file_stream << "-"; + out_file_stream << std::endl; + out_file_stream << std::setw(14) <<std::left << 5 << "0|2|div|exp|1|sub" << std::endl; + out_file_stream << std::setw(14) <<std::left << 6 << "0|2|div|nexp|1|sub" << std::endl; + out_file_stream << std::setw(14) <<std::left << 7 << "0|2|div|sq|1|sub" << std::endl; + out_file_stream << std::setw(14) <<std::left << 8 << "0|2|div|cb|1|sub" << std::endl; + out_file_stream << std::setw(14) <<std::left << 9 << "0|2|div|sp|1|sub" << std::endl; + out_file_stream << "#"; + for(int dd = 0; dd < 71; ++dd) + out_file_stream << "-"; + out_file_stream << std::endl; + out_file_stream.close(); + + std::vector<node_ptr> phi_sel = str2node::phi_selected_from_file("phi_sel.txt", _phi0); + + ASSERT_EQ(phi_sel.size(), 10); + EXPECT_EQ(phi_sel[0]->type(), NODE_TYPE::MODEL_FEATURE); + EXPECT_EQ(phi_sel[0]->rung(), 3); + EXPECT_LT(abs(phi_sel[0]->value()[1] - (std::exp(2.0) + 2.0)), 1e-10); + EXPECT_STREQ(phi_sel[0]->expr().c_str(), "(exp([(A) / (C)]) + B)"); + + EXPECT_EQ(phi_sel[5]->type(), NODE_TYPE::MODEL_FEATURE); + EXPECT_EQ(phi_sel[5]->rung(), 3); + EXPECT_LT(abs(phi_sel[5]->value()[1] - (std::exp(2.0) - 2.0)), 1e-10); + EXPECT_STREQ(phi_sel[5]->expr().c_str(), "[(exp([(A) / (C)])) - (B)]"); + boost::filesystem::remove("phi_sel.txt"); + } + + TEST_F(FeatCreationUtilsTest, TestPhiFromFile) + { + std::ofstream out_file_stream = std::ofstream(); + out_file_stream.open("phi.txt"); + out_file_stream << "0|2|div|exp|1|add" << std::endl; + out_file_stream << "0|2|div|nexp|1|add" << std::endl; + out_file_stream << "0|2|div|sq|1|add" << std::endl; + out_file_stream << "0|2|div|cb|1|add" << std::endl; + out_file_stream << "0|2|div|sp|1|add" << std::endl; + out_file_stream << "0|2|div|exp|1|sub" << std::endl; + out_file_stream << "0|2|div|nexp|1|sub" << std::endl; + out_file_stream << "0|2|div|sq|1|sub" << std::endl; + out_file_stream << "0|2|div|cb|1|sub" << std::endl; + out_file_stream << "0|2|div|sp|1|sub" << std::endl; + out_file_stream << "#"; + for(int dd = 0; dd < 71; ++dd) + out_file_stream << "-"; + out_file_stream << std::endl; + out_file_stream.close(); + std::vector<node_ptr> phi = str2node::phi_from_file("phi.txt", _phi0); + + ASSERT_EQ(phi.size(), 10); + EXPECT_EQ(phi[0]->type(), NODE_TYPE::ADD); + EXPECT_EQ(phi[0]->rung(), 3); + EXPECT_LT(abs(phi[0]->value()[1] - (std::exp(2.0) + 2.0)), 1e-10); + EXPECT_STREQ(phi[0]->expr().c_str(), "(exp([(A) / (C)]) + B)"); + + EXPECT_EQ(phi[5]->type(), NODE_TYPE::SUB); + EXPECT_EQ(phi[5]->rung(), 3); + EXPECT_LT(abs(phi[5]->value()[1] - (std::exp(2.0) - 2.0)), 1e-10); + EXPECT_STREQ(phi[5]->expr().c_str(), "[(exp([(A) / (C)])) - (B)]"); + boost::filesystem::remove("phi.txt"); + } +} diff --git a/tests/googletest/feature_creation/value_storage/test_value_storage.cc b/tests/googletest/feature_creation/value_storage/test_value_storage.cc new file mode 100644 index 0000000000000000000000000000000000000000..de08d837a85461a0179d1be9064eab9388a77c09 --- /dev/null +++ b/tests/googletest/feature_creation/value_storage/test_value_storage.cc @@ -0,0 +1,91 @@ +#include "gtest/gtest.h" +#include <utils/project.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> + +namespace { + + //test mean calculations + TEST(ValueStorage, ValueStorageTest) + { + node_value_arrs::initialize_values_arr(5, 2, 1); + EXPECT_EQ(node_value_arrs::N_SAMPLES, 5); + EXPECT_EQ(node_value_arrs::N_SAMPLES_TEST, 2); + EXPECT_EQ(node_value_arrs::N_RUNGS_STORED, 0); + EXPECT_EQ(node_value_arrs::N_STORE_FEATURES, 1); + EXPECT_EQ(node_value_arrs::VALUES_ARR.size(), 5); + EXPECT_EQ(node_value_arrs::TEST_VALUES_ARR.size(), 2); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_ARR.size(), node_value_arrs::MAX_N_THREADS * (3 * 1 + 1) * 5); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_REG.size(), node_value_arrs::MAX_N_THREADS * (3 * 1 + 1)); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_TEST_ARR.size(), node_value_arrs::MAX_N_THREADS * (3 * 1 + 1) * 2); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_TEST_REG.size(), node_value_arrs::MAX_N_THREADS * (3 * 1 + 1)); + + node_value_arrs::resize_values_arr(1, 2, false); + EXPECT_EQ(node_value_arrs::N_SAMPLES, 5); + EXPECT_EQ(node_value_arrs::N_SAMPLES_TEST, 2); + EXPECT_EQ(node_value_arrs::N_RUNGS_STORED, 1); + EXPECT_EQ(node_value_arrs::N_STORE_FEATURES, 2); + EXPECT_EQ(node_value_arrs::VALUES_ARR.size(), 10); + EXPECT_EQ(node_value_arrs::TEST_VALUES_ARR.size(), 4); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_ARR.size(), 0); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_REG.size(), 0); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_TEST_ARR.size(), 0); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_TEST_REG.size(), 0); + + node_value_arrs::resize_values_arr(1, 2, true); + EXPECT_EQ(node_value_arrs::N_SAMPLES, 5); + EXPECT_EQ(node_value_arrs::N_SAMPLES_TEST, 2); + EXPECT_EQ(node_value_arrs::N_RUNGS_STORED, 1); + EXPECT_EQ(node_value_arrs::N_STORE_FEATURES, 2); + EXPECT_EQ(node_value_arrs::VALUES_ARR.size(), 10); + EXPECT_EQ(node_value_arrs::TEST_VALUES_ARR.size(), 4); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_ARR.size(), node_value_arrs::MAX_N_THREADS * (3 * 2 + 1) * 5); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_REG.size(), node_value_arrs::MAX_N_THREADS * (3 * 2 + 1)); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_TEST_ARR.size(), node_value_arrs::MAX_N_THREADS * (3 * 2 + 1) * 2); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_TEST_REG.size(), node_value_arrs::MAX_N_THREADS * (3 * 2 + 1)); + + node_value_arrs::initialize_d_matrix_arr(); + EXPECT_EQ(node_value_arrs::N_SELECTED, 0); + EXPECT_EQ(node_value_arrs::D_MATRIX.size(), 0); + + node_value_arrs::resize_d_matrix_arr(2); + EXPECT_EQ(node_value_arrs::N_SELECTED, 2); + EXPECT_EQ(node_value_arrs::D_MATRIX.size(), 10); + + node_value_arrs::resize_d_matrix_arr(3); + EXPECT_EQ(node_value_arrs::N_SELECTED, 5); + EXPECT_EQ(node_value_arrs::D_MATRIX.size(), 25); + + node_value_arrs::get_value_ptr(1, 1, 0)[1] = 1.0; + EXPECT_EQ(node_value_arrs::VALUES_ARR[6], 1.0); + + node_value_arrs::get_test_value_ptr(1, 1, 0)[1] = 1.0; + EXPECT_EQ(node_value_arrs::TEST_VALUES_ARR[3], 1.0); + + node_value_arrs::get_value_ptr(10, 141, 1)[1] = 1.0; + EXPECT_EQ(node_value_arrs::temp_storage_reg(10, 1), 141); + EXPECT_EQ(node_value_arrs::access_temp_storage((10 % 2) + 2 + omp_get_thread_num() * (2 * 3 + 1))[1], 1.0); + + node_value_arrs::get_test_value_ptr(10, 141, 1)[1] = 1.0; + EXPECT_EQ(node_value_arrs::temp_storage_test_reg(10, 1), 141); + EXPECT_EQ(node_value_arrs::access_temp_storage_test((10 % 2) + 2 + omp_get_thread_num() * (2 * 3 + 1))[1], 1.0); + + node_value_arrs::get_d_matrix_ptr(1)[0] = 1.0; + EXPECT_EQ(node_value_arrs::D_MATRIX[5], 1.0); + + #pragma omp parallel + { + std::fill_n(node_value_arrs::TEMP_STORAGE_REG.data() + 6 * omp_get_thread_num(), 6, omp_get_thread_num()); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_REG[6 * omp_get_thread_num()], omp_get_thread_num()); + node_value_arrs::clear_temp_reg_thread(); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_REG[6 * omp_get_thread_num()], -1); + } + + std::fill_n(node_value_arrs::TEMP_STORAGE_REG.data(), node_value_arrs::TEMP_STORAGE_REG.size(), 2.0); + node_value_arrs::clear_temp_reg(); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_REG[0], -1); + + std::fill_n(node_value_arrs::TEMP_STORAGE_TEST_REG.data(), node_value_arrs::TEMP_STORAGE_REG.size(), 2.0); + node_value_arrs::clear_temp_test_reg(); + EXPECT_EQ(node_value_arrs::TEMP_STORAGE_TEST_REG[0], -1); + } +} \ No newline at end of file diff --git a/tests/googletest/test_main.cpp b/tests/googletest/test_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4db8d28e8ae6f9113652df45b00ca27a8be51f4 --- /dev/null +++ b/tests/googletest/test_main.cpp @@ -0,0 +1,6 @@ +#include <googletest/utils/test_math_utils.cc> + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/tests/googletest/utils/test_compare_features.cc b/tests/googletest/utils/test_compare_features.cc new file mode 100644 index 0000000000000000000000000000000000000000..826469278a3b09f45cb7b407e6dcf4c1a6714087 --- /dev/null +++ b/tests/googletest/utils/test_compare_features.cc @@ -0,0 +1,34 @@ +#include "gtest/gtest.h" +#include <utils/compare_features.hpp> +#include <feature_creation/node/ModelNode.hpp> + +namespace { + //test mean calculations + TEST(CompFeats, CompFeatTest) + { + std::vector<double> val_1 = {1.0, 2.0, 3.0, 4.0}; + std::vector<double> val_2 = {2.0, 2.0, 3.0, 4.0}; + std::vector<double> val_3 = {2.0, 4.0, 6.0, 8.0}; + std::vector<double> target = {1.0, 3.0, 5.0, 6.0}; + std::vector<double> scores = {0.9897782665572893}; + std::vector<node_ptr> selected(1); + + selected[0] = std::make_shared<ModelNode>(0, 0, "A", "$A$", "0", val_3, std::vector<double>(), Unit()); + + node_value_arrs::initialize_values_arr(4, 0, 1); + node_value_arrs::initialize_d_matrix_arr(); + node_value_arrs::resize_d_matrix_arr(1); + + std::copy_n(val_3.data(), val_3.size(), node_value_arrs::get_d_matrix_ptr(0)); + + EXPECT_FALSE(comp_feats::valid_feature_against_selected_max_corr_1(val_1.data(), 4, 1.0, scores, 0.9897782665572893, 1, 0)); + EXPECT_FALSE(comp_feats::valid_feature_against_selected_max_corr_1_feat_list(val_1.data(), 4, 1.0, selected, scores, 0.9897782665572893)); + EXPECT_FALSE(comp_feats::valid_feature_against_selected(val_1.data(), 4, 1.0, scores, 0.9897782665572893, 1, 0)); + EXPECT_FALSE(comp_feats::valid_feature_against_selected_feat_list(val_1.data(), 4, 1.0, selected, scores, 0.9897782665572893)); + + EXPECT_TRUE(comp_feats::valid_feature_against_selected_max_corr_1(val_2.data(), 4, 1.0, scores, 0.9028289727756884, 1, 0)); + EXPECT_TRUE(comp_feats::valid_feature_against_selected_max_corr_1_feat_list(val_2.data(), 4, 1.0, selected, scores, 0.9028289727756884)); + EXPECT_TRUE(comp_feats::valid_feature_against_selected(val_2.data(), 4, 1.0, scores, 0.9028289727756884, 1, 0)); + EXPECT_TRUE(comp_feats::valid_feature_against_selected_feat_list(val_2.data(), 4, 1.0, selected, scores, 0.9028289727756884)); + } +} diff --git a/tests/googletest/utils/test_math_utils.cc b/tests/googletest/utils/test_math_utils.cc new file mode 100644 index 0000000000000000000000000000000000000000..139114bf9fc871e45a37b5bce6bf8142b60c2ab6 --- /dev/null +++ b/tests/googletest/utils/test_math_utils.cc @@ -0,0 +1,193 @@ +#include "gtest/gtest.h" +#include <utils/math_funcs.hpp> + +namespace { + // Setup initial test vectors + std::vector<double> dVec1(16, 1.0); + std::vector<double> dVec2 = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}; + std::vector<double> dVec3 = {2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0}; + + std::vector<int> iVec1(16, 1); + std::vector<int> iVec2 = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector<int> iVec3 = {2, 4, 4, 4, 5, 5, 7, 9}; + + //test mean calculations + TEST(MathUtils, MeanTest) + { + EXPECT_EQ(util_funcs::mean(dVec1), 1.0); + EXPECT_EQ(util_funcs::mean(iVec1), 1.0); + + EXPECT_EQ(util_funcs::mean(dVec1.data(), 16), 1.0); + EXPECT_EQ(util_funcs::mean(iVec1.data(), 16), 1.0); + + EXPECT_EQ(util_funcs::mean(dVec2), 0.25); + EXPECT_EQ(util_funcs::mean(iVec2), 0.25); + + EXPECT_EQ(util_funcs::mean(dVec2.data(), 16), 0.25); + EXPECT_EQ(util_funcs::mean(iVec2.data(), 16), 0.25); + + EXPECT_EQ(util_funcs::mean(dVec3), 5.0); + EXPECT_EQ(util_funcs::mean(iVec3), 5.0); + + EXPECT_EQ(util_funcs::mean(dVec3.data(), 8), 5.0); + EXPECT_EQ(util_funcs::mean(iVec3.data(), 8), 5.0); + } + + //test standard deviation calculations + TEST(MathUtils, STDTest) + { + EXPECT_EQ(util_funcs::stand_dev(dVec1), 0.0); + EXPECT_EQ(util_funcs::stand_dev(dVec1.data(), 16), 0.0); + EXPECT_EQ(util_funcs::stand_dev(dVec1, 1.0), 0.0); + EXPECT_EQ(util_funcs::stand_dev(dVec1.data(), 16, 1.0), 0.0); + + EXPECT_EQ(util_funcs::stand_dev(dVec3), 2.0); + EXPECT_EQ(util_funcs::stand_dev(dVec3.data(), 8), 2.0); + EXPECT_EQ(util_funcs::stand_dev(dVec3, 5.0), 2.0); + EXPECT_EQ(util_funcs::stand_dev(dVec3.data(), 8, 5.0), 2.0); + } + + //test norm calculations + TEST(MathUtils, NormTest) + { + EXPECT_EQ(util_funcs::norm(dVec1), 4.0); + EXPECT_EQ(util_funcs::norm(dVec1.data(), 16), 4.0); + + EXPECT_EQ(util_funcs::norm(dVec2), 2.0); + EXPECT_EQ(util_funcs::norm(dVec2.data(), 16), 2.0); + } + + //test Pearson correlation + TEST(MathUtils, RTest) + { + std::vector<double> dNeg2(16, 0); + std::transform(dVec2.begin(), dVec2.end(), dNeg2.begin(), [](double dd){return -1.0 * dd;}); + + std::vector<int> szs = {2, 14}; + EXPECT_FALSE(std::isfinite(util_funcs::r(dVec1.data(), dVec2.data(), 16))); + EXPECT_FALSE(std::isfinite(util_funcs::r(dVec1.data(), dVec2.data(), szs))); + EXPECT_FALSE(std::isfinite(util_funcs::r(dVec1.data(), dVec2.data(), szs.data(), 2))); + + EXPECT_TRUE(std::isfinite(util_funcs::r(dVec2.data(), dVec2.data(), 16))); + EXPECT_FALSE(std::isfinite(util_funcs::r(dVec2.data(), dVec2.data(), szs))); + EXPECT_FALSE(std::isfinite(util_funcs::r(dVec2.data(), dVec2.data(), szs.data(), 2))); + + szs = {8, 8}; + EXPECT_LT(std::abs(1.0 - util_funcs::r(dVec2.data(), dVec2.data(), 16)), 1.0e-10); + EXPECT_LT(std::abs(1.0 - util_funcs::r(dVec2.data(), dVec2.data(), szs)), 1.0e-10); + EXPECT_LT(std::abs(1.0 - util_funcs::r(dVec2.data(), dVec2.data(), szs.data(), 2)), 1.0e-10); + + EXPECT_LT(std::abs(1.0 + util_funcs::r(dVec2.data(), dNeg2.data(), 16)), 1e-10); + EXPECT_LT(std::abs(1.0 - util_funcs::r(dVec2.data(), dNeg2.data(), szs)), 1e-10); + EXPECT_LT(std::abs(1.0 - util_funcs::r(dVec2.data(), dNeg2.data(), szs.data(), 2)), 1e-10); + } + + //test r^2 + TEST(MathUtils, R2Test) + { + std::vector<double> dNeg2(16, 0); + std::transform(dVec2.begin(), dVec2.end(), dNeg2.begin(), [](double dd){return -1.0 * dd;}); + + std::vector<int> szs = {2, 14}; + EXPECT_FALSE(std::isfinite(util_funcs::r2(dVec1.data(), dVec2.data(), 16))); + EXPECT_FALSE(std::isfinite(util_funcs::r2(dVec1.data(), dVec2.data(), szs))); + EXPECT_FALSE(std::isfinite(util_funcs::r2(dVec1.data(), dVec2.data(), szs.data(), 2))); + + EXPECT_TRUE(std::isfinite(util_funcs::r2(dVec2.data(), dVec2.data(), 16))); + EXPECT_FALSE(std::isfinite(util_funcs::r2(dVec2.data(), dVec2.data(), szs))); + EXPECT_FALSE(std::isfinite(util_funcs::r2(dVec2.data(), dVec2.data(), szs.data(), 2))); + + szs = {8, 8}; + EXPECT_LT(std::abs(1.0 - util_funcs::r2(dVec2.data(), dVec2.data(), 16)), 1.0e-10); + EXPECT_LT(std::abs(1.0 - util_funcs::r2(dVec2.data(), dVec2.data(), szs)), 1.0e-10); + EXPECT_LT(std::abs(1.0 - util_funcs::r2(dVec2.data(), dVec2.data(), szs.data(), 2)), 1.0e-10); + + EXPECT_LT(std::abs(1.0 - util_funcs::r2(dVec2.data(), dNeg2.data(), 16)), 1.0e-10); + EXPECT_LT(std::abs(1.0 - util_funcs::r2(dVec2.data(), dNeg2.data(), szs)), 1.0e-10); + EXPECT_LT(std::abs(1.0 - util_funcs::r2(dVec2.data(), dNeg2.data(), szs.data(), 2)), 1.0e-10); + } + + //test log_r^2 + TEST(MathUtils, LogR2Test) + { + std::vector<double> dNeg2(16, 0); + std::vector<double> log_x(16, 0); + std::transform(dVec2.begin(), dVec2.end(), dNeg2.begin(), [](double dd){return -1.0 * dd;}); + + std::vector<int> szs = {2, 14}; + EXPECT_FALSE(std::isfinite(util_funcs::log_r2(dVec1.data(), dVec2.data(), log_x.data(), 16))); + EXPECT_FALSE(std::isfinite(util_funcs::log_r2(dVec1.data(), dVec2.data(), log_x.data(), szs))); + EXPECT_FALSE(std::isfinite(util_funcs::log_r2(dVec1.data(), dVec2.data(), log_x.data(), szs.data(), 2))); + + EXPECT_FALSE(std::isfinite(util_funcs::log_r2(dVec2.data(), dVec2.data(), log_x.data(), 16))); + EXPECT_FALSE(std::isfinite(util_funcs::log_r2(dVec2.data(), dVec2.data(), log_x.data(), szs))); + EXPECT_FALSE(std::isfinite(util_funcs::log_r2(dVec2.data(), dVec2.data(), log_x.data(), szs.data(), 2))); + + szs = {2, 2}; + std::vector<double> x = {1, 10, 1000, 10000}; + std::vector<double> y = {0, 1, 3, 4}; + EXPECT_LT(std::abs(1.0 - util_funcs::log_r2(x.data(), y.data(), log_x.data(), 4)), 1.0); + EXPECT_LT(std::abs(1.0 - util_funcs::log_r2(x.data(), y.data(), log_x.data(), szs)), 1.0); + EXPECT_LT(std::abs(1.0 - util_funcs::log_r2(x.data(), y.data(), log_x.data(), szs.data(), 2)), 1.0); + + } + + //test argsort + TEST(MathUtils, ArgSortTest) + { + std::vector<double> to_sort = {3.0, 4.0, 2.0}; + std::vector<int> inds; + + inds = util_funcs::argsort(to_sort); + EXPECT_EQ(std::abs(inds[0] - 2) + std::abs(inds[1] - 0) + std::abs(inds[2] - 1), 0.0); + + util_funcs::argsort(inds.data(), inds.data() + inds.size(), to_sort); + EXPECT_EQ(std::abs(inds[0] - 2) + std::abs(inds[1] - 0) + std::abs(inds[2] - 1), 0.0); + + util_funcs::argsort(inds.data(), inds.data() + inds.size(), to_sort.data()); + EXPECT_EQ(std::abs(inds[0] - 2) + std::abs(inds[1] - 0) + std::abs(inds[2] - 1), 0.0); + + std::vector<double> to_sort_int = {3, 4, 2}; + inds = util_funcs::argsort(to_sort_int); + EXPECT_EQ(std::abs(inds[0] - 2) + std::abs(inds[1] - 0) + std::abs(inds[2] - 1), 0.0); + + util_funcs::argsort(inds.data(), inds.data() + inds.size(), to_sort_int); + EXPECT_EQ(std::abs(inds[0] - 2) + std::abs(inds[1] - 0) + std::abs(inds[2] - 1), 0.0); + + util_funcs::argsort(inds.data(), inds.data() + inds.size(), to_sort_int.data()); + EXPECT_EQ(std::abs(inds[0] - 2) + std::abs(inds[1] - 0) + std::abs(inds[2] - 1), 0.0); + } + + // test max_abs_val + TEST(MathUtils, MaxAbsValTest) + { + std::vector<double> dNeg3(16, 0); + std::transform(dVec3.begin(), dVec3.end(), dNeg3.begin(), [](double dd){return -1.0 * dd;}); + + EXPECT_EQ(util_funcs::max_abs_val<double>(dVec3.data(), dVec3.data() + dVec3.size()), 9.0); + EXPECT_EQ(util_funcs::max_abs_val<double>(dVec3.data(), dVec3.size()), 9.0); + + EXPECT_EQ(util_funcs::max_abs_val<double>(dNeg3.data(), dNeg3.data() + dNeg3.size()), 9.0); + EXPECT_EQ(util_funcs::max_abs_val<double>(dNeg3.data(), dNeg3.size()), 9.0); + } + + // test iterate + TEST(MathUtils, IterateTest) + { + std::vector<int> inds = {5, 4, 3}; + + util_funcs::iterate(inds, 3, 1); + EXPECT_EQ(std::abs(inds[0] - 5) + std::abs(inds[1] - 4) + std::abs(inds[2] - 2), 0.0); + + util_funcs::iterate(inds, 3, 2); + EXPECT_EQ(std::abs(inds[0] - 5) + std::abs(inds[1] - 4) + std::abs(inds[2] - 0), 0.0); + + util_funcs::iterate(inds, 3, 7); + EXPECT_EQ(std::abs(inds[0] - 4) + std::abs(inds[1] - 3) + std::abs(inds[2] - 2), 0.0); + + util_funcs::iterate(inds, 3, 9); + EXPECT_EQ(std::abs(inds[0] - 2) + std::abs(inds[1] - 1) + std::abs(inds[2] - 0), 0.0); + + EXPECT_FALSE(util_funcs::iterate(inds, 3, 1)); + } +} \ No newline at end of file diff --git a/tests/googletest/utils/test_project.cc b/tests/googletest/utils/test_project.cc new file mode 100644 index 0000000000000000000000000000000000000000..af5932cf59c72a0dbb521836f14aa306506c2e27 --- /dev/null +++ b/tests/googletest/utils/test_project.cc @@ -0,0 +1,51 @@ +#include "gtest/gtest.h" +#include <utils/project.hpp> +#include <feature_creation/node/ModelNode.hpp> + +namespace { + + //test mean calculations + TEST(Project, ProjectTest) + { + std::vector<double> prop = {1.0, 3.0, 5.0, 6.0}; + std::vector<double> prop_class = {0.0, 0.0, 0.0, 1.0}; + std::vector<double> val = {2.0, 2.0, 3.0, 4.0}; + std::vector<double> scores(1, 0.0); + std::vector<int> sizes(1, 4); + + std::vector<node_ptr> phi = {std::make_shared<ModelNode>(0, 0, "A", "$A$", "0", val, std::vector<double>(), Unit())}; + + project_funcs::project_r(prop.data(), scores.data(), phi, sizes, 1); + EXPECT_LT(std::abs(-0.9028289727756884 - scores[0]), 1e-10); + scores[0] = 0.0; + + project_funcs::project_r2(prop.data(), scores.data(), phi, sizes, 1); + EXPECT_LT(std::abs(-0.8151001540832047 - scores[0]), 1e-10); + scores[0] = 0.0; + + project_funcs::project_log_r2(prop.data(), scores.data(), phi, sizes, 1); + EXPECT_LT(std::abs(-0.8437210425744424 - scores[0]), 1e-10); + scores[0] = 0.0; + + project_funcs::project_classify(prop_class.data(), scores.data(), phi, sizes, 1); + EXPECT_LT(std::abs(-0.4999850001499985 - scores[0]), 1e-10); + scores[0] = 0.0; + + project_funcs::project_r_no_omp(prop.data(), scores.data(), phi, sizes, 1); + EXPECT_LT(std::abs(-0.9028289727756884 - scores[0]), 1e-10); + scores[0] = 0.0; + + project_funcs::project_r2_no_omp(prop.data(), scores.data(), phi, sizes, 1); + EXPECT_LT(std::abs(-0.8151001540832047 - scores[0]), 1e-10); + scores[0] = 0.0; + + project_funcs::project_log_r2_no_omp(prop.data(), scores.data(), phi, sizes, 1); + EXPECT_LT(std::abs(-0.8437210425744424 - scores[0]), 1e-10); + scores[0] = 0.0; + + project_funcs::project_classify_no_omp(prop_class.data(), scores.data(), phi, sizes, 1); + EXPECT_LT(std::abs(-0.4999850001499985 - scores[0]), 1e-10); + scores[0] = 0.0; + + } +} diff --git a/tests/googletest/utils/test_str_utils.cc b/tests/googletest/utils/test_str_utils.cc new file mode 100644 index 0000000000000000000000000000000000000000..1e15717b7d81e39586af932811ad90c2b2134e4e --- /dev/null +++ b/tests/googletest/utils/test_str_utils.cc @@ -0,0 +1,24 @@ +#include "gtest/gtest.h" +#include <utils/string_utils.hpp> + +namespace { + + //test mean calculations + TEST(StrUtils, SplitTrimTest) + { + std::vector<std::string> str_split = str_utils::split_string_trim("A ; B ; C , D : 5"); + EXPECT_EQ(str_split.size(), 5); + EXPECT_STREQ(str_split[0].c_str(), "A"); + EXPECT_STREQ(str_split[1].c_str(), "B"); + EXPECT_STREQ(str_split[2].c_str(), "C"); + EXPECT_STREQ(str_split[3].c_str(), "D"); + EXPECT_STREQ(str_split[4].c_str(), "5"); + + str_split = str_utils::split_string_trim("A ; B ; C , D : 5", ";,"); + EXPECT_EQ(str_split.size(), 4); + EXPECT_STREQ(str_split[0].c_str(), "A"); + EXPECT_STREQ(str_split[1].c_str(), "B"); + EXPECT_STREQ(str_split[2].c_str(), "C"); + EXPECT_STREQ(str_split[3].c_str(), "D : 5"); + } +} \ No newline at end of file