New shocks(learnt_in=…) and endval(learnt_in=…) blocks

For use with perfect_foresight_with_expectation_errors_setup.
fix-tolerance-parameters
Sébastien Villemot 2022-04-20 16:57:39 +02:00
parent 54ca5d9cc0
commit b5a4df1608
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
11 changed files with 227 additions and 18 deletions

View File

@ -267,7 +267,7 @@ PerfectForesightWithExpectationErrorsSolverStatement::PerfectForesightWithExpect
void
PerfectForesightWithExpectationErrorsSolverStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
mod_file_struct.perfect_foresight_solver_present = true;
mod_file_struct.perfect_foresight_with_expectation_errors_solver_present = true;
}
void

View File

@ -186,7 +186,7 @@ class ParsingDriver;
%token NO_IDENTIFICATION_MINIMAL NO_IDENTIFICATION_SPECTRUM NORMALIZE_JACOBIANS GRID_NBR
%token TOL_RANK TOL_DERIV TOL_SV CHECKS_VIA_SUBSETS MAX_DIM_SUBSETS_GROUPS ZERO_MOMENTS_TOLERANCE
%token MAX_NROWS SQUEEZE_SHOCK_DECOMPOSITION WITH_EPILOGUE MODEL_REMOVE MODEL_REPLACE MODEL_OPTIONS
%token VAR_REMOVE ESTIMATED_PARAMS_REMOVE STATIC INCIDENCE RESID NON_ZERO
%token VAR_REMOVE ESTIMATED_PARAMS_REMOVE STATIC INCIDENCE RESID NON_ZERO LEARNT_IN
%token <vector<string>> SYMBOL_VEC
@ -757,6 +757,8 @@ endval : ENDVAL ';' initval_list END ';'
{ driver.end_endval(false); }
| ENDVAL '(' ALL_VALUES_REQUIRED ')' ';' initval_list END ';'
{ driver.end_endval(true); }
| ENDVAL '(' LEARNT_IN EQUAL INT_NUMBER ')' ';' initval_list END ';'
{ driver.end_endval_learnt_in($5); }
;
initval_list : initval_list initval_elem
@ -1126,9 +1128,12 @@ tag_pair_list_for_selection : QUOTED_STRING
shocks : SHOCKS ';' shock_list END ';' { driver.end_shocks(false); }
| SHOCKS '(' OVERWRITE ')' ';' shock_list END ';' { driver.end_shocks(true); }
| SHOCKS '(' OVERWRITE ')' ';' END ';' { driver.end_shocks(true); }
| SHOCKS '(' SURPRISE ')' ';' surprise_shock_list END ';' { driver.end_shocks_surprise(false); }
| SHOCKS '(' SURPRISE COMMA OVERWRITE ')' ';' surprise_shock_list END ';' { driver.end_shocks_surprise(true); }
| SHOCKS '(' OVERWRITE COMMA SURPRISE ')' ';' surprise_shock_list END ';' { driver.end_shocks_surprise(true); }
| SHOCKS '(' SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(false); }
| SHOCKS '(' SURPRISE COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); }
| SHOCKS '(' OVERWRITE COMMA SURPRISE ')' ';' det_shock_list END ';' { driver.end_shocks_surprise(true); }
| SHOCKS '(' LEARNT_IN EQUAL INT_NUMBER ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, false); }
| SHOCKS '(' LEARNT_IN EQUAL INT_NUMBER COMMA OVERWRITE ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($5, true); }
| SHOCKS '(' OVERWRITE COMMA LEARNT_IN EQUAL INT_NUMBER ')' ';' det_shock_list END ';' { driver.end_shocks_learnt_in($7, true); }
;
shock_list : shock_list shock_elem
@ -1150,9 +1155,9 @@ det_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';'
{ driver.add_det_shock($2, $5, $8, false); }
;
surprise_shock_list : surprise_shock_list det_shock_elem
| det_shock_elem
;
det_shock_list : det_shock_list det_shock_elem
| det_shock_elem
;
heteroskedastic_shocks : HETEROSKEDASTIC_SHOCKS ';' heteroskedastic_shock_list END ';'
{ driver.end_heteroskedastic_shocks(false); }

View File

@ -888,6 +888,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_BLOCK>lag {return token::LAG;}
<DYNARE_BLOCK>coeff {return token::COEFF;}
<DYNARE_BLOCK>overwrite {return token::OVERWRITE;}
<DYNARE_BLOCK>learnt_in {return token::LEARNT_IN;}
<DYNARE_STATEMENT,DYNARE_BLOCK>upper_cholesky {return token::UPPER_CHOLESKY;}
<DYNARE_STATEMENT,DYNARE_BLOCK>lower_cholesky {return token::LOWER_CHOLESKY;}
<DYNARE_STATEMENT>chain {return token::CHAIN;}

