pac_model: allow diff as argument to growth option

issue#70
Houtan Bastani 2019-02-28 19:22:34 +01:00
parent 5f013756f2
commit 341b9c6667
No known key found for this signature in database
GPG Key ID: 000094FB955BE169
9 changed files with 106 additions and 54 deletions

View File

@ -260,46 +260,78 @@ PriorPosteriorFunctionStatement::writeJsonOutput(ostream &output) const
PacModelStatement::PacModelStatement(string name_arg,
string aux_model_name_arg,
string discount_arg,
int growth_symb_id_arg,
int growth_lag_arg,
expr_t growth_arg,
double steady_state_growth_rate_number_arg,
int steady_state_growth_rate_symb_id_arg,
const SymbolTable &symbol_table_arg) :
name{move(name_arg)},
aux_model_name{move(aux_model_name_arg)},
discount{move(discount_arg)},
growth_symb_id{growth_symb_id_arg},
growth_lag{growth_lag_arg},
growth{growth_arg},
steady_state_growth_rate_number{steady_state_growth_rate_number_arg},
steady_state_growth_rate_symb_id{steady_state_growth_rate_symb_id_arg},
symbol_table{symbol_table_arg}
{
growth_symb_id = -1;
growth_lag = 0;
}
void
PacModelStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
mod_file_struct.pac_params.insert(symbol_table.getID(discount));
if (growth_symb_id >= 0)
if (growth == nullptr)
return;
VariableNode *vn = dynamic_cast<VariableNode *>(growth);
if (vn != nullptr)
{
switch (symbol_table.getType(growth_symb_id))
{
case SymbolType::endogenous:
case SymbolType::exogenous:
case SymbolType::parameter:
break;
default:
mod_file_struct.pac_params.insert(vn->symb_id);
mod_file_struct.pac_params.insert(vn->lag);
}
UnaryOpNode *uon = dynamic_cast<UnaryOpNode *>(growth);
if (uon != nullptr)
if (uon->op_code == UnaryOpcode::diff)
{
VariableNode *uonvn = dynamic_cast<VariableNode *>(uon->arg);
UnaryOpNode *uon1 = dynamic_cast<UnaryOpNode *>(uon->arg);
while (uonvn == nullptr && uon1 != nullptr)
{
cerr << "ERROR: The Expression passed to the growth option of pac_model must be an "
<< "endogenous (lagged or not), exogenous (lagged or not), or parameter" << endl;
uonvn = dynamic_cast<VariableNode *>(uon1->arg);
uon1 = dynamic_cast<UnaryOpNode *>(uon1->arg);
}
if (uonvn == nullptr)
{
cerr << "Pac growth parameter must be either a variable or a diff unary op of a variable" << endl;
exit(EXIT_FAILURE);
}
}
mod_file_struct.pac_params.insert(growth_symb_id);
mod_file_struct.pac_params.insert(growth_lag);
mod_file_struct.pac_params.insert(uonvn->symb_id);
mod_file_struct.pac_params.insert(uonvn->lag);
}
if (vn == nullptr && uon == nullptr)
{
cerr << "Pac growth parameter must be either a variable or a diff unary op of a variable" << endl;
exit(EXIT_FAILURE);
}
}
void
PacModelStatement::overwriteGrowth(expr_t new_growth)
{
if (new_growth == nullptr || growth == nullptr)
return;
growth = new_growth;
VariableNode *vn = dynamic_cast<VariableNode *>(growth);
if (vn == nullptr)
{
cerr << "PacModelStatement::overwriteGrowth: Internal Dynare error: should not arrive here" << endl;
}
growth_symb_id = vn->symb_id;
growth_lag = vn->lag;
}
void
PacModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{

View File

@ -138,22 +138,23 @@ class PacModelStatement : public Statement
{
public:
const string name, aux_model_name, discount;
const int growth_symb_id, growth_lag;
expr_t growth;
private:
const double steady_state_growth_rate_number;
const int steady_state_growth_rate_symb_id;
const SymbolTable &symbol_table;
vector<int> lhs;
public:
int growth_symb_id;
int growth_lag;
PacModelStatement(string name_arg,
string aux_model_name_arg,
string discount_arg,
int growth_symb_id_arg,
int growth_lag_arg,
expr_t growth_arg,
double steady_state_growth_rate_number_arg,
int steady_state_growth_rate_symb_id_arg,
const SymbolTable &symbol_table_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void overwriteGrowth(expr_t new_growth);
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
};

View File

@ -6303,7 +6303,7 @@ DynamicModel::substituteUnaryOps(StaticModel &static_model, diff_table_t &nodes,
}
void
DynamicModel::substituteDiff(StaticModel &static_model, diff_table_t &diff_table, ExprNode::subst_table_t &diff_subst_table)
DynamicModel::substituteDiff(StaticModel &static_model, diff_table_t &diff_table, ExprNode::subst_table_t &diff_subst_table, vector<expr_t> &pac_growth)
{
set<int> used_local_vars;
for (const auto & equation : equations)
@ -6354,6 +6354,10 @@ DynamicModel::substituteDiff(StaticModel &static_model, diff_table_t &diff_table
equation = substeq;
}
for (auto & it : pac_growth)
if (it != nullptr)
it = it->substituteDiff(static_model, diff_table, diff_subst_table, neweqs);
// Add new equations
for (auto & neweq : neweqs)
addEquation(neweq, -1);

View File

@ -444,7 +444,7 @@ public:
void substituteUnaryOps(StaticModel &static_model, diff_table_t &nodes, ExprNode::subst_table_t &subst_table, vector<int> &eqnumbers);
//! Substitutes diff operator
void substituteDiff(StaticModel &static_model, diff_table_t &diff_table, ExprNode::subst_table_t &diff_subst_table);
void substituteDiff(StaticModel &static_model, diff_table_t &diff_table, ExprNode::subst_table_t &diff_subst_table, vector<expr_t> &pac_growth);
//! Substitute VarExpectation operators
void substituteVarExpectation(const map<string, expr_t> &subst_table);

View File

@ -388,7 +388,7 @@ trend_component_model_options : o_trend_component_model_name
| o_trend_component_model_eq_tags
;
pac_model : PAC_MODEL '(' pac_model_options_list ')' ';' { driver.pac_model(); } ;
pac_model : PAC_MODEL '(' { driver.begin_pac_model(); } pac_model_options_list ')' ';' { driver.pac_model(); };
pac_model_options_list : pac_model_options_list COMMA pac_model_options
| pac_model_options
@ -3131,9 +3131,7 @@ o_file : FILE EQUAL filename { driver.option_str("file", $3); };
o_pac_name : MODEL_NAME EQUAL symbol { driver.option_str("pac.model_name", $3); };
o_pac_aux_model_name : AUXILIARY_MODEL_NAME EQUAL symbol { driver.option_str("pac.aux_model_name", $3); };
o_pac_discount : DISCOUNT EQUAL symbol { driver.option_str("pac.discount", $3); };
o_pac_growth : GROWTH EQUAL symbol { driver.set_pac_growth($3, 0); }
| GROWTH EQUAL symbol '(' MINUS INT_NUMBER ')' { driver.set_pac_growth($3, stoi($6)); }
;
o_pac_growth : GROWTH { driver.begin_pac_growth(); } EQUAL hand_side { driver.set_pac_growth($4); };
o_pac_steady_state_growth : STEADY_STATE_GROWTH EQUAL signed_number { driver.set_pac_steady_state_growth($3); }
| STEADY_STATE_GROWTH EQUAL symbol { driver.set_pac_steady_state_growth($3); }
;

View File

@ -370,8 +370,13 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
for (auto & statement : statements)
{
auto pms = dynamic_cast<PacModelStatement *>(statement.get());
if (pms != nullptr && pms->aux_model_name == "")
dynamic_model.declarePacModelConsistentExpectationEndogs(pms->name);
if (pms != nullptr)
{
if (pms->growth != nullptr)
pac_growth.push_back(pms->growth);
if (pms->aux_model_name == "")
dynamic_model.declarePacModelConsistentExpectationEndogs(pms->name);
}
}
dynamic_model.substituteAdl();
dynamic_model.setLeadsLagsOrig();
@ -409,7 +414,7 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
// Create auxiliary variable and equations for Diff operators
diff_table_t diff_table;
ExprNode::subst_table_t diff_subst_table;
dynamic_model.substituteDiff(diff_static_model, diff_table, diff_subst_table);
dynamic_model.substituteDiff(diff_static_model, diff_table, diff_subst_table, pac_growth);
// Fill Trend Component Model Table
dynamic_model.fillTrendComponentModelTable();
@ -419,11 +424,15 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
original_model.fillVarModelTableFromOrigModel(diff_static_model);
// Pac Model
int i = 0;
for (auto & statement : statements)
{
auto pms = dynamic_cast<PacModelStatement *>(statement.get());
if (pms != nullptr)
{
if (pms->growth != nullptr)
pms->overwriteGrowth(pac_growth.at(i++));
int max_lag;
vector<int> lhs;
vector<bool> nonstationary;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2006-2018 Dynare Team
* Copyright (C) 2006-2019 Dynare Team
*
* This file is part of Dynare.
*
@ -130,6 +130,7 @@ private:
void writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType json_output_mode, bool transformpass, bool computingpass) const;
void writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode, bool jsonderivsimple) const;
void writeJsonFileHelper(const string &fname, ostringstream &output) const;
vector<expr_t> pac_growth;
public:
//! Add a statement
void addStatement(unique_ptr<Statement> st);

View File

@ -2607,6 +2607,22 @@ ParsingDriver::add_pac_expectation(const string &var_model_name)
return data_tree->AddPacExpectation(var_model_name);
}
void
ParsingDriver::begin_pac_growth()
{
set_current_data_tree(&mod_file->dynamic_model);
}
void
ParsingDriver::begin_pac_model()
{
parsing_pac_model = true;
pac_growth = nullptr;
pac_steady_state_growth_rate_number = -1;
pac_steady_state_growth_rate_symb_id = -1;
options_list.clear();
}
void
ParsingDriver::pac_model()
{
@ -2626,13 +2642,6 @@ ParsingDriver::pac_model()
}
else
aux_model_name = it->second;
else
if (pac_growth_symb_id >= 0 && mod_file->symbol_table.getType(pac_growth_symb_id) == SymbolType::parameter
&& (pac_steady_state_growth_rate_number >= 0 || pac_steady_state_growth_rate_symb_id >=0))
warning("If growth option is constant, steady_state_growth is ignored");
else if (pac_growth_symb_id >= 0 && mod_file->symbol_table.getType(pac_growth_symb_id) != SymbolType::parameter
&& (pac_steady_state_growth_rate_number < 0 || pac_steady_state_growth_rate_symb_id < 0))
error("The steady state growth rate of the target must be provided (steady_state_growth option) if option growth is not constant");
if (pac_steady_state_growth_rate_symb_id >= 0
&& mod_file->symbol_table.getType(pac_steady_state_growth_rate_symb_id) != SymbolType::parameter)
@ -2644,24 +2653,18 @@ ParsingDriver::pac_model()
auto discount = it->second;
mod_file->addStatement(make_unique<PacModelStatement>(name, aux_model_name, discount,
pac_growth_symb_id, pac_growth_lag,
pac_growth,
pac_steady_state_growth_rate_number,
pac_steady_state_growth_rate_symb_id,
mod_file->symbol_table));
pac_growth_symb_id = -1;
pac_growth_lag = 0;
pac_steady_state_growth_rate_number = -1;
pac_steady_state_growth_rate_symb_id = -1;
options_list.clear();
parsing_pac_model = false;
}
void
ParsingDriver::set_pac_growth(const string &name, int lag)
ParsingDriver::set_pac_growth(expr_t pac_growth_arg)
{
if (!mod_file->symbol_table.exists(name))
error("Unknown symbol used in pac_growth option: " + name + "\n");
pac_growth_symb_id = mod_file->symbol_table.getID(name);
pac_growth_lag = -lag;
pac_growth = pac_growth_arg;
reset_data_tree();
}
void
@ -2981,7 +2984,7 @@ ParsingDriver::add_model_var_or_external_function(const string &function_name, b
expr_t nid;
if (mod_file->symbol_table.exists(function_name))
if (mod_file->symbol_table.getType(function_name) != SymbolType::externalFunction)
if (!in_model_block && !parsing_epilogue)
if (!in_model_block && !parsing_epilogue && !parsing_pac_model)
{
if (stack_external_function_args.top().size() > 0)
error(string("Symbol ") + function_name + string(" cannot take arguments."));

View File

@ -255,8 +255,7 @@ private:
WarningConsolidation &warnings;
//! Temporary storage for growth declared in pac_model
int pac_growth_symb_id = -1;
int pac_growth_lag = 0;
expr_t pac_growth;
double pac_steady_state_growth_rate_number = -1;
int pac_steady_state_growth_rate_symb_id = -1;
@ -271,6 +270,9 @@ private:
//! True when parsing the epilogue block
bool parsing_epilogue{false};
//! True when parsing pac_model statement
bool parsing_pac_model{false};
public:
ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) :
warnings{warnings_arg}, nostrict{nostrict_arg} { };
@ -732,9 +734,11 @@ public:
//! Writes token "PAC_EXPECTATION(model_name, discount, growth)" to model tree
expr_t add_pac_expectation(const string &var_model_name);
//! Creates pac_model statement
void begin_pac_growth();
void begin_pac_model();
void pac_model();
//! Adds growth for pac
void set_pac_growth(const string &name, int lag = 0);
void set_pac_growth(expr_t pac_growth_arg);
//! Adds steady state growth for pac
void set_pac_steady_state_growth(const string &name_or_number);
//! Writes token "diff(arg1)" to model tree