Add copy constructors / assignment operators for the DataTree class hierarchy

In particular, it is necessary to turn back DataTree::AddVariable() into a
non-virtual method, because it is called from DataTree's constructor. Enforcing
the absence of leads/lags is now done using a new boolean DataTree::is_static.

Take advantage of the new copy constructor for handling
PlannerObjectiveStatement more elegantly.

Unfortunately it is not possible to implement *move* constructor / assigment
operators, because the reference ExprNode::datatree is not mutable.
issue#70
Sébastien Villemot 2018-10-09 18:27:19 +02:00
parent 215283005e
commit f2cf86b734
15 changed files with 670 additions and 93 deletions

View File

@ -2111,10 +2111,8 @@ ModelComparisonStatement::writeJsonOutput(ostream &output) const
output << "}";
}
PlannerObjectiveStatement::PlannerObjectiveStatement(SymbolTable &symbol_table,
NumericalConstants &num_constants,
ExternalFunctionsTable &external_functions_table) :
model_tree{symbol_table, num_constants, external_functions_table}
PlannerObjectiveStatement::PlannerObjectiveStatement(const StaticModel &model_tree_arg) :
model_tree {model_tree_arg}
{
}
@ -2132,8 +2130,8 @@ PlannerObjectiveStatement::checkPass(ModFileStructure &mod_file_struct, WarningC
mod_file_struct.planner_objective_present = true;
}
StaticModel &
PlannerObjectiveStatement::getPlannerObjective()
const StaticModel &
PlannerObjectiveStatement::getPlannerObjective() const
{
return model_tree;
}

View File

@ -523,9 +523,7 @@ private:
StaticModel model_tree;
bool computing_pass_called{false};
public:
PlannerObjectiveStatement(SymbolTable &symbol_table,
NumericalConstants &num_constants,
ExternalFunctionsTable &external_functions_table);
PlannerObjectiveStatement(const StaticModel &model_tree_arg);
/*! \todo check there are only endogenous variables at the current period in the objective
(no exogenous, no lead/lag) */
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
@ -534,7 +532,7 @@ public:
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
//! Return a reference the Planner Objective model tree
StaticModel &getPlannerObjective();
const StaticModel &getPlannerObjective() const;
};
class BVARDensityStatement : public Statement

View File

