New “add” and “multiply” keywords in “shocks(learnt_in=…)” block
parent
dbe14ecfd4
commit
76a16a69a8
|
@ -175,7 +175,7 @@ class ParsingDriver;
|
|||
%token HETEROSKEDASTIC_FILTER TIME_SHIFT STRUCTURAL TERMINAL_STEADY_STATE_AS_GUESS_VALUE CONSTANT_SIMULATION_LENGTH
|
||||
%token SURPRISE OCCBIN_CONSTRAINTS
|
||||
%token PAC_TARGET_INFO COMPONENT TARGET AUXNAME AUXNAME_TARGET_NONSTATIONARY PAC_TARGET_NONSTATIONARY
|
||||
%token <string> KIND LL DL DD
|
||||
%token <string> KIND LL DL DD ADD MULTIPLY
|
||||
/* Method of Moments */
|
||||
%token METHOD_OF_MOMENTS MOM_METHOD
|
||||
%token BARTLETT_KERNEL_LAG WEIGHTING_MATRIX WEIGHTING_MATRIX_SCALING_FACTOR ANALYTIC_STANDARD_ERRORS ANALYTIC_JACOBIAN PENALIZED_ESTIMATOR VERBOSE
|
||||
|
@ -1152,7 +1152,11 @@ shock_elem : det_shock_elem
|
|||
;
|
||||
|
||||
det_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';'
|
||||
{ driver.add_det_shock($2, $5, $8, false); }
|
||||
{ driver.add_det_shock($2, $5, $8, ParsingDriver::DetShockType::standard); }
|
||||
| VAR symbol ';' PERIODS period_list ';' ADD value_list ';'
|
||||
{ driver.add_det_shock($2, $5, $8, ParsingDriver::DetShockType::add); }
|
||||
| VAR symbol ';' PERIODS period_list ';' MULTIPLY value_list ';'
|
||||
{ driver.add_det_shock($2, $5, $8, ParsingDriver::DetShockType::multiply); }
|
||||
;
|
||||
|
||||
det_shock_list : det_shock_list det_shock_elem
|
||||
|
@ -3207,7 +3211,7 @@ conditional_forecast_paths_shock_list : conditional_forecast_paths_shock_elem
|
|||
;
|
||||
|
||||
conditional_forecast_paths_shock_elem : VAR symbol ';' PERIODS period_list ';' VALUES value_list ';'
|
||||
{ driver.add_det_shock($2, $5, $8, true); }
|
||||
{ driver.add_det_shock($2, $5, $8, ParsingDriver::DetShockType::conditional_forecast); }
|
||||
;
|
||||
|
||||
steady_state_model : STEADY_STATE_MODEL ';' { driver.begin_steady_state_model(); }
|
||||
|
@ -4284,6 +4288,8 @@ symbol : NAME
|
|||
| LL
|
||||
| DL
|
||||
| DD
|
||||
| ADD
|
||||
| MULTIPLY
|
||||
;
|
||||
|
||||
%%
|
||||
|
|
|
@ -770,6 +770,14 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
|
|||
<DYNARE_BLOCK>corr {return token::CORR;}
|
||||
<DYNARE_BLOCK>periods {return token::PERIODS;}
|
||||
<DYNARE_BLOCK>scales {return token::SCALES;}
|
||||
<DYNARE_BLOCK>add {
|
||||
yylval->build<string>(yytext);
|
||||
return token::ADD;
|
||||
}
|
||||
<DYNARE_BLOCK>multiply {
|
||||
yylval->build<string>(yytext);
|
||||
return token::MULTIPLY;
|
||||
}
|
||||
<DYNARE_STATEMENT,DYNARE_BLOCK>cutoff {return token::CUTOFF;}
|
||||
<DYNARE_STATEMENT,DYNARE_BLOCK>mfs {return token::MFS;}
|
||||
<DYNARE_STATEMENT,DYNARE_BLOCK>balanced_growth_test_tol {return token::BALANCED_GROWTH_TEST_TOL;}
|
||||
|
|
|
@ -841,6 +841,10 @@ ParsingDriver::end_shocks(bool overwrite)
|
|||
mod_file->addStatement(make_unique<ShocksStatement>(overwrite, det_shocks, var_shocks, std_shocks,
|
||||
covar_shocks, corr_shocks, mod_file->symbol_table));
|
||||
det_shocks.clear();
|
||||
if (!learnt_shocks_add.empty())
|
||||
error("shocks: 'add' keyword not allowed unless 'learnt_in' option is passed");
|
||||
if (!learnt_shocks_multiply.empty())
|
||||
error("shocks: 'multiply' keyword not allowed unless 'learnt_in' option is passed");
|
||||
var_shocks.clear();
|
||||
std_shocks.clear();
|
||||
covar_shocks.clear();
|
||||
|
@ -852,6 +856,10 @@ ParsingDriver::end_mshocks(bool overwrite)
|
|||
{
|
||||
mod_file->addStatement(make_unique<MShocksStatement>(overwrite, det_shocks, mod_file->symbol_table));
|
||||
det_shocks.clear();
|
||||
if (!learnt_shocks_add.empty())
|
||||
error("mshocks: 'add' keyword not allowed");
|
||||
if (!learnt_shocks_multiply.empty())
|
||||
error("mshocks: 'multiply' keyword not allowed");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -859,6 +867,10 @@ ParsingDriver::end_shocks_surprise(bool overwrite)
|
|||
{
|
||||
mod_file->addStatement(make_unique<ShocksSurpriseStatement>(overwrite, det_shocks, mod_file->symbol_table));
|
||||
det_shocks.clear();
|
||||
if (!learnt_shocks_add.empty())
|
||||
error("shocks(surprise): 'add' keyword not allowed");
|
||||
if (!learnt_shocks_multiply.empty())
|
||||
error("shocks(surprise): 'multiply' keyword not allowed");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -871,8 +883,35 @@ ParsingDriver::end_shocks_learnt_in(const string &learnt_in_period, bool overwri
|
|||
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));
|
||||
|
||||
// Aggregate the three types of shocks
|
||||
ShocksLearntInStatement::learnt_shocks_t learnt_shocks;
|
||||
for (const auto &[id, v] : det_shocks)
|
||||
{
|
||||
vector<tuple<ShocksLearntInStatement::LearntShockType, int, int, expr_t>> v2;
|
||||
for (auto [period1, period2, value] : v)
|
||||
v2.emplace_back(ShocksLearntInStatement::LearntShockType::level, period1, period2, value);
|
||||
learnt_shocks[id] = v2;
|
||||
}
|
||||
for (const auto &[id, v] : learnt_shocks_add)
|
||||
{
|
||||
vector<tuple<ShocksLearntInStatement::LearntShockType, int, int, expr_t>> v2;
|
||||
for (auto [period1, period2, value] : v)
|
||||
v2.emplace_back(ShocksLearntInStatement::LearntShockType::add, period1, period2, value);
|
||||
learnt_shocks[id] = v2;
|
||||
}
|
||||
for (const auto &[id, v] : learnt_shocks_multiply)
|
||||
{
|
||||
vector<tuple<ShocksLearntInStatement::LearntShockType, int, int, expr_t>> v2;
|
||||
for (auto [period1, period2, value] : v)
|
||||
v2.emplace_back(ShocksLearntInStatement::LearntShockType::multiply, period1, period2, value);
|
||||
learnt_shocks[id] = v2;
|
||||
}
|
||||
|
||||
mod_file->addStatement(make_unique<ShocksLearntInStatement>(learnt_in_period_int, overwrite, learnt_shocks, mod_file->symbol_table));
|
||||
det_shocks.clear();
|
||||
learnt_shocks_add.clear();
|
||||
learnt_shocks_multiply.clear();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -885,16 +924,28 @@ ParsingDriver::end_heteroskedastic_shocks(bool overwrite)
|
|||
}
|
||||
|
||||
void
|
||||
ParsingDriver::add_det_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, bool conditional_forecast)
|
||||
ParsingDriver::add_det_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, DetShockType type)
|
||||
{
|
||||
if (conditional_forecast)
|
||||
check_symbol_is_endogenous(var);
|
||||
else
|
||||
check_symbol_is_exogenous(var, true);
|
||||
switch (type)
|
||||
{
|
||||
case DetShockType::conditional_forecast:
|
||||
check_symbol_is_endogenous(var);
|
||||
break;
|
||||
case DetShockType::standard:
|
||||
// Allow exo_det, for stochastic context
|
||||
check_symbol_is_exogenous(var, true);
|
||||
break;
|
||||
case DetShockType::add:
|
||||
case DetShockType::multiply:
|
||||
check_symbol_is_exogenous(var, false);
|
||||
break;
|
||||
}
|
||||
|
||||
int symb_id = mod_file->symbol_table.getID(var);
|
||||
|
||||
if (det_shocks.find(symb_id) != det_shocks.end())
|
||||
if (det_shocks.find(symb_id) != det_shocks.end()
|
||||
|| learnt_shocks_add.find(symb_id) != learnt_shocks_add.end()
|
||||
|| learnt_shocks_multiply.find(symb_id) != learnt_shocks_multiply.end())
|
||||
error("shocks/conditional_forecast_paths: variable " + var + " declared twice");
|
||||
|
||||
if (periods.size() != values.size())
|
||||
|
@ -905,7 +956,19 @@ ParsingDriver::add_det_shock(const string &var, const vector<pair<int, int>> &pe
|
|||
for (size_t i = 0; i < periods.size(); i++)
|
||||
v.emplace_back(periods[i].first, periods[i].second, values[i]);
|
||||
|
||||
det_shocks[symb_id] = v;
|
||||
switch (type)
|
||||
{
|
||||
case DetShockType::standard:
|
||||
case DetShockType::conditional_forecast:
|
||||
det_shocks[symb_id] = v;
|
||||
break;
|
||||
case DetShockType::add:
|
||||
learnt_shocks_add[symb_id] = v;
|
||||
break;
|
||||
case DetShockType::multiply:
|
||||
learnt_shocks_multiply[symb_id] = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2435,6 +2498,10 @@ ParsingDriver::conditional_forecast_paths()
|
|||
{
|
||||
mod_file->addStatement(make_unique<ConditionalForecastPathsStatement>(det_shocks, mod_file->symbol_table));
|
||||
det_shocks.clear();
|
||||
if (!learnt_shocks_add.empty())
|
||||
error("conditional_forecast_paths: 'add' keyword not allowed");
|
||||
if (!learnt_shocks_multiply.empty())
|
||||
error("conditional_forecast_paths: 'multiply' keyword not allowed");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -150,8 +150,11 @@ private:
|
|||
//! Temporary storage of covariances from optim_weights
|
||||
OptimWeightsStatement::covar_weights_t covar_weights;
|
||||
/* Temporary storage for deterministic shocks. Also used for
|
||||
conditional_forecast paths and for surprise shocks. */
|
||||
conditional_forecast paths, for shocks(surprise), and shocks(learnt_in=…)
|
||||
(for the latter, only used for shocks declared in level through “values”). */
|
||||
ShocksStatement::det_shocks_t det_shocks;
|
||||
// Temporary storage for shocks declared with “add” and “multiply” in shocks(learnt_in=…)
|
||||
ShocksStatement::det_shocks_t learnt_shocks_add, learnt_shocks_multiply;
|
||||
//! Temporary storage for variances of shocks
|
||||
ShocksStatement::var_and_std_shocks_t var_shocks;
|
||||
//! Temporary storage for standard errors of shocks
|
||||
|
@ -455,7 +458,14 @@ public:
|
|||
void end_heteroskedastic_shocks(bool overwrite);
|
||||
/* Adds a deterministic shock, a path element inside a
|
||||
conditional_forecast_paths block, or a surprise shock */
|
||||
void add_det_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, bool conditional_forecast);
|
||||
enum class DetShockType
|
||||
{
|
||||
standard,
|
||||
add, // for “add” in “shocks(learnt_in)”
|
||||
multiply, // for “multiply” in “shocks(learnt_in)”
|
||||
conditional_forecast
|
||||
};
|
||||
void add_det_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, DetShockType type);
|
||||
//! Adds a heteroskedastic shock (either values or scales)
|
||||
void add_heteroskedastic_shock(const string &var, const vector<pair<int, int>> &periods, const vector<expr_t> &values, bool scales);
|
||||
//! Adds a std error shock
|
||||
|
|
|
@ -492,7 +492,7 @@ ShocksSurpriseStatement::writeJsonOutput(ostream &output) const
|
|||
}
|
||||
|
||||
ShocksLearntInStatement::ShocksLearntInStatement(int learnt_in_period_arg, bool overwrite_arg,
|
||||
AbstractShocksStatement::det_shocks_t learnt_shocks_arg,
|
||||
learnt_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}
|
||||
|
@ -505,6 +505,21 @@ ShocksLearntInStatement::checkPass(ModFileStructure &mod_file_struct, WarningCon
|
|||
mod_file_struct.shocks_learnt_in_present = true;
|
||||
}
|
||||
|
||||
string
|
||||
ShocksLearntInStatement::typeToString(LearntShockType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LearntShockType::level:
|
||||
return "level";
|
||||
case LearntShockType::add:
|
||||
return "add";
|
||||
case LearntShockType::multiply:
|
||||
return "multiply";
|
||||
}
|
||||
exit(EXIT_FAILURE); // Silence GCC warning
|
||||
}
|
||||
|
||||
void
|
||||
ShocksLearntInStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
|
||||
{
|
||||
|
@ -516,11 +531,12 @@ ShocksLearntInStatement::writeOutput(ostream &output, const string &basename, bo
|
|||
output << "M_.learnt_shocks = [ M_.learnt_shocks;" << endl;
|
||||
for (const auto &[id, shock_vec] : learnt_shocks)
|
||||
{
|
||||
for (const auto &[period1, period2, value] : shock_vec)
|
||||
for (const auto &[type, period1, period2, value] : shock_vec)
|
||||
{
|
||||
output << "struct('learnt_in'," << learnt_in_period
|
||||
<< ",'exo_id'," << symbol_table.getTypeSpecificID(id)+1
|
||||
<< ",'periods'," << period1 << ":" << period2
|
||||
<< ",'type','" << typeToString(type) << "'"
|
||||
<< ",'value',";
|
||||
value->writeOutput(output);
|
||||
output << ");" << endl;
|
||||
|
@ -544,11 +560,12 @@ ShocksLearntInStatement::writeJsonOutput(ostream &output) const
|
|||
<< R"("values": [)";
|
||||
for (auto it1 = it->second.begin(); it1 != it->second.end(); ++it1)
|
||||
{
|
||||
auto [period1, period2, value] = *it1;
|
||||
auto [type, period1, period2, value] = *it1;
|
||||
if (it1 != it->second.begin())
|
||||
output << ", ";
|
||||
output << R"({"period1": )" << period1 << ", "
|
||||
<< R"("period2": )" << period2 << ", "
|
||||
<< R"("type": ")" << typeToString(type) << R"(", )"
|
||||
<< R"("value": ")";
|
||||
value->writeJsonOutput(output, {}, {});
|
||||
output << R"("})";
|
||||
|
|
|
@ -115,12 +115,21 @@ 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;
|
||||
enum class LearntShockType
|
||||
{
|
||||
level,
|
||||
add,
|
||||
multiply
|
||||
};
|
||||
// The tuple is (type, period1, period2, value)
|
||||
using learnt_shocks_t = map<int, vector<tuple<LearntShockType, int, int, expr_t>>>;
|
||||
const learnt_shocks_t learnt_shocks;
|
||||
private:
|
||||
const SymbolTable &symbol_table;
|
||||
static string typeToString(LearntShockType type);
|
||||
public:
|
||||
ShocksLearntInStatement(int learnt_in_period_arg, bool overwrite_arg,
|
||||
AbstractShocksStatement::det_shocks_t learnt_shocks_arg,
|
||||
learnt_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;
|
||||
|
|
Loading…
Reference in New Issue