From c94914adb3ad21084fe8c7038e8c5caa18df2cfb Mon Sep 17 00:00:00 2001
From: Thomas Purcell <purcell@fhi-berlin.mpg.de>
Date: Tue, 9 Jun 2020 07:28:43 +0200
Subject: [PATCH] Replaced vetor node_ptr feats with templated array

This should hopefully reduce the codes memory footprint
---
 src/feature_creation/node/FeatureNode.hpp     |  2 -
 src/feature_creation/node/Node.hpp            |  2 -
 .../node/operator_nodes/OperatorNode.cpp      | 96 +++++++++----------
 .../node/operator_nodes/OperatorNode.hpp      | 54 +++++++++--
 .../absolute_difference.cpp                   |  2 +-
 .../absolute_difference.hpp                   |  4 +-
 .../allowed_operator_nodes/absolute_value.cpp |  2 +-
 .../allowed_operator_nodes/absolute_value.hpp |  4 +-
 .../allowed_operator_nodes/add.cpp            |  2 +-
 .../allowed_operator_nodes/add.hpp            |  4 +-
 .../allowed_operator_nodes/cos.cpp            |  2 +-
 .../allowed_operator_nodes/cos.hpp            |  4 +-
 .../allowed_operator_nodes/cube.cpp           |  2 +-
 .../allowed_operator_nodes/cube.hpp           |  4 +-
 .../allowed_operator_nodes/cube_root.cpp      |  2 +-
 .../allowed_operator_nodes/cube_root.hpp      |  4 +-
 .../allowed_operator_nodes/divide.cpp         |  2 +-
 .../allowed_operator_nodes/divide.hpp         |  4 +-
 .../allowed_operator_nodes/exponential.cpp    |  2 +-
 .../allowed_operator_nodes/exponential.hpp    |  4 +-
 .../allowed_operator_nodes/inverse.cpp        |  2 +-
 .../allowed_operator_nodes/inverse.hpp        |  4 +-
 .../allowed_operator_nodes/log.cpp            |  2 +-
 .../allowed_operator_nodes/log.hpp            |  4 +-
 .../allowed_operator_nodes/multiply.cpp       |  2 +-
 .../allowed_operator_nodes/multiply.hpp       |  4 +-
 .../negative_exponential.cpp                  |  2 +-
 .../negative_exponential.hpp                  |  4 +-
 .../allowed_operator_nodes/sin.cpp            |  2 +-
 .../allowed_operator_nodes/sin.hpp            |  4 +-
 .../allowed_operator_nodes/sixth_power.cpp    |  2 +-
 .../allowed_operator_nodes/sixth_power.hpp    |  4 +-
 .../allowed_operator_nodes/square.cpp         |  2 +-
 .../allowed_operator_nodes/square.hpp         |  4 +-
 .../allowed_operator_nodes/square_root.cpp    |  2 +-
 .../allowed_operator_nodes/square_root.hpp    |  4 +-
 .../allowed_operator_nodes/subtract.cpp       |  2 +-
 .../allowed_operator_nodes/subtract.hpp       |  4 +-
 38 files changed, 143 insertions(+), 113 deletions(-)

diff --git a/src/feature_creation/node/FeatureNode.hpp b/src/feature_creation/node/FeatureNode.hpp
index f6504d49..20562e86 100644
--- a/src/feature_creation/node/FeatureNode.hpp
+++ b/src/feature_creation/node/FeatureNode.hpp
@@ -124,8 +124,6 @@ public:
      */
     inline int rung(int cur_rung = 0){return cur_rung;}
 
-    inline std::vector<node_ptr> feats(){return {};}
-
     /**
      * @brief update the dictionary used to check if an Add/Sub node is valid
      *
diff --git a/src/feature_creation/node/Node.hpp b/src/feature_creation/node/Node.hpp
index d3d60fad..a4602172 100644
--- a/src/feature_creation/node/Node.hpp
+++ b/src/feature_creation/node/Node.hpp
@@ -118,8 +118,6 @@ public:
      */
     virtual std::vector<double> test_value() = 0;
 
-    virtual std::vector<std::shared_ptr<Node>> feats() = 0;
-
     /**
      * @brief Set the value for the feature
      */