@ -26,12 +26,8 @@
#include "DataTree.hh"
DataTree::DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg) :
symbol_table{symbol_table_arg},
num_constants{num_constants_arg},
external_functions_table{external_functions_table_arg}
void
DataTree::initConstants()
{
Zero = AddNonNegativeConstant("0");
One = AddNonNegativeConstant("1");
@ -46,8 +42,76 @@ DataTree::DataTree(SymbolTable &symbol_table_arg,
Pi = AddNonNegativeConstant("3.141592653589793");
}
DataTree::DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
bool is_dynamic_arg) :
symbol_table{symbol_table_arg},
num_constants{num_constants_arg},
external_functions_table{external_functions_table_arg},
is_dynamic {is_dynamic_arg}
{
initConstants();
}
DataTree::~DataTree() = default;
DataTree::DataTree(const DataTree &d) :
symbol_table {d.symbol_table},
num_constants {d.num_constants},
external_functions_table {d.external_functions_table},
is_dynamic {d.is_dynamic},
local_variables_vector {d.local_variables_vector}
{
// Constants must be initialized first because they are used in some Add* methods
initConstants();
for (const auto & it : d.node_list)
it->cloneDynamic(*this);
assert(node_list.size() == d.node_list.size());
for (const auto & it : d.local_variables_table)
local_variables_table[it.first] = it.second->cloneDynamic(*this);
}
DataTree &
DataTree::operator=(const DataTree &d)
{
assert (&symbol_table == &d.symbol_table);
assert (&num_constants == &d.num_constants);
assert (&external_functions_table == &d.external_functions_table);
assert (is_dynamic == d.is_dynamic);
num_const_node_map.clear();
variable_node_map.clear();
unary_op_node_map.clear();
binary_op_node_map.clear();
trinary_op_node_map.clear();
external_function_node_map.clear();
var_expectation_node_map.clear();
pac_expectation_node_map.clear();
first_deriv_external_function_node_map.clear();
second_deriv_external_function_node_map.clear();
node_list.clear();
// Constants must be initialized first because they are used in some Add* methods
initConstants();
for (const auto & it : d.node_list)
it->cloneDynamic(*this);
assert(node_list.size() == d.node_list.size());
local_variables_vector = d.local_variables_vector;
for (const auto & it : d.local_variables_table)
local_variables_table[it.first] = it.second->cloneDynamic(*this);
return *this;
}
expr_t
DataTree::AddNonNegativeConstant(const string &value)
{
@ -65,8 +129,14 @@ DataTree::AddNonNegativeConstant(const string &value)
}
VariableNode *
DataTree::AddVariableInternal(int symb_id, int lag)
DataTree::AddVariable(int symb_id, int lag)
{
if (lag != 0 && !is_dynamic)
{
cerr << "Leads/lags not authorized in this DataTree" << endl;
exit(EXIT_FAILURE);
}
auto it = variable_node_map.find({ symb_id, lag });
if (it != variable_node_map.end())
return it->second;
@ -87,13 +157,6 @@ DataTree::ParamUsedWithLeadLagInternal() const
return false;
}
VariableNode *
DataTree::AddVariable(int symb_id, int lag)
{
assert(lag == 0);
return AddVariableInternal(symb_id, lag);
}
expr_t
DataTree::AddPlus(expr_t iArg1, expr_t iArg2)
{

View File

@ -45,6 +45,8 @@ public:
NumericalConstants &num_constants;
//! A reference to the external functions table
ExternalFunctionsTable &external_functions_table;
//! Is it possible to use leads/lags on variable nodes?
const bool is_dynamic;
protected:
//! num_constant_id -> NumConstNode
@ -92,9 +94,6 @@ protected:
//! Stores the order of appearance of local variables in the model block. Needed following change in #563
vector<int> local_variables_vector;
//! Internal implementation of AddVariable(), without the check on the lag
VariableNode *AddVariableInternal(int symb_id, int lag);
//! Internal implementation of ParamUsedWithLeadLag()
bool ParamUsedWithLeadLagInternal() const;
@ -115,17 +114,21 @@ private:
inline expr_t AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder = 0);
inline expr_t AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3);
//! Initializes the predefined constants, used only from the constructors
void initConstants();
public:
DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg);
ExternalFunctionsTable &external_functions_table_arg,
bool is_static_args = false);
virtual
~DataTree();
DataTree(const DataTree &) = delete;
DataTree(const DataTree &d);
DataTree(DataTree &&) = delete;
DataTree & operator=(const DataTree &) = delete;
DataTree & operator=(const DataTree &d);
DataTree & operator=(DataTree &&) = delete;
//! Some predefined constants
@ -149,8 +152,7 @@ public:
//! Adds a non-negative numerical constant (possibly Inf or NaN)
expr_t AddNonNegativeConstant(const string &value);
//! Adds a variable
/*! The default implementation of the method refuses any lag != 0 */
virtual VariableNode *AddVariable(int symb_id, int lag = 0);
VariableNode *AddVariable(int symb_id, int lag = 0);
//! Adds "arg1+arg2" to model tree
expr_t AddPlus(expr_t iArg1, expr_t iArg2);
//! Adds "arg1-arg2" to model tree

View File

