From 004d90962179102728c584039d726b2dc543e8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org> Date: Wed, 5 Sep 2018 16:41:33 +0200 Subject: [PATCH] Use smart pointers for storage of ExprNode in DataTree class - BTW, store them in a std::vector rather than std::list - incidentally, fix issue in VariableNode::removeTrendLeadLag where expression sharing was possibly violated when creating a new VariableNode --- src/DataTree.cc | 55 +++++++++++++++++++++++++----------- src/DataTree.hh | 28 ++++++++++++------ src/ExprNode.cc | 75 ++++++++++++++++--------------------------------- src/ExprNode.hh | 28 +++++++++--------- 4 files changed, 96 insertions(+), 90 deletions(-) diff --git a/src/DataTree.cc b/src/DataTree.cc index a349c383..736e49e8 100644 --- a/src/DataTree.cc +++ b/src/DataTree.cc @@ -35,8 +35,7 @@ DataTree::DataTree(SymbolTable &symbol_table_arg, num_constants(num_constants_arg), external_functions_table(external_functions_table_arg), trend_component_model_table(trend_component_model_table_arg), - var_model_table(var_model_table_arg), - node_counter(0) + var_model_table(var_model_table_arg) { Zero = AddNonNegativeConstant("0"); One = AddNonNegativeConstant("1"); @@ -51,11 +50,7 @@ DataTree::DataTree(SymbolTable &symbol_table_arg, Pi = AddNonNegativeConstant("3.141592653589793"); } -DataTree::~DataTree() -{ - for (auto & it : node_list) - delete it; -} +DataTree::~DataTree() = default; expr_t DataTree::AddNonNegativeConstant(const string &value) @@ -65,8 +60,12 @@ DataTree::AddNonNegativeConstant(const string &value) auto it = num_const_node_map.find(id); if (it != num_const_node_map.end()) return it->second; - else - return new NumConstNode(*this, id); + + auto sp = make_unique<NumConstNode>(*this, node_list.size(), id); + auto p = sp.get(); + node_list.push_back(move(sp)); + num_const_node_map[id] = p; + return p; } VariableNode * @@ -75,8 +74,12 @@ DataTree::AddVariableInternal(int symb_id, int lag) auto it = variable_node_map.find({ symb_id, lag }); if (it != variable_node_map.end()) return it->second; - else - return new VariableNode(*this, symb_id, lag); + + auto sp = make_unique<VariableNode>(*this, node_list.size(), symb_id, lag); + auto p = sp.get(); + node_list.push_back(move(sp)); + variable_node_map[{ symb_id, lag }] = p; + return p; } bool @@ -515,7 +518,11 @@ DataTree::AddVarExpectation(const string &model_name) if (it != var_expectation_node_map.end()) return it->second; - return new VarExpectationNode(*this, model_name); + auto sp = make_unique<VarExpectationNode>(*this, node_list.size(), model_name); + auto p = sp.get(); + node_list.push_back(move(sp)); + var_expectation_node_map[model_name] = p; + return p; } expr_t @@ -525,7 +532,11 @@ DataTree::AddPacExpectation(const string &model_name) if (it != pac_expectation_node_map.end()) return it->second; - return new PacExpectationNode(*this, model_name); + auto sp = make_unique<PacExpectationNode>(*this, node_list.size(), model_name); + auto p = sp.get(); + node_list.push_back(move(sp)); + pac_expectation_node_map[model_name] = p; + return p; } expr_t @@ -557,7 +568,11 @@ DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments) if (it != external_function_node_map.end()) return it->second; - return new ExternalFunctionNode(*this, symb_id, arguments); + auto sp = make_unique<ExternalFunctionNode>(*this, node_list.size(), symb_id, arguments); + auto p = sp.get(); + node_list.push_back(move(sp)); + external_function_node_map[{ arguments, symb_id }] = p; + return p; } expr_t @@ -570,7 +585,11 @@ DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr if (it != first_deriv_external_function_node_map.end()) return it->second; - return new FirstDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index); + auto sp = make_unique<FirstDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index); + auto p = sp.get(); + node_list.push_back(move(sp)); + first_deriv_external_function_node_map[{ arguments, input_index, top_level_symb_id }] = p; + return p; } expr_t @@ -584,7 +603,11 @@ DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<exp if (it != second_deriv_external_function_node_map.end()) return it->second; - return new SecondDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index1, input_index2); + auto sp = make_unique<SecondDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index1, input_index2); + auto p = sp.get(); + node_list.push_back(move(sp)); + second_deriv_external_function_node_map[{ arguments, input_index1, input_index2, top_level_symb_id }] = p; + return p; } bool diff --git a/src/DataTree.hh b/src/DataTree.hh index 55a7c810..d84ca9df 100644 --- a/src/DataTree.hh +++ b/src/DataTree.hh @@ -24,7 +24,7 @@ using namespace std; #include <string> #include <map> -#include <list> +#include <vector> #include <sstream> #include <iomanip> #include <cmath> @@ -123,11 +123,8 @@ protected: private: const static int constants_precision{16}; - using node_list_t = list<expr_t>; //! The list of nodes - node_list_t node_list; - //! A counter for filling ExprNode's idx field - int node_counter; + vector<unique_ptr<ExprNode>> node_list; inline expr_t AddPossiblyNegativeConstant(double val); inline expr_t AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set = 0, int param1_symb_id = 0, int param2_symb_id = 0, const string &adl_param_name = "", const vector<int> &adl_lags = vector<int>()); @@ -371,7 +368,12 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int { } } - return new UnaryOpNode(*this, op_code, arg, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags); + + auto sp = make_unique<UnaryOpNode>(*this, node_list.size(), op_code, arg, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags); + auto p = sp.get(); + node_list.push_back(move(sp)); + unary_op_node_map[{ arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags }] = p; + return p; } inline expr_t @@ -392,7 +394,12 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD catch (ExprNode::EvalException &e) { } - return new BinaryOpNode(*this, arg1, op_code, arg2, powerDerivOrder); + + auto sp = make_unique<BinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, powerDerivOrder); + auto p = sp.get(); + node_list.push_back(move(sp)); + binary_op_node_map[{ arg1, arg2, op_code, powerDerivOrder }] = p; + return p; } inline expr_t @@ -414,7 +421,12 @@ DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t a catch (ExprNode::EvalException &e) { } - return new TrinaryOpNode(*this, arg1, op_code, arg2, arg3); + + auto sp = make_unique<TrinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, arg3); + auto p = sp.get(); + node_list.push_back(move(sp)); + trinary_op_node_map[{ arg1, arg2, arg3, op_code }] = p; + return p; } #endif diff --git a/src/ExprNode.cc b/src/ExprNode.cc index 80ca2741..42611a1f 100644 --- a/src/ExprNode.cc +++ b/src/ExprNode.cc @@ -30,13 +30,8 @@ #include "DataTree.hh" #include "ModFile.hh" -ExprNode::ExprNode(DataTree &datatree_arg) : datatree(datatree_arg), preparedForDerivation(false) +ExprNode::ExprNode(DataTree &datatree_arg, int idx_arg) : datatree{datatree_arg}, idx{idx_arg}, preparedForDerivation{false} { - // Add myself to datatree - datatree.node_list.push_back(this); - - // Set my index and increment counter - idx = datatree.node_counter++; } ExprNode::~ExprNode() @@ -321,12 +316,10 @@ ExprNode::getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const { } -NumConstNode::NumConstNode(DataTree &datatree_arg, int id_arg) : - ExprNode(datatree_arg), +NumConstNode::NumConstNode(DataTree &datatree_arg, int idx_arg, int id_arg) : + ExprNode(datatree_arg, idx_arg), id(id_arg) { - // Add myself to the num const map - datatree.num_const_node_map[id] = this; } int @@ -702,15 +695,12 @@ NumConstNode::substituteStaticAuxiliaryVariable() const return const_cast<NumConstNode *>(this); } -VariableNode::VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg) : - ExprNode(datatree_arg), +VariableNode::VariableNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, int lag_arg) : + ExprNode(datatree_arg, idx_arg), symb_id(symb_id_arg), type(datatree.symbol_table.getType(symb_id_arg)), lag(lag_arg) { - // Add myself to the variable map - datatree.variable_node_map[{ symb_id, lag }] = this; - // It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped assert(type != SymbolType::externalFunction && (lag == 0 || (type != SymbolType::modelLocalVariable && type != SymbolType::modFileLocalVariable))); @@ -1831,7 +1821,7 @@ VariableNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const return const_cast<VariableNode *>(this); map<int, expr_t>::const_iterator it = trend_symbols_map.find(symb_id); - expr_t noTrendLeadLagNode = new VariableNode(datatree, it->first, 0); + expr_t noTrendLeadLagNode = datatree.AddVariable(it->first); bool log_trend = get_type() == SymbolType::logTrend; expr_t trend = it->second; @@ -1938,8 +1928,8 @@ VariableNode::getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const model_endos_and_lags[varname] = lag; } -UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg) : - ExprNode(datatree_arg), +UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg) : + ExprNode(datatree_arg, idx_arg), arg(arg_arg), expectation_information_set(expectation_information_set_arg), param1_symb_id(param1_symb_id_arg), @@ -1948,8 +1938,6 @@ UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const adl_param_name(move(adl_param_name_arg)), 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; } void @@ -3573,27 +3561,15 @@ UnaryOpNode::substituteStaticAuxiliaryVariable() const return buildSimilarUnaryOpNode(argsubst, datatree); } -BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg, - BinaryOpcode op_code_arg, const expr_t arg2_arg) : - ExprNode(datatree_arg), - arg1(arg1_arg), - arg2(arg2_arg), - op_code(op_code_arg), - powerDerivOrder(0) -{ - datatree.binary_op_node_map[{ arg1, arg2, op_code, powerDerivOrder }] = this; -} - -BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg, +BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg, BinaryOpcode op_code_arg, const expr_t arg2_arg, int powerDerivOrder_arg) : - ExprNode(datatree_arg), + ExprNode(datatree_arg, idx_arg), arg1(arg1_arg), arg2(arg2_arg), op_code(op_code_arg), powerDerivOrder(powerDerivOrder_arg) { assert(powerDerivOrder >= 0); - datatree.binary_op_node_map[{ arg1, arg2, op_code, powerDerivOrder }] = this; } void @@ -5494,15 +5470,14 @@ BinaryOpNode::substituteStaticAuxiliaryDefinition() const return buildSimilarBinaryOpNode(arg1, arg2subst, datatree); } -TrinaryOpNode::TrinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg, +TrinaryOpNode::TrinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg, TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg) : - ExprNode(datatree_arg), + ExprNode(datatree_arg, idx_arg), arg1(arg1_arg), arg2(arg2_arg), arg3(arg3_arg), op_code(op_code_arg) { - datatree.trinary_op_node_map[{ arg1, arg2, arg3, op_code }] = this; } void @@ -6395,9 +6370,10 @@ TrinaryOpNode::substituteStaticAuxiliaryVariable() const } AbstractExternalFunctionNode::AbstractExternalFunctionNode(DataTree &datatree_arg, + int idx_arg, int symb_id_arg, vector<expr_t> arguments_arg) : - ExprNode(datatree_arg), + ExprNode(datatree_arg, idx_arg), symb_id(symb_id_arg), arguments(move(arguments_arg)) { @@ -7000,12 +6976,11 @@ AbstractExternalFunctionNode::substituteStaticAuxiliaryVariable() const } ExternalFunctionNode::ExternalFunctionNode(DataTree &datatree_arg, + int idx_arg, int symb_id_arg, const vector<expr_t> &arguments_arg) : - AbstractExternalFunctionNode(datatree_arg, symb_id_arg, arguments_arg) + AbstractExternalFunctionNode(datatree_arg, idx_arg, symb_id_arg, arguments_arg) { - // Add myself to the external function map - datatree.external_function_node_map[{ arguments, symb_id }] = this; } expr_t @@ -7321,14 +7296,13 @@ ExternalFunctionNode::sameTefTermPredicate() const } FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatree_arg, + int idx_arg, int top_level_symb_id_arg, const vector<expr_t> &arguments_arg, int inputIndex_arg) : - AbstractExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg), + AbstractExternalFunctionNode(datatree_arg, idx_arg, top_level_symb_id_arg, arguments_arg), inputIndex(inputIndex_arg) { - // Add myself to the first derivative external function map - datatree.first_deriv_external_function_node_map[{ arguments, inputIndex, symb_id }] = this; } void @@ -7705,16 +7679,15 @@ FirstDerivExternalFunctionNode::sameTefTermPredicate() const } SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datatree_arg, + int idx_arg, int top_level_symb_id_arg, const vector<expr_t> &arguments_arg, int inputIndex1_arg, int inputIndex2_arg) : - AbstractExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg), + AbstractExternalFunctionNode(datatree_arg, idx_arg, top_level_symb_id_arg, arguments_arg), inputIndex1(inputIndex1_arg), 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; } void @@ -8040,11 +8013,11 @@ SecondDerivExternalFunctionNode::sameTefTermPredicate() const } VarExpectationNode::VarExpectationNode(DataTree &datatree_arg, + int idx_arg, string model_name_arg) : - ExprNode(datatree_arg), + ExprNode(datatree_arg, idx_arg), model_name{move(model_name_arg)} { - datatree.var_expectation_node_map[model_name] = this; } void @@ -8485,11 +8458,11 @@ VarExpectationNode::writeJsonOutput(ostream &output, } PacExpectationNode::PacExpectationNode(DataTree &datatree_arg, + int idx_arg, string model_name_arg) : - ExprNode(datatree_arg), + ExprNode(datatree_arg, idx_arg), model_name(move(model_name_arg)) { - datatree.pac_expectation_node_map[model_name] = this; } void diff --git a/src/ExprNode.hh b/src/ExprNode.hh index a519d88a..62370cb4 100644 --- a/src/ExprNode.hh +++ b/src/ExprNode.hh @@ -153,7 +153,7 @@ class ExprNode DataTree &datatree; //! Index number - int idx; + const int idx; //! Is the data member non_null_derivatives initialized ? bool preparedForDerivation; @@ -190,7 +190,7 @@ class ExprNode const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs) const; public: - ExprNode(DataTree &datatree_arg); + ExprNode(DataTree &datatree_arg, int idx_arg); virtual ~ExprNode(); @@ -581,7 +581,7 @@ private: const int id; expr_t computeDerivative(int deriv_id) override; public: - NumConstNode(DataTree &datatree_arg, int id_arg); + NumConstNode(DataTree &datatree_arg, int idx_arg, int id_arg); int get_id() const { @@ -664,7 +664,7 @@ private: const int lag; expr_t computeDerivative(int deriv_id) override; public: - VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg); + VariableNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, int lag_arg); void prepareForDerivation() override; void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; @@ -771,7 +771,7 @@ private: //! Returns the derivative of this node if darg is the derivative of the argument expr_t composeDerivatives(expr_t darg, int deriv_id); public: - UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg); + UnaryOpNode(DataTree &datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg); void prepareForDerivation() override; void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, map<NodeTreeReference, temporary_terms_t> &temp_terms_map, @@ -890,9 +890,7 @@ private: const int powerDerivOrder; const string adlparam; public: - BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg, - BinaryOpcode op_code_arg, const expr_t arg2_arg); - BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg, + BinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg, BinaryOpcode op_code_arg, const expr_t arg2_arg, int powerDerivOrder); void prepareForDerivation() override; int precedenceJson(const temporary_terms_t &temporary_terms) const override; @@ -1042,7 +1040,7 @@ private: //! Returns the derivative of this node if darg1, darg2 and darg3 are the derivatives of the arguments expr_t composeDerivatives(expr_t darg1, expr_t darg2, expr_t darg3); public: - TrinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg, + TrinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg, TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg); void prepareForDerivation() override; int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override; @@ -1160,7 +1158,7 @@ protected: the same so-called "Tef" index) */ virtual function<bool (expr_t)> sameTefTermPredicate() const = 0; public: - AbstractExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg, + AbstractExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, vector<expr_t> arguments_arg); void prepareForDerivation() override; void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, @@ -1265,7 +1263,7 @@ private: protected: function<bool (expr_t)> sameTefTermPredicate() const override; public: - ExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg, + ExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, const vector<expr_t> &arguments_arg); void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override; @@ -1302,7 +1300,7 @@ private: protected: function<bool (expr_t)> sameTefTermPredicate() const override; public: - FirstDerivExternalFunctionNode(DataTree &datatree_arg, + FirstDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int top_level_symb_id_arg, const vector<expr_t> &arguments_arg, int inputIndex_arg); @@ -1345,7 +1343,7 @@ private: protected: function<bool (expr_t)> sameTefTermPredicate() const override; public: - SecondDerivExternalFunctionNode(DataTree &datatree_arg, + SecondDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int top_level_symb_id_arg, const vector<expr_t> &arguments_arg, int inputIndex1_arg, @@ -1385,7 +1383,7 @@ class VarExpectationNode : public ExprNode private: const string model_name; public: - VarExpectationNode(DataTree &datatree_arg, string model_name_arg); + VarExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name_arg); void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, map<NodeTreeReference, temporary_terms_t> &temp_terms_map, bool is_matlab, NodeTreeReference tr) const override; @@ -1481,7 +1479,7 @@ private: set<pair<int, pair<int, int>>> ar_params_and_vars; set<pair<int, pair<pair<int, int>, double>>> params_vars_and_scaling_factor; public: - PacExpectationNode(DataTree &datatree_arg, string model_name); + PacExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name); void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count, map<NodeTreeReference, temporary_terms_t> &temp_terms_map, bool is_matlab, NodeTreeReference tr) const override; -- GitLab