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
issue#70
Sébastien Villemot 2018-09-05 16:41:33 +02:00
parent 5d2e1cf7b9
commit 004d909621
4 changed files with 96 additions and 90 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;