@ -31,21 +31,217 @@
#include "DynamicModel.hh"
void
DynamicModel::copyHelper(const DynamicModel &m)
{
auto f = [this](const ExprNode *e) { return e->cloneDynamic(*this); };
for (const auto &it : m.static_only_equations)
static_only_equations.push_back(dynamic_cast<BinaryOpNode *>(f(it)));
auto convert_vector_tt = [this,f](vector<temporary_terms_t> vtt)
{
vector<temporary_terms_t> vtt2;
for (const auto &tt : vtt)
{
temporary_terms_t tt2;
for (const auto &it : tt)
tt2.insert(f(it));
vtt2.push_back(tt2);
}
return vtt2;
};
for (const auto &it : m.v_temporary_terms)
v_temporary_terms.push_back(convert_vector_tt(it));
for (const auto &it : m.first_chain_rule_derivatives)
first_chain_rule_derivatives[it.first] = f(it.second);
for (const auto &it : m.equation_type_and_normalized_equation)
equation_type_and_normalized_equation.push_back(make_pair(it.first, f(it.second)));
for (const auto &it : m.blocks_derivatives)
{
block_derivatives_equation_variable_laglead_nodeid_t v;
for (const auto &it2 : it)
v.push_back(make_pair(it2.first, make_pair(it2.second.first, f(it2.second.second))));
blocks_derivatives.push_back(v);
}
for (const auto &it : m.dynamic_jacobian)
dynamic_jacobian[it.first] = f(it.second);
auto convert_derivative_t = [this,f](derivative_t dt)
{
derivative_t dt2;
for (const auto &it : dt)
dt2[it.first] = f(it.second);
return dt2;
};
for (const auto &it : m.derivative_endo)
derivative_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_other_endo)
derivative_other_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo)
derivative_exo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo_det)
derivative_exo_det.push_back(convert_derivative_t(it));
for (const auto &it : m.pac_expectation_info)
pac_expectation_info.insert(dynamic_cast<const PacExpectationNode *>(f(it)));
}
DynamicModel::DynamicModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
TrendComponentModelTable &trend_component_model_table_arg,
VarModelTable &var_model_table_arg) :
ModelTree{symbol_table_arg, num_constants_arg, external_functions_table_arg},
ModelTree {symbol_table_arg, num_constants_arg, external_functions_table_arg, true},
trend_component_model_table{trend_component_model_table_arg},
var_model_table{var_model_table_arg}
{
}
VariableNode *
DynamicModel::AddVariable(int symb_id, int lag)
DynamicModel::DynamicModel(const DynamicModel &m) :
ModelTree {m},
trend_component_model_table {m.trend_component_model_table},
var_model_table {m.var_model_table},
static_only_equations_lineno {m.static_only_equations_lineno},
static_only_equations_equation_tags {m.static_only_equations_equation_tags},
deriv_id_table {m.deriv_id_table},
inv_deriv_id_table {m.inv_deriv_id_table},
dyn_jacobian_cols_table {m.dyn_jacobian_cols_table},
max_lag {m.max_lag},
max_lead {m.max_lead},
max_endo_lag {m.max_endo_lag},
max_endo_lead {m.max_endo_lead},
max_exo_lag {m.max_exo_lag},
max_exo_lead {m.max_exo_lead},
max_exo_det_lag {m.max_exo_det_lag},
max_exo_det_lead {m.max_exo_det_lead},
max_lag_orig {m.max_lag_orig},
max_lead_orig {m.max_lead_orig},
max_endo_lag_orig {m.max_endo_lag_orig},
max_endo_lead_orig {m.max_endo_lead_orig},
max_exo_lag_orig {m.max_exo_lag_orig},
max_exo_lead_orig {m.max_exo_lead_orig},
max_exo_det_lag_orig {m.max_exo_det_lag_orig},
max_exo_det_lead_orig {m.max_exo_det_lead_orig},
xrefs {m.xrefs},
xref_param {m.xref_param},
xref_endo {m.xref_endo},
xref_exo {m.xref_exo},
xref_exo_det {m.xref_exo_det},
nonzero_hessian_eqs {m.nonzero_hessian_eqs},
v_temporary_terms_inuse {m.v_temporary_terms_inuse},
map_idx {m.map_idx},
global_temporary_terms {m.global_temporary_terms},
block_type_firstequation_size_mfs {m.block_type_firstequation_size_mfs},
blocks_linear {m.blocks_linear},
other_endo_block {m.other_endo_block},
exo_block {m.exo_block},
exo_det_block {m.exo_det_block},
block_var_exo {m.block_var_exo},
block_exo_index {m.block_exo_index},
block_det_exo_index {m.block_det_exo_index},
block_other_endo_index {m.block_other_endo_index},
block_col_type {m.block_col_type},
variable_block_lead_lag {m.variable_block_lead_lag},
equation_block {m.equation_block},
var_expectation_functions_to_write {m.var_expectation_functions_to_write},
endo_max_leadlag_block {m.endo_max_leadlag_block},
other_endo_max_leadlag_block {m.other_endo_max_leadlag_block},
exo_max_leadlag_block {m.exo_max_leadlag_block},
exo_det_max_leadlag_block {m.exo_det_max_leadlag_block},
max_leadlag_block {m.max_leadlag_block}
{
return AddVariableInternal(symb_id, lag);
copyHelper(m);
}
DynamicModel &
DynamicModel::operator=(const DynamicModel &m)
{
ModelTree::operator=(m);
assert(&trend_component_model_table == &m.trend_component_model_table);
assert(&var_model_table == &m.var_model_table);
static_only_equations_lineno = m.static_only_equations_lineno;
static_only_equations_equation_tags = m.static_only_equations_equation_tags;
deriv_id_table = m.deriv_id_table;
inv_deriv_id_table = m.inv_deriv_id_table;
dyn_jacobian_cols_table = m.dyn_jacobian_cols_table;
max_lag = m.max_lag;
max_lead = m.max_lead;
max_endo_lag = m.max_endo_lag;
max_endo_lead = m.max_endo_lead;
max_exo_lag = m.max_exo_lag;
max_exo_lead = m.max_exo_lead;
max_exo_det_lag = m.max_exo_det_lag;
max_exo_det_lead = m.max_exo_det_lead;
max_lag_orig = m.max_lag_orig;
max_lead_orig = m.max_lead_orig;
max_endo_lag_orig = m.max_endo_lag_orig;
max_endo_lead_orig = m.max_endo_lead_orig;
max_exo_lag_orig = m.max_exo_lag_orig;
max_exo_lead_orig = m.max_exo_lead_orig;
max_exo_det_lag_orig = m.max_exo_det_lag_orig;
max_exo_det_lead_orig = m.max_exo_det_lead_orig;
xrefs = m.xrefs;
xref_param = m.xref_param;
xref_endo = m.xref_endo;
xref_exo = m.xref_exo;
xref_exo_det = m.xref_exo_det;
nonzero_hessian_eqs = m.nonzero_hessian_eqs;
v_temporary_terms.clear();
v_temporary_terms_inuse = m.v_temporary_terms_inuse;
first_chain_rule_derivatives.clear();
map_idx = m.map_idx;
global_temporary_terms = m.global_temporary_terms;
equation_type_and_normalized_equation.clear();
block_type_firstequation_size_mfs = m.block_type_firstequation_size_mfs;
blocks_derivatives.clear();
dynamic_jacobian.clear();
blocks_linear = m.blocks_linear;
derivative_endo.clear();
derivative_other_endo.clear();
derivative_exo.clear();
derivative_exo_det.clear();
other_endo_block = m.other_endo_block;
exo_block = m.exo_block;
exo_det_block = m.exo_det_block;
block_var_exo = m.block_var_exo;
block_exo_index = m.block_exo_index;
block_det_exo_index = m.block_det_exo_index;
block_other_endo_index = m.block_other_endo_index;
block_col_type = m.block_col_type;
variable_block_lead_lag = m.variable_block_lead_lag;
equation_block = m.equation_block;
var_expectation_functions_to_write = m.var_expectation_functions_to_write;
pac_expectation_info.clear();
endo_max_leadlag_block = m.endo_max_leadlag_block;
other_endo_max_leadlag_block = m.other_endo_max_leadlag_block;
exo_max_leadlag_block = m.exo_max_leadlag_block;
exo_det_max_leadlag_block = m.exo_det_max_leadlag_block;
max_leadlag_block = m.max_leadlag_block;
copyHelper(m);
return *this;
}
void
@ -4827,40 +5023,6 @@ DynamicModel::writeAuxVarRecursiveDefinitions(ostream &output, ExprNodeOutputTyp
}
}
void
DynamicModel::cloneDynamic(DynamicModel &dynamic_model) const
{
/* Ensure that we are using the same symbol table, because at many places we manipulate
symbol IDs rather than strings */
assert(&symbol_table == &dynamic_model.symbol_table);
// Convert model local variables (need to be done first)
for (int it : local_variables_vector)
dynamic_model.AddLocalVariable(it, local_variables_table.find(it)->second->cloneDynamic(dynamic_model));
// Convert equations
for (size_t i = 0; i < equations.size(); i++)
{
vector<pair<string, string>> eq_tags;
for (const auto & equation_tag : equation_tags)
if (equation_tag.first == (int)i)
eq_tags.push_back(equation_tag.second);
dynamic_model.addEquation(equations[i]->cloneDynamic(dynamic_model), equations_lineno[i], eq_tags);
}
// Convert auxiliary equations
for (auto aux_equation : aux_equations)
dynamic_model.addAuxEquation(aux_equation->cloneDynamic(dynamic_model));
// Convert static_only equations
for (size_t i = 0; i < static_only_equations.size(); i++)
dynamic_model.addStaticOnlyEquation(static_only_equations[i]->cloneDynamic(dynamic_model),
static_only_equations_lineno[i],
static_only_equations_equation_tags[i]);
dynamic_model.setLeadsLagsOrig();
}
void
DynamicModel::replaceMyEquations(DynamicModel &dynamic_model) const
{

View File

@ -254,15 +254,22 @@ private:
void findPacExpectationEquationNumbers(vector<int> &eqnumber) const;
//! Internal helper for the copy constructor and assignment operator
/*! Copies all the structures that contain ExprNode*, by the converting the
pointers into their equivalent in the new tree */
void copyHelper(const DynamicModel &m);
public:
DynamicModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
TrendComponentModelTable &trend_component_model_table_arg,
VarModelTable &var_model_table_arg);
//! Adds a variable node
/*! This implementation allows for non-zero lag */
VariableNode *AddVariable(int symb_id, int lag = 0) override;
DynamicModel(const DynamicModel &m);
DynamicModel(DynamicModel &&) = delete;
DynamicModel & operator=(const DynamicModel &m);
DynamicModel & operator=(DynamicModel &&) = delete;
//! Compute cross references
void computeXrefs();
@ -374,10 +381,6 @@ public:
//! Set the max leads/lags of the original model
void setLeadsLagsOrig();
//! Copies a dynamic model (only the equations)
/*! It assumes that the dynamic model given in argument has just been allocated */
void cloneDynamic(DynamicModel &dynamic_model) const;
//! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous
void computeRamseyPolicyFOCs(const StaticModel &static_model, const bool nopreprocessoroutput);
//! Replaces the model equations in dynamic_model with those in this model

