From f38637d7b5344a38ec1a94c3731713c6fe0a01fc Mon Sep 17 00:00:00 2001 From: Thomas <purcell@fhi-berlin.mpg.de> Date: Fri, 7 May 2021 14:34:30 +0200 Subject: [PATCH] Add functionality to automatically generate Matlab Functions for models Used for sensitivity analysis with UQLab --- src/descriptor_identifier/Model/Model.cpp | 77 +++++++++++++++++++ src/descriptor_identifier/Model/Model.hpp | 22 ++++++ .../Model/ModelClassifier.cpp | 64 +++++++++++++-- .../Model/ModelClassifier.hpp | 7 ++ .../Model/ModelLogRegressor.cpp | 13 +++- .../Model/ModelLogRegressor.hpp | 9 ++- .../Model/ModelRegressor.cpp | 66 ++++++++++++++-- .../Model/ModelRegressor.hpp | 7 ++ .../SISSO_DI/SISSORegressor.cpp | 2 + src/feature_creation/node/FeatureNode.hpp | 24 ++++++ src/feature_creation/node/ModelNode.cpp | 3 + src/feature_creation/node/ModelNode.hpp | 33 ++++++++ src/feature_creation/node/Node.hpp | 17 ++++ .../node/operator_nodes/OperatorNode.hpp | 17 ++++ .../abs/absolute_value.hpp | 31 ++++++++ .../abs/parameterized_absolute_value.hpp | 9 +++ .../abs_diff/absolute_difference.hpp | 33 ++++++++ .../parameterized_absolute_difference.hpp | 9 +++ .../allowed_operator_nodes/add/add.hpp | 32 ++++++++ .../add/parameterized_add.hpp | 9 +++ .../allowed_operator_nodes/cb/cube.hpp | 31 ++++++++ .../cb/parameterized_cube.hpp | 9 +++ .../allowed_operator_nodes/cbrt/cube_root.hpp | 31 ++++++++ .../cbrt/parameterized_cube_root.hpp | 9 +++ .../allowed_operator_nodes/cos/cos.hpp | 31 ++++++++ .../cos/parameterized_cos.hpp | 9 +++ .../allowed_operator_nodes/div/divide.hpp | 33 ++++++++ .../div/parameterized_divide.hpp | 9 +++ .../exp/exponential.hpp | 31 ++++++++ .../exp/parameterized_exponential.hpp | 9 +++ .../allowed_operator_nodes/inv/inverse.hpp | 31 ++++++++ .../inv/parameterized_inverse.hpp | 9 +++ .../allowed_operator_nodes/log/log.hpp | 31 ++++++++ .../log/parameterized_log.hpp | 9 +++ .../allowed_operator_nodes/mult/multiply.hpp | 33 ++++++++ .../mult/parameterized_multiply.hpp | 9 +++ .../neg_exp/negative_exponential.hpp | 35 ++++++++- .../parameterized_negative_exponential.hpp | 9 +++ .../sin/parameterized_sin.hpp | 9 +++ .../allowed_operator_nodes/sin/sin.hpp | 32 ++++++++ .../six_pow/parameterized_sixth_power.hpp | 9 +++ .../six_pow/sixth_power.hpp | 31 ++++++++ .../sq/parameterized_square.hpp | 9 +++ .../allowed_operator_nodes/sq/square.hpp | 31 ++++++++ .../sqrt/parameterized_square_root.hpp | 9 +++ .../sqrt/square_root.hpp | 31 ++++++++ .../sub/parameterized_subtract.hpp | 9 +++ .../allowed_operator_nodes/sub/subtract.hpp | 33 ++++++++ src/python/bindings_docstring_keyed.cpp | 14 ++-- src/python/bindings_docstring_keyed.hpp | 7 ++ src/utils/string_utils.cpp | 34 ++++++++ src/utils/string_utils.hpp | 21 ++++- src/utils/vector_utils.hpp | 32 ++++++++ 53 files changed, 1133 insertions(+), 30 deletions(-) create mode 100644 src/utils/vector_utils.hpp diff --git a/src/descriptor_identifier/Model/Model.cpp b/src/descriptor_identifier/Model/Model.cpp index 1e05768c..9cc13840 100644 --- a/src/descriptor_identifier/Model/Model.cpp +++ b/src/descriptor_identifier/Model/Model.cpp @@ -112,3 +112,80 @@ std::vector<double> Model::eval(std::map<std::string, std::vector<double>> x_in_ } return eval(x_in); } + +void Model::write_matlab_fxn(std::string fxn_filename) +{ + if(fxn_filename.substr(fxn_filename.size() - 2, 2).compare(".m") != 0) + { + fxn_filename += ".m"; + } + + boost::filesystem::path p(fxn_filename.c_str()); + 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(fxn_filename); + + // Get the list of all unique leaves in all features + std::vector<std::string> leaves; + for(auto& feat : _feats) + { + std::vector<std::string> x_in = feat->get_x_in_expr_list(); + leaves.insert(leaves.end(), x_in.begin(), x_in.end()); + } + leaves = vector_utils::unique<std::string>(leaves); + std::transform(leaves.begin(), leaves.end(), leaves.begin(), [](std::string s){return str_utils::matlabify(s);}); + + // Write the header of the function + out_file_stream << "function P = " << fxn_filename.substr(0, fxn_filename.size() - 2) << "(X)\n"; + out_file_stream << "% Returns the value of " << _prop_label << " = " << toString() << "\n%\n"; + out_file_stream << "% X = [\n"; + for(auto & leaf : leaves) + { + out_file_stream << "% " << leaf << ",\n"; + } + out_file_stream << "% ]\n\n"; + + // Check X contains the correct number of columns + out_file_stream << "if(size(X, 2) ~= " << leaves.size() << ")\n"; + out_file_stream << " error(\"ERROR: X must have a size of " << leaves.size() << " in the second dimension.\")\n"; + out_file_stream << "end\n"; + int len_rename = (*std::max_element(leaves.begin(), leaves.end(), [](std::string s1, std::string s2){return s1.size() < s2.size();})).size(); + + // Rename X + for(int ll = 0; ll < leaves.size(); ++ll) + { + out_file_stream << std::setw(len_rename) << leaves[ll] << std::setw(3) << " = " << "reshape(X(:, " << ll + 1 << "), 1, []);\n"; + } + out_file_stream << "\n"; + + // Set features + for(int ff = 0; ff < _feats.size(); ++ff) + { + out_file_stream << "f" << ff << " = " << _feats[ff]->matlab_fxn_expr() << ";\n"; + } + out_file_stream << "\n"; + + // Set Constants + if(_fix_intercept) + { + out_file_stream << "c0 = 0.0;\n"; + } + else + { + out_file_stream << "c0 = " << _coefs[0].back() << ";\n"; + } + for(int ff = 0; ff < _feats.size(); ++ff) + { + out_file_stream << "a" << ff <<" = " << _coefs[0][ff] << ";\n"; + } + out_file_stream << "\n"; + + // Calculate the property + out_file_stream << "P = reshape(" << matlab_expr() << ", [], 1);\nend\n"; + out_file_stream.close(); +} diff --git a/src/descriptor_identifier/Model/Model.hpp b/src/descriptor_identifier/Model/Model.hpp index ba545681..1210caaa 100644 --- a/src/descriptor_identifier/Model/Model.hpp +++ b/src/descriptor_identifier/Model/Model.hpp @@ -20,6 +20,7 @@ #include "feature_creation/node/ModelNode.hpp" #include "utils/string_utils.hpp" +#include "utils/vector_utils.hpp" #ifdef PY_BINDINGS namespace np = boost::python::numpy; @@ -232,6 +233,27 @@ public: */ inline std::vector<std::vector<double>> coefs() const {return _coefs;} + /** + * @brief Convert the model to a string + + * @return The string representation of the model + */ + virtual std::string toString() const = 0; + + /** + * @brief Get the matlab expression for this model + + * @return The matlab exprssion for the model + */ + virtual std::string matlab_expr() const = 0; + + /** + * @brief Convert the model into a Matlab function + * + * @param fxn_filename name of the file to print the function to + */ + void write_matlab_fxn(std::string fxn_filename); + #ifdef PY_BINDINGS // DocString: model_coefs /** diff --git a/src/descriptor_identifier/Model/ModelClassifier.cpp b/src/descriptor_identifier/Model/ModelClassifier.cpp index 3fb778cf..18b7c9ee 100644 --- a/src/descriptor_identifier/Model/ModelClassifier.cpp +++ b/src/descriptor_identifier/Model/ModelClassifier.cpp @@ -97,12 +97,21 @@ ModelClassifier::ModelClassifier(const std::string train_file) std::string postfix_expr = split_str[3]; std::string expr = split_str[4]; std::string latex_expr = "Property"; + std::string matlab_expr; std::vector<std::string> x_in_expr_list; if(split_str.size() > 5) { - x_in_expr_list = str_utils::split_string_trim(split_str[5]); + x_in_expr_list = str_utils::split_string_trim(split_str.back()); } - feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); + if(split_str.size() > 6) + { + matlab_expr = split_str[5]; + } + else + { + matlab_expr = "NaN"; + } + feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, matlab_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); } else { @@ -110,12 +119,21 @@ ModelClassifier::ModelClassifier(const std::string train_file) std::string postfix_expr = split_str[2]; std::string expr = split_str[3]; std::string latex_expr = split_str[4]; + std::string matlab_expr; std::vector<std::string> x_in_expr_list; if(split_str.size() > 5) { - x_in_expr_list = str_utils::split_string_trim(split_str[5]); + x_in_expr_list = str_utils::split_string_trim(split_str.back()); + } + if(split_str.size() > 6) + { + matlab_expr = split_str[5]; } - feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); + else + { + matlab_expr = "NaN"; + } + feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, matlab_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); } _feats.push_back(feat); } @@ -157,12 +175,21 @@ ModelClassifier::ModelClassifier(const std::string train_file, const std::string std::string postfix_expr = split_str[3]; std::string expr = split_str[4]; std::string latex_expr = "Property"; + std::string matlab_expr; std::vector<std::string> x_in_expr_list; if(split_str.size() > 5) { - x_in_expr_list = str_utils::split_string_trim(split_str[5]); + x_in_expr_list = str_utils::split_string_trim(split_str.back()); + } + if(split_str.size() > 6) + { + matlab_expr = split_str[5]; + } + else + { + matlab_expr = "NaN"; } - feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); + feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, matlab_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); } else { @@ -170,12 +197,21 @@ ModelClassifier::ModelClassifier(const std::string train_file, const std::string std::string postfix_expr = split_str[2]; std::string expr = split_str[3]; std::string latex_expr = split_str[4]; + std::string matlab_expr; std::vector<std::string> x_in_expr_list; if(split_str.size() > 5) { - x_in_expr_list = str_utils::split_string_trim(split_str[5]); + x_in_expr_list = str_utils::split_string_trim(split_str.back()); + } + if(split_str.size() > 6) + { + matlab_expr = split_str[5]; + } + else + { + matlab_expr = "NaN"; } - feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); + feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, matlab_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); } _feats.push_back(feat); } @@ -572,6 +608,17 @@ std::string ModelClassifier::toLatexString() const return unit_rep.str(); } +std::string ModelClassifier::matlab_expr() const +{ + std::string to_ret = ""; + to_ret += "c0"; + for(int ff = 0; ff < _feats.size(); ++ff) + { + to_ret += " + a" + std::to_string(ff) + " * f" + std::to_string(ff); + } + return to_ret; +} + std::ostream& operator<< (std::ostream& outStream, const ModelClassifier& model) { outStream << model.toString(); @@ -632,6 +679,7 @@ void ModelClassifier::to_file(std::string filename, bool train, std::vector<int> out_file_stream << _feats[ff]->postfix_expr() + "; "; out_file_stream << _feats[ff]->expr() + "; "; out_file_stream << _feats[ff]->latex_expr() + "; "; + out_file_stream << _feats[ff]->matlab_fxn_expr() + "; "; out_file_stream << boost::algorithm::join(_feats[ff]->get_x_in_expr_list(), ",") << std::endl; } diff --git a/src/descriptor_identifier/Model/ModelClassifier.hpp b/src/descriptor_identifier/Model/ModelClassifier.hpp index 1ff38237..13169d09 100644 --- a/src/descriptor_identifier/Model/ModelClassifier.hpp +++ b/src/descriptor_identifier/Model/ModelClassifier.hpp @@ -166,6 +166,13 @@ public: */ std::string toLatexString() const; + /** + * @brief Get the matlab expression for this model + + * @return The matlab exprssion for the model + */ + std::string matlab_expr() const; + /** * @brief Copy the error into a new array * diff --git a/src/descriptor_identifier/Model/ModelLogRegressor.cpp b/src/descriptor_identifier/Model/ModelLogRegressor.cpp index 56e6fbee..64b6b347 100644 --- a/src/descriptor_identifier/Model/ModelLogRegressor.cpp +++ b/src/descriptor_identifier/Model/ModelLogRegressor.cpp @@ -247,7 +247,7 @@ std::string ModelLogRegressor::toLatexString() const } else { - model_rep << "$c_0"; + model_rep << "$\\exp\\left(c_0\\right)"; for(int ff = 0; ff < _feats.size(); ++ff) { model_rep << "\\left(" << _feats[ff]->get_latex_expr() << "\\right)^{a_" << ff << "}"; @@ -257,6 +257,17 @@ std::string ModelLogRegressor::toLatexString() const return model_rep.str(); } +std::string ModelLogRegressor::matlab_expr() const +{ + std::string to_ret = ""; + to_ret += "exp(c0)"; + for(int ff = 0; ff < _feats.size(); ++ff) + { + to_ret += " .* f" + std::to_string(ff) + ".^a" + std::to_string(ff); + } + return to_ret; +} + std::ostream& operator<< (std::ostream& outStream, const ModelLogRegressor& model) { outStream << model.toString(); diff --git a/src/descriptor_identifier/Model/ModelLogRegressor.hpp b/src/descriptor_identifier/Model/ModelLogRegressor.hpp index 3309bcf1..ae537579 100644 --- a/src/descriptor_identifier/Model/ModelLogRegressor.hpp +++ b/src/descriptor_identifier/Model/ModelLogRegressor.hpp @@ -135,7 +135,7 @@ public: * @return The string representation of the model */ - virtual std::string toString() const; + std::string toString() const; // DocString: model_log_reg_latex_str /** @@ -145,6 +145,13 @@ public: */ std::string toLatexString() const; + /** + * @brief Get the matlab expression for this model + + * @return The matlab exprssion for the model + */ + std::string matlab_expr() const; + /** * @brief Copy the error into a new array * diff --git a/src/descriptor_identifier/Model/ModelRegressor.cpp b/src/descriptor_identifier/Model/ModelRegressor.cpp index 59a50872..f60220bc 100644 --- a/src/descriptor_identifier/Model/ModelRegressor.cpp +++ b/src/descriptor_identifier/Model/ModelRegressor.cpp @@ -108,12 +108,21 @@ ModelRegressor::ModelRegressor(const std::string train_file) std::string postfix_expr = split_str[3]; std::string expr = split_str[4]; std::string latex_expr = "Property"; + std::string matlab_expr; std::vector<std::string> x_in_expr_list; if(split_str.size() > 5) { - x_in_expr_list = str_utils::split_string_trim(split_str[5]); + x_in_expr_list = str_utils::split_string_trim(split_str.back()); } - feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); + if(split_str.size() > 6) + { + matlab_expr = split_str[5]; + } + else + { + matlab_expr = "NaN"; + } + feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, matlab_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); } else { @@ -121,12 +130,21 @@ ModelRegressor::ModelRegressor(const std::string train_file) std::string postfix_expr = split_str[2]; std::string expr = split_str[3]; std::string latex_expr = split_str[4]; + std::string matlab_expr; std::vector<std::string> x_in_expr_list; if(split_str.size() > 5) { - x_in_expr_list = str_utils::split_string_trim(split_str[5]); + x_in_expr_list = str_utils::split_string_trim(split_str.back()); + } + if(split_str.size() > 6) + { + matlab_expr = split_str[5]; } - feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); + else + { + matlab_expr = "NaN"; + } + feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, matlab_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); } _feats.push_back(feat); } @@ -161,12 +179,21 @@ ModelRegressor::ModelRegressor(const std::string train_file, std::string test_fi std::string postfix_expr = split_str[3]; std::string expr = split_str[4]; std::string latex_expr = "Property"; + std::string matlab_expr; std::vector<std::string> x_in_expr_list; if(split_str.size() > 5) { - x_in_expr_list = str_utils::split_string_trim(split_str[5]); + x_in_expr_list = str_utils::split_string_trim(split_str.back()); + } + if(split_str.size() > 6) + { + matlab_expr = split_str[5]; + } + else + { + matlab_expr = "NaN"; } - feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); + feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, matlab_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); } else { @@ -174,12 +201,21 @@ ModelRegressor::ModelRegressor(const std::string train_file, std::string test_fi std::string postfix_expr = split_str[2]; std::string expr = split_str[3]; std::string latex_expr = split_str[4]; + std::string matlab_expr; std::vector<std::string> x_in_expr_list; if(split_str.size() > 5) { - x_in_expr_list = str_utils::split_string_trim(split_str[5]); + x_in_expr_list = str_utils::split_string_trim(split_str.back()); } - feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); + if(split_str.size() > 6) + { + matlab_expr = split_str[5]; + } + else + { + matlab_expr = "NaN"; + } + feat = std::make_shared<ModelNode>(ff, rung, expr, latex_expr, postfix_expr, matlab_expr, feat_val, feat_test_val, x_in_expr_list, Unit(unit_str)); } _feats.push_back(feat); } @@ -414,6 +450,17 @@ std::string ModelRegressor::toLatexString() const return model_rep.str(); } +std::string ModelRegressor::matlab_expr() const +{ + std::string to_ret = ""; + to_ret += "c0"; + for(int ff = 0; ff < _feats.size(); ++ff) + { + to_ret += " + a" + std::to_string(ff) + " * f" + std::to_string(ff); + } + return to_ret; +} + std::ostream& operator<< (std::ostream& outStream, const ModelRegressor& model) { outStream << model.toString(); @@ -425,7 +472,9 @@ void ModelRegressor::to_file(const std::string filename, const bool train, const boost::filesystem::path p(filename.c_str()); 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); @@ -474,6 +523,7 @@ void ModelRegressor::to_file(const std::string filename, const bool train, const out_file_stream << std::setw(50) << _feats[ff]->unit().toString() + "; "; out_file_stream << _feats[ff]->postfix_expr() + "; " << _feats[ff]->expr() + "; "; out_file_stream << _feats[ff]->latex_expr() + "; "; + out_file_stream << _feats[ff]->matlab_fxn_expr() + "; "; out_file_stream << boost::algorithm::join(_feats[ff]->get_x_in_expr_list(), ",") << std::endl; } diff --git a/src/descriptor_identifier/Model/ModelRegressor.hpp b/src/descriptor_identifier/Model/ModelRegressor.hpp index 86fbdac3..4bdbece9 100644 --- a/src/descriptor_identifier/Model/ModelRegressor.hpp +++ b/src/descriptor_identifier/Model/ModelRegressor.hpp @@ -163,6 +163,13 @@ public: */ std::string toLatexString() const; + /** + * @brief Get the matlab expression for this model + + * @return The matlab exprssion for the model + */ + virtual std::string matlab_expr() const; + /** * @brief Copy the error into a new array * diff --git a/src/descriptor_identifier/SISSO_DI/SISSORegressor.cpp b/src/descriptor_identifier/SISSO_DI/SISSORegressor.cpp index d710b5e1..c46950a4 100644 --- a/src/descriptor_identifier/SISSO_DI/SISSORegressor.cpp +++ b/src/descriptor_identifier/SISSO_DI/SISSORegressor.cpp @@ -110,7 +110,9 @@ void SISSORegressor::set_error(const std::vector<int>& inds, const double* coefs void SISSORegressor::add_model(const std::vector<int> indexes) { if(_models.size() < indexes.size()) + { _models.push_back({}); + } std::vector<model_node_ptr> min_nodes(indexes.size()); for(int ii = 0; ii < indexes.size(); ++ii) diff --git a/src/feature_creation/node/FeatureNode.hpp b/src/feature_creation/node/FeatureNode.hpp index 0bb3be61..f19e63f8 100644 --- a/src/feature_creation/node/FeatureNode.hpp +++ b/src/feature_creation/node/FeatureNode.hpp @@ -286,6 +286,17 @@ public: */ inline std::string get_postfix_term() const {return std::to_string(_feat_ind);} + // DocString: feat_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + virtual inline std::string matlab_fxn_expr() const + { + return str_utils::matlabify(_expr); + } + //DocString: feat_node_nfeats /** * @brief Number of features used for an operator node @@ -416,6 +427,19 @@ public: */ inline std::string get_latex_expr(const double* params, const int depth=1) const {return str_utils::latexify(_expr);} + // DocString: feat_node_matlab_expr_param + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + virtual inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return str_utils::matlabify(_expr); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/ModelNode.cpp b/src/feature_creation/node/ModelNode.cpp index c23d0aa2..92f07cee 100644 --- a/src/feature_creation/node/ModelNode.cpp +++ b/src/feature_creation/node/ModelNode.cpp @@ -9,6 +9,7 @@ ModelNode::ModelNode( const std::string expr, const std::string latex_expr, const std::string expr_postfix, + const std::string matlab_fxn_expr, const std::vector<double> value, const std::vector<double> test_value, const std::vector<std::string> x_in_expr_list, @@ -20,6 +21,7 @@ ModelNode::ModelNode( _x_in_expr_list(x_in_expr_list), _latex_expr(latex_expr), _expr_postfix(expr_postfix), + _matlab_fxn_expr(matlab_fxn_expr), _b_remap_svm(0.0), _w_remap_svm(1.0), _rung(rung), @@ -55,6 +57,7 @@ ModelNode::ModelNode(node_ptr in_node) : _x_in_expr_list(in_node->get_x_in_expr_list()), _latex_expr(in_node->latex_expr()), _expr_postfix(in_node->postfix_expr()), + _matlab_fxn_expr(in_node->matlab_fxn_expr()), _b_remap_svm(0.0), _w_remap_svm(1.0), _rung(in_node->rung()), diff --git a/src/feature_creation/node/ModelNode.hpp b/src/feature_creation/node/ModelNode.hpp index 9ee722b8..0c19dbe1 100644 --- a/src/feature_creation/node/ModelNode.hpp +++ b/src/feature_creation/node/ModelNode.hpp @@ -39,6 +39,7 @@ class ModelNode: public FeatureNode ar & _x_in_expr_list; ar & _expr_postfix; ar & _latex_expr; + ar & _matlab_fxn_expr; ar & _b_remap_svm; ar & _w_remap_svm; ar & _rung; @@ -54,6 +55,7 @@ protected: std::vector<std::string> _x_in_expr_list; //!< vector storing the expressions for all primary features that show up in feature in the order they appear in the postfix notation std::string _expr_postfix; //!< postfix expression for the feature std::string _latex_expr; //!< postfix expression for the feature + std::string _matlab_fxn_expr; //!< The Matlab code needed to evaluate the feature double _b_remap_svm; //!< value to remap the b from SVM to real life double _w_remap_svm; //!< value to remap the w from SVM to real life @@ -73,6 +75,8 @@ public: * @param feat_ind index of the feature * @param rung the rung of the feature * @param expr Expression for the feature + * @param latex_expr The LaTeXified expression for the feature + * @param matlab_fxn_expr The code to evaluate the feature in matlab * @param value Value of the feature for each sample * @param test_value Value of the feature for each test sample * @param x_in_expr_list //!< vector storing the expressions for all primary features that show up in feature in the order they appear in the postfix notation @@ -84,6 +88,7 @@ public: const std::string expr, const std::string latex_expr, const std::string expr_postfix, + const std::string matlab_fxn_expr, const std::vector<double> value, const std::vector<double> test_value, const std::vector<std::string> x_in_expr_list, @@ -334,6 +339,17 @@ public: */ inline std::string get_latex_expr() const {return _latex_expr.substr(1, _latex_expr.size() - 2);} + // DocString: model_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return _matlab_fxn_expr; + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -400,6 +416,23 @@ public: */ inline py::list x_in_expr_list_py(){return python_conv_utils::to_list<std::string>(_x_in_expr_list);} #endif + + #ifdef PARAMETERIZE + // DocString: model_node_matlab_expr_param + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + std::cerr << "WARNING: ModelNode can't accept new parameters for getting Matlab code expressions" << std::endl; + return _matlab_fxn_expr; + } + #endif + }; #endif diff --git a/src/feature_creation/node/Node.hpp b/src/feature_creation/node/Node.hpp index 4f0bc9d4..ecd01989 100644 --- a/src/feature_creation/node/Node.hpp +++ b/src/feature_creation/node/Node.hpp @@ -326,6 +326,13 @@ public: */ virtual std::string get_postfix_term() const = 0; + // DocString: node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * @return The matlab code for the feature + */ + virtual std::string matlab_fxn_expr() const = 0; + /** * @brief update the dictionary used to check if an Add/Sub/AbsDiff node is valid * @@ -433,6 +440,16 @@ public: */ virtual std::string get_latex_expr(const double* params, const int depth=1) const = 0; + // DocString: node_matlab_expr_param + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + virtual std::string matlab_fxn_expr(const double* params, const int depth=1) const = 0; + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/OperatorNode.hpp b/src/feature_creation/node/operator_nodes/OperatorNode.hpp index 8583f9ef..64a19d35 100644 --- a/src/feature_creation/node/operator_nodes/OperatorNode.hpp +++ b/src/feature_creation/node/operator_nodes/OperatorNode.hpp @@ -331,6 +331,14 @@ public: */ virtual std::string get_postfix_term() const = 0; + // DocString: op_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + virtual std::string matlab_fxn_expr() const = 0; + //DocString: op_node_nfeats /** * @brief Number of features used for an operator node @@ -494,6 +502,15 @@ public: */ virtual std::string get_latex_expr(const double* params, const int depth=1) const = 0; + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + virtual std::string matlab_fxn_expr(const double* params, const int depth=1) const = 0; + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp index 7446c42f..a7474922 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp @@ -125,6 +125,20 @@ public: */ inline std::string get_postfix_term() const {return "abs";} + // DocString: abs_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "abs({})", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -225,6 +239,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "abs({:.10e}.*{}{:+15.10e})", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp index 5f666a6c..1be28f8e 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp @@ -41,6 +41,7 @@ protected: using AbsNode::test_value_ptr; using AbsNode::expr; using AbsNode::get_latex_expr; + using AbsNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector double _sign_alpha; //!< 1 if alpha is positive, -1 if alpha is negative @@ -143,6 +144,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: abs_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp index 0a7ce56c..bb4715bd 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp @@ -132,6 +132,21 @@ public: */ inline std::string get_postfix_term() const {return "abd";} + // DocString: abs_diff_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "abs({} - {})", + _feats[0]->matlab_fxn_expr(), + _feats[1]->matlab_fxn_expr() + ); + } + /** * @brief Check if the feature will be valid, if it is then set the value * @return True if the feature is valid @@ -240,6 +255,24 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "abs({} - ({:.10e}.*{}{:+15.10e}))", + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + _feats[1]->n_params() + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp index 2e18643e..2fdf16be 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp @@ -39,6 +39,7 @@ protected: using AbsDiffNode::test_value_ptr; using AbsDiffNode::expr; using AbsDiffNode::get_latex_expr; + using AbsDiffNode::matlab_fxn_expr; std::vector<double> _params; public: @@ -143,6 +144,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: abs_diff_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp index 63f8e814..6c24be40 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp @@ -128,6 +128,20 @@ public: */ inline std::string get_postfix_term() const {return "add";} + // DocString: add_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "({} + {})", + _feats[0]->matlab_fxn_expr(), + _feats[1]->matlab_fxn_expr() + ); + } /** * @brief Check if the feature will be valid, if it is then set the value * @return True if the feature is valid @@ -236,6 +250,24 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "({} + ({:.10e}.*{}{:+15.10e}))", + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + _feats[1]->n_params() + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp index 62706621..1b79820f 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp @@ -40,6 +40,7 @@ protected: using AddNode::test_value_ptr; using AddNode::expr; using AddNode::get_latex_expr; + using AddNode::matlab_fxn_expr; std::vector<double> _params; @@ -144,6 +145,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: add_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp index b3002a0e..a16d6e22 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp @@ -125,6 +125,20 @@ public: */ inline std::string get_postfix_term() const {return "cb";} + // DocString: cb_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "({}).^3", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -225,6 +239,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "({:.10e}.*{}{:+15.10e}).^3", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp index 1bcb3511..940b5f2b 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp @@ -40,6 +40,7 @@ protected: using CbNode::test_value_ptr; using CbNode::expr; using CbNode::get_latex_expr; + using CbNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector @@ -141,6 +142,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: cb_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp index e78d6b3d..bc5223cb 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp @@ -125,6 +125,20 @@ public: */ inline std::string get_postfix_term() const {return "cbrt";} + // DocString: cbrt_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "nthroot({}, 3)", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -224,6 +238,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "nthroot({:.10e}.*{}{:+15.10e}, 3)", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp index 30dc9375..7f64a539 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp @@ -40,6 +40,7 @@ protected: using CbrtNode::test_value_ptr; using CbrtNode::expr; using CbrtNode::get_latex_expr; + using CbrtNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector public: @@ -140,6 +141,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: cbrt_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp index 0d7ae874..bbfcc9e4 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp @@ -125,6 +125,20 @@ public: */ inline std::string get_postfix_term() const {return "cos";} + // DocString: cos_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "cos({})", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -224,6 +238,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "cos({:.10e}.*{}{:+15.10e})", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp index a46796d8..5c527bc9 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp @@ -40,6 +40,7 @@ protected: using CosNode::test_value_ptr; using CosNode::expr; using CosNode::get_latex_expr; + using CosNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector @@ -141,6 +142,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: cos_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp index e9be9a27..04da33a0 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp @@ -129,6 +129,21 @@ public: */ inline std::string get_postfix_term() const {return "div";} + // DocString: div_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "({} ./ {})", + _feats[0]->matlab_fxn_expr(), + _feats[1]->matlab_fxn_expr() + ); + } + /** * @brief Check if the feature will be valid, if it is then set the value * @return True if the feature is valid @@ -237,6 +252,24 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "({} ./ ({:.10e}.*{}{:+15.10e}))", + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + _feats[1]->n_params() + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp index 8c666a0f..7e9b24eb 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp @@ -40,6 +40,7 @@ protected: using DivNode::test_value_ptr; using DivNode::expr; using DivNode::get_latex_expr; + using DivNode::matlab_fxn_expr; std::vector<double> _params; @@ -144,6 +145,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: div_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp index 7766f133..eb27decc 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp @@ -125,6 +125,20 @@ public: */ inline std::string get_postfix_term() const {return "exp";} + // DocString: exp_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "exp({})", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -224,6 +238,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "exp({:.10e}.*{}{:+15.10e})", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp index ae31484d..4a069699 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp @@ -40,6 +40,7 @@ protected: using ExpNode::test_value_ptr; using ExpNode::expr; using ExpNode::get_latex_expr; + using ExpNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector @@ -141,6 +142,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: exp_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp index 62da8626..a83a7a05 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp @@ -121,6 +121,20 @@ public: */ inline std::string get_postfix_term() const {return "inv";} + // DocString: inv_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "({}).^(-1)", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -220,6 +234,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "({:.10e}.*{}{:+15.10e}).^(-1)", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp index 8f58e32e..51d8f5db 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp @@ -40,6 +40,7 @@ protected: using InvNode::test_value_ptr; using InvNode::expr; using InvNode::get_latex_expr; + using InvNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector @@ -141,6 +142,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: inv_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp index f6a87c75..717260aa 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp @@ -131,6 +131,20 @@ public: */ inline std::string get_postfix_term() const {return "log";} + // DocString: log_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "log({})", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -224,6 +238,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "log({:.10e}.*{}{:+15.10e})", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp index 9fb591a9..3c742c52 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp @@ -40,6 +40,7 @@ protected: using LogNode::value_ptr; using LogNode::test_value_ptr; using LogNode::get_latex_expr; + using LogNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector @@ -141,6 +142,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: log_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp index 6def1093..38eea1b0 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp @@ -130,6 +130,21 @@ public: */ inline std::string get_postfix_term() const {return "mult";} + // DocString: mult_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "({} .* {})", + _feats[0]->matlab_fxn_expr(), + _feats[1]->matlab_fxn_expr() + ); + } + /** * @brief Check if the feature will be valid, if it is then set the value * @return True if the feature is valid @@ -238,6 +253,24 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "({} .* ({:.10e}.*{}{:+15.10e}))", + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + _feats[1]->n_params() + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp index e55534a2..29d4681c 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp @@ -40,6 +40,7 @@ protected: using MultNode::test_value_ptr; using MultNode::expr; using MultNode::get_latex_expr; + using MultNode::matlab_fxn_expr; std::vector<double> _params; @@ -142,6 +143,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: mult_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp index 98975e3c..24af3755 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp @@ -126,6 +126,20 @@ public: */ inline std::string get_postfix_term() const {return "nexp";} + // DocString: neg_exp_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "exp(-1.0 * ({}))", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -201,7 +215,7 @@ public: inline std::string expr(const double* params, const int depth=1) const { return fmt::format( - "(exp(-1.0 * {:.10e}*{}{:+15.10e}))", + "(exp(-1.0 * ({:.10e}*{}{:+15.10e})))", params[0], (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->expr(params + 2, depth + 1) : _feats[0]->expr()), params[1] @@ -218,13 +232,30 @@ public: inline std::string get_latex_expr(const double* params, const int depth=1) const { return fmt::format( - "\\left(\\exp{{ \\left(-\\left({:.3e}{}{:+8.3e} \\right)\\right)}}\\right)", + "\\left(\\exp{{ \\left(-1.0\\left({:.3e}{}{:+8.3e} \\right)\\right)}}\\right)", params[0], (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->get_latex_expr(params + 2, depth + 1) : _feats[0]->get_latex_expr()), params[1] ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "exp(-1.0 .* ({:.10e}.*{}{:+15.10e}))", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp index 74956035..a828030b 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp @@ -40,6 +40,7 @@ protected: using NegExpNode::test_value_ptr; using NegExpNode::expr; using NegExpNode::get_latex_expr; + using NegExpNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector @@ -107,6 +108,14 @@ public: */ inline void set_test_value(int offset=-1, const bool for_comp=false) const {set_test_value(_params.data(), offset, for_comp);} + // DocString: neg_exp_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief Get the pointer to the feature's training data * @details If the feature is not already stored in memory, then calculate the feature and return the pointer to the data diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp index a2f95172..48d84813 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp @@ -40,6 +40,7 @@ protected: using SinNode::test_value_ptr; using SinNode::expr; using SinNode::get_latex_expr; + using SinNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector @@ -141,6 +142,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: sin_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp index 1af69ec1..f363f2dd 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp @@ -126,6 +126,20 @@ public: */ inline std::string get_postfix_term() const {return "sin";} + // DocString: sin_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "sin({})", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -224,6 +238,24 @@ public: params[1] ); } + + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "sin({:.10e}.*{}{:+15.10e})", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp index 0d3fcf3d..29c3bc2c 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp @@ -40,6 +40,7 @@ protected: using SixPowNode::test_value_ptr; using SixPowNode::expr; using SixPowNode::get_latex_expr; + using SixPowNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector @@ -141,6 +142,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: six_pow_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp index fbf27095..73e1ecb5 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp @@ -126,6 +126,20 @@ public: */ inline std::string get_postfix_term() const {return "sp";} + // DocString: six_pow_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "({}).^6", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -226,6 +240,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "({:.10e}.*{}{:+15.10e}).^6", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp index 626c67b9..b9012a6e 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp @@ -40,6 +40,7 @@ protected: using SqNode::test_value_ptr; using SqNode::expr; using SqNode::get_latex_expr; + using SqNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector @@ -141,6 +142,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: sq_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp index d852d1b8..3dc753b2 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp @@ -125,6 +125,20 @@ public: */ inline std::string get_postfix_term() const {return "sq";} + // DocString: sq_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "({}).^2", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -225,6 +239,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "({:.10e}.*{}{:+15.10e}).^6", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp index 96abd3df..f7b71322 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp @@ -41,6 +41,7 @@ protected: using SqrtNode::test_value_ptr; using SqrtNode::expr; using SqrtNode::get_latex_expr; + using SqrtNode::matlab_fxn_expr; std::vector<double> _params; //!< The parameters vector double _sign_alpha; //!< 1 if alpha is positive, -1 if alpha is negative @@ -143,6 +144,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: sqrt_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp index d13662a3..2d4ef736 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp @@ -126,6 +126,20 @@ public: */ inline std::string get_postfix_term() const {return "sqrt";} + // DocString: sqrt_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "sqrt({})", + _feats[0]->matlab_fxn_expr() + ); + } + /** * @brief update the dictionary used to check if an Add/Sub node is valid * @@ -225,6 +239,23 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "sqrt({:.10e}.*{}{:+15.10e})", + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp index 056f11b5..8550534f 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp @@ -40,6 +40,7 @@ protected: using SubNode::test_value_ptr; using SubNode::expr; using SubNode::get_latex_expr; + using SubNode::matlab_fxn_expr; std::vector<double> _params; @@ -144,6 +145,14 @@ public: */ inline std::string get_latex_expr() const {return get_latex_expr(_params.data());} + // DocString: sub_param_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const {return matlab_fxn_expr(_params.data());} + /** * @brief The parameters used for introducing more non linearity in the operators */ diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp index 8bafd68c..04645366 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp @@ -131,6 +131,21 @@ public: */ inline std::string get_postfix_term() const {return "sub";} + // DocString: sub_node_matlab_expr + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr() const + { + return fmt::format( + "({} - {})", + _feats[0]->matlab_fxn_expr(), + _feats[1]->matlab_fxn_expr() + ); + } + /** * @brief Check if the feature will be valid, if it is then set the value * @return True if the feature is valid @@ -239,6 +254,24 @@ public: ); } + /** + * @brief Get the string that corresponds to the code needed to evaluate the node in matlab + * + * @param params parameter values for non-linear operations + * @param depth the current depth of the node on the Binary expression tree + * @return The matlab code for the feature + */ + inline std::string matlab_fxn_expr(const double* params, const int depth=1) const + { + return fmt::format( + "({} - ({:.10e}.*{}{:+15.10e}))", + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + _feats[1]->n_params() + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[0], + (depth < nlopt_wrapper::MAX_PARAM_DEPTH ? _feats[0]->matlab_fxn_expr(params + 2, depth + 1) : _feats[0]->matlab_fxn_expr()), + params[1] + ); + } + /** * @brief Set the bounds for the nl parameterization * diff --git a/src/python/bindings_docstring_keyed.cpp b/src/python/bindings_docstring_keyed.cpp index 0fc86568..55cf3be3 100644 --- a/src/python/bindings_docstring_keyed.cpp +++ b/src/python/bindings_docstring_keyed.cpp @@ -42,7 +42,7 @@ void sisso::register_all() def("phi_selected_from_file", &str2node::phi_selected_from_file_py); def("initialize_values_arr", init_val_ar); def("initialize_d_matrix_arr", &node_value_arrs::initialize_d_matrix_arr); - + def("matlabify", &str_utils::matlabify); #ifdef PARAMETERIZE sisso::feature_creation::node::registerAddParamNode(); @@ -266,10 +266,9 @@ void sisso::feature_creation::registerUnit() void sisso::feature_creation::node::registerFeatureNode() { - std::string (FeatureNode::*expr_1)() const = &FeatureNode::expr; - std::string (FeatureNode::*expr_const)() const = &FeatureNode::expr; void (FeatureNode::*set_value_no_param)(int, bool) const = &FeatureNode::set_value; void (FeatureNode::*set_test_value_no_param)(int, bool) const = &FeatureNode::set_test_value; + std::string (FeatureNode::*expr_no_param)() const = &FeatureNode::expr; using namespace boost::python; class_<FeatureNode, bases<Node>>("FeatureNode", init<int, std::string, np::ndarray, np::ndarray, Unit>()) @@ -278,8 +277,7 @@ void sisso::feature_creation::node::registerFeatureNode() .def("is_const", &FeatureNode::is_const, "@DocString_feat_node_is_const@") .def("set_value", set_value_no_param, "@DocString_feat_node_set_value@") .def("set_test_value", set_test_value_no_param, "@DocString_feat_node_set_test_value@") - .add_property("expr", expr_1, "@DocString_feat_node_expr_1@") - .add_property("expr", expr_const, "@DocString_feat_node_expr_const@") + .add_property("expr", expr_no_param, "@DocString_feat_node_expr_const@") .add_property("unit", &FeatureNode::unit, "@DocString_feat_node_unit@") .add_property("rung", &FeatureNode::rung, "@DocString_feat_node_rung@") .add_property("n_leaves", &FeatureNode::n_leaves) @@ -289,9 +287,6 @@ void sisso::feature_creation::node::registerFeatureNode() void sisso::feature_creation::node::registerModelNode() { - std::string (ModelNode::*expr_1)() const = &ModelNode::expr; - std::string (ModelNode::*expr_const)() const = &ModelNode::expr; - np::ndarray (ModelNode::*eval_many_dict)(py::dict) = &ModelNode::eval_many_py; np::ndarray (ModelNode::*eval_many_ndarr)(np::ndarray) = &ModelNode::eval_many_py; @@ -300,7 +295,7 @@ void sisso::feature_creation::node::registerModelNode() double (ModelNode::*eval_dict)(py::dict) = &ModelNode::eval_py; using namespace boost::python; - class_<ModelNode, bases<FeatureNode>>("ModelNode", init<int, int, std::string, std::string, std::string, std::vector<double>, std::vector<double>, std::vector<std::string>, Unit>()) + class_<ModelNode, bases<FeatureNode>>("ModelNode", init<int, int, std::string, std::string, std::string, std::string, std::vector<double>, std::vector<double>, std::vector<std::string>, Unit>()) .def(init<node_ptr>()) .def("is_nan", &ModelNode::is_nan, "@DocString_model_node_is_nan@") .def("is_const", &ModelNode::is_const, "@DocString_model_node_is_const@") @@ -842,6 +837,7 @@ void sisso::descriptor_identifier::registerModel() .def("eval", eval_ndarr) .def("eval", eval_list) .def("eval", eval_dict) + .def("write_matlab_fxn", &Model::write_matlab_fxn) .add_property("n_samp_train", &Model::n_samp_train, "@DocString_model_n_samp_train@") .add_property("n_samp_test", &Model::n_samp_test, "@DocString_model_n_samp_test@") .add_property("n_dim", &Model::n_dim, "@DocString_model_n_dim@") diff --git a/src/python/bindings_docstring_keyed.hpp b/src/python/bindings_docstring_keyed.hpp index 156e3384..412c5e2f 100644 --- a/src/python/bindings_docstring_keyed.hpp +++ b/src/python/bindings_docstring_keyed.hpp @@ -63,6 +63,8 @@ namespace sisso inline std::string expr(double*, int depth=1) const {return this->get_override("expr")();} inline std::string get_latex_expr() const {return this->get_override("latex_expr")();} inline std::string get_latex_expr(double*, int depth=1) const {return this->get_override("latex_expr")();} + inline std::string matlab_fxn_expr() const {return this->get_override("matlab_fxn_expr")();} + inline std::string matlab_fxn_expr(const double*, int depth=1) const {return this->get_override("matlab_fxn_expr")();} inline Unit unit() const {return this->get_override("unit")();} inline std::vector<double> value() const {return this->get_override("value")();} inline std::vector<double> test_value() const {return this->get_override("test_value")();} @@ -116,6 +118,8 @@ namespace sisso inline std::string expr() const {return this->get_override("expr")();} inline std::string get_latex_expr(const double* params, const int depth=1) const {return this->get_override("latex_expr")();} inline std::string get_latex_expr() const {return this->get_override("latex_expr")();} + inline std::string matlab_fxn_expr() const {return this->get_override("matlab_fxn_expr")();} + inline std::string matlab_fxn_expr(const double*, int depth=1) const {return this->get_override("matlab_fxn_expr")();} inline void update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, const int pl_mn, int& expected_abs_tot) const {this->get_override("update_add_sub_leaves")();} inline void update_div_mult_leaves(std::map<std::string, double>& div_mult_leaves, const double fact, double& expected_abs_tot) const {this->get_override("update_div_mult_leaves")();} inline void get_parameters(std::shared_ptr<NLOptimizer> optimizer){this->get_override("get_parameters")();} @@ -135,6 +139,7 @@ namespace sisso public: inline std::string expr() const {return this->get_override("expr")();} inline std::string get_latex_expr() const {return this->get_override("latex_expr")();} + inline std::string matlab_fxn_expr() const {return this->get_override("matlab_fxn_expr")();} inline Unit unit() const {return this->get_override("unit")();} inline std::vector<double> value() const {return this->get_override("value")();} inline std::vector<double> test_value() const {return this->get_override("test_value")();} @@ -172,6 +177,7 @@ namespace sisso inline std::string get_postfix_term() const {return this->get_override("get_postfix_term")();} inline std::string expr() const {return this->get_override("expr")();} inline std::string get_latex_expr() const {return this->get_override("latex_expr")();} + inline std::string matlab_fxn_expr() const {return this->get_override("matlab_fxn_expr")();} inline void update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, const int pl_mn, int& expected_abs_tot) const {this->get_override("update_add_sub_leaves")();} inline void update_div_mult_leaves(std::map<std::string, double>& div_mult_leaves, const double fact, double& expected_abs_tot) const {this->get_override("update_div_mult_leaves")();} }; @@ -421,6 +427,7 @@ namespace sisso struct Model_Wrap : Model, py::wrapper<Model> { inline void to_file(std::string filename, bool train = true, std::vector<int> test_inds = {}){this->get_override("to_file")();} + inline void matlab_expr(){this->get_override("matlab_expr")();} }; /** diff --git a/src/utils/string_utils.cpp b/src/utils/string_utils.cpp index e7b71b8c..366c250c 100644 --- a/src/utils/string_utils.cpp +++ b/src/utils/string_utils.cpp @@ -33,3 +33,37 @@ std::string str_utils::latexify(const std::string str) } return to_ret.substr(0, to_ret.size() - 1); } + +std::string str_utils::op2str(const std::string str, const std::string op, const std::string op_str) +{ + std::string to_ret = ""; + std::vector<std::string> split_term_str = split_string_trim(str, op); + to_ret += split_term_str[0]; + for(int ii = 1; ii < split_term_str.size(); ++ii) + { + to_ret += op_str + split_term_str[ii]; + } + + return to_ret; +} + +std::string str_utils::matlabify(const std::string str) +{ + std::string to_ret = ""; + + std::string copy_str = str; + std::replace(copy_str.begin(), copy_str.end(), ' ', '_'); + + std::vector<std::string> split_str = split_string_trim(str, "\\"); + for(auto& term_str : split_str) + { + std::string add_str = term_str; + add_str = op2str(add_str, "/", "_div_"); + add_str = op2str(add_str, "*", "_mult_"); + add_str = op2str(add_str, "+", "_add_"); + add_str = op2str(add_str, "-", "_sub_"); + add_str = op2str(add_str, "^", "_pow_"); + to_ret += add_str; + } + return to_ret; +} diff --git a/src/utils/string_utils.hpp b/src/utils/string_utils.hpp index 53ce035f..28a4ff59 100644 --- a/src/utils/string_utils.hpp +++ b/src/utils/string_utils.hpp @@ -7,10 +7,11 @@ #ifndef STRING_UTILS #define STRING_UTILS +#include <algorithm> #include <cmath> +#include <iostream> #include <string> #include <vector> -#include <iostream> #include <boost/algorithm/string.hpp> #include <boost/algorithm/string/trim.hpp> @@ -33,6 +34,24 @@ namespace str_utils * @return The latexified version of the string */ std::string latexify(const std::string str); + + /** + * @brief Convert a string into a matlab valid name + * + * @param str String to convert to a valid matlab name + * @return The matlab safe version of the string + */ + std::string matlabify(const std::string str); + + /** + * @brief Convert an operator into a valid matlab string + * + * @param str String to remove operators from + * @param op The operator to replace + * @param op_str The string to replace the operator with + * @return The string with the operators replaced + */ + std::string op2str(const std::string str, const std::string op, const std::string op_str); } diff --git a/src/utils/vector_utils.hpp b/src/utils/vector_utils.hpp new file mode 100644 index 00000000..c60771e2 --- /dev/null +++ b/src/utils/vector_utils.hpp @@ -0,0 +1,32 @@ +/** @file utils/vector_utils.hpp + * @brief A set of functions to manipulate vectors + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef VECTOR_UTILS +#define VECTOR_UTILS + +#include <algorithm> +#include <vector> + +namespace vector_utils +{ +template<typename T> +std::vector<T> unique(const std::vector<T> in_vec) +{ + std::vector<T> out_vec; + for(auto& el : in_vec) + { + if(find(out_vec.begin(), out_vec.end(), el) == out_vec.end()) + { + out_vec.push_back(el); + } + } + + return out_vec; +} +} + + +#endif -- GitLab