diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6489f0c99b49d863785fb93edcd578b0ec0a2e7d..d6a04a58251617ac02fb881f996947896b82539a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,7 +32,7 @@ install(TARGETS sisso++ DESTINATION ${CMAKE_CURRENT_LIST_DIR}/../bin/) if(USE_PYTHON) include(${CMAKE_CURRENT_LIST_DIR}/../cmake/TransferDocStrings.cmake) file(GLOB_RECURSE SISSOLIB_SOURCES *.cpp) - list(REMOVE_ITEM SISSOLIB_SOURCES main.cpp) + list(REMOVE_ITEM SISSOLIB_SOURCES ${CMAKE_CURRENT_LIST_DIR}/main.cpp) list(REMOVE_ITEM SISSOLIB_SOURCES ${CMAKE_CURRENT_LIST_DIR}/python/bindings_docstring_keyed.cpp) list(REMOVE_ITEM SISSOLIB_SOURCES ${CMAKE_CURRENT_LIST_DIR}/python/bindings_docstring_keyed.hpp) diff --git a/src/descriptor_identifier/Model/Model.cpp b/src/descriptor_identifier/Model/Model.cpp index 744348a0da84c8fd501fa29d3378658bc0e6725d..0b21669aff7287042c7ef330c09a20750a7b4132 100644 --- a/src/descriptor_identifier/Model/Model.cpp +++ b/src/descriptor_identifier/Model/Model.cpp @@ -80,13 +80,14 @@ Model::Model(std::string train_file) int rung = std::stoi(split_str[0]); std::string unit_str = split_str[1]; - std::string expr = split_str[2]; + std::string postfix_expr = split_str[2]; + std::string expr = split_str[3]; std::vector<double> feat_val(_n_samp_train); std::vector<double> feat_test_val = {}; std::copy_n(&_D_train[ff * _n_samp_train], _n_samp_train, feat_val.data()); - model_node_ptr feat = std::make_shared<ModelNode>(ff, rung, expr, feat_val, feat_test_val, Unit(unit_str)); + model_node_ptr feat = std::make_shared<ModelNode>(ff, rung, expr, postfix_expr, feat_val, feat_test_val, Unit(unit_str)); _feats.push_back(feat); } @@ -107,14 +108,16 @@ Model::Model(std::string train_file, std::string test_file) int rung = std::stoi(split_str[0]); std::string unit_str = split_str[1]; - std::string expr = split_str[2]; + std::string postfix_expr = split_str[2]; + std::string expr = split_str[3]; + std::vector<double> feat_val(_n_samp_train); std::vector<double> feat_test_val(_n_samp_test); std::copy_n(&_D_train[ff * _n_samp_train], _n_samp_train, feat_val.data()); std::copy_n(&_D_test[ff * _n_samp_test], _n_samp_test, feat_test_val.data()); - _feats.push_back(std::make_shared<ModelNode>(ff, rung, expr, feat_val, feat_test_val, Unit(unit_str))); + _feats.push_back(std::make_shared<ModelNode>(ff, rung, expr, postfix_expr, feat_val, feat_test_val, Unit(unit_str))); } } @@ -283,7 +286,7 @@ void Model::to_file(std::string filename, bool train, std::vector<int> test_inds out_file_stream << "# Feature Rung, Units, and Expressions" << std::endl; for(int ff = 0; ff < _feats.size(); ++ff) - out_file_stream << std::setw(6) << std::left << "# " + std::to_string(ff) + ", " << std::to_string(_feats[ff]->rung()) + ", " << std::setw(50) << _feats[ff]->unit().toString() + ", " << _feats[ff]->expr() << std::endl; + out_file_stream << std::setw(6) << std::left << "# " + std::to_string(ff) + ", " << std::to_string(_feats[ff]->rung()) + ", " << std::setw(50) << _feats[ff]->unit().toString() + ", " << _feats[ff]->postfix_expr() + "," << _feats[ff]->expr() << std::endl; out_file_stream << "# Number of Samples Per Task" << std::endl; if(train) diff --git a/src/descriptor_identifier/SISSORegressor.cpp b/src/descriptor_identifier/SISSORegressor.cpp index ae27fe0d5ab02526095682e0e98cef1f75d044be..8542e30a3eeafe72b2c8e766fe86adab79d7b0c1 100644 --- a/src/descriptor_identifier/SISSORegressor.cpp +++ b/src/descriptor_identifier/SISSORegressor.cpp @@ -110,7 +110,7 @@ void SISSORegressor::fit() for(int rr = 0; rr < _n_residual; ++rr) { node_value_arrs::clear_temp_test_reg(); - model_node_ptr model_feat = std::make_shared<ModelNode>(_feat_space->phi_selected()[rr]->arr_ind(), _feat_space->phi_selected()[rr]->rung(), _feat_space->phi_selected()[rr]->expr(), _feat_space->phi_selected()[rr]->value(), _feat_space->phi_selected()[rr]->test_value(), _feat_space->phi_selected()[rr]->unit()); + model_node_ptr model_feat = std::make_shared<ModelNode>(_feat_space->phi_selected()[rr]->arr_ind(), _feat_space->phi_selected()[rr]->rung(), _feat_space->phi_selected()[rr]->expr(), _feat_space->phi_selected()[rr]->postfix_expr(), _feat_space->phi_selected()[rr]->value(), _feat_space->phi_selected()[rr]->test_value(), _feat_space->phi_selected()[rr]->unit()); models.push_back(Model(_prop, _prop_test, {model_feat}, _task_sizes_train, _task_sizes_test)); models.back().copy_error(&residual[rr * _n_samp]); if(_mpi_comm->rank() == 0) @@ -210,7 +210,7 @@ void SISSORegressor::l0_norm(std::vector<double>& prop, int n_dim) for(int ii = 0; ii < n_dim; ++ii) { int index = all_inds_min[inds[rr] * n_dim + ii]; - min_nodes[ii] = std::make_shared<ModelNode>(_feat_space->phi_selected()[index]->arr_ind(), _feat_space->phi_selected()[index]->rung(), _feat_space->phi_selected()[index]->expr(), _feat_space->phi_selected()[index]->value(), _feat_space->phi_selected()[index]->test_value(), _feat_space->phi_selected()[index]->unit()); + min_nodes[ii] = std::make_shared<ModelNode>(_feat_space->phi_selected()[index]->arr_ind(), _feat_space->phi_selected()[index]->rung(), _feat_space->phi_selected()[index]->expr(), _feat_space->phi_selected()[index]->postfix_expr(), _feat_space->phi_selected()[index]->value(), _feat_space->phi_selected()[index]->test_value(), _feat_space->phi_selected()[index]->unit()); } models.push_back(Model(_prop, _prop_test, min_nodes, _task_sizes_train, _task_sizes_test)); } diff --git a/src/feature_creation/feature_space/FeatureSpace.cpp b/src/feature_creation/feature_space/FeatureSpace.cpp index 79a06815d88ac19509ae68b6b493e541fc3e4695..b49a7ef03b579201228bf0894206d78dc779ee24 100644 --- a/src/feature_creation/feature_space/FeatureSpace.cpp +++ b/src/feature_creation/feature_space/FeatureSpace.cpp @@ -66,7 +66,7 @@ void FeatureSpace::initialize_fs(std::vector<double> prop) { std::ofstream out_file_stream = std::ofstream(); out_file_stream.open(_feature_space_file); - out_file_stream << std::setw(14) <<std::left << "# FEAT_ID" << std::setw(24) << std::left << "Score" << "Feature Expression" << std::endl; + out_file_stream << std::setw(14) <<std::left << "# FEAT_ID" << std::setw(24) << std::left << "Score" << "Feature Postfix Expression (RPN)" << std::endl; out_file_stream.close(); } _project = project_funcs::project_r; @@ -535,7 +535,6 @@ void FeatureSpace::sis(std::vector<double>& prop) if(is_valid) { scores_sel[cur_feat_local] = _scores[inds[ii]]; - // phi_sel.push_back(std::make_shared<FeatureNode>(cur_feat + cur_feat_local, _phi[inds[ii]]->expr(), _phi[inds[ii]]->value(), _phi[inds[ii]]->test_value(), _phi[inds[ii]]->unit(), true)); phi_sel.push_back(_phi[inds[ii]]); phi_sel.back()->set_selected(true); phi_sel.back()->set_d_mat_ind(cur_feat + cur_feat_local); @@ -642,7 +641,7 @@ void FeatureSpace::sis(std::vector<double>& prop) inds = util_funcs::argsort(sent_scores); for(int ii = 0; ii < _n_sis_select; ++ii) { - out_file_stream << std::setw(14) <<std::left << cur_feat << std::setw(24) << std::setprecision(18) << std::left << -1 * sent_scores[inds[ii]] << sent_phi[inds[ii]]->expr() << std::endl; + out_file_stream << std::setw(14) <<std::left << cur_feat << std::setw(24) << std::setprecision(18) << std::left << -1 * sent_scores[inds[ii]] << sent_phi[inds[ii]]->postfix_expr() << std::endl; _phi_selected.push_back(sent_phi[inds[ii]]); _phi_selected.back()->set_selected(true); _phi_selected.back()->set_d_mat_ind(cur_feat); @@ -665,7 +664,7 @@ void FeatureSpace::sis(std::vector<double>& prop) { if(valid_score_against_current(cur_feat_local, sent_phi[inds[ii]]->value().data(), sent_scores[inds[ii]], scores_sel, scores_comp)) { - out_file_stream << std::setw(14) <<std::left << cur_feat << std::setw(24) << std::setprecision(18) << std::left << -1 * sent_scores[inds[ii]] << sent_phi[inds[ii]]->expr() << std::endl; + out_file_stream << std::setw(14) <<std::left << cur_feat << std::setw(24) << std::setprecision(18) << std::left << -1 * sent_scores[inds[ii]] << sent_phi[inds[ii]]->postfix_expr() << std::endl; _phi_selected.push_back(sent_phi[inds[ii]]); @@ -711,7 +710,7 @@ void FeatureSpace::sis(std::vector<double>& prop) inds = util_funcs::argsort(scores_sel); for(auto& ind : inds) { - out_file_stream << std::setw(14) <<std::left << cur_feat << std::setw(24) << std::setprecision(18) << std::left << -1 * scores_sel[ind] << phi_sel[ind]->expr() << std::endl; + out_file_stream << std::setw(14) <<std::left << cur_feat << std::setw(24) << std::setprecision(18) << std::left << -1 * scores_sel[ind] << phi_sel[ind]->postfix_expr() << std::endl; _phi_selected.push_back(phi_sel[ind]); _phi_selected.back()->set_d_mat_ind(cur_feat); _phi_selected.back()->set_value(); diff --git a/src/feature_creation/node/FeatureNode.cpp b/src/feature_creation/node/FeatureNode.cpp index 9b0031d4dc42a0609f98521a8e7c2d293d2236ff..1145a4f2eddc63436ce0690c7da1eb8d5084ff89 100644 --- a/src/feature_creation/node/FeatureNode.cpp +++ b/src/feature_creation/node/FeatureNode.cpp @@ -40,4 +40,19 @@ void FeatureNode::update_div_mult_leaves(std::map<std::string, double>& div_mult expected_abs_tot += std::abs(fact); } +std::map<int, int> FeatureNode::primary_feature_decomp() +{ + std::map<int, int> pf_decomp; + pf_decomp[_arr_ind] = 1; + return pf_decomp; +} + +void FeatureNode::update_primary_feature_decomp(std::map<int, int>& pf_decomp) +{ + if(pf_decomp.count(_arr_ind) > 0) + pf_decomp[_arr_ind] += 1; + else + pf_decomp[_arr_ind] = 1; +} + // BOOST_CLASS_EXPORT(FeatureNode) diff --git a/src/feature_creation/node/FeatureNode.hpp b/src/feature_creation/node/FeatureNode.hpp index c1d05d921cbfdae69da460bf82b7846f28a60ea7..abf9086b0b7dfd539240bd20b8f752224082dc57 100644 --- a/src/feature_creation/node/FeatureNode.hpp +++ b/src/feature_creation/node/FeatureNode.hpp @@ -214,6 +214,35 @@ public: */ inline int rung(int cur_rung = 0){return cur_rung;} + /** + * @brief Get the primary feature decomposition of a feature + * @return A map representing the primary feature comprising a feature + */ + std::map<int, int> primary_feature_decomp(); + + /** + * @brief Update the primary feature decomposition of a feature + * + * @param pf_decomp The primary feature decomposition of the feature calling this function. + */ + void update_primary_feature_decomp(std::map<int, int>& pf_decomp); + + /** + * @brief Converts a feature into a postfix expression (reverse polish notation) + * + * @details Recursively creates a postfix representation of the string + * + * @param cur_expr The current expression + * @return The current postfix expression of the feature + */ + inline void update_postfix(std::string& cur_expr){cur_expr = get_postfix_term() + "|" + cur_expr;}; + + /** + * @brief Get the three character representation of the operator + * @return the three character representation of the operator + */ + inline std::string get_postfix_term(){return std::to_string(_feat_ind);} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/ModelNode.cpp b/src/feature_creation/node/ModelNode.cpp index 13b962916bd0b8fb6636b487f38f9de9f238928d..b6f4d2142ad1b5d43ac9030006e13a6d4bc9cb76 100644 --- a/src/feature_creation/node/ModelNode.cpp +++ b/src/feature_creation/node/ModelNode.cpp @@ -3,8 +3,9 @@ ModelNode::ModelNode() {} -ModelNode::ModelNode(int feat_ind, int rung, std::string expr, std::vector<double> value, std::vector<double> test_value, Unit unit) : +ModelNode::ModelNode(int feat_ind, int rung, std::string expr, std::string post_fix_expr, std::vector<double> value, std::vector<double> test_value, Unit unit) : FeatureNode(feat_ind, expr, value, test_value, unit, false), + _expr_postfix(post_fix_expr), _rung(rung) {} @@ -30,3 +31,45 @@ void ModelNode::update_div_mult_leaves(std::map<std::string, double>& div_mult_l expected_abs_tot += std::abs(fact); } + +std::map<int, int> ModelNode::primary_feature_decomp() +{ + std::map<int, int> pf_decomp; + std::vector<std::string> split_postfix = str_utils::split_string_trim(_expr_postfix, "|"); + for(auto& part : split_postfix) + { + try + { + if(pf_decomp.count(std::stoi(part))) + ++pf_decomp[std::stoi(part)]; + else + pf_decomp[std::stoi(part)] = 1; + } + catch(const std::invalid_argument e) + { + // Do Nothing + } + } + + return pf_decomp; +} + +void ModelNode::update_primary_feature_decomp(std::map<int, int>& pf_decomp) +{ + pf_decomp.clear(); + std::vector<std::string> split_postfix = str_utils::split_string_trim(_expr_postfix, "|"); + for(auto& part : split_postfix) + { + try + { + if(pf_decomp.count(std::stoi(part))) + ++pf_decomp[std::stoi(part)]; + else + pf_decomp[std::stoi(part)] = 1; + } + catch(const std::invalid_argument e) + { + // Do Nothing + } + } +} diff --git a/src/feature_creation/node/ModelNode.hpp b/src/feature_creation/node/ModelNode.hpp index 2609c874ff8fcb598049f8478c0a55671e8adfb2..eabb2f7be417ca47552f8180de940f48fcada786 100644 --- a/src/feature_creation/node/ModelNode.hpp +++ b/src/feature_creation/node/ModelNode.hpp @@ -10,6 +10,7 @@ #define MODEL_NODE #include <feature_creation/node/FeatureNode.hpp> +#include <utils/string_utils.hpp> // DocString: cls_model_node /** @@ -33,7 +34,7 @@ class ModelNode: public FeatureNode protected: int _rung; - + std::string _expr_postfix; public: /** * @brief Base Constructor @@ -51,7 +52,7 @@ public: * @param value Value of the feature for each test sample * @param unit Unit of the feature */ - ModelNode(int feat_ind, int rung, std::string expr, std::vector<double> value, std::vector<double> test_value, Unit unit); + ModelNode(int feat_ind, int rung, std::string expr, std::string expr_postfix, std::vector<double> value, std::vector<double> test_value, Unit unit); /** * @brief Copy Constructor @@ -132,7 +133,6 @@ public: */ inline double* test_value_ptr(int offset = -1){return _test_value.data();} - // DocString: model_node_rung /** * @brief return the rung of the feature @@ -141,6 +141,25 @@ public: */ inline int rung(int cur_rung = 0){return _rung;} + /** + * @brief Update the primary feature decomposition of a feature + * + * @param pf_decomp The primary feature decomposition of the feature calling this function. + */ + void update_primary_feature_decomp(std::map<int, int>& pf_decomp); + + /** + * @brief Get the primary feature decomposition of a feature + * @return A map representing the primary feature comprising a feature + */ + std::map<int, int> primary_feature_decomp(); + + /** + * @brief Get the three character representation of the operator + * @return the three character representation of the operator + */ + inline std::string get_postfix_term(){return _expr_postfix;} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/Node.hpp b/src/feature_creation/node/Node.hpp index c15b32e953279f6870efa914e68b5f347629a3c3..b258b5e728116203fe58e4dc43325a16f6a79555 100644 --- a/src/feature_creation/node/Node.hpp +++ b/src/feature_creation/node/Node.hpp @@ -28,6 +28,7 @@ #include <boost/serialization/unique_ptr.hpp> #ifdef PY_BINDINGS + namespace py = boost::python; namespace np = boost::python::numpy; #endif @@ -262,6 +263,42 @@ public: */ virtual int rung(int cur_rung = 0) = 0; + /** + * @brief Get the primary feature decomposition of a feature + * @return A map representing the primary feature comprising a feature + */ + virtual std::map<int, int> primary_feature_decomp() = 0; + + /** + * @brief Update the primary feature decomposition of a feature + * + * @param pf_decomp The primary feature decomposition of the feature calling this function. + */ + virtual void update_primary_feature_decomp(std::map<int, int>& pf_decomp) = 0; + + /** + * @brief Converts a feature into a postfix expression (reverse polish notation) + * + * @details Recursively creates a postfix representation of the string + * + * @param cur_expr The current expression + * @return The current postfix expression of the feature + */ + virtual void update_postfix(std::string& cur_expr) = 0; + + // DocString: node_postfix_expr + /** + * @brief Get the postfix expression for the feature + * @return The postfix string for the expression + */ + inline std::string postfix_expr(){std::string cur_expr = ""; update_postfix(cur_expr); return cur_expr.substr(0, cur_expr.size() - 1);} + + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + virtual std::string get_postfix_term() = 0; + /** * @brief update the dictionary used to check if an Add/Sub/AbsDiff node is valid * @@ -279,6 +316,8 @@ public: * @param expected_abs_tot The expected absolute sum of all values in div_mult_leaves */ virtual void update_div_mult_leaves(std::map<std::string, double>& div_mult_leaves, double fact, double& expected_abs_tot) = 0; + + #ifdef PY_BINDINGS // DocString: node_value_py @@ -294,6 +333,13 @@ public: * @return The test data as a numpy array */ inline np::ndarray test_value_py(){return python_conv_utils::to_ndarray<double>(test_value());} + + // DocString: node_primary_feature_decomp + /** + * @brief Get the primary feature decomposition of a feature + * @return A python dict representing the primary feature comprising a feature + */ + inline py::dict primary_feature_decomp_py(){return python_conv_utils::to_dict<int, int>(primary_feature_decomp());} #endif }; diff --git a/src/feature_creation/node/operator_nodes/OperatorNode.hpp b/src/feature_creation/node/operator_nodes/OperatorNode.hpp index 070e24fe68fbec7d6285d4603aeba24fb526a64b..2fca627650f79516a2136b31f7885fe07723b27f 100644 --- a/src/feature_creation/node/operator_nodes/OperatorNode.hpp +++ b/src/feature_creation/node/operator_nodes/OperatorNode.hpp @@ -217,6 +217,49 @@ public: */ virtual NODE_TYPE type() = 0; + /** + * @brief Get the primary feature decomposition of a feature + * @return A map representing the primary feature comprising a feature + */ + std::map<int, int> primary_feature_decomp() + { + std::map<int, int> pf_decomp; + update_primary_feature_decomp(pf_decomp); + return pf_decomp; + } + + /** + * @brief Update the primary feature decomposition of a feature + * + * @param pf_decomp The primary feature decomposition of the feature calling this function. + */ + void update_primary_feature_decomp(std::map<int, int>& pf_decomp) + { + for(auto& feat : _feats) + feat->update_primary_feature_decomp(pf_decomp); + } + + /** + * @brief Converts a feature into a postfix expression (reverse polish notation) + * + * @details Recursively creates a postfix representation of the string + * + * @param cur_expr The current expression + * @return The current postfix expression of the feature + */ + inline void update_postfix(std::string& cur_expr) + { + cur_expr = get_postfix_term() + "|" + cur_expr; + for(int nn = N - 1; nn >= 0; --nn) + _feats[nn]->update_postfix(cur_expr); + }; + + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + virtual std::string get_postfix_term() = 0; + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp index faa4f5630c7265b5d8e4745661c7827e10e7ddd8..1f4de2a1afb21b881035ac9743c822c2e381cee1 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp @@ -113,6 +113,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::ABS_DIFF;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "abd";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp index 26c1107837982dc5592f5dd080f6b09197bcd80c..e8e9734f42c839ec14ed69a1d6357ef0b8deea29 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp @@ -111,6 +111,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::ABS;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "abs";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp index 38a63e82f8e64daa4bc2246ef181e647a8bee966..5bbb668cb35d78eb50b5452d1b96c4facf3813b7 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp @@ -112,6 +112,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::ADD;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "add";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp index b168913569714b3367febff99058e3adf6a3b344..90475353897d76816ff36b56112398a6a4173850 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp @@ -111,6 +111,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::COS;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "cos";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp index 4730e17985c55aa792af04a4c7b435d1e9042c73..6166868d127d7f0cde93c5757581e61a4c753c16 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp @@ -111,6 +111,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::CB;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "cb";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp index 5054cdd39c4dad4e290c60d1171af66ef845228d..41acf2cb8847301d5a42de770ac488a282fe3f2e 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp @@ -111,6 +111,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::CBRT;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "cbrt";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp index 3d5dc138b8540474cc55dc16c7b188a29185f8b5..b7ba2d1eaf5f9472e396a894907d8ab291b4f146 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp @@ -112,6 +112,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::DIV;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "div";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp index b03ab0b143e77a99c1b4453efdb2ac3e80550fdd..8355ebc4390b4e20580eac45687bbf8ee0fd48af 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp @@ -111,6 +111,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::EXP;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "exp";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp index 80735aa383fddd89f0a6504d3193caba391b18f5..60109dc4f9f49218d427953e10b51f191a2364a1 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp @@ -99,6 +99,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::INV;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "inv";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp index e59fd4dfcc8a91a6984f1780596b6b6f4fa4bb54..a3c4542d07412f584dc4ad44da7197b5333fd026 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp @@ -111,6 +111,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::LOG;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "log";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp index e58b0ce4a74e93efc27d7c3294b782d6a4ebd0e9..ba528c4302d4c175a3034f52f56f07a073ee411f 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp @@ -113,6 +113,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::MULT;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "mult";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp index 517f396fd2bae4c1fbaffdf6cc72b2766b925ef7..66c17bf1d771b6d12ae9f3c5ca4774928aa39734 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp @@ -112,6 +112,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::NEG_EXP;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "nexp";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp index e06d55b66f539f34a3a2244584df22f1f2c88652..69f5147d0263c264a63dfd75b97baff0f99a0534 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp @@ -112,6 +112,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::SIN;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "sin";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp index e2e6ad8ca2736282247a4735359968da8aa17316..dda10de5ad8fe519c08c73d0915105f1bd39e3c4 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp @@ -112,6 +112,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::SIX_POW;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "sp";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp index cf9fa6df0eaa4fd780e2ea051dfe2ee4dada52aa..b4044035ac9ad0c6e3129e3e625b2688373c90e6 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp @@ -111,6 +111,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::SQ;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "sq";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp index c1bcb8808ac6f03a38c11ec2d53102dbc0cd6127..cce30e4e932686fd0496dc8adc6c5b7c17f56492 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp @@ -112,6 +112,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::SQRT;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "sqrt";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp index 64b5e59be984d6677b54c88a93776f3f0ca3e779..246391a4cf314d12249937280efca8c818ddea31 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp @@ -113,6 +113,12 @@ public: */ inline NODE_TYPE type(){return NODE_TYPE::SUB;} + /** + * @brief Get the string character representation of the node for the postfix expression + * @return the string representation of the node for the postfix expression + */ + inline std::string get_postfix_term(){return "sub";} + /** * @brief update the dictionary used to check if an Add/Sub node is valid * diff --git a/src/feature_creation/node/utils.cpp b/src/feature_creation/node/utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ce5260798b82bc3d477183ad15e8b4e3bc7bd99 --- /dev/null +++ b/src/feature_creation/node/utils.cpp @@ -0,0 +1,112 @@ +#include <feature_creation/node/utils.hpp> + +node_ptr str2node::postfix2node(std::string postfix_expr, const std::vector<node_ptr>& phi_0, int feat_ind) +{ + std::vector<node_ptr> stack; + std::vector<std::string> postfix_split = str_utils::split_string_trim(postfix_expr, "|"); + feat_ind += postfix_split.size() - 1; + for(int ff = 0; ff < postfix_split.size(); ++ff) + { + std::string term = postfix_split[ff]; + try + { + stack.push_back(phi_0[std::stoi(term)]); + --feat_ind; + } + catch(const std::invalid_argument e) + { + if(term == "add") + { + stack[stack.size() - 2] = std::make_shared<AddNode>(stack[stack.size() - 2], stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + stack.pop_back(); + } + else if(term == "sub") + { + stack[stack.size() - 2] = std::make_shared<SubNode>(stack[stack.size() - 2], stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + stack.pop_back(); + } + else if(term == "abd") + { + stack[stack.size() - 2] = std::make_shared<AbsDiffNode>(stack[stack.size() - 2], stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + stack.pop_back(); + } + else if(term == "mult") + { + stack[stack.size() - 2] = std::make_shared<MultNode>(stack[stack.size() - 2], stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + stack.pop_back(); + } + else if(term == "div") + { + stack[stack.size() - 2] = std::make_shared<DivNode>(stack[stack.size() - 2], stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + stack.pop_back(); + } + else if(term == "abs") + stack[stack.size() - 1] = std::make_shared<AbsNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "inv") + stack[stack.size() - 1] = std::make_shared<InvNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "exp") + stack[stack.size() - 1] = std::make_shared<ExpNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "nexp") + stack[stack.size() - 1] = std::make_shared<NegExpNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "log") + stack[stack.size() - 1] = std::make_shared<LogNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "sin") + stack[stack.size() - 1] = std::make_shared<SinNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "cos") + stack[stack.size() - 1] = std::make_shared<CosNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "sq") + stack[stack.size() - 1] = std::make_shared<SqNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "sqrt") + stack[stack.size() - 1] = std::make_shared<SqrtNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "cb") + stack[stack.size() - 1] = std::make_shared<CbNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "cbrt") + stack[stack.size() - 1] = std::make_shared<CbrtNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else if(term == "sp") + stack[stack.size() - 1] = std::make_shared<SixPowNode>(stack[stack.size() - 1], feat_ind, 1e-50, 1e50); + else + throw std::logic_error("Term in postfix expression does not represent a node"); + --feat_ind; + } + } + if(stack.size() != 1) + throw std::logic_error("Went through postfix expression and still more than one node in the list. This must be an invalid expression: " + postfix_expr + "."); + return stack[0]; +} + +std::vector<node_ptr> str2node::phi_selected_from_file(std::string filename, std::vector<node_ptr> phi_0) +{ + node_value_arrs::resize_values_arr(0, phi_0.size(), true); + node_value_arrs::initialize_d_matrix_arr(); + + std::ifstream file_stream; + file_stream.open(filename, std::ios::in); + + std::string line; + std::vector<std::string> split_line; + + std::vector<node_ptr> phi_selected; + int feat_ind = phi_0.size(); + int feat_sel = 0; + std::getline(file_stream, line); + + while(std::getline(file_stream, line)) + { + if(line[0] == '#') + continue; + + node_value_arrs::resize_d_matrix_arr(1); + boost::algorithm::split(split_line, line, boost::algorithm::is_any_of("\t "), boost::token_compress_on); + + node_ptr new_feat = postfix2node(split_line[2], phi_0, feat_ind); + + new_feat->set_selected(true); + new_feat->set_d_mat_ind(feat_sel); + new_feat->set_value(); + phi_selected.push_back(std::make_shared<ModelNode>(feat_ind, new_feat->rung(), new_feat->expr(), new_feat->postfix_expr(), new_feat->value(), new_feat->test_value(), new_feat->unit())); + ++feat_ind; + ++feat_sel; + } + file_stream.close(); + return phi_selected; +} diff --git a/src/feature_creation/node/utils.hpp b/src/feature_creation/node/utils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e8d7d4a39a0a0efa23834b87c4564e46aefc8f90 --- /dev/null +++ b/src/feature_creation/node/utils.hpp @@ -0,0 +1,43 @@ +/** @file feature_creation/node/utils.hpp + * @brief utility functions to build node_ptrs from strings + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef NODE_UTILS +#define NODE_UTILS + +#include <fstream> +#include <feature_creation/node/FeatureNode.hpp> +#include <feature_creation/node/ModelNode.hpp> +#include <feature_creation/node/operator_nodes/allowed_ops.hpp> +#include <feature_creation/node/value_storage/nodes_value_containers.hpp> + +#include <utils/string_utils.hpp> + +namespace str2node +{ + /** + * @brief Convert a postfix expression into a node_ptr + * @details Creates a stack to iteratively generate the feature represented by the expression + * + * @param postfix_expr The postfix expression of the feature node + * @param phi_0 The initial feature set + * @param feat_ind The desired feature index + * @return The feature node described by the postfix expression + */ + node_ptr postfix2node(std::string postfix_expr, const std::vector<node_ptr>& phi_0, int feat_ind); + + /** + * @brief Convert a feature_space/selected_features.txt into a phi_selected; + * @details Read in the file to get the postfix expressions and regenerate the selected features using phi_0 + * + * @param filename The name of the feature_space/selected_features.txt file + * @param phi_0 The initial feature space + * + * @return The selected feature set from the file + */ + std::vector<node_ptr> phi_selected_from_file(std::string filename, std::vector<node_ptr> phi_0); +} + +#endif \ No newline at end of file diff --git a/src/python/bindings_docstring_keyed.cpp b/src/python/bindings_docstring_keyed.cpp index aa507ff7713eca566857c5041710fc744ca46753..c4f609b3949c0d5cbc461b9da11b58288402203a 100644 --- a/src/python/bindings_docstring_keyed.cpp +++ b/src/python/bindings_docstring_keyed.cpp @@ -30,6 +30,8 @@ void sisso::register_all() sisso::feature_creation::node::registerSqNode(); sisso::feature_creation::node::registerSqrtNode(); sisso::feature_creation::node::registerSixPowNode(); + + def("phi_selected_from_file", &str2node::phi_selected_from_file_py); } void sisso::feature_creation::registerFeatureSpace() @@ -96,6 +98,8 @@ void sisso::feature_creation::node::registerNode() .add_property("d_mat_ind", &Node::d_mat_ind, &Node::set_d_mat_ind, "@DocString_node_set_d_mat_ind@") .add_property("value", &Node::value_py, "@DocString_node_value_py@") .add_property("test_value", &Node::test_value_py, "@DocString_node_test_value_py@") + .add_property("primary_feat_decomp", &Node::primary_feature_decomp_py, "@DocString_node_primary_feature_decomp@") + .add_property("postfix_expr", &Node::postfix_expr, "@DocString_node_postfix_expr@") .def("expr", pure_virtual(&Node::expr), "@DocString_node_expr@") .def("unit", pure_virtual(&Node::unit), "@DocString_node_unit@") .def("set_value", pure_virtual(&Node::set_value), "@DocString_node_set_value@") @@ -131,7 +135,7 @@ void sisso::feature_creation::node::registerModelNode() std::string (ModelNode::*expr_const)() const = &ModelNode::expr; using namespace boost::python; - class_<ModelNode, bases<FeatureNode>>("ModelNode", init<int, int, std::string, std::vector<double>, std::vector<double>, Unit>()) + class_<ModelNode, bases<FeatureNode>>("ModelNode", init<int, int, std::string, std::string, std::vector<double>, std::vector<double>, Unit>()) .def("is_nan", &ModelNode::is_nan, "@DocString_model_node_is_nan@") .def("is_const", &ModelNode::is_const, "@DocString_model_node_is_const@") .def("set_value", &ModelNode::set_value, "@DocString_model_node_set_value@") diff --git a/src/python/bindings_docstring_keyed.hpp b/src/python/bindings_docstring_keyed.hpp index a68dc5e9319a390d77922bf2c662ec6517c7417b..e11568b8946ff41e22497b10a8af101e441dbd37 100644 --- a/src/python/bindings_docstring_keyed.hpp +++ b/src/python/bindings_docstring_keyed.hpp @@ -9,6 +9,7 @@ #include <descriptor_identifier/SISSORegressor.hpp> #include <feature_creation/feature_space/FeatureSpace.hpp> +#include <python/feature_creation/node_utils.hpp> namespace py = boost::python; namespace np = boost::python::numpy; @@ -45,6 +46,10 @@ namespace sisso inline bool is_const(){return this->get_override("is_const")();} inline NODE_TYPE type(){return this->get_override("type")();} inline int rung(int cur_rung = 0){return this->get_override("rung")();} + std::map<int, int> primary_feature_decomp(){return this->get_override("primary_feature_decomp")();} + void update_primary_feature_decomp(std::map<int, int>& pf_decomp){this->get_override("update_primary_feature_decomp")();} + void update_postfix(std::string& cur_expr){this->get_override("update_postfix")();} + std::string get_postfix_term(){return this->get_override("get_postfix_term")();} inline void update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot){this->get_override("update_add_sub_leaves");} inline void update_div_mult_leaves(std::map<std::string, double>& div_mult_leaves, double fact, double& expected_abs_tot){this->get_override("update_div_mult_leaves");} }; @@ -60,6 +65,7 @@ namespace sisso inline int rung(int cur_rung = 0){return this->get_override("rung")();} inline std::string expr(){return this->get_override("expr")();} inline Unit unit(){return this->get_override("unit")();} + std::string get_postfix_term(){return this->get_override("get_postfix_term")();} inline void update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot){this->get_override("update_add_sub_leaves")();} inline void update_div_mult_leaves(std::map<std::string, double>& div_mult_leaves, double fact, double& expected_abs_tot){this->get_override("update_div_mult_leaves")();} }; diff --git a/src/python/conversion_utils.hpp b/src/python/conversion_utils.hpp index 2549ec8ce49be49ff7dfb56d4ddab1031e8a9837..cd82cf4398049b4bb43c5af2e9e138db08abea9c 100644 --- a/src/python/conversion_utils.hpp +++ b/src/python/conversion_utils.hpp @@ -102,6 +102,16 @@ namespace python_conv_utils std::copy_n(vec.data(), vec.size(), reinterpret_cast<T*>(arr.get_data())); return arr; } + + template<typename key, typename val> + py::dict to_dict(std::map<key, val> map) + { + py::dict dct; + for(auto& iter : map) + dct[iter.first] = iter.second; + + return dct; + } } #endif \ No newline at end of file diff --git a/src/python/feature_creation/FeatureSpace.cpp b/src/python/feature_creation/FeatureSpace.cpp index 589bb14ab2360a60dd932228408abd2df007d459..73cbcd2ae398ed23e9d6a290afe4eea4ff0b24eb 100644 --- a/src/python/feature_creation/FeatureSpace.cpp +++ b/src/python/feature_creation/FeatureSpace.cpp @@ -76,6 +76,6 @@ py::list FeatureSpace::phi_selected_py() { py::list feat_lst; for(auto& feat : _phi_selected) - feat_lst.append<ModelNode>(ModelNode(feat->d_mat_ind(), feat->rung(), feat->expr(), feat->value(), feat->test_value(), feat->unit())); + feat_lst.append<ModelNode>(ModelNode(feat->d_mat_ind(), feat->rung(), feat->expr(), feat->postfix_expr(), feat->value(), feat->test_value(), feat->unit())); return feat_lst; } diff --git a/src/python/feature_creation/node_utils.cpp b/src/python/feature_creation/node_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec2b1c637692da574787486dd0be86491cd6727c --- /dev/null +++ b/src/python/feature_creation/node_utils.cpp @@ -0,0 +1,11 @@ +#include <python/feature_creation/node_utils.hpp> + +py::list str2node::phi_selected_from_file_py(std::string filename, py::list phi_0) +{ + std::vector<node_ptr> phi_selected = phi_selected_from_file(filename, python_conv_utils::shared_ptr_vec_from_list<Node, FeatureNode>(phi_0)); + + py::list feat_lst; + for(auto& feat : phi_selected) + feat_lst.append<ModelNode>(ModelNode(feat->d_mat_ind(), feat->rung(), feat->expr(), feat->postfix_expr(), feat->value(), feat->test_value(), feat->unit())); + return feat_lst; +} \ No newline at end of file diff --git a/src/python/feature_creation/node_utils.hpp b/src/python/feature_creation/node_utils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5d3d7e9a5fa63721642587f70fa0b0279a4e1563 --- /dev/null +++ b/src/python/feature_creation/node_utils.hpp @@ -0,0 +1,28 @@ +/** @file python/feature_creation/node_utils.hpp + * @brief python binding functions for node utilities + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef NODE_UTILS_PY +#define NODE_UTILS_PY + +#include <feature_creation/node/utils.hpp> + +namespace py = boost::python; + +namespace str2node +{ + /** + * @brief Convert a feature_space/selected_features.txt into a phi_selected; + * @details Read in the file to get the postfix expressions and regenerate the selected features using phi_0 + * + * @param filename The name of the feature_space/selected_features.txt file + * @param phi_0 The initial feature space + * + * @return The selected feature set from the file as a python file + */ + py::list phi_selected_from_file_py(std::string filename, py::list phi_0); +} + +#endif \ No newline at end of file diff --git a/test/sisso.json b/test/sisso.json index 1011b74c95a1081d81df63ff5cec61742336affc..51cc8128c51a676c62d22cef7dbd14a0ac3d05f6 100644 --- a/test/sisso.json +++ b/test/sisso.json @@ -7,7 +7,7 @@ "max_abs_feat_val": 1e5, "data_file": "data.csv", "property_key": "energy_diff", - "leave_out_frac": 0.05, + "leave_out_frac": 0.0, "n_rung_generate": 0, "n_rung_store": 1, "leave_out_inds": [],