diff --git a/src/feature_creation/node/operator_nodes/OperatorNode.cpp b/src/feature_creation/node/operator_nodes/OperatorNode.cpp
index 80b6ea13..df0a67d2 100644
--- a/src/feature_creation/node/operator_nodes/OperatorNode.cpp
+++ b/src/feature_creation/node/operator_nodes/OperatorNode.cpp
@@ -1,52 +1,52 @@
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-OperatorNode::OperatorNode()
-{}
-
-OperatorNode::OperatorNode(std::vector<node_ptr> feats, int rung, int feat_ind) :
-    Node(feat_ind, feats[0]->n_samp(), feats[0]->n_test_samp()),
-    _feats(feats)
-{}
-
-OperatorNode::~OperatorNode()
-{}
-
-double* OperatorNode::value_ptr(int offset)
-{
-    offset = (offset == -1) ? rung() : offset;
-    if((rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_arr_ind, offset) != _arr_ind))
-    {
-        set_value(offset);
-        node_value_arrs::temp_storage_reg(_arr_ind, offset) = _arr_ind;
-    }
-
-    return node_value_arrs::get_value_ptr(_arr_ind, offset);
-}
-
-double* OperatorNode::test_value_ptr(int offset)
-{
-    offset = (offset == -1) ? rung() : offset;
-    if((rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_test_reg(_arr_ind, offset) != _arr_ind))
-    {
-        set_test_value(offset);
-        node_value_arrs::temp_storage_test_reg(_arr_ind, offset) = _arr_ind;
-    }
-
-    return node_value_arrs::get_test_value_ptr(_arr_ind, offset);
-}
-
-std::vector<double> OperatorNode::value()
-{
-    std::vector<double> val(_n_samp, 0.0);
-    std::copy_n(value_ptr(), _n_samp, val.data());
-    return val;
-}
-
-std::vector<double> OperatorNode::test_value()
-{
-    std::vector<double> val(_n_test_samp, 0.0);
-    std::copy_n(test_value_ptr(), _n_test_samp, val.data());
-    return val;
-}
+// OperatorNode::OperatorNode()
+// {}
+
+// OperatorNode::OperatorNode(std::array<node_ptr, 1> feats, int rung, int feat_ind) :
+//     Node(feat_ind, feats[0]->n_samp(), feats[0]->n_test_samp()),
+//     _feats(feats)
+// {}
+
+// OperatorNode::~OperatorNode()
+// {}
+
+// double* OperatorNode::value_ptr(int offset)
+// {
+//     offset = (offset == -1) ? rung() : offset;
+//     if((rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_arr_ind, offset) != _arr_ind))
+//     {
+//         set_value(offset);
+//         node_value_arrs::temp_storage_reg(_arr_ind, offset) = _arr_ind;
+//     }
+
+//     return node_value_arrs::get_value_ptr(_arr_ind, offset);
+// }
+
+// double* OperatorNode::test_value_ptr(int offset)
+// {
+//     offset = (offset == -1) ? rung() : offset;
+//     if((rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_test_reg(_arr_ind, offset) != _arr_ind))
+//     {
+//         set_test_value(offset);
+//         node_value_arrs::temp_storage_test_reg(_arr_ind, offset) = _arr_ind;
+//     }
+
+//     return node_value_arrs::get_test_value_ptr(_arr_ind, offset);
+// }
+
+// std::vector<double> OperatorNode::value()
+// {
+//     std::vector<double> val(_n_samp, 0.0);
+//     std::copy_n(value_ptr(), _n_samp, val.data());
+//     return val;
+// }
+
+// std::vector<double> OperatorNode::test_value()
+// {
+//     std::vector<double> val(_n_test_samp, 0.0);
+//     std::copy_n(test_value_ptr(), _n_test_samp, val.data());
+//     return val;
+// }
 
 BOOST_SERIALIZATION_ASSUME_ABSTRACT(OperatorNode)
diff --git a/src/feature_creation/node/operator_nodes/OperatorNode.hpp b/src/feature_creation/node/operator_nodes/OperatorNode.hpp
index d8aaa8bb..bf7ce32f 100644
--- a/src/feature_creation/node/operator_nodes/OperatorNode.hpp
+++ b/src/feature_creation/node/operator_nodes/OperatorNode.hpp
@@ -17,6 +17,7 @@
  * @details
  *
  */
+template<int N>
 class OperatorNode: public Node
 {
     friend class boost::serialization::access;
@@ -28,14 +29,15 @@ class OperatorNode: public Node
         ar & _feats;
     }
 protected:
-    std::vector<node_ptr> _feats;
+    std::array<node_ptr, N> _feats;
 
 public:
     /**
      * @brief Base Constructor
      * @details This is only used for serialization
      */
-    OperatorNode();
+    OperatorNode()
+    {}
 
     /**
      * @brief Constructor
@@ -45,19 +47,31 @@ public:
      * @param rung run the feature is on (depth of the tree)
      * @param feat_ind index of the feature
      */
-    OperatorNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    OperatorNode(std::array<node_ptr, N> feats, int rung, int feat_ind) :
+        Node(feat_ind, feats[0]->n_samp(), feats[0]->n_test_samp()),
+        _feats(feats)
+    {}
 
-    virtual ~OperatorNode();
+    virtual ~OperatorNode()
+    {}
 
     virtual std::string expr() = 0;
 
     virtual Unit unit() = 0;
 
-    std::vector<double> value();
-
-    std::vector<double> test_value();
+    std::vector<double> value()
+    {
+        std::vector<double> val(_n_samp, 0.0);
+        std::copy_n(value_ptr(), _n_samp, val.data());
+        return val;
+    }
 
-    inline std::vector<node_ptr> feats(){return _feats;}
+    std::vector<double> test_value()
+    {
+        std::vector<double> val(_n_test_samp, 0.0);
+        std::copy_n(test_value_ptr(), _n_test_samp, val.data());
+        return val;
+    }
 
     virtual void set_value(int offset = -1) = 0;
 
@@ -71,7 +85,17 @@ public:
      *
      * @return pointer to the feature's value
      */
-    double* value_ptr(int offset=-1);
+    double* value_ptr(int offset=-1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        if((rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_arr_ind, offset) != _arr_ind))
+        {
+            set_value(offset);
+            node_value_arrs::temp_storage_reg(_arr_ind, offset) = _arr_ind;
+        }
+
+        return node_value_arrs::get_value_ptr(_arr_ind, offset);
+    }
 
     /**
      * @brief Get the pointer to the feature's data
@@ -81,7 +105,17 @@ public:
      *
      * @return pointer to the feature's test values
      */
