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