View File

@ -148,6 +148,7 @@ ModFile::checkPass(bool nostrict, bool stochastic)
if (dynamic_model.equation_number() == 0
&& (mod_file_struct.check_present
|| mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present
|| stochastic_statement_present))
{
cerr << "ERROR: At least one model equation must be declared!" << endl;
@ -184,9 +185,10 @@ ModFile::checkPass(bool nostrict, bool stochastic)
exit(EXIT_FAILURE);
}
if (mod_file_struct.perfect_foresight_solver_present && stochastic_statement_present)
if ((mod_file_struct.perfect_foresight_solver_present || mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
&& stochastic_statement_present)
{
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver,simul} and one of {stoch_simul, estimation, osr, ramsey_policy, discretionary_policy}. This is not possible: one cannot mix perfect foresight context with stochastic context in the same file." << endl;
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, perfect_foresight_with_expectation_errors_solver} and one of {stoch_simul, estimation, osr, ramsey_policy, discretionary_policy}. This is not possible: one cannot mix perfect foresight context with stochastic context in the same file." << endl;
exit(EXIT_FAILURE);
}
@ -308,6 +310,7 @@ ModFile::checkPass(bool nostrict, bool stochastic)
if (linear
&& !mod_file_struct.perfect_foresight_solver_present
&& !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present
&& (dynamic_model.isUnaryOpUsedOnType(SymbolType::exogenous, UnaryOpcode::sign)
|| dynamic_model.isUnaryOpUsedOnType(SymbolType::exogenous, UnaryOpcode::abs)
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::max)
@ -576,9 +579,10 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
exit(EXIT_FAILURE);
}
if (symbol_table.exo_det_nbr() > 0 && mod_file_struct.perfect_foresight_solver_present)
if (symbol_table.exo_det_nbr() > 0
&& (mod_file_struct.perfect_foresight_solver_present || mod_file_struct.perfect_foresight_with_expectation_errors_solver_present))
{
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul} and varexo_det declaration (all exogenous variables are deterministic in this case)" << endl;
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, perfect_foresight_with_expectation_errors_solver} and varexo_det declaration (all exogenous variables are deterministic in this case)" << endl;
exit(EXIT_FAILURE);
}
@ -610,6 +614,18 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool
exit(EXIT_FAILURE);
}
if (mod_file_struct.shocks_learnt_in_present && !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
{
cerr << "ERROR: the 'shocks(learnt_in=…)' block can only be used in conjunction with the 'perfect_foresight_with_expectation_errors_solver' command." << endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.endval_learnt_in_present && !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
{
cerr << "ERROR: the 'endval(learnt_in=…)' block can only be used in conjunction with the 'perfect_foresight_with_expectation_errors_solver' command." << endl;
exit(EXIT_FAILURE);
}
if (!mod_file_struct.ramsey_model_present)
cout << "Found " << dynamic_model.equation_number() << " equation(s)." << endl;
else
@ -669,13 +685,16 @@ ModFile::computingPass(bool no_tmp_terms, OutputType output, int params_derivs_o
static_model.computingPass(derivsOrder, paramsDerivsOrder, global_eval_context, no_tmp_terms, block, bytecode);
}
// Set things to compute for dynamic model
if (mod_file_struct.perfect_foresight_solver_present || mod_file_struct.check_present
if (mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present
|| mod_file_struct.check_present
|| mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present || mod_file_struct.osr_present
|| mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
|| mod_file_struct.calib_smoother_present || mod_file_struct.mom_estimation_present)
{
if (mod_file_struct.perfect_foresight_solver_present)
if (mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
{
int derivsOrder = 1;
if (output == OutputType::second)
@ -897,9 +916,11 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global,
// May be later modified by a shocks block
mOutputFile << "M_.sigma_e_is_diagonal = true;" << endl;
// Initialize M_.det_shocks, M_.surprise_shocks and M_.heteroskedastic_shocks
// Initialize M_.det_shocks, M_.surprise_shocks, M_.learnt_shocks, M_.learnt_endval and M_.heteroskedastic_shocks
mOutputFile << "M_.det_shocks = [];" << endl
<< "M_.surprise_shocks = [];" << endl
<< "M_.learnt_shocks = [];" << endl
<< "M_.learnt_endval = [];" << endl
<< "M_.heteroskedastic_shocks.Qvalue_orig = [];" << endl
<< "M_.heteroskedastic_shocks.Qscale_orig = [];" << endl;

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2003-2021 Dynare Team
* Copyright © 2003-2022 Dynare Team
*
* This file is part of Dynare.
*
@ -299,6 +299,54 @@ EndValStatement::writeJsonOutput(ostream &output) const
output << "]}";
}
EndValLearntInStatement::EndValLearntInStatement(int learnt_in_period_arg,
const InitOrEndValStatement::init_values_t &init_values_arg,
const SymbolTable &symbol_table_arg) :
learnt_in_period{learnt_in_period_arg},
init_values{move(init_values_arg)},
symbol_table{symbol_table_arg}
{
}
void
EndValLearntInStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
mod_file_struct.endval_learnt_in_present = true;
}
void
EndValLearntInStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "M_.learnt_endval = [ M_.learnt_endval;" << endl;
for (auto [symb_id, value] : init_values)
{
output << "struct('learnt_in'," << learnt_in_period
<< ",'exo_id'," << symbol_table.getTypeSpecificID(symb_id)+1
<< ",'value',";
value->writeOutput(output);
output << ");" << endl;
}
output << "];" << endl;
}
void
EndValLearntInStatement::writeJsonOutput(ostream &output) const
{
output << R"({"statementName": "endval", "learnt_in": )"
<< learnt_in_period << R"(, "vals": [)";
for (auto it = init_values.begin();
it != init_values.end(); ++it)
{
auto [symb_id, value] = *it;
if (it != init_values.begin())
output << ", ";
output << R"({"name": ")" << symbol_table.getName(symb_id) << R"(", )" << R"("value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}
HistValStatement::HistValStatement(hist_values_t hist_values_arg,
const SymbolTable &symbol_table_arg,
bool all_values_required_arg) :

View File

@ -96,6 +96,20 @@ public:
void writeJsonOutput(ostream &output) const override;
};
class EndValLearntInStatement : public Statement
{
public:
const int learnt_in_period;
const InitOrEndValStatement::init_values_t init_values;
const SymbolTable &symbol_table;
EndValLearntInStatement(int learnt_in_period_arg,
const InitOrEndValStatement::init_values_t &init_values_arg,
const SymbolTable &symbol_table_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
};
class HistValStatement : public Statement
{
public:

View File

@ -747,6 +747,16 @@ ParsingDriver::end_endval(bool all_values_required)
init_values.clear();
}
void
ParsingDriver::end_endval_learnt_in(const string &learnt_in_period)
{
for (auto [symb_id, value] : init_values)
if (mod_file->symbol_table.getType(symb_id) != SymbolType::exogenous)
error("endval(learnt_in=...): " + mod_file->symbol_table.getName(symb_id) + " is not an exogenous variable");
mod_file->addStatement(make_unique<EndValLearntInStatement>(stoi(learnt_in_period), init_values, mod_file->symbol_table));
init_values.clear();
}
void
ParsingDriver::end_histval(bool all_values_required)
{
@ -848,6 +858,18 @@ ParsingDriver::end_shocks_surprise(bool overwrite)
det_shocks.clear();
}
void
ParsingDriver::end_shocks_learnt_in(const string &learnt_in_period, bool overwrite)
{
int learnt_in_period_int = stoi(learnt_in_period);
for (auto &[symb_id, vals] : det_shocks)
for (auto [period1, period2, expr] : vals)
if (period1 < learnt_in_period_int)
error("shocks: for variable " + mod_file->symbol_table.getName(symb_id) + ", shock period (" + to_string(period1) + ") is earlier than the period in which the shock is learnt (" + learnt_in_period + ")");
mod_file->addStatement(make_unique<ShocksLearntInStatement>(learnt_in_period_int, overwrite, det_shocks, mod_file->symbol_table));
det_shocks.clear();
}
void
ParsingDriver::end_heteroskedastic_shocks(bool overwrite)
{

View File

@ -101,7 +101,7 @@ private:
//! Checks that a given symbol exists and is a endogenous, and stops with an error message if it isn't
void check_symbol_is_endogenous(const string &name);
//! Checks that a given symbol exists and is a exogenous, and stops with an error message if it isn't
//! Checks that a given symbol exists and is a exogenous (possibly deterministic), and stops with an error message if it isn't
void check_symbol_is_exogenous(const string &name);
//! Checks for symbol existence in model block. If it doesn't exist, an error message is stored to be printed at
@ -423,6 +423,8 @@ public:
void end_initval(bool all_values_required);
//! Writes end of an endval block
void end_endval(bool all_values_required);
//! Writes end of an endval(learnt_in=…) block
void end_endval_learnt_in(const string &learnt_in_period);
//! Writes end of an histval block
void end_histval(bool all_values_required);
//! Writes end of an homotopy_setup block
@ -447,6 +449,8 @@ public:
void end_mshocks(bool overwrite);
//! Writes a shocks(surprise) statement
void end_shocks_surprise(bool overwrite);
//! Writes a shocks(learnt_in=…) block
void end_shocks_learnt_in(const string &learnt_in_period, bool overwrite);
//! Writes a heteroskedastic_shocks statement
void end_heteroskedastic_shocks(bool overwrite);
/* Adds a deterministic shock, a path element inside a

View File

@ -491,6 +491,73 @@ ShocksSurpriseStatement::writeJsonOutput(ostream &output) const
output << "]}";
}
ShocksLearntInStatement::ShocksLearntInStatement(int learnt_in_period_arg, bool overwrite_arg,
AbstractShocksStatement::det_shocks_t learnt_shocks_arg,
const SymbolTable &symbol_table_arg) :
learnt_in_period{learnt_in_period_arg}, overwrite{overwrite_arg},
learnt_shocks{move(learnt_shocks_arg)}, symbol_table{symbol_table_arg}
{
}
void
ShocksLearntInStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
mod_file_struct.shocks_learnt_in_present = true;
}
void
ShocksLearntInStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
if (overwrite)
output << "if ~isempty(M_.learnt_shocks)" << endl
<< " M_.learnt_shocks = M_.learnt_shocks([M_.learnt_shocks.learnt_in] ~= " << learnt_in_period << ");" << endl
<< "end" << endl;
output << "M_.learnt_shocks = [ M_.learnt_shocks;" << endl;
for (const auto &[id, shock_vec] : learnt_shocks)
{
for (const auto &[period1, period2, value] : shock_vec)
{
output << "struct('learnt_in'," << learnt_in_period
<< ",'exo_id'," << symbol_table.getTypeSpecificID(id)+1
<< ",'periods'," << period1 << ":" << period2
<< ",'value',";
value->writeOutput(output);
output << ");" << endl;
}
}
output << "];" << endl;
}
void
ShocksLearntInStatement::writeJsonOutput(ostream &output) const
{
output << R"({"statementName": "shocks")"
<< R"(, "learnt_in": )" << learnt_in_period
<< R"(, "overwrite": )" << (overwrite ? "true" : "false")
<< R"(, "learnt_shocks": [)";
for (auto it = learnt_shocks.begin(); it != learnt_shocks.end(); ++it)
{
if (it != learnt_shocks.begin())
output << ", ";
output << R"({"var": ")" << symbol_table.getName(it->first) << R"(", )"
<< R"("values": [)";
for (auto it1 = it->second.begin(); it1 != it->second.end(); ++it1)
{
auto [period1, period2, value] = *it1;
if (it1 != it->second.begin())
output << ", ";
output << R"({"period1": )" << period1 << ", "
<< R"("period2": )" << period2 << ", "
<< R"("value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}
output << "]}";
}
ConditionalForecastPathsStatement::ConditionalForecastPathsStatement(AbstractShocksStatement::det_shocks_t paths_arg,
const SymbolTable &symbol_table_arg) :
paths{move(paths_arg)},

View File

@ -106,6 +106,27 @@ public:
void writeJsonOutput(ostream &output) const override;
};
/* Represents a shocks(learnt_in=…) block.
Given the differences with the plain shocks block, it was easier to make
it a separate class. */
class ShocksLearntInStatement : public Statement
{
public:
const int learnt_in_period;
//! Does this "shocks(learnt_in=…)" statement replace the previous ones?
const bool overwrite;
const AbstractShocksStatement::det_shocks_t learnt_shocks;
private:
const SymbolTable &symbol_table;
public:
ShocksLearntInStatement(int learnt_in_period_arg, bool overwrite_arg,
AbstractShocksStatement::det_shocks_t learnt_shocks_arg,
const SymbolTable &symbol_table_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream &output) const override;
};
class ConditionalForecastPathsStatement : public Statement
{
private:

View File

@ -36,8 +36,10 @@ public:
bool check_present{false};
//! Whether steady is present
bool steady_present{false};
//! Whether a perfect_foresight_solver/simul/perfect_foresight_with_expectation_errors_solver statement is present
//! Whether a perfect_foresight_solver/simul statement is present
bool perfect_foresight_solver_present{false};
//! Whether a perfect_foresight_with_expectation_errors_solver statement is present
bool perfect_foresight_with_expectation_errors_solver_present{false};
//! Whether a stoch_simul statement is present
bool stoch_simul_present{false};
//! Whether an estimation statement is present
@ -147,6 +149,10 @@ public:
set<int> parameters_in_planner_discount;
// Whether a shocks(surprise) block appears
bool shocks_surprise_present{false};
// Whether a shocks(learnt_in=…) block appears
bool shocks_learnt_in_present{false};
// Whether an endval(learnt_in=…) block appears
bool endval_learnt_in_present{false};
// Whether an occbin_constraints block appears
bool occbin_constraints_present{false};
// Whether a ramsey_constraints block appears