View File

@ -367,7 +367,7 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
// - except adl and diff which we always want expanded
dynamic_model.substituteAdl();
dynamic_model.setLeadsLagsOrig();
dynamic_model.cloneDynamic(original_model);
original_model = dynamic_model;
if (nostrict)
{
@ -457,7 +457,7 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
if (nonstationary_variables)
{
dynamic_model.detrendEquations();
dynamic_model.cloneDynamic(trend_dynamic_model);
trend_dynamic_model = dynamic_model;
dynamic_model.removeTrendVariableFromEquations();
}
@ -485,8 +485,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
we have to call computeDerivIDs (in computeRamseyPolicyFOCs and computingPass)
*/
if (linear)
dynamic_model.cloneDynamic(orig_ramsey_dynamic_model);
dynamic_model.cloneDynamic(ramsey_FOC_equations_dynamic_model);
orig_ramsey_dynamic_model = dynamic_model;
ramsey_FOC_equations_dynamic_model = dynamic_model;
ramsey_FOC_equations_dynamic_model.computeRamseyPolicyFOCs(planner_objective, nopreprocessoroutput);
ramsey_FOC_equations_dynamic_model.replaceMyEquations(dynamic_model);
mod_file_struct.ramsey_eq_nbr = dynamic_model.equation_number() - mod_file_struct.orig_eq_nbr;
@ -696,7 +696,7 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output, int params_deri
dynamic_model.toStatic(static_model);
if (linear_decomposition)
{
dynamic_model.cloneDynamic(non_linear_equations_dynamic_model);
non_linear_equations_dynamic_model = dynamic_model;
non_linear_equations_dynamic_model.set_cutoff_to_zero();
non_linear_equations_dynamic_model.computingPass(true, false, false, 0, global_eval_context, no_tmp_terms, block, use_dll, byte_code, nopreprocessoroutput, linear_decomposition);
}

View File

@ -31,6 +31,28 @@ SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg,
{
}
SteadyStateModel::SteadyStateModel(const SteadyStateModel &m) :
DataTree {m},
static_model {m.static_model}
{
for (const auto &it : m.def_table)
def_table.push_back(make_pair(it.first, it.second->cloneDynamic(*this)));
}
SteadyStateModel &
SteadyStateModel::operator=(const SteadyStateModel &m)
{
DataTree::operator=(m);
assert(&static_model == &m.static_model);
def_table.clear();
for (const auto &it : m.def_table)
def_table.push_back(make_pair(it.first, it.second->cloneDynamic(*this)));
return *this;
}
void
SteadyStateModel::addDefinition(int symb_id, expr_t expr)
{
@ -277,6 +299,30 @@ Epilogue::Epilogue(SymbolTable &symbol_table_arg,
{
}
Epilogue::Epilogue(const Epilogue &m) :
DynamicModel {m},
endogs {m.endogs},
exogs {m.exogs}
{
for (const auto &it : m.def_table)
def_table.push_back(make_pair(it.first, it.second->cloneDynamic(*this)));
}
Epilogue &
Epilogue::operator=(const Epilogue &m)
{
DynamicModel::operator=(m);
endogs = m.endogs;
exogs = m.exogs;
def_table.clear();
for (const auto &it : m.def_table)
def_table.push_back(make_pair(it.first, it.second->cloneDynamic(*this)));
return *this;
}
void
Epilogue::addDefinition(int symb_id, expr_t expr)
{

View File

@ -40,6 +40,12 @@ public:
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
const StaticModel &static_model_arg);
SteadyStateModel(const SteadyStateModel &m);
SteadyStateModel(SteadyStateModel &&) = delete;
SteadyStateModel & operator=(const SteadyStateModel &m);
SteadyStateModel & operator=(SteadyStateModel &&) = delete;
//! Add an expression of the form "var = expr;"
void addDefinition(int symb_id, expr_t expr);
//! Add an expression of the form "[ var1, var2, ... ] = expr;"
@ -76,6 +82,11 @@ public:
TrendComponentModelTable &trend_component_model_table_arg,
VarModelTable &var_model_table_arg);
Epilogue(const Epilogue &m);
Epilogue(Epilogue &&) = delete;
Epilogue & operator=(const Epilogue &m);
Epilogue & operator=(Epilogue &&) = delete;
//! Add an expression of the form "var = expr;"
void addDefinition(int symb_id, expr_t expr);

View File

@ -32,6 +32,148 @@
using namespace MFS;
void
ModelTree::copyHelper(const ModelTree &m)
{
auto f = [this](expr_t e) { return e->cloneDynamic(*this); };
// Equations
for (const auto & it : m.equations)
equations.push_back(dynamic_cast<BinaryOpNode *>(f(it)));
for (const auto & it : m.aux_equations)
aux_equations.push_back(dynamic_cast<BinaryOpNode *>(f(it)));
// Derivatives
for (const auto & it : m.first_derivatives)
first_derivatives[it.first] = f(it.second);
for (const auto & it : m.second_derivatives)
second_derivatives[it.first] = f(it.second);
for (const auto & it : m.third_derivatives)
third_derivatives[it.first] = f(it.second);
for (const auto & it : m.residuals_params_derivatives)
residuals_params_derivatives[it.first] = f(it.second);
for (const auto & it : m.residuals_params_second_derivatives)
residuals_params_second_derivatives[it.first] = f(it.second);
for (const auto & it : m.jacobian_params_derivatives)
jacobian_params_derivatives[it.first] = f(it.second);
for (const auto & it : m.jacobian_params_second_derivatives)
jacobian_params_second_derivatives[it.first] = f(it.second);
for (const auto & it : m.hessian_params_derivatives)
hessian_params_derivatives[it.first] = f(it.second);
// Temporary terms
for (const auto & it : m.temporary_terms)
temporary_terms.insert(f(it));
for (const auto & it : m.temporary_terms_mlv)
temporary_terms_mlv[f(it.first)] = f(it.second);
for (const auto & it : m.temporary_terms_res)
temporary_terms_res.insert(f(it));
for (const auto & it : m.temporary_terms_g1)
temporary_terms_g1.insert(f(it));
for (const auto & it : m.temporary_terms_g2)
temporary_terms_g2.insert(f(it));
for (const auto & it : m.temporary_terms_g3)
temporary_terms_g3.insert(f(it));
for (const auto & it : m.temporary_terms_idxs)
temporary_terms_idxs[f(it.first)] = it.second;
for (const auto & it : m.params_derivs_temporary_terms)
params_derivs_temporary_terms.insert(f(it));
for (const auto & it : m.params_derivs_temporary_terms_res)
params_derivs_temporary_terms_res.insert(f(it));
for (const auto & it : m.params_derivs_temporary_terms_g1)
params_derivs_temporary_terms_g1.insert(f(it));
for (const auto & it : m.params_derivs_temporary_terms_res2)
params_derivs_temporary_terms_res2.insert(f(it));
for (const auto & it : m.params_derivs_temporary_terms_g12)
params_derivs_temporary_terms_g12.insert(f(it));
for (const auto & it : m.params_derivs_temporary_terms_g2)
params_derivs_temporary_terms_g2.insert(f(it));
for (const auto & it : m.params_derivs_temporary_terms_idxs)
params_derivs_temporary_terms_idxs[f(it.first)] = it.second;
// Other stuff
for (const auto & it : m.trend_symbols_map)
trend_symbols_map[it.first] = f(it.second);
for (const auto & it : m.nonstationary_symbols_map)
nonstationary_symbols_map[it.first] = make_pair(it.second.first, f(it.second.second));
}
ModelTree::ModelTree(const ModelTree &m) :
DataTree {m},
equations_lineno {m.equations_lineno},
equation_tags {m.equation_tags},
NNZDerivatives {m.NNZDerivatives},
equation_reordered {m.equation_reordered},
variable_reordered {m.variable_reordered},
inv_equation_reordered {m.inv_equation_reordered},
inv_variable_reordered {m.inv_variable_reordered},
is_equation_linear {m.is_equation_linear},
endo2eq {m.endo2eq},
epilogue {m.epilogue},
prologue {m.prologue},
block_lag_lead {m.block_lag_lead},
cutoff {m.cutoff},
mfs {m.mfs}
{
copyHelper(m);
}
ModelTree &
ModelTree::operator=(const ModelTree &m)
{
DataTree::operator=(m);
equations.clear();
equations_lineno = m.equations_lineno;
aux_equations.clear();
equation_tags = m.equation_tags;
NNZDerivatives = m.NNZDerivatives;
first_derivatives.clear();
second_derivatives.clear();
third_derivatives.clear();
residuals_params_derivatives.clear();
residuals_params_second_derivatives.clear();
jacobian_params_derivatives.clear();
jacobian_params_second_derivatives.clear();
hessian_params_derivatives.clear();
temporary_terms.clear();
temporary_terms_mlv.clear();
temporary_terms_res.clear();
temporary_terms_g1.clear();
temporary_terms_g2.clear();
temporary_terms_g3.clear();
temporary_terms_idxs.clear();
params_derivs_temporary_terms.clear();
params_derivs_temporary_terms_res.clear();
params_derivs_temporary_terms_g1.clear();
params_derivs_temporary_terms_res2.clear();
params_derivs_temporary_terms_g12.clear();
params_derivs_temporary_terms_g2.clear();
params_derivs_temporary_terms_idxs.clear();
trend_symbols_map.clear();
nonstationary_symbols_map.clear();
equation_reordered = m.equation_reordered;
variable_reordered = m.variable_reordered;
inv_equation_reordered = m.inv_equation_reordered;
inv_variable_reordered = m.inv_variable_reordered;
is_equation_linear = m.is_equation_linear;
endo2eq = m.endo2eq;
epilogue = m.epilogue;
prologue = m.prologue;
block_lag_lead = m.block_lag_lead;
cutoff = m.cutoff;
mfs = m.mfs;
copyHelper(m);
return *this;
}
bool
ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool verbose)
{
@ -1133,8 +1275,9 @@ ModelTree::BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vec
ModelTree::ModelTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg) :
DataTree{symbol_table_arg, num_constants_arg, external_functions_table_arg}
ExternalFunctionsTable &external_functions_table_arg,
bool is_dynamic_arg) :
DataTree {symbol_table_arg, num_constants_arg, external_functions_table_arg, is_dynamic_arg}
{
for (int & NNZDerivative : NNZDerivatives)
NNZDerivative = 0;

View File

@ -74,7 +74,7 @@ protected:
vector<pair<int, pair<string, string>>> equation_tags;
//! Number of non-zero derivatives
int NNZDerivatives[3];
array<int, 3> NNZDerivatives;
using first_derivatives_t = map<pair<int, int>, expr_t>;
//! First order derivatives
@ -331,10 +331,24 @@ protected:
virtual int getBlockInitialOtherEndogenousID(int block_number, int variable_number) const = 0;
//! Initialize equation_reordered & variable_reordered
void initializeVariablesAndEquations();
private:
//! Internal helper for the copy constructor and assignment operator
/*! Copies all the structures that contain ExprNode*, by the converting the
pointers into their equivalent in the new tree */
void copyHelper(const ModelTree &m);
public:
ModelTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg);
ExternalFunctionsTable &external_functions_table_arg,
bool is_dynamic_arg = false);
ModelTree(const ModelTree &m);
ModelTree(ModelTree &&) = delete;
ModelTree & operator=(const ModelTree &m);
ModelTree & operator=(ModelTree &&) = delete;
//! Absolute value under which a number is considered to be zero
double cutoff{1e-15};
//! Compute the minimum feedback set

