diff --git a/src/DataTree.cc b/src/DataTree.cc
index 2bd4ff11a878f861863b278a785a94e26d6512a1..9dd438eec9bb847990dcc68efe1cd8ec73dafc82 100644
--- a/src/DataTree.cc
+++ b/src/DataTree.cc
@@ -506,7 +506,7 @@ DataTree::AddVarExpectation(const int symb_id, const int forecast_horizon, const
 {
   assert(symbol_table.getType(symb_id) == eEndogenous);
 
-  auto it = var_expectation_node_map.find({ model_name, { symb_id, forecast_horizon } });
+  auto it = var_expectation_node_map.find({ model_name, symb_id, forecast_horizon });
   if (it != var_expectation_node_map.end())
     return it->second;
 
@@ -561,7 +561,7 @@ DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr
   assert(symbol_table.getType(top_level_symb_id) == eExternalFunction);
 
   auto it
-    = first_deriv_external_function_node_map.find({ { arguments, input_index }, top_level_symb_id });
+    = first_deriv_external_function_node_map.find({ arguments, input_index, top_level_symb_id });
   if (it != first_deriv_external_function_node_map.end())
     return it->second;
 
@@ -574,7 +574,7 @@ DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<exp
   assert(symbol_table.getType(top_level_symb_id) == eExternalFunction);
 
   auto it
-    = second_deriv_external_function_node_map.find({ { arguments, { input_index1, input_index2 } },
+    = second_deriv_external_function_node_map.find({ arguments, input_index1, input_index2,
           top_level_symb_id });
   if (it != second_deriv_external_function_node_map.end())
     return it->second;
@@ -634,7 +634,7 @@ bool
 DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
 {
   for (const auto & it : unary_op_node_map)
-    if (it.first.first.second == opcode)
+    if (get<1>(it.first) == opcode)
       return true;
 
   return false;
@@ -644,7 +644,7 @@ bool
 DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
 {
   for (const auto & it : binary_op_node_map)
-    if (it.first.second == opcode)
+    if (get<2>(it.first) == opcode)
       return true;
 
   return false;
@@ -654,7 +654,7 @@ bool
 DataTree::isTrinaryOpUsed(TrinaryOpcode opcode) const
 {
   for (const auto & it : trinary_op_node_map)
-    if (it.first.second == opcode)
+    if (get<3>(it.first) == opcode)
       return true;
 
   return false;
@@ -674,7 +674,7 @@ bool
 DataTree::isFirstDerivExternalFunctionUsed(int symb_id) const
 {
   for (const auto & it : first_deriv_external_function_node_map)
-    if (it.first.second == symb_id)
+    if (get<2>(it.first) == symb_id)
       return true;
 
   return false;
@@ -684,7 +684,7 @@ bool
 DataTree::isSecondDerivExternalFunctionUsed(int symb_id) const
 {
   for (const auto & it : second_deriv_external_function_node_map)
-    if (it.first.second == symb_id)
+    if (get<3>(it.first) == symb_id)
       return true;
 
   return false;
diff --git a/src/DataTree.hh b/src/DataTree.hh
index e6537631fe2d479f6e10dd1099ba8ed41c760759..612579af64f0bb2b41d57891e4d0e84efc52adc0 100644
--- a/src/DataTree.hh
+++ b/src/DataTree.hh
@@ -59,39 +59,44 @@ protected:
   //! A reference to the external functions table
   ExternalFunctionsTable &external_functions_table;
 
+  //! num_constant_id -> NumConstNode
   using num_const_node_map_t = map<int, NumConstNode *>;
   num_const_node_map_t num_const_node_map;
-  //! Pair (symbol_id, lag) used as key
+
+  //! (symbol_id, lag) -> VariableNode
   using variable_node_map_t = map<pair<int, int>, VariableNode *>;
   variable_node_map_t variable_node_map;
-  //! Pair( Pair(arg1, UnaryOpCode), Pair( Expectation Info Set, Pair(param1_symb_id, param2_symb_id)) ))
 
-  using unary_op_node_map_t = map<pair<pair<expr_t, UnaryOpcode>, pair<pair<int, pair<int, int>>, pair<string, vector<int>>>>, UnaryOpNode *>;
+  //! (arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags) -> UnaryOpNode
+  using unary_op_node_map_t = map<tuple<expr_t, UnaryOpcode, int, int, int, string, vector<int>>, UnaryOpNode *>;
   unary_op_node_map_t unary_op_node_map;
-  //! Pair( Pair( Pair(arg1, arg2), order of Power Derivative), opCode)
-  using binary_op_node_map_t = map<pair<pair<pair<expr_t, expr_t>, int>, BinaryOpcode>, BinaryOpNode *>;
+
+  //! ( arg1, arg2, opCode, order of Power Derivative) -> BinaryOpNode
+  using binary_op_node_map_t = map<tuple<expr_t, expr_t, BinaryOpcode, int>, BinaryOpNode *>;
   binary_op_node_map_t binary_op_node_map;
-  using trinary_op_node_map_t = map<pair<pair<pair<expr_t, expr_t>, expr_t>, TrinaryOpcode>, TrinaryOpNode *>;
+
+  //! ( arg1, arg2, arg3, opCode) -> TrinaryOpNode
+  using trinary_op_node_map_t = map<tuple<expr_t, expr_t, expr_t, TrinaryOpcode>, TrinaryOpNode *>;
   trinary_op_node_map_t trinary_op_node_map;
 
   // (arguments, symb_id) -> ExternalFunctionNode
   using external_function_node_map_t = map<pair<vector<expr_t>, int>, ExternalFunctionNode *>;
   external_function_node_map_t external_function_node_map;
 
-  // (model_name, (symb_id, forecast_horizon)) -> VarExpectationNode
-  using var_expectation_node_map_t = map<pair<string, pair<int, int>>, VarExpectationNode *>;
+  // (model_name, symb_id, forecast_horizon) -> VarExpectationNode
+  using var_expectation_node_map_t = map<tuple<string, int, int>, VarExpectationNode *>;
   var_expectation_node_map_t var_expectation_node_map;
 
   // model_name -> PacExpectationNode
   using pac_expectation_node_map_t = map<string, PacExpectationNode *>;
   pac_expectation_node_map_t pac_expectation_node_map;
 
-  // ((arguments, deriv_idx), symb_id) -> FirstDerivExternalFunctionNode
-  using first_deriv_external_function_node_map_t = map<pair<pair<vector<expr_t>, int>, int>, FirstDerivExternalFunctionNode *>;
+  // (arguments, deriv_idx, symb_id) -> FirstDerivExternalFunctionNode
+  using first_deriv_external_function_node_map_t = map<tuple<vector<expr_t>, int, int>, FirstDerivExternalFunctionNode *>;
   first_deriv_external_function_node_map_t first_deriv_external_function_node_map;
 
-  // ((arguments, (deriv_idx1, deriv_idx2)), symb_id) -> SecondDerivExternalFunctionNode
-  using second_deriv_external_function_node_map_t = map<pair<pair<vector<expr_t>, pair<int, int>>, int>, SecondDerivExternalFunctionNode *>;
+  // (arguments, deriv_idx1, deriv_idx2, symb_id) -> SecondDerivExternalFunctionNode
+  using second_deriv_external_function_node_map_t = map<tuple<vector<expr_t>, int, int, int>, SecondDerivExternalFunctionNode *>;
   second_deriv_external_function_node_map_t second_deriv_external_function_node_map;
 
   //! Stores local variables value (maps symbol ID to corresponding node)
@@ -330,7 +335,7 @@ inline expr_t
 DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int param1_symb_id, int param2_symb_id, const string &adl_param_name, const vector<int> &adl_lags)
 {
   // If the node already exists in tree, share it
-  auto it = unary_op_node_map.find({ { arg, op_code }, { { arg_exp_info_set, { param1_symb_id, param2_symb_id } }, { adl_param_name, adl_lags } } });
+  auto it = unary_op_node_map.find({ arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags });
   if (it != unary_op_node_map.end())
     return it->second;
 
@@ -355,7 +360,7 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int
 inline expr_t
 DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder)
 {
-  auto it = binary_op_node_map.find({ { { arg1, arg2 }, powerDerivOrder }, op_code });
+  auto it = binary_op_node_map.find({ arg1, arg2, op_code, powerDerivOrder });
   if (it != binary_op_node_map.end())
     return it->second;
 
@@ -376,7 +381,7 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD
 inline expr_t
 DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3)
 {
-  auto it = trinary_op_node_map.find({ { { arg1, arg2 }, arg3 }, op_code });
+  auto it = trinary_op_node_map.find({ arg1, arg2, arg3, op_code });
   if (it != trinary_op_node_map.end())
     return it->second;
 
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 2a90ad2c29b41a785c30cbedc015e8ab65131b84..be88fd09d0681526e8634c56695b342ae26e4bf0 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -1523,9 +1523,8 @@ DynamicModel::writeDynamicMFile(const string &dynamic_basename) const
 void
 DynamicModel::fillVarExpectationFunctionsToWrite()
 {
-  for (var_expectation_node_map_t::const_iterator it = var_expectation_node_map.begin();
-       it != var_expectation_node_map.end(); it++)
-    var_expectation_functions_to_write[it->first.first].insert(it->first.second.second);
+  for (auto &it : var_expectation_node_map)
+    var_expectation_functions_to_write[get<0>(it.first)].insert(get<2>(it.first));
 }
 
 map<string, set<int>>
diff --git a/src/ExprNode.cc b/src/ExprNode.cc
index 95793bb203223396d329b876ac4caab04f8c7d42..191c3a59fb12f1b3ea3ff2803a1f9f9a7cd2b476 100644
--- a/src/ExprNode.cc
+++ b/src/ExprNode.cc
@@ -1841,8 +1841,7 @@ UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const
   adl_lags(move(adl_lags_arg))
 {
   // Add myself to the unary op map
-  datatree.unary_op_node_map[{ { arg, op_code },
-        { { expectation_information_set, { param1_symb_id, param2_symb_id } }, { adl_param_name, adl_lags } } }] = this;
+  datatree.unary_op_node_map[{ arg, op_code, expectation_information_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags }] = this;
 }
 
 void
@@ -3453,7 +3452,7 @@ BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
   op_code(op_code_arg),
   powerDerivOrder(0)
 {
-  datatree.binary_op_node_map[{ { { arg1, arg2 }, powerDerivOrder }, op_code }] = this;
+  datatree.binary_op_node_map[{ arg1, arg2, op_code, powerDerivOrder }] = this;
 }
 
 BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
@@ -3465,7 +3464,7 @@ BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
   powerDerivOrder(powerDerivOrder_arg)
 {
   assert(powerDerivOrder >= 0);
-  datatree.binary_op_node_map[{ { { arg1, arg2 }, powerDerivOrder }, op_code }] = this;
+  datatree.binary_op_node_map[{ arg1, arg2, op_code, powerDerivOrder }] = this;
 }
 
 void
@@ -5110,7 +5109,7 @@ TrinaryOpNode::TrinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
   arg3(arg3_arg),
   op_code(op_code_arg)
 {
-  datatree.trinary_op_node_map[{ { { arg1, arg2 }, arg3 }, op_code }] = this;
+  datatree.trinary_op_node_map[{ arg1, arg2, arg3, op_code }] = this;
 }
 
 void
@@ -6837,7 +6836,7 @@ FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatre
   inputIndex(inputIndex_arg)
 {
   // Add myself to the first derivative external function map
-  datatree.first_deriv_external_function_node_map[{ { arguments, inputIndex }, symb_id }] = this;
+  datatree.first_deriv_external_function_node_map[{ arguments, inputIndex, symb_id }] = this;
 }
 
 void
@@ -7223,7 +7222,7 @@ SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datat
   inputIndex2(inputIndex2_arg)
 {
   // Add myself to the second derivative external function map
-  datatree.second_deriv_external_function_node_map[{ { arguments, { inputIndex1, inputIndex2 } }, symb_id }] = this;
+  datatree.second_deriv_external_function_node_map[{ arguments, inputIndex1, inputIndex2, symb_id }] = this;
 }
 
 void
@@ -7558,7 +7557,7 @@ VarExpectationNode::VarExpectationNode(DataTree &datatree_arg,
   model_name(model_name_arg),
   yidx(-1)
 {
-  datatree.var_expectation_node_map[{ model_name, { symb_id, forecast_horizon } }] = this;
+  datatree.var_expectation_node_map[{ model_name, symb_id, forecast_horizon }] = this;
 }
 
 void