-    double* test_value_ptr(int offset=-1);
+    double* test_value_ptr(int offset=-1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        if((rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_test_reg(_arr_ind, offset) != _arr_ind))
+        {
+            set_test_value(offset);
+            node_value_arrs::temp_storage_test_reg(_arr_ind, offset) = _arr_ind;
+        }
+
+        return node_value_arrs::get_test_value_ptr(_arr_ind, offset);
+    }
 
     /**
      * @brief Check if the feature contains NaN
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.cpp
index ae7ee26a..881891f8 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.cpp
@@ -5,7 +5,7 @@
 AbsDiffNode::AbsDiffNode()
 {}
 
-AbsDiffNode::AbsDiffNode(std::vector<node_ptr> feats, int rung, int feat_ind) :
+AbsDiffNode::AbsDiffNode(std::array<node_ptr, 2> feats, int rung, int feat_ind) :
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->unit() != feats[1]->unit())
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp
index 7434f27e..e6a4d9ad 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class AbsDiffNode: public OperatorNode
+class AbsDiffNode: public OperatorNode<2>
 {
     friend class boost::serialization::access;
 
@@ -16,7 +16,7 @@ class AbsDiffNode: public OperatorNode
 public:
     AbsDiffNode();
 
-    AbsDiffNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    AbsDiffNode(std::array<node_ptr, 2> feats, int rung, int feat_ind);
 
     AbsDiffNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.cpp
index 7c01d21a..65873d33 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.cpp
@@ -5,7 +5,7 @@
 AbsNode::AbsNode()
 {}
 
-AbsNode::AbsNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+AbsNode::AbsNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     set_value();
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp
index 11cb5c7c..092acd3c 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class AbsNode: public OperatorNode
+class AbsNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -15,7 +15,7 @@ class AbsNode: public OperatorNode
 public:
     AbsNode();
 
-    AbsNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    AbsNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     AbsNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.cpp
index 0a4742b5..9b8751a8 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.cpp
@@ -3,7 +3,7 @@
 AddNode::AddNode()
 {}
 
-AddNode::AddNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+AddNode::AddNode(std::array<node_ptr, 2> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->unit() != feats[1]->unit())
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp
index de207aa7..2b09833e 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class AddNode: public OperatorNode
+class AddNode: public OperatorNode<2>
 {
     friend class boost::serialization::access;
 
@@ -15,7 +15,7 @@ class AddNode: public OperatorNode
 public:
     AddNode();
 
-    AddNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    AddNode(std::array<node_ptr, 2> feats, int rung, int feat_ind);
 
     AddNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.cpp
index 697094e2..d1fa2e0a 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.cpp
@@ -3,7 +3,7 @@
 CosNode::CosNode()
 {}
 
-CosNode::CosNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+CosNode::CosNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->unit() != Unit())
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp
index 97eda826..be84327b 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class CosNode: public OperatorNode
+class CosNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -15,7 +15,7 @@ class CosNode: public OperatorNode
 public:
     CosNode();
 
-    CosNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    CosNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     CosNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.cpp
index d98cc3e3..a49c5195 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.cpp
@@ -3,7 +3,7 @@
 CbNode::CbNode()
 {}
 
-CbNode::CbNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+CbNode::CbNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->type() == NODE_TYPE::CBRT)
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp
index 420af5ca..3afa8b20 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class CbNode: public OperatorNode
+class CbNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -15,7 +15,7 @@ class CbNode: public OperatorNode
 public:
     CbNode();
 
-    CbNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    CbNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     CbNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.cpp
index b824bec6..20cde3f9 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.cpp
@@ -3,7 +3,7 @@
 CbrtNode::CbrtNode()
 {}
 
-CbrtNode::CbrtNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+CbrtNode::CbrtNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->type() == NODE_TYPE::CB)
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp
index b69afd46..1152fd2a 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class CbrtNode: public OperatorNode
+class CbrtNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -15,7 +15,7 @@ class CbrtNode: public OperatorNode
 public:
     CbrtNode();
 
-    CbrtNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    CbrtNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     CbrtNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.cpp
index 6aa3db93..837fb44b 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.cpp
@@ -3,7 +3,7 @@
 DivNode::DivNode()
 {}
 
-DivNode::DivNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+DivNode::DivNode(std::array<node_ptr, 2> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if((feats[0]->type() == NODE_TYPE::INV) || (feats[1]->type() == NODE_TYPE::INV))
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp
index 7b06b84e..89738715 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class DivNode: public OperatorNode
+class DivNode: public OperatorNode<2>
 {
     friend class boost::serialization::access;
 
@@ -15,7 +15,7 @@ class DivNode: public OperatorNode
 public:
     DivNode();
 
-    DivNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    DivNode(std::array<node_ptr, 2> feats, int rung, int feat_ind);
 
     DivNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.cpp
index c12d2397..c4691ed9 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.cpp
@@ -3,7 +3,7 @@
 ExpNode::ExpNode()
 {}
 
-ExpNode::ExpNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+ExpNode::ExpNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->unit() != Unit())
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp
index 4903e366..c35f8ee0 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class ExpNode: public OperatorNode
+class ExpNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -15,7 +15,7 @@ class ExpNode: public OperatorNode
 public:
     ExpNode();
 
-    ExpNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    ExpNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     ExpNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.cpp
index b8f0e456..d39a8d6a 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.cpp
@@ -3,7 +3,7 @@
 InvNode::InvNode()
 {}
 
-InvNode::InvNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+InvNode::InvNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if((feats[0]->type() == NODE_TYPE::DIV) || (feats[0]->type() == NODE_TYPE::EXP) || (feats[0]->type() == NODE_TYPE::NEG_EXP))
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp
index 8147863d..8a8f69be 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class InvNode: public OperatorNode
+class InvNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -16,7 +16,7 @@ class InvNode: public OperatorNode
 public:
     InvNode();
 
-    InvNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    InvNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     InvNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.cpp
index d0af2839..8d8c3b10 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.cpp
@@ -3,7 +3,7 @@
 LogNode::LogNode()
 {}
 
-LogNode::LogNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+LogNode::LogNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->unit() != Unit())
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp
index 864b60c7..5c194abc 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class LogNode: public OperatorNode
+class LogNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -15,7 +15,7 @@ class LogNode: public OperatorNode
 public:
     LogNode();
 
-    LogNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    LogNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     LogNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.cpp
index bc0e13fa..fa6c8245 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.cpp
@@ -3,7 +3,7 @@
 MultNode::MultNode()
 {}
 
-MultNode::MultNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+MultNode::MultNode(std::array<node_ptr, 2> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     std::map<std::string, double> div_mult_leaves;
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp
index f78a0ed7..a25cce65 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class MultNode: public OperatorNode
+class MultNode: public OperatorNode<2>
 {
     friend class boost::serialization::access;
 
@@ -16,7 +16,7 @@ class MultNode: public OperatorNode
 public:
     MultNode();
 
-    MultNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    MultNode(std::array<node_ptr, 2> feats, int rung, int feat_ind);
 
     MultNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.cpp
index df28a9e1..fdf125f2 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.cpp
@@ -3,7 +3,7 @@
 NegExpNode::NegExpNode()
 {}
 
-NegExpNode::NegExpNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+NegExpNode::NegExpNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->unit() != Unit())
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp
index c7dde942..6b6f4f1a 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class NegExpNode: public OperatorNode
+class NegExpNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -16,7 +16,7 @@ class NegExpNode: public OperatorNode
 public:
     NegExpNode();
 
-    NegExpNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    NegExpNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     NegExpNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.cpp
index 3aedd073..4c9bbc4b 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.cpp
@@ -3,7 +3,7 @@
 SinNode::SinNode()
 {}
 
-SinNode::SinNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+SinNode::SinNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->unit() != Unit())
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp
index cb606b10..d048df82 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class SinNode: public OperatorNode
+class SinNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -16,7 +16,7 @@ class SinNode: public OperatorNode
 public:
     SinNode();
 
-    SinNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    SinNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     SinNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.cpp
index a74ef6d6..5fe889b4 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.cpp
@@ -3,7 +3,7 @@
 SixPowNode::SixPowNode()
 {}
 
-SixPowNode::SixPowNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+SixPowNode::SixPowNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if((feats[0]->type() == NODE_TYPE::CBRT) || (feats[0]->type() == NODE_TYPE::SQRT))
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp
index 8fb575b4..d21b1b23 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class SixPowNode: public OperatorNode
+class SixPowNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -16,7 +16,7 @@ class SixPowNode: public OperatorNode
 public:
     SixPowNode();
 
-    SixPowNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    SixPowNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     SixPowNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.cpp
index 7bfb9c6e..2251bddc 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.cpp
@@ -3,7 +3,7 @@
 SqNode::SqNode()
 {}
 
-SqNode::SqNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+SqNode::SqNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->type() == NODE_TYPE::SQRT)
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp
index dc5a7acc..64ecd33a 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class SqNode: public OperatorNode
+class SqNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -15,7 +15,7 @@ class SqNode: public OperatorNode
 public:
     SqNode();
 
-    SqNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    SqNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     SqNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.cpp
index 0f30bb2b..fb824138 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.cpp
@@ -3,7 +3,7 @@
 SqrtNode::SqrtNode()
 {}
 
-SqrtNode::SqrtNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+SqrtNode::SqrtNode(std::array<node_ptr, 1> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->type() == NODE_TYPE::SQRT)
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp
index 07d2736e..ae76c2d2 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class SqrtNode: public OperatorNode
+class SqrtNode: public OperatorNode<1>
 {
     friend class boost::serialization::access;
 
@@ -16,7 +16,7 @@ class SqrtNode: public OperatorNode
 public:
     SqrtNode();
 
-    SqrtNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    SqrtNode(std::array<node_ptr, 1> feats, int rung, int feat_ind);
 
     SqrtNode(node_ptr feat, int rung, int feat_ind);
 
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.cpp
index 0760bc8b..0b98078d 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.cpp
@@ -3,7 +3,7 @@
 SubNode::SubNode()
 {}
 
-SubNode::SubNode(std::vector<node_ptr> feats, int rung, int feat_ind):
+SubNode::SubNode(std::array<node_ptr, 2> feats, int rung, int feat_ind):
     OperatorNode(feats, rung, feat_ind)
 {
     if(feats[0]->unit() != feats[1]->unit())
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp
index 8883fe3e..469864a3 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp
@@ -3,7 +3,7 @@
 
 #include <feature_creation/node/operator_nodes/OperatorNode.hpp>
 
-class SubNode: public OperatorNode
+class SubNode: public OperatorNode<2>
 {
     friend class boost::serialization::access;
 
@@ -16,7 +16,7 @@ class SubNode: public OperatorNode
 public:
     SubNode();
 
-    SubNode(std::vector<node_ptr> feats, int rung, int feat_ind);
+    SubNode(std::array<node_ptr, 2> feats, int rung, int feat_ind);
 
     SubNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_ind);
 
-- 
GitLab