View File

@ -2132,10 +2132,10 @@ ParsingDriver::run_model_comparison()
void
ParsingDriver::begin_planner_objective()
{
planner_objective_statement = make_unique<PlannerObjectiveStatement>(mod_file->symbol_table,
mod_file->num_constants,
mod_file->external_functions_table);
set_current_data_tree(&planner_objective_statement->getPlannerObjective());
planner_objective = make_unique<StaticModel>(mod_file->symbol_table,
mod_file->num_constants,
mod_file->external_functions_table);
set_current_data_tree(planner_objective.get());
}
void
@ -2145,7 +2145,7 @@ ParsingDriver::end_planner_objective(expr_t expr)
expr_t eq = model_tree->AddEqual(expr, model_tree->Zero);
model_tree->addEquation(eq, location.begin.line);
mod_file->addStatement(move(planner_objective_statement));
mod_file->addStatement(make_unique<PlannerObjectiveStatement>(*planner_objective));
reset_data_tree();
}

View File

@ -119,7 +119,7 @@ private:
SymbolList symbol_list;
//! Temporary store for the planner objective
unique_ptr<PlannerObjectiveStatement> planner_objective_statement;
unique_ptr<StaticModel> planner_objective;
//! The data tree in which to add expressions currently parsed
/*! The object pointed to is not owned by the parsing driver. It is essentially a

View File

@ -29,6 +29,63 @@
#include "StaticModel.hh"
void
StaticModel::copyHelper(const StaticModel &m)
{
auto f = [this](expr_t e) { return e->cloneDynamic(*this); };
auto convert_vector_tt = [this,f](vector<temporary_terms_t> vtt)
{
vector<temporary_terms_t> vtt2;
for (const auto &tt : vtt)
{
temporary_terms_t tt2;
for (const auto &it : tt)
tt2.insert(f(it));
vtt2.push_back(tt2);
}
return vtt2;
};
for (const auto &it : m.v_temporary_terms)
v_temporary_terms.push_back(convert_vector_tt(it));
for (const auto &it : m.v_temporary_terms_local)
v_temporary_terms_local.push_back(convert_vector_tt(it));
for (const auto &it : m.first_chain_rule_derivatives)
first_chain_rule_derivatives[it.first] = f(it.second);
for (const auto &it : m.equation_type_and_normalized_equation)
equation_type_and_normalized_equation.push_back(make_pair(it.first, f(it.second)));
for (const auto &it : m.blocks_derivatives)
{
block_derivatives_equation_variable_laglead_nodeid_t v;
for (const auto &it2 : it)
v.push_back(make_pair(it2.first, make_pair(it2.second.first, f(it2.second.second))));
blocks_derivatives.push_back(v);
}
for (const auto &it : m.dynamic_jacobian)
dynamic_jacobian[it.first] = f(it.second);
auto convert_derivative_t = [this,f](derivative_t dt)
{
derivative_t dt2;
for (const auto &it : dt)
dt2[it.first] = f(it.second);
return dt2;
};
for (const auto &it : m.derivative_endo)
derivative_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_other_endo)
derivative_other_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo)
derivative_exo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo_det)
derivative_exo_det.push_back(convert_derivative_t(it));
}
StaticModel::StaticModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg) :
@ -36,6 +93,76 @@ StaticModel::StaticModel(SymbolTable &symbol_table_arg,
{
}
StaticModel::StaticModel(const StaticModel &m) :
ModelTree {m},
v_temporary_terms_inuse {m.v_temporary_terms_inuse},
map_idx {m.map_idx},
map_idx2 {m.map_idx2},
global_temporary_terms {m.global_temporary_terms},
block_type_firstequation_size_mfs {m.block_type_firstequation_size_mfs},
blocks_linear {m.blocks_linear},
other_endo_block {m.other_endo_block},
exo_block {m.exo_block},
exo_det_block {m.exo_det_block},
block_col_type {m.block_col_type},
variable_block_lead_lag {m.variable_block_lead_lag},
equation_block {m.equation_block},
endo_max_leadlag_block {m.endo_max_leadlag_block},
other_endo_max_leadlag_block {m.other_endo_max_leadlag_block},
exo_max_leadlag_block {m.exo_max_leadlag_block},
exo_det_max_leadlag_block {m.exo_det_max_leadlag_block},
max_leadlag_block {m.max_leadlag_block}
{
copyHelper(m);
}
StaticModel &
StaticModel::operator=(const StaticModel &m)
{
ModelTree::operator=(m);
v_temporary_terms.clear();
v_temporary_terms_local.clear();
v_temporary_terms_inuse = m.v_temporary_terms_inuse;
first_chain_rule_derivatives.clear();
map_idx = m.map_idx;
map_idx2 = m.map_idx2;
global_temporary_terms = m.global_temporary_terms;
equation_type_and_normalized_equation.clear();
block_type_firstequation_size_mfs = m.block_type_firstequation_size_mfs;
blocks_derivatives.clear();
dynamic_jacobian.clear();
blocks_linear = m.blocks_linear;
derivative_endo.clear();
derivative_other_endo.clear();
derivative_exo.clear();
derivative_exo_det.clear();
other_endo_block = m.other_endo_block;
exo_block = m.exo_block;
exo_det_block = m.exo_det_block;
block_col_type = m.block_col_type;
variable_block_lead_lag = m.variable_block_lead_lag;
equation_block = m.equation_block;
endo_max_leadlag_block = m.endo_max_leadlag_block;
other_endo_max_leadlag_block = m.other_endo_max_leadlag_block;
exo_max_leadlag_block = m.exo_max_leadlag_block;
exo_det_max_leadlag_block = m.exo_det_max_leadlag_block;
max_leadlag_block = m.max_leadlag_block;
copyHelper(m);
return *this;
}
void
StaticModel::compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, map_idx_t &map_idx, temporary_terms_t temporary_terms) const
{

View File

@ -104,7 +104,6 @@ private:
//! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
void collect_block_first_order_derivatives();
protected:
//! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
bool global_temporary_terms{true};
@ -159,11 +158,22 @@ protected:
void writeStaticModel(ostream &DynamicOutput, bool use_dll, bool julia) const;
void writeStaticModel(const string &dynamic_basename, bool use_dll, bool julia) const;
//! Internal helper for the copy constructor and assignment operator
/*! Copies all the structures that contain ExprNode*, by the converting the
pointers into their equivalent in the new tree */
void copyHelper(const StaticModel &m);
public:
StaticModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants,
ExternalFunctionsTable &external_functions_table_arg);
StaticModel(const StaticModel &m);
StaticModel(StaticModel &&) = delete;
StaticModel & operator=(const StaticModel &m);
StaticModel & operator=(StaticModel &&) = delete;
//! Writes information on block decomposition when relevant
void writeOutput(ostream &output, bool block) const;