preprocessor/src/ComputingTasks.cc

5586 lines
188 KiB
C++

/*
* Copyright © 2003-2023 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <sstream>
using namespace std;
#include "ComputingTasks.hh"
#include "ParsingDriver.hh"
#include "Statement.hh"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/tokenizer.hpp>
#pragma GCC diagnostic pop
#include <algorithm>
#include <utility>
SteadyStatement::SteadyStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
SteadyStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.steady_present = true;
}
void
SteadyStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "steady;" << endl;
}
void
SteadyStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "steady")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
CheckStatement::CheckStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
{
}
void
CheckStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "oo_.dr.eigval = check(M_,options_,oo_);" << endl;
}
void
CheckStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.check_present = true;
}
void
CheckStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "check")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
ModelInfoStatement::ModelInfoStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
ModelInfoStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_model_info_");
output << "model_info(options_model_info_);" << endl;
}
void
ModelInfoStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "model_info")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
SimulStatement::SimulStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
{
}
void
SimulStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.perfect_foresight_solver_present = true;
}
void
SimulStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
// Translate the “datafile” option into “initval_file” (see dynare#1663)
auto options_list_new = options_list; // Need a copy, because of const
if (auto opt = options_list_new.get_if<OptionsList::StringVal>("datafile"))
{
output << "options_.initval_file = true;" << endl
<< "options_initvalf = struct();" << endl
<< "options_initvalf.datafile = '" << *opt << "';" << endl
<< "oo_.initval_series = histvalf_initvalf('INITVALF', M_, options_initvalf);" << endl;
options_list_new.erase("datafile");
}
options_list_new.writeOutput(output);
output << "oo_ = perfect_foresight_setup(M_, options_, oo_);" << endl
<< "[oo_, Simulated_time_series] = perfect_foresight_solver(M_, options_, oo_);" << endl;
}
void
SimulStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "simul")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
PerfectForesightSetupStatement::PerfectForesightSetupStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
PerfectForesightSetupStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
auto options_list_new = options_list; // Need a copy, because of const
if (auto opt = options_list_new.get_if<OptionsList::StringVal>("datafile"))
{
output << "options_.initval_file = true;" << endl
<< "options_initvalf = struct();" << endl
<< "options_initvalf.datafile = '" << *opt << "';" << endl
<< "oo_.initval_series = histvalf_initvalf('INITVALF', M_, options_initvalf);" << endl;
options_list_new.erase("datafile");
}
options_list_new.writeOutput(output);
output << "oo_ = perfect_foresight_setup(M_, options_, oo_);" << endl;
}
void
PerfectForesightSetupStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "perfect_foresight_setup")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
PerfectForesightSolverStatement::PerfectForesightSolverStatement(OptionsList options_list_arg) :
options_list(move(options_list_arg))
{
}
void
PerfectForesightSolverStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.perfect_foresight_solver_present = true;
}
void
PerfectForesightSolverStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "[oo_, Simulated_time_series] = perfect_foresight_solver(M_, options_, oo_);" << endl;
}
void
PerfectForesightSolverStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "perfect_foresight_solver")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
PerfectForesightWithExpectationErrorsSetupStatement::
PerfectForesightWithExpectationErrorsSetupStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
PerfectForesightWithExpectationErrorsSetupStatement::writeOutput(
ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "oo_ = perfect_foresight_with_expectation_errors_setup(M_, options_, oo_);" << endl;
}
void
PerfectForesightWithExpectationErrorsSetupStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "perfect_foresight_with_expectation_errors_setup")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
PerfectForesightWithExpectationErrorsSolverStatement::
PerfectForesightWithExpectationErrorsSolverStatement(OptionsList options_list_arg) :
options_list(move(options_list_arg))
{
}
void
PerfectForesightWithExpectationErrorsSolverStatement::checkPass(
ModFileStructure& mod_file_struct, [[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.perfect_foresight_with_expectation_errors_solver_present = true;
}
void
PerfectForesightWithExpectationErrorsSolverStatement::writeOutput(
ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "oo_ = perfect_foresight_with_expectation_errors_solver(M_, options_, oo_);" << endl;
}
void
PerfectForesightWithExpectationErrorsSolverStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "perfect_foresight_with_expectation_errors_solver")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
PriorPosteriorFunctionStatement::PriorPosteriorFunctionStatement(const bool prior_func_arg,
OptionsList options_list_arg) :
prior_func {prior_func_arg}, options_list {move(options_list_arg)}
{
}
void
PriorPosteriorFunctionStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (auto opt = options_list.get_if<OptionsList::StringVal>("function"); !opt || opt->empty())
{
cerr << "ERROR: both the 'prior_function' and 'posterior_function' commands require the "
"'function' option"
<< endl;
exit(EXIT_FAILURE);
}
}
void
PriorPosteriorFunctionStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
string type = prior_func ? "prior" : "posterior";
output << "oo_ = execute_prior_posterior_function("
<< "'" << options_list.get<OptionsList::StringVal>("function") << "', "
<< "M_, options_, oo_, estim_params_, bayestopt_, dataset_, dataset_info, "
<< "'" << type << "');" << endl;
}
void
PriorPosteriorFunctionStatement::writeJsonOutput(ostream& output) const
{
string type = prior_func ? "prior" : "posterior";
output << R"({"statementName": "prior_posterior_function", "type": ")" << type << R"(")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
StochSimulStatement::StochSimulStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
StochSimulStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings)
{
mod_file_struct.stoch_simul_present = true;
// Fill in option_order of mod_file_struct
if (auto opt = options_list.get_if<OptionsList::NumVal>("order"))
mod_file_struct.order_option = max(mod_file_struct.order_option, stoi(*opt));
// Fill in mod_file_struct.partial_information
if (auto opt = options_list.get_if<OptionsList::NumVal>("partial_information");
opt && *opt == "true")
mod_file_struct.partial_information = true;
// Option k_order_solver (implicit when order >= 3)
if (auto opt = options_list.get_if<OptionsList::NumVal>("k_order_solver");
(opt && *opt == "true") || mod_file_struct.order_option >= 3)
mod_file_struct.k_order_solver = true;
if (bool hp = options_list.contains("hp_filter"),
bandpass = options_list.contains("bandpass.indicator"),
one_sided_hp = options_list.contains("one_sided_hp_filter");
(hp && bandpass) || (hp && one_sided_hp) || (bandpass && one_sided_hp))
{
cerr << "ERROR: stoch_simul: can only use one of hp, one-sided hp, and bandpass filters"
<< endl;
exit(EXIT_FAILURE);
}
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: stoch_simul: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
StochSimulStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
// Ensure that order 3 implies k_order (#844)
if (auto opt1 = options_list.get_if<OptionsList::NumVal>("order"),
opt2 = options_list.get_if<OptionsList::NumVal>("k_order_solver");
(opt2 && *opt2 == "true") || (opt1 && stoi(*opt1) >= 3))
output << "options_.k_order_solver = true;" << endl;
options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output);
output << "[info, oo_, options_, M_] = stoch_simul(M_, options_, oo_, var_list_);" << endl;
}
void
StochSimulStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "stoch_simul")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
ForecastStatement::ForecastStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
ForecastStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: forecast: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
ForecastStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output);
output << "oo_.forecast = dyn_forecast(var_list_,M_,options_,oo_,'simul');" << endl;
}
void
ForecastStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "forecast")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
RamseyModelStatement::RamseyModelStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
RamseyModelStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.ramsey_model_present = true;
// Fill list of instruments
if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("instruments"))
mod_file_struct.instruments = *opt;
}
void
RamseyModelStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
}
void
RamseyModelStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ramsey_model")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
RamseyConstraintsStatement::RamseyConstraintsStatement(const SymbolTable& symbol_table_arg,
constraints_t constraints_arg) :
symbol_table {symbol_table_arg}, constraints {move(constraints_arg)}
{
}
void
RamseyConstraintsStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.ramsey_constraints_present = true;
}
void
RamseyConstraintsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "M_.ramsey_model_constraints = {" << endl;
for (bool printed_something {false}; const auto& it : constraints)
{
if (exchange(printed_something, true))
output << ", ";
output << "{" << it.endo + 1 << ", '";
switch (it.code)
{
case BinaryOpcode::less:
output << '<';
break;
case BinaryOpcode::greater:
output << '>';
break;
case BinaryOpcode::lessEqual:
output << "<=";
break;
case BinaryOpcode::greaterEqual:
output << ">=";
break;
default:
cerr << "Ramsey constraints: this shouldn't happen." << endl;
exit(EXIT_FAILURE);
}
output << "', '";
it.expression->writeOutput(output);
output << "'}" << endl;
}
output << "};" << endl;
}
void
RamseyConstraintsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ramsey_constraints")"
<< R"(, "ramsey_model_constraints": [)" << endl;
for (bool printed_something {false}; const auto& it : constraints)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"constraint": ")" << symbol_table.getName(it.endo) << " ";
switch (it.code)
{
case BinaryOpcode::less:
output << '<';
break;
case BinaryOpcode::greater:
output << '>';
break;
case BinaryOpcode::lessEqual:
output << "<=";
break;
case BinaryOpcode::greaterEqual:
output << ">=";
break;
default:
cerr << "Ramsey constraints: this shouldn't happen." << endl;
exit(EXIT_FAILURE);
}
output << " ";
it.expression->writeJsonOutput(output, {}, {});
output << R"("})" << endl;
}
output << "]" << endl;
output << "}";
}
RamseyPolicyStatement::RamseyPolicyStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
RamseyPolicyStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings)
{
// Copied from RamseyModelStatement::checkPass()
mod_file_struct.ramsey_model_present = true;
if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("instruments"))
mod_file_struct.instruments = *opt;
// Copied from StochSimulStatement::checkPass()
mod_file_struct.stoch_simul_present = true;
if (auto opt = options_list.get_if<OptionsList::NumVal>("order"))
mod_file_struct.order_option = max(mod_file_struct.order_option, stoi(*opt));
if (auto opt = options_list.get_if<OptionsList::NumVal>("partial_information");
opt && *opt == "true")
mod_file_struct.partial_information = true;
if (auto opt = options_list.get_if<OptionsList::NumVal>("k_order_solver");
(opt && *opt == "true") || mod_file_struct.order_option >= 3)
mod_file_struct.k_order_solver = true;
if (bool hp = options_list.contains("hp_filter"),
bandpass = options_list.contains("bandpass.indicator"),
one_sided_hp = options_list.contains("one_sided_hp_filter");
(hp && bandpass) || (hp && one_sided_hp) || (bandpass && one_sided_hp))
{
cerr << "ERROR: ramsey_policy: can only use one of hp, one-sided hp, and bandpass filters"
<< endl;
exit(EXIT_FAILURE);
}
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: ramsey_policy: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
RamseyPolicyStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
// Ensure that order 3 implies k_order (#844)
if (auto opt1 = options_list.get_if<OptionsList::NumVal>("order"),
opt2 = options_list.get_if<OptionsList::NumVal>("k_order_solver");
(opt2 && *opt2 == "true") || (opt1 && stoi(*opt1) >= 3))
output << "options_.k_order_solver = true;" << endl;
options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output);
output << "[info, oo_, options_, M_] = stoch_simul(M_, options_, oo_, var_list_);" << endl
<< "oo_.steady_state = oo_.dr.ys;" << endl
<< "oo_.planner_objective_value = evaluate_planner_objective(M_, options_, oo_);" << endl;
}
void
RamseyPolicyStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ramsey_policy")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
EvaluatePlannerObjectiveStatement::EvaluatePlannerObjectiveStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
EvaluatePlannerObjectiveStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "oo_.planner_objective_value = evaluate_planner_objective(M_, options_, oo_);" << endl;
}
void
EvaluatePlannerObjectiveStatement::writeJsonOutput(ostream& output) const
{
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << R"({"statementName": "evaluate_planner_objective"})";
}
DiscretionaryPolicyStatement::DiscretionaryPolicyStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
DiscretionaryPolicyStatement::checkPass(ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
mod_file_struct.discretionary_policy_present = true;
if (!options_list.contains("instruments"))
{
cerr << "ERROR: discretionary_policy: the instruments option is required." << endl;
exit(EXIT_FAILURE);
}
/* Fill in option_order of mod_file_struct
Since discretionary policy needs one further order of derivation (for example, for 1st order
approximation, it needs 2nd derivatives), we add 1 to the order declared by user */
if (auto opt = options_list.get_if<OptionsList::NumVal>("order"))
{
int order = stoi(*opt);
if (order > 1)
{
cerr << "ERROR: discretionary_policy: order > 1 is not yet implemented" << endl;
exit(EXIT_FAILURE);
}
mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1);
}
// Fill in mod_file_struct.partial_information
if (auto opt = options_list.get_if<OptionsList::NumVal>("partial_information");
opt && *opt == "true")
mod_file_struct.partial_information = true;
// Option k_order_solver (implicit when order >= 3)
if (auto opt = options_list.get_if<OptionsList::NumVal>("k_order_solver");
(opt && *opt == "true") || mod_file_struct.order_option >= 3)
mod_file_struct.k_order_solver = true;
// Fill list of instruments
if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("instruments"))
mod_file_struct.instruments = *opt;
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: discretionary_policy: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
DiscretionaryPolicyStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
// Ensure that order 3 implies k_order (#844)
if (auto opt1 = options_list.get_if<OptionsList::NumVal>("order"),
opt2 = options_list.get_if<OptionsList::NumVal>("k_order_solver");
(opt2 && *opt2 == "true") || (opt1 && stoi(*opt1) >= 3))
output << "options_.k_order_solver = true;" << endl;
options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output);
output << "[info, oo_, options_, M_] = discretionary_policy(M_, options_, oo_, var_list_);"
<< endl;
}
void
DiscretionaryPolicyStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "discretionary_policy")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
OccbinSetupStatement::OccbinSetupStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
OccbinSetupStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_occbin_");
output << "[M_, options_] = occbin.setup(M_, options_, options_occbin_);" << endl;
}
void
OccbinSetupStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "occbin_setup")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
OccbinSolverStatement::OccbinSolverStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
OccbinSolverStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_.occbin");
output << "[oo_.dr, oo_.occbin.simul]= occbin.solver(M_, options_, oo_.dr , oo_.steady_state, "
"oo_.exo_steady_state, oo_.exo_det_steady_state);"
<< endl;
}
void
OccbinSolverStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "occbin_solver")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
OccbinWriteRegimesStatement::OccbinWriteRegimesStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
OccbinWriteRegimesStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_.occbin");
output << "occbin.write_regimes_to_xls(oo_.occbin, M_, options_);" << endl;
}
void
OccbinWriteRegimesStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "occbin_write_regimes_xls")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
OccbinGraphStatement::OccbinGraphStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg) :
symbol_list {move(symbol_list_arg)}, options_list {move(options_list_arg)}
{
}
void
OccbinGraphStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
symbol_list.writeOutput("var_list_", output);
options_list.writeOutput(output, "options_occbin_");
output << "occbin.graph(M_, options_, options_occbin_, oo_, var_list_);" << endl;
}
void
OccbinGraphStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "occbin_graph")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
EstimationStatement::EstimationStatement(const SymbolTable& symbol_table_arg,
SymbolList symbol_list_arg, OptionsList options_list_arg) :
symbol_table {symbol_table_arg},
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)}
{
}
void
EstimationStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings)
{
mod_file_struct.estimation_present = true;
// Fill in option_order of mod_file_struct
if (auto opt = options_list.get_if<OptionsList::NumVal>("order"))
{
int order = stoi(*opt);
if (order > 2)
mod_file_struct.k_order_solver = true;
mod_file_struct.order_option = max(mod_file_struct.order_option, order);
}
// Fill in mod_file_struct.partial_information
if (auto opt = options_list.get_if<OptionsList::NumVal>("partial_information");
opt && *opt == "true")
mod_file_struct.partial_information = true;
// Fill in mod_file_struct.estimation_analytic_derivation
if (auto opt = options_list.get_if<OptionsList::NumVal>("analytic_derivation");
opt && *opt == "1")
mod_file_struct.estimation_analytic_derivation = true;
if (options_list.contains("dsge_var"))
options_list.visit("dsge_var", [&]<class T>(const T& v) {
if constexpr (is_same_v<T, OptionsList::StringVal>)
mod_file_struct.dsge_var_estimated = true;
else if constexpr (is_same_v<T, OptionsList::NumVal>)
mod_file_struct.dsge_var_calibrated = v;
});
// Fill in mod_file_struct.bayesian_irf_present
if (auto opt = options_list.get_if<OptionsList::NumVal>("bayesian_irf"); opt && *opt == "true")
mod_file_struct.bayesian_irf_present = true;
if (options_list.contains("dsge_varlag"))
if (mod_file_struct.dsge_var_calibrated.empty() && !mod_file_struct.dsge_var_estimated)
{
cerr << "ERROR: The estimation statement requires a dsge_var option to be passed "
<< "if the dsge_varlag option is passed." << endl;
exit(EXIT_FAILURE);
}
if (!mod_file_struct.dsge_var_calibrated.empty() && mod_file_struct.dsge_var_estimated)
{
cerr << "ERROR: An estimation statement cannot take more than one dsge_var option." << endl;
exit(EXIT_FAILURE);
}
if (!options_list.contains("datafile") && !mod_file_struct.estimation_data_statement_present)
{
cerr << "ERROR: The estimation statement requires a data file to be supplied via the "
"datafile option."
<< endl;
exit(EXIT_FAILURE);
}
if (options_list.contains("mode_file") && mod_file_struct.estim_params_use_calib)
{
cerr << "ERROR: The mode_file option of the estimation statement is incompatible with the "
"use_calibration option of the estimated_params_init block."
<< endl;
exit(EXIT_FAILURE);
}
if (auto opt = options_list.get_if<OptionsList::NumVal>("mh_tune_jscale.status");
opt && *opt == "true")
{
if (options_list.contains("mh_jscale"))
{
cerr << "ERROR: The mh_tune_jscale and mh_jscale options of the estimation statement are "
"incompatible."
<< endl;
exit(EXIT_FAILURE);
}
}
else if (options_list.contains("mh_tune_jscale.guess"))
{
cerr << "ERROR: The option mh_tune_guess in estimation statement cannot be used without "
"option mh_tune_jscale."
<< endl;
exit(EXIT_FAILURE);
}
/* Check that we are not trying to estimate a parameter appearing in the
planner discount factor (see dynare#1173) */
vector<int> estimated_params_in_planner_discount;
set_intersection(mod_file_struct.estimated_parameters.begin(),
mod_file_struct.estimated_parameters.end(),
mod_file_struct.parameters_in_planner_discount.begin(),
mod_file_struct.parameters_in_planner_discount.end(),
back_inserter(estimated_params_in_planner_discount));
if (!estimated_params_in_planner_discount.empty())
{
cerr << "ERROR: It is not possible to estimate a parameter ("
<< symbol_table.getName(estimated_params_in_planner_discount[0])
<< ") that appears in the discount factor of the planner (i.e. in the "
"'planner_discount' option)."
<< endl;
exit(EXIT_FAILURE);
}
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: estimation: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
EstimationStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
// Special treatment for order option and particle filter
if (auto opt = options_list.get_if<OptionsList::NumVal>("order"); !opt)
output << "options_.order = 1;" << endl;
else if (int order {stoi(*opt)}; order >= 2)
{
output << "options_.particle.status = true;" << endl;
if (order > 2)
output << "options_.k_order_solver = true;" << endl;
}
// Do not check for the steady state in diffuse filter mode (#400)
if (auto opt = options_list.get_if<OptionsList::NumVal>("diffuse_filter"); opt && *opt == "true")
output << "options_.steadystate.nocheck = true;" << endl;
symbol_list.writeOutput("var_list_", output);
output << "oo_recursive_=dynare_estimation(var_list_);" << endl;
}
void
EstimationStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "estimation")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
SensitivityStatement::SensitivityStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
SensitivityStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (auto opt = options_list.get_if<OptionsList::NumVal>("identification"); opt && *opt == "1")
{
mod_file_struct.identification_present = true;
// The following triggers 3rd order derivatives, see preprocessor#40
mod_file_struct.identification_order = max(mod_file_struct.identification_order, 2);
}
mod_file_struct.sensitivity_present = true;
}
void
SensitivityStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_gsa");
/* Ensure that nograph, nodisplay and graph_format are also set in top-level
options_.
\todo factorize this code between identification and dynare_sensitivity,
and provide a generic mechanism for this situation (maybe using regexps).
graph_format can then be turned into a VecCellStrVal. */
if (auto opt = options_list.get_if<OptionsList::NumVal>("nodisplay"))
output << "options_.nodisplay = " << *opt << ";" << endl;
if (auto opt = options_list.get_if<OptionsList::NumVal>("nograph"))
output << "options_.nograph = " << *opt << ";" << endl;
if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format"))
opt->writeOutput("options_.graph_format", output);
output << "gsa.run(M_,oo_,options_,bayestopt_,estim_params_,options_gsa);" << endl;
}
void
SensitivityStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "sensitivity")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
RplotStatement::RplotStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)}, symbol_table {symbol_table_arg}
{
}
void
RplotStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous, SymbolType::exogenous},
symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: rplot: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
RplotStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
symbol_list.writeOutput("var_list_", output);
output << "rplot(var_list_);" << endl;
}
void
RplotStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "rplot")";
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
void
UnitRootVarsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_.diffuse_filter = 1;" << endl << "options_.steadystate.nocheck = 1;" << endl;
}
void
UnitRootVarsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "unit_root_vars", )"
<< R"("diffuse_filter": 1, )"
<< R"("steady_state.nocheck": 1})";
}
DsampleStatement::DsampleStatement(int val1_arg) : val1 {val1_arg}, val2 {-1}
{
}
DsampleStatement::DsampleStatement(int val1_arg, int val2_arg) : val1 {val1_arg}, val2 {val2_arg}
{
}
void
DsampleStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (val2 < 0)
output << "dsample(" << val1 << ");" << endl;
else
output << "dsample(" << val1 << ", " << val2 << ");" << endl;
}
void
DsampleStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "dsample", )"
<< R"("value1": )" << val1 << ", "
<< R"("value2": )" << val2 << "}";
}
AbstractEstimatedParamsStatement::AbstractEstimatedParamsStatement(
vector<EstimationParams> estim_params_list_arg, const SymbolTable& symbol_table_arg) :
estim_params_list {move(estim_params_list_arg)}, symbol_table {symbol_table_arg}
{
}
void
AbstractEstimatedParamsStatement::commonCheckPass() const
{
// Check that no parameter/endogenous is declared twice in the block.
/* In the case of the estimated_params block, there is a similar check across
concatenated blocks that is implemented in the writeOutput() method. */
set<string> already_declared;
set<pair<string, string>> already_declared_corr;
for (const auto& it : estim_params_list)
{
if (it.type == 3) // Correlation
{
// Use lexical ordering for the pair of symbols
auto x = it.name < it.name2 ? pair {it.name, it.name2} : pair {it.name2, it.name};
if (already_declared_corr.contains(x))
{
cerr << "ERROR: in `" << blockName() << "' block, the correlation between " << it.name
<< " and " << it.name2 << " is declared twice." << endl;
exit(EXIT_FAILURE);
}
else
already_declared_corr.insert(x);
}
else
{
if (already_declared.contains(it.name))
{
cerr << "ERROR: in `" << blockName() << "' block, the symbol " << it.name
<< " is declared twice." << endl;
exit(EXIT_FAILURE);
}
else
already_declared.insert(it.name);
}
}
/* Check that a parameter declared in this block is not used in expressions
associated to other parameters in the same block (see issue #77) */
// First compute the symbol IDs of parameters declared in this block
set<int> declared_params;
for (const string& name : already_declared)
if (name != "dsge_prior_weight")
declared_params.insert(symbol_table.getID(name));
// Then look for (apparently) recursive definitions
for (const auto& it : estim_params_list)
{
set<int> used_params;
it.init_val->collectVariables(SymbolType::parameter, used_params);
it.low_bound->collectVariables(SymbolType::parameter, used_params);
it.up_bound->collectVariables(SymbolType::parameter, used_params);
it.mean->collectVariables(SymbolType::parameter, used_params);
it.std->collectVariables(SymbolType::parameter, used_params);
it.p3->collectVariables(SymbolType::parameter, used_params);
it.p4->collectVariables(SymbolType::parameter, used_params);
it.jscale->collectVariables(SymbolType::parameter, used_params);
vector<int> intersect;
set_intersection(declared_params.begin(), declared_params.end(), used_params.begin(),
used_params.end(), back_inserter(intersect));
if (intersect.size() > 0)
{
cerr << "ERROR: in `" << blockName() << "' block, the value of estimated parameter "
<< symbol_table.getName(intersect[0]) << " is used in the declaration for ";
if (it.type == 3)
cerr << "correlation between " << it.name << " and " << it.name2;
else // either a parameter, the stderr of an exo, or the measurement error of an endo
cerr << "symbol " << it.name;
cerr << ". This behaviour is undefined." << endl;
exit(EXIT_FAILURE);
}
}
}
EstimatedParamsStatement::EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable& symbol_table_arg,
bool overwrite_arg) :
AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg),
overwrite {overwrite_arg}
{
}
void
EstimatedParamsStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
commonCheckPass();
for (const auto& it : estim_params_list)
{
if (it.name == "dsge_prior_weight")
mod_file_struct.dsge_prior_weight_in_estimated_params = true;
// Handle case of degenerate beta prior
if (it.prior == PriorDistributions::beta)
try
{
if (it.mean->eval(eval_context_t()) == 0.5 && it.std->eval(eval_context_t()) == 0.5)
{
cerr << "ERROR: The prior density is not defined for the beta distribution when "
"the mean = standard deviation = 0.5."
<< endl;
exit(EXIT_FAILURE);
}
}
catch (ExprNode::EvalException& e)
{
// We don't have enough information to compute the numerical value, skip the test
}
}
// Fill in mod_file_struct.estimated_parameters (related to #469)
for (const auto& it : estim_params_list)
if (it.type == 2 && it.name != "dsge_prior_weight")
mod_file_struct.estimated_parameters.insert(symbol_table.getID(it.name));
}
void
EstimatedParamsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string indent;
if (!overwrite)
{
output << "if isempty(estim_params_)" << endl;
indent = " ";
}
output << indent << "estim_params_.var_exo = zeros(0, 10);" << endl
<< indent << "estim_params_.var_endo = zeros(0, 10);" << endl
<< indent << "estim_params_.corrx = zeros(0, 11);" << endl
<< indent << "estim_params_.corrn = zeros(0, 11);" << endl
<< indent << "estim_params_.param_vals = zeros(0, 10);" << endl;
if (!overwrite)
output << "end" << endl;
/* Note that we verify that parameters are not declared twice across
concatenated blocks, because this case is not covered by the check
implemented in AbstractEstimatedParamsStatement::commonCheckPass() */
for (const auto& it : estim_params_list)
{
int tsid = symbol_table.getTypeSpecificID(it.name) + 1;
int tsid2;
SymbolType symb_type = symbol_table.getType(it.name);
string errmsg = " has been specified twice in two concatenated ''estimated_params'' blocks. "
"Depending on your intention, you may want to use the ''overwrite'' option "
"or an ''estimated_params_remove'' block.";
switch (it.type)
{
case 1:
if (symb_type == SymbolType::exogenous)
output << "if ~isempty(find(estim_params_.var_exo(:,1)==" << tsid << "))" << endl
<< " error('The standard deviation for " << it.name << errmsg << "')" << endl
<< "end" << endl
<< "estim_params_.var_exo = [estim_params_.var_exo; ";
else if (symb_type == SymbolType::endogenous)
output << "if ~isempty(find(estim_params_.var_endo(:,1)==" << tsid << "))" << endl
<< " error('The standard deviation of the measurement error for " << it.name
<< errmsg << "')" << endl
<< "end" << endl
<< "estim_params_.var_endo = [estim_params_.var_endo; ";
output << tsid;
break;
case 2:
output << "if ~isempty(find(estim_params_.param_vals(:,1)==" << tsid << "))" << endl
<< " error('Parameter " << it.name << errmsg << "')" << endl
<< "end" << endl
<< "estim_params_.param_vals = [estim_params_.param_vals; " << tsid;
break;
case 3:
tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1;
if (symb_type == SymbolType::exogenous)
output << "if ~isempty(find((estim_params_.corrx(:,1)==" << tsid
<< " & estim_params_.corrx(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrx(:,2)==" << tsid
<< " & estim_params_.corrx(:,1)==" << tsid2 << ")))" << endl
<< " error('The correlation between " << it.name << " and " << it.name2
<< errmsg << "')" << endl
<< "end" << endl
<< "estim_params_.corrx = [estim_params_.corrx; ";
else if (symb_type == SymbolType::endogenous)
output << "if ~isempty(find((estim_params_.corrn(:,1)==" << tsid
<< " & estim_params_.corrn(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrn(:,2)==" << tsid
<< " & estim_params_.corrn(:,1)==" << tsid2 << ")))" << endl
<< " error('The correlation between measurement errors on " << it.name
<< " and " << it.name2 << errmsg << "')" << endl
<< "end" << endl
<< "estim_params_.corrn = [estim_params_.corrn; ";
output << tsid << ", " << symbol_table.getTypeSpecificID(it.name2) + 1;
break;
}
output << ", ";
it.init_val->writeOutput(output);
output << ", ";
it.low_bound->writeOutput(output);
output << ", ";
it.up_bound->writeOutput(output);
output << ", " << static_cast<int>(it.prior) << ", ";
it.mean->writeOutput(output);
output << ", ";
it.std->writeOutput(output);
output << ", ";
it.p3->writeOutput(output);
output << ", ";
it.p4->writeOutput(output);
output << ", ";
it.jscale->writeOutput(output);
output << " ];" << endl;
}
}
void
EstimatedParamsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "estimated_params", )"
<< R"("params": [)";
for (bool printed_something {false}; const auto& it : estim_params_list)
{
if (exchange(printed_something, true))
output << ", ";
output << "{";
switch (it.type)
{
case 1:
output << R"("var": ")" << it.name << R"(")";
break;
case 2:
output << R"("param": ")" << it.name << R"(")";
break;
case 3:
output << R"("var1": ")" << it.name << R"(",)"
<< R"("var2": ")" << it.name2 << R"(")";
break;
}
output << R"(, "init_val": ")";
it.init_val->writeJsonOutput(output, {}, {});
output << R"(", "lower_bound": ")";
it.low_bound->writeJsonOutput(output, {}, {});
output << R"(", "upper_bound": ")";
it.up_bound->writeJsonOutput(output, {}, {});
output << R"(", "prior_distribution": )" << static_cast<int>(it.prior) << R"(, "mean": ")";
it.mean->writeJsonOutput(output, {}, {});
output << R"(", "std": ")";
it.std->writeJsonOutput(output, {}, {});
output << R"(", "p3": ")";
it.p3->writeJsonOutput(output, {}, {});
output << R"(", "p4": ")";
it.p4->writeJsonOutput(output, {}, {});
output << R"(", "jscale": ")";
it.jscale->writeJsonOutput(output, {}, {});
output << R"("})" << endl;
}
output << "]"
<< "}";
}
EstimatedParamsInitStatement::EstimatedParamsInitStatement(
vector<EstimationParams> estim_params_list_arg, const SymbolTable& symbol_table_arg,
const bool use_calibration_arg) :
AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg),
use_calibration {use_calibration_arg}
{
}
void
EstimatedParamsInitStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
commonCheckPass();
if (use_calibration)
mod_file_struct.estim_params_use_calib = true;
}
void
EstimatedParamsInitStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (use_calibration)
output << "options_.use_calibration_initialization = 1;" << endl;
bool skipline = false;
for (const auto& it : estim_params_list)
{
int tsid = symbol_table.getTypeSpecificID(it.name) + 1;
SymbolType symb_type = symbol_table.getType(it.name);
if (it.type < 3)
{
if (symb_type == SymbolType::exogenous)
{
output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl
<< " disp(sprintf('The standard deviation of %s is not estimated (the "
"value provided in estimated_params_init is not used).', M_.exo_names{"
<< tsid << "}))" << endl;
skipline = true;
output << "else" << endl << " estim_params_.var_exo(tmp1,2) = ";
it.init_val->writeOutput(output);
output << ";" << endl << "end" << endl;
}
else if (symb_type == SymbolType::endogenous)
{
output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl
<< " disp(sprintf('The standard deviation of the measurement error on %s "
"is not estimated (the value provided in estimated_params_init is not "
"used).', M_.endo_names{"
<< tsid << "}))" << endl;
skipline = true;
output << "else" << endl << " estim_params_.var_endo(tmp1,2) = ";
it.init_val->writeOutput(output);
output << ";" << endl << "end" << endl;
}
else if (symb_type == SymbolType::parameter)
{
output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl
<< " disp(sprintf('Parameter %s is not estimated (the value provided in "
"estimated_params_init is not used).', M_.param_names{"
<< tsid << "}))" << endl;
skipline = true;
output << "else" << endl << " estim_params_.param_vals(tmp1,2) = ";
it.init_val->writeOutput(output);
output << ";" << endl << "end" << endl;
}
}
else
{
int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1;
if (symb_type == SymbolType::exogenous)
{
output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid
<< " & estim_params_.corrx(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrx(:,2)==" << tsid
<< " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl
<< "if isempty(tmp1)" << endl
<< " disp(sprintf('The correlation between %s and %s is not estimated (the "
"value provided in estimated_params_init is not used).', M_.exo_names{"
<< tsid << "}, M_.exo_names{" << tsid2 << "}))" << endl;
skipline = true;
output << "else" << endl << " estim_params_.corrx(tmp1,3) = ";
it.init_val->writeOutput(output);
output << ";" << endl << "end" << endl;
}
else if (symb_type == SymbolType::endogenous)
{
output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid
<< " & estim_params_.corrn(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrn(:,2)==" << tsid
<< " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl
<< "if isempty(tmp1)" << endl
<< " disp(sprintf('The correlation between measurement errors on %s and %s "
"is not estimated (the value provided in estimated_params_init is not "
"used).', M_.endo_names{"
<< tsid << "}, M_.endo_names{" << tsid2 << "}))" << endl;
skipline = true;
output << "else" << endl << " estim_params_.corrn(tmp1,3) = ";
it.init_val->writeOutput(output);
output << ";" << endl << "end" << endl;
}
}
}
if (skipline == true)
output << "skipline()" << endl;
}
void
EstimatedParamsInitStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "estimated_params_init")";
if (use_calibration)
output << R"(, "use_calibration_initialization": 1)";
output << R"(, "params": [)";
for (bool printed_something {false}; const auto& it : estim_params_list)
{
if (exchange(printed_something, true))
output << ", ";
output << "{";
switch (it.type)
{
case 1:
output << R"("var": ")" << it.name << R"(")";
break;
case 2:
output << R"("param": ")" << it.name << R"(")";
break;
case 3:
output << R"("var1": ")" << it.name << R"(",)"
<< R"("var2": ")" << it.name2 << R"(")";
break;
}
output << R"(, "init_val": ")";
it.init_val->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]"
<< "}";
}
EstimatedParamsBoundsStatement::EstimatedParamsBoundsStatement(
vector<EstimationParams> estim_params_list_arg, const SymbolTable& symbol_table_arg) :
AbstractEstimatedParamsStatement(move(estim_params_list_arg), symbol_table_arg)
{
}
void
EstimatedParamsBoundsStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
commonCheckPass();
}
void
EstimatedParamsBoundsStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
for (const auto& it : estim_params_list)
{
int tsid = symbol_table.getTypeSpecificID(it.name) + 1;
SymbolType symb_type = symbol_table.getType(it.name);
if (it.type < 3)
{
if (symb_type == SymbolType::exogenous)
{
output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl
<< "estim_params_.var_exo(tmp1,3) = ";
it.low_bound->writeOutput(output);
output << ";" << endl << "estim_params_.var_exo(tmp1,4) = ";
it.up_bound->writeOutput(output);
output << ";" << endl;
}
else if (symb_type == SymbolType::endogenous)
{
output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl
<< "estim_params_.var_endo(tmp1,3) = ";
it.low_bound->writeOutput(output);
output << ";" << endl << "estim_params_.var_endo(tmp1,4) = ";
it.up_bound->writeOutput(output);
output << ";" << endl;
}
else if (symb_type == SymbolType::parameter)
{
output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl
<< "estim_params_.param_vals(tmp1,3) = ";
it.low_bound->writeOutput(output);
output << ";" << endl << "estim_params_.param_vals(tmp1,4) = ";
it.up_bound->writeOutput(output);
output << ";" << endl;
}
}
else
{
int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1;
if (symb_type == SymbolType::exogenous)
{
output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid
<< " & estim_params_.corrx(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrx(:,2)==" << tsid
<< " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl
<< "estim_params_.corrx(tmp1,4) = ";
it.low_bound->writeOutput(output);
output << ";" << endl << "estim_params_.corrx(tmp1,5) = ";
it.up_bound->writeOutput(output);
output << ";" << endl;
}
else if (symb_type == SymbolType::endogenous)
{
output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid
<< " & estim_params_.corrn(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrn(:,2)==" << tsid
<< " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl
<< "estim_params_.corrn(tmp1,4) = ";
it.low_bound->writeOutput(output);
output << ";" << endl << "estim_params_.corrn(tmp1,5) = ";
it.up_bound->writeOutput(output);
output << ";" << endl;
}
}
}
}
void
EstimatedParamsBoundsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "estimated_params_bounds", )"
<< R"("params": [)";
for (bool printed_something {false}; const auto& it : estim_params_list)
{
if (exchange(printed_something, true))
output << ", ";
output << "{";
switch (it.type)
{
case 1:
output << R"("var": ")" << it.name << R"(")";
break;
case 2:
output << R"("param": ")" << it.name << R"(")";
break;
case 3:
output << R"("var1": ")" << it.name << R"(",)"
<< R"("var2": ")" << it.name2 << R"(")";
break;
}
output << R"(, "lower_bound": )";
it.low_bound->writeJsonOutput(output, {}, {});
output << R"(, "upper_bound": )";
it.up_bound->writeJsonOutput(output, {}, {});
output << "}";
}
output << "]"
<< "}";
}
EstimatedParamsRemoveStatement::EstimatedParamsRemoveStatement(
vector<EstimationParams> estim_params_list_arg, const SymbolTable& symbol_table_arg) :
estim_params_list {move(estim_params_list_arg)}, symbol_table {symbol_table_arg}
{
}
void
EstimatedParamsRemoveStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
for (const auto& it : estim_params_list)
{
int tsid = symbol_table.getTypeSpecificID(it.name) + 1;
SymbolType symb_type = symbol_table.getType(it.name);
if (it.type < 3)
{
if (symb_type == SymbolType::exogenous)
output << "tmp1 = find(estim_params_.var_exo(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: the standard deviation of %s is "
"not estimated.', M_.exo_names{"
<< tsid << "}))" << endl
<< "else" << endl
<< " estim_params_.var_exo(tmp1,:) = [];"
<< "end" << endl;
else if (symb_type == SymbolType::endogenous)
output << "tmp1 = find(estim_params_.var_endo(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: the standard deviation of the "
"measurement error on %s is not estimated.', M_.endo_names{"
<< tsid << "}))" << endl
<< "else" << endl
<< " estim_params_.var_endo(tmp1,:) = [];"
<< "end" << endl;
else if (symb_type == SymbolType::parameter)
output << "tmp1 = find(estim_params_.param_vals(:,1)==" << tsid << ");" << endl
<< "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: parameter %s is not "
"estimated.', M_.param_names{"
<< tsid << "}))" << endl
<< "else" << endl
<< " estim_params_.param_vals(tmp1,:) = [];"
<< "end" << endl;
}
else
{
int tsid2 = symbol_table.getTypeSpecificID(it.name2) + 1;
if (symb_type == SymbolType::exogenous)
output << "tmp1 = find((estim_params_.corrx(:,1)==" << tsid
<< " & estim_params_.corrx(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrx(:,2)==" << tsid
<< " & estim_params_.corrx(:,1)==" << tsid2 << "));" << endl
<< "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: the correlation between %s and "
"%s is not estimated.', M_.exo_names{"
<< tsid << "}, M_.exo_names{" << tsid2 << "}))" << endl
<< "else" << endl
<< " estim_params_.corrx(tmp1,:) = [];"
<< "end" << endl;
else if (symb_type == SymbolType::endogenous)
output << "tmp1 = find((estim_params_.corrn(:,1)==" << tsid
<< " & estim_params_.corrn(:,2)==" << tsid2 << ") | "
<< "(estim_params_.corrn(:,2)==" << tsid
<< " & estim_params_.corrn(:,1)==" << tsid2 << "));" << endl
<< "if isempty(tmp1)" << endl
<< " error(sprintf('estimated_params_remove: the correlation between "
"measurement errors on %s and %s is not estimated.', M_.endo_names{"
<< tsid << "}, M_.endo_names{" << tsid2 << "}))" << endl
<< "else" << endl
<< " estim_params_.corrn(tmp1,:) = [];"
<< "end" << endl;
}
}
}
void
EstimatedParamsRemoveStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "estimated_params_remove", )"
<< R"("params": [)";
for (bool printed_something {false}; const auto& it : estim_params_list)
{
if (exchange(printed_something, true))
output << ", ";
output << "{";
switch (it.type)
{
case 1:
output << R"("var": ")" << it.name << R"(")";
break;
case 2:
output << R"("param": ")" << it.name << R"(")";
break;
case 3:
output << R"("var1": ")" << it.name << R"(",)"
<< R"("var2": ")" << it.name2 << R"(")";
break;
}
output << "}";
}
output << "]"
<< "}";
}
DeterministicTrendsStatement::DeterministicTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg) :
trend_elements {move(trend_elements_arg)}, symbol_table {symbol_table_arg}
{
}
void
DeterministicTrendsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_.trend_coeff = {};" << endl;
for (const auto& trend_element : trend_elements)
{
SymbolType type = symbol_table.getType(trend_element.first);
if (type == SymbolType::endogenous)
{
output << "tmp1 = strmatch('" << trend_element.first << "',M_.endogenous_names,'exact');"
<< endl;
output << "options_.deterministic_trend_coeffs{tmp1} = '";
trend_element.second->writeOutput(output);
output << "';" << endl;
}
else
cerr << "Warning : Non-variable symbol used in deterministic_trends: "
<< trend_element.first << endl;
}
}
void
DeterministicTrendsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "deterministic_trends", )"
<< R"("trends" : {)";
for (bool printed_something {false}; const auto& trend_element : trend_elements)
{
if (symbol_table.getType(trend_element.first) == SymbolType::endogenous)
{
if (exchange(printed_something, true))
output << ", ";
output << R"(")" << trend_element.first << R"(": ")";
trend_element.second->writeJsonOutput(output, {}, {});
output << R"(")" << endl;
}
else
cerr << "Warning : Non-variable symbol used in deterministic_trends: "
<< trend_element.first << endl;
}
output << "}"
<< "}";
}
ObservationTrendsStatement::ObservationTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg) :
trend_elements {move(trend_elements_arg)}, symbol_table {symbol_table_arg}
{
}
void
ObservationTrendsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_.trend_coeff = {};" << endl;
for (const auto& trend_element : trend_elements)
{
SymbolType type = symbol_table.getType(trend_element.first);
if (type == SymbolType::endogenous)
{
output << "tmp1 = strmatch('" << trend_element.first << "',options_.varobs,'exact');"
<< endl;
output << "options_.trend_coeffs{tmp1} = '";
trend_element.second->writeOutput(output);
output << "';" << endl;
}
else
cerr << "Warning : Non-variable symbol used in observation_trends: " << trend_element.first
<< endl;
}
}
void
ObservationTrendsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "observation_trends", )"
<< R"("trends" : {)";
for (bool printed_something {false}; const auto& trend_element : trend_elements)
{
if (symbol_table.getType(trend_element.first) == SymbolType::endogenous)
{
if (exchange(printed_something, true))
output << ", ";
output << R"(")" << trend_element.first << R"(": ")";
trend_element.second->writeJsonOutput(output, {}, {});
output << R"(")" << endl;
}
else
cerr << "Warning : Non-variable symbol used in observation_trends: " << trend_element.first
<< endl;
}
output << "}"
<< "}";
}
FilterInitialStateStatement::FilterInitialStateStatement(
filter_initial_state_elements_t filter_initial_state_elements_arg,
const SymbolTable& symbol_table_arg) :
filter_initial_state_elements {move(filter_initial_state_elements_arg)},
symbol_table {symbol_table_arg}
{
}
void
FilterInitialStateStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "M_.filter_initial_state = cell(M_.endo_nbr, 2);" << endl;
for (const auto& [key, val] : filter_initial_state_elements)
{
auto [symb_id, lag] = key;
SymbolType type = symbol_table.getType(symb_id);
if ((type == SymbolType::endogenous && lag < 0) || type == SymbolType::exogenous)
{
try
{
// This function call must remain the 1st statement in this block
symb_id = symbol_table.searchAuxiliaryVars(symb_id, lag);
}
catch (SymbolTable::SearchFailedException& e)
{
if (type == SymbolType::endogenous)
{
cerr << "filter_initial_state: internal error, please contact the developers";
exit(EXIT_FAILURE);
}
// We don't fail for exogenous, because they are not replaced by
// auxiliary variables in deterministic mode.
}
}
output << "M_.filter_initial_state(" << symbol_table.getTypeSpecificID(symb_id) + 1
<< ",:) = {'" << symbol_table.getName(symb_id) << "', '";
val->writeOutput(output);
output << ";'};" << endl;
}
}
void
FilterInitialStateStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "filter_initial_state", )"
<< R"("states": [)";
for (bool printed_something {false}; const auto& [key, val] : filter_initial_state_elements)
{
if (exchange(printed_something, true))
output << ", ";
auto& [symb_id, lag] = key;
output << R"({ "var": ")" << symbol_table.getName(symb_id) << R"(", "lag": )" << lag
<< R"(, "value": ")";
val->writeJsonOutput(output, {}, {});
output << R"(" })";
}
output << "] }";
}
OsrParamsStatement::OsrParamsStatement(SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)}, symbol_table {symbol_table_arg}
{
}
void
OsrParamsStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings)
{
if (mod_file_struct.osr_params_present)
cerr << "WARNING: You have more than one osr_params statement in the .mod file." << endl;
mod_file_struct.osr_params_present = true;
try
{
symbol_list.checkPass(warnings, {SymbolType::parameter}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: osr: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
OsrParamsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
symbol_list.writeOutput("M_.osr.param_names", output);
output << "M_.osr.param_names = cellstr(M_.osr.param_names);" << endl
<< "M_.osr.param_indices = zeros(length(M_.osr.param_names), 1);" << endl;
for (int i {0}; auto& symbol : symbol_list.getSymbols())
output << "M_.osr.param_indices(" << ++i << ") = " << symbol_table.getTypeSpecificID(symbol) + 1
<< ";" << endl;
}
void
OsrParamsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "osr_params")";
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
OsrParamsBoundsStatement::OsrParamsBoundsStatement(vector<OsrParams> osr_params_list_arg) :
osr_params_list {move(osr_params_list_arg)}
{
}
void
OsrParamsBoundsStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (!mod_file_struct.osr_params_present)
{
cerr << "ERROR: you must have an osr_params statement before the osr_params_bounds block."
<< endl;
exit(EXIT_FAILURE);
}
}
void
OsrParamsBoundsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "M_.osr.param_bounds = [-inf(length(M_.osr.param_names), 1), "
"inf(length(M_.osr.param_names), 1)];"
<< endl;
for (const auto& it : osr_params_list)
{
output << "M_.osr.param_bounds(strcmp(M_.osr.param_names, '" << it.name << "'), :) = [";
it.low_bound->writeOutput(output);
output << ", ";
it.up_bound->writeOutput(output);
output << "];" << endl;
}
}
void
OsrParamsBoundsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "osr_params_bounds")"
<< R"(, "bounds": [)";
for (bool printed_something {false}; const auto& it : osr_params_list)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"parameter": ")" << it.name << R"(",)"
<< R"("bounds": [")";
it.low_bound->writeJsonOutput(output, {}, {});
output << R"(", ")";
it.up_bound->writeJsonOutput(output, {}, {});
output << R"("])"
<< "}";
}
output << "]"
<< "}";
}
OsrStatement::OsrStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
OsrStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings)
{
mod_file_struct.osr_present = true;
// Fill in option_order of mod_file_struct
if (auto opt = options_list.get_if<OptionsList::NumVal>("order"))
mod_file_struct.order_option = max(mod_file_struct.order_option, stoi(*opt));
// Fill in mod_file_struct.partial_information
if (auto opt = options_list.get_if<OptionsList::NumVal>("partial_information");
opt && *opt == "true")
mod_file_struct.partial_information = true;
// Fill in mod_file_struct.estimation_analytic_derivation
if (auto opt = options_list.get_if<OptionsList::NumVal>("analytic_derivation");
opt && *opt == "1")
mod_file_struct.osr_analytic_derivation = true;
// Option k_order_solver (implicit when order >= 3)
if (auto opt = options_list.get_if<OptionsList::NumVal>("k_order_solver");
(opt && *opt == "true") || mod_file_struct.order_option >= 3)
mod_file_struct.k_order_solver = true;
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: osr: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
OsrStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
// Ensure that order 3 implies k_order (#844)
if (auto opt1 = options_list.get_if<OptionsList::NumVal>("order"),
opt2 = options_list.get_if<OptionsList::NumVal>("k_order_solver");
(opt2 && *opt2 == "true") || (opt1 && stoi(*opt1) >= 3))
output << "options_.k_order_solver = true;" << endl;
options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output);
output << "[info, oo_, options_, M_] = osr.run(M_, options_, oo_, "
"var_list_,M_.osr.param_names,M_.osr.variable_indices,M_.osr.variable_weights);"
<< endl;
}
void
OsrStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "osr")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
OptimWeightsStatement::OptimWeightsStatement(var_weights_t var_weights_arg,
covar_weights_t covar_weights_arg,
const SymbolTable& symbol_table_arg) :
var_weights {move(var_weights_arg)},
covar_weights {move(covar_weights_arg)},
symbol_table {symbol_table_arg}
{
}
void
OptimWeightsStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.optim_weights_present = true;
}
void
OptimWeightsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "%" << endl
<< "% OPTIM_WEIGHTS" << endl
<< "%" << endl
<< "M_.osr.variable_weights = sparse(M_.endo_nbr,M_.endo_nbr);" << endl
<< "M_.osr.variable_indices = [];" << endl
<< endl;
for (const auto& [name, value] : var_weights)
{
int id = symbol_table.getTypeSpecificID(name) + 1;
output << "M_.osr.variable_weights(" << id << "," << id << ") = ";
value->writeOutput(output);
output << ";" << endl;
output << "M_.osr.variable_indices = [M_.osr.variable_indices; " << id << "];" << endl;
}
for (const auto& [names, value] : covar_weights)
{
int id1 = symbol_table.getTypeSpecificID(names.first) + 1;
int id2 = symbol_table.getTypeSpecificID(names.second) + 1;
output << "M_.osr.variable_weights(" << id1 << "," << id2 << ") = ";
value->writeOutput(output);
output << ";" << endl;
output << "M_.osr.variable_indices = [M_.osr.variable_indices; " << id1 << "; " << id2 << "];"
<< endl;
}
}
void
OptimWeightsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "optim_weights", )"
<< R"("weights": [)";
bool printed_something {false};
for (const auto& [name, value] : var_weights)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"name": ")" << name << R"(")"
<< R"(, "value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
}
for (const auto& [names, value] : covar_weights)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"name1": ")" << names.first << R"(")"
<< R"(, "name2": ")" << names.second << R"(")"
<< R"(, "value": ")";
value->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}
DynaSaveStatement::DynaSaveStatement(SymbolList symbol_list_arg, string filename_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
filename {move(filename_arg)},
symbol_table {symbol_table_arg}
{
}
void
DynaSaveStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous, SymbolType::exogenous},
symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: dynasave: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
DynaSaveStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
symbol_list.writeOutput("var_list_", output);
output << "dynasave('" << filename << "',var_list_);" << endl;
}
void
DynaSaveStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "dynasave", )"
<< R"("filename": ")" << filename << R"(")";
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
DynaTypeStatement::DynaTypeStatement(SymbolList symbol_list_arg, string filename_arg,
const SymbolTable& symbol_table_arg) :
symbol_list(move(symbol_list_arg)),
filename(move(filename_arg)),
symbol_table {symbol_table_arg}
{
}
void
DynaTypeStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous, SymbolType::exogenous},
symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: dynatype: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
DynaTypeStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
symbol_list.writeOutput("var_list_", output);
output << "dynatype('" << filename << "',var_list_);" << endl;
}
void
DynaTypeStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "dynatype", )"
<< R"("filename": ")" << filename << R"(")";
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
ModelComparisonStatement::ModelComparisonStatement(filename_list_t filename_list_arg,
OptionsList options_list_arg) :
filename_list {move(filename_list_arg)}, options_list {move(options_list_arg)}
{
}
void
ModelComparisonStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "ModelNames_ = {};" << endl << "ModelPriors_ = [];" << endl;
for (const auto& [name, prior] : filename_list)
output << "ModelNames_ = { ModelNames_{:} '" << name << "'};" << endl
<< "ModelPriors_ = [ ModelPriors_ ; " << prior << "];" << endl;
output << "oo_ = model_comparison(ModelNames_,ModelPriors_,oo_,options_,M_.fname);" << endl;
}
void
ModelComparisonStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "model_comparison")";
if (!filename_list.empty())
output << R"(, "filename_list": {)";
for (bool printed_something {false}; const auto& [name, prior] : filename_list)
{
if (exchange(printed_something, true))
output << ", ";
output << R"("name": ")" << name << R"(")"
<< R"("prior": ")" << prior << R"(")";
}
if (!filename_list.empty())
output << "}";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
PlannerObjectiveStatement::PlannerObjectiveStatement(unique_ptr<PlannerObjective> model_tree_arg) :
model_tree {move(model_tree_arg)}
{
}
void
PlannerObjectiveStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
assert(model_tree->equation_number() == 1);
if (model_tree->exoPresentInEqs())
{
cerr << "ERROR: You cannot include exogenous variables (or variables of undeclared type) in "
"the planner objective. Please "
<< "define an auxiliary endogenous variable like eps_aux=epsilon and use it instead "
<< "of the varexo." << endl;
exit(EXIT_FAILURE);
}
mod_file_struct.planner_objective_present = true;
}
const PlannerObjective&
PlannerObjectiveStatement::getPlannerObjective() const
{
return *model_tree;
}
void
PlannerObjectiveStatement::computingPass(const ModFileStructure& mod_file_struct)
{
model_tree->computingPass(max(3, mod_file_struct.order_option), 0, {}, false, false, false);
computing_pass_called = true;
}
void
PlannerObjectiveStatement::writeOutput(ostream& output, const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "M_.NNZDerivatives_objective = [";
for (int i = 1; i < static_cast<int>(model_tree->getNNZDerivatives().size()); i++)
output << (i > model_tree->getComputedDerivsOrder() ? -1 : model_tree->getNNZDerivatives()[i])
<< ";";
output << "];" << endl << "M_.objective_tmp_nbr = [";
for (const auto& temporary_terms_derivative : model_tree->getTemporaryTermsDerivatives())
output << temporary_terms_derivative.size() << "; ";
output << "];" << endl;
model_tree->writeStaticFile(basename + ".objective", false, "", {}, false);
}
void
PlannerObjectiveStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "planner_objective")"
<< ", ";
if (computing_pass_called)
model_tree->writeJsonComputingPassOutput(output, false);
else
model_tree->writeJsonOutput(output);
output << "}";
}
BVARDensityStatement::BVARDensityStatement(int maxnlags_arg, OptionsList options_list_arg) :
maxnlags {maxnlags_arg}, options_list {move(options_list_arg)}
{
}
void
BVARDensityStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
}
void
BVARDensityStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "bvar.density(" << maxnlags << ");" << endl;
}
void
BVARDensityStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "bvar_density")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
BVARForecastStatement::BVARForecastStatement(int nlags_arg, OptionsList options_list_arg) :
nlags {nlags_arg}, options_list {move(options_list_arg)}
{
}
void
BVARForecastStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
}
void
BVARForecastStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "bvar.forecast(" << nlags << ");" << endl;
}
void
BVARForecastStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "bvar_forecast")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
BVARIRFStatement::BVARIRFStatement(int nirf_arg, string identificationname_arg) :
nirf {nirf_arg}, identificationname {move(identificationname_arg)}
{
}
void
BVARIRFStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
}
void
BVARIRFStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "bvar.irf(" << nirf << ",'" << identificationname << "');" << endl;
}
void
BVARIRFStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "bvar_irf")";
output << "}";
}
SBVARStatement::SBVARStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
{
}
void
SBVARStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
}
void
SBVARStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "sbvar(M_,options_);" << endl;
}
void
SBVARStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "sbvar")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
MSSBVAREstimationStatement::MSSBVAREstimationStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
MSSBVAREstimationStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
if (!options_list.contains("ms.create_init")
&& (!options_list.contains("datafile") || !options_list.contains("ms.initial_year")))
{
cerr << "ERROR: If you do not pass no_create_init to ms_estimation, "
<< "you must pass the datafile and initial_year options." << endl;
exit(EXIT_FAILURE);
}
}
void
MSSBVAREstimationStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl
<< "options_.datafile = '';" << endl;
options_list.writeOutput(output);
output << "[options_, oo_] = ms_estimation(M_, options_, oo_);" << endl;
}
void
MSSBVAREstimationStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ms_sbvar_estimation")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
MSSBVARSimulationStatement::MSSBVARSimulationStatement(OptionsList options_list_arg) :
options_list(move(options_list_arg))
{
}
void
MSSBVARSimulationStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
}
void
MSSBVARSimulationStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
options_list.writeOutput(output);
// Redeclare drop option if necessary
if ((options_list.contains("ms.mh_replic") || options_list.contains("ms.thinning_factor"))
&& !options_list.contains("ms.drop"))
output << "options_.ms.drop = 0.1*options_.ms.mh_replic*options_.ms.thinning_factor;" << endl;
output << "[options_, oo_] = ms_simulation(M_, options_, oo_);" << endl;
}
void
MSSBVARSimulationStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ms_sbvar_simulation")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
MSSBVARComputeMDDStatement::MSSBVARComputeMDDStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
MSSBVARComputeMDDStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
}
void
MSSBVARComputeMDDStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
options_list.writeOutput(output);
output << "[options_, oo_] = ms_compute_mdd(M_, options_, oo_);" << endl;
}
void
MSSBVARComputeMDDStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ms_sbvar_compute_mdd")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
MSSBVARComputeProbabilitiesStatement::MSSBVARComputeProbabilitiesStatement(
OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
MSSBVARComputeProbabilitiesStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
if (options_list.contains("ms.real_time_smoothed_probabilities")
&& options_list.contains("ms.filtered_probabilities"))
{
cerr << "ERROR: You may only pass one of real_time_smoothed "
<< "and filtered_probabilities to ms_compute_probabilities." << endl;
exit(EXIT_FAILURE);
}
}
void
MSSBVARComputeProbabilitiesStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
options_list.writeOutput(output);
output << "[options_, oo_] = ms_compute_probabilities(M_, options_, oo_);" << endl;
}
void
MSSBVARComputeProbabilitiesStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ms_sbvar_compute_probabilities")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
MSSBVARIrfStatement::MSSBVARIrfStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
MSSBVARIrfStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
if (bool regime_present = options_list.contains("ms.regime"),
regimes_present = options_list.contains("ms.regimes"),
filtered_probabilities_present = options_list.contains("ms.filtered_probabilities");
(filtered_probabilities_present && regime_present)
|| (filtered_probabilities_present && regimes_present) || (regimes_present && regime_present))
{
cerr << "ERROR: You may only pass one of regime, regimes and "
<< "filtered_probabilities to ms_irf" << endl;
exit(EXIT_FAILURE);
}
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: ms_irf: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
MSSBVARIrfStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
symbol_list.writeOutput("var_list_", output);
options_list.writeOutput(output);
output << "[options_, oo_] = ms_irf(var_list_,M_, options_, oo_);" << endl;
}
void
MSSBVARIrfStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ms_sbvar_irf")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
MSSBVARForecastStatement::MSSBVARForecastStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
MSSBVARForecastStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
if (options_list.contains("ms.regimes") && options_list.contains("ms.regime"))
{
cerr << "ERROR: You may only pass one of regime and regimes to ms_forecast" << endl;
exit(EXIT_FAILURE);
}
}
void
MSSBVARForecastStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
options_list.writeOutput(output);
output << "[options_, oo_] = ms_forecast(M_, options_, oo_);" << endl;
}
void
MSSBVARForecastStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ms_sbvar_forecast")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
MSSBVARVarianceDecompositionStatement::MSSBVARVarianceDecompositionStatement(
OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
MSSBVARVarianceDecompositionStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.bvar_present = true;
if (bool regime_present = options_list.contains("ms.regime"),
regimes_present = options_list.contains("ms.regimes"),
filtered_probabilities_present = options_list.contains("ms.filtered_probabilities");
(filtered_probabilities_present && regime_present)
|| (filtered_probabilities_present && regimes_present) || (regimes_present && regime_present))
{
cerr << "ERROR: You may only pass one of regime, regimes and "
<< "filtered_probabilities to ms_variance_decomposition" << endl;
exit(EXIT_FAILURE);
}
}
void
MSSBVARVarianceDecompositionStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
options_list.writeOutput(output);
output << "[options_, oo_] = ms_variance_decomposition(M_, options_, oo_);" << endl;
}
void
MSSBVARVarianceDecompositionStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "ms_sbvar_variance_decomposition")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
IdentificationStatement::IdentificationStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
if (auto opt = options_list.get_if<OptionsList::NumVal>("max_dim_cova_group");
opt && stoi(*opt) == 0)
{
cerr << "ERROR: The max_dim_cova_group option to identification only accepts integers > 0."
<< endl;
exit(EXIT_FAILURE);
}
}
void
IdentificationStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.identification_present = true;
if (auto opt = options_list.get_if<OptionsList::NumVal>("order"))
{
int order = stoi(*opt);
if (order < 1 || order > 3)
{
cerr << "ERROR: the order option of identification command must be between 1 and 3"
<< endl;
exit(EXIT_FAILURE);
}
mod_file_struct.identification_order = max(mod_file_struct.identification_order, order);
}
else
// The default value for order is 1 (which triggers 2nd order dynamic derivatives, see
// preprocessor#40)
mod_file_struct.identification_order = max(mod_file_struct.identification_order, 1);
}
void
IdentificationStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_ident");
/* Ensure that nograph, nodisplay and graph_format are also set in top-level
options_.
\todo factorize this code between identification and dynare_sensitivity,
and provide a generic mechanism for this situation (maybe using regexps).
graph_format can then be turned into a VecCellStrVal. */
if (auto opt = options_list.get_if<OptionsList::NumVal>("nodisplay"))
output << "options_.nodisplay = " << *opt << ";" << endl;
if (auto opt = options_list.get_if<OptionsList::NumVal>("nograph"))
output << "options_.nograph = " << *opt << ";" << endl;
if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format"))
opt->writeOutput("options_.graph_format", output);
output << "identification.run(M_,oo_,options_,bayestopt_,estim_params_,"
<< "options_ident);" << endl;
}
void
IdentificationStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "identification")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
WriteLatexDynamicModelStatement::WriteLatexDynamicModelStatement(
const DynamicModel& dynamic_model_arg, bool write_equation_tags_arg) :
dynamic_model {dynamic_model_arg}, write_equation_tags {write_equation_tags_arg}
{
}
void
WriteLatexDynamicModelStatement::writeOutput([[maybe_unused]] ostream& output,
const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
dynamic_model.writeLatexFile(basename, write_equation_tags);
}
void
WriteLatexDynamicModelStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "write_latex_dynamic_model"})";
}
WriteLatexStaticModelStatement::WriteLatexStaticModelStatement(const StaticModel& static_model_arg,
bool write_equation_tags_arg) :
static_model(static_model_arg), write_equation_tags(write_equation_tags_arg)
{
}
void
WriteLatexStaticModelStatement::writeOutput([[maybe_unused]] ostream& output,
const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
static_model.writeLatexFile(basename, write_equation_tags);
}
void
WriteLatexStaticModelStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "write_latex_static_model"})";
}
WriteLatexOriginalModelStatement::WriteLatexOriginalModelStatement(
const DynamicModel& original_model_arg, bool write_equation_tags_arg) :
original_model {original_model_arg}, write_equation_tags {write_equation_tags_arg}
{
}
void
WriteLatexOriginalModelStatement::writeOutput([[maybe_unused]] ostream& output,
const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
original_model.writeLatexOriginalFile(basename, write_equation_tags);
}
void
WriteLatexOriginalModelStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "write_latex_original_model"})";
}
WriteLatexSteadyStateModelStatement::WriteLatexSteadyStateModelStatement(
const SteadyStateModel& steady_state_model_arg) :
steady_state_model {steady_state_model_arg}
{
}
void
WriteLatexSteadyStateModelStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.write_latex_steady_state_model_present = true;
}
void
WriteLatexSteadyStateModelStatement::writeOutput([[maybe_unused]] ostream& output,
const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
steady_state_model.writeLatexSteadyStateFile(basename);
}
void
WriteLatexSteadyStateModelStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "write_latex_steady_state_model"})";
}
ShockDecompositionStatement::ShockDecompositionStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
ShockDecompositionStatement::checkPass(ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
if (auto opt = options_list.get_if<OptionsList::NumVal>("shock_decomp.with_epilogue");
opt && *opt == "true")
mod_file_struct.with_epilogue_option = true;
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: shock_decomposition: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
ShockDecompositionStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output);
output << "oo_ = shock_decomposition(M_,oo_,options_,var_list_,bayestopt_,estim_params_);"
<< endl;
}
void
ShockDecompositionStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "shock_decomposition")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
RealtimeShockDecompositionStatement::RealtimeShockDecompositionStatement(
SymbolList symbol_list_arg, OptionsList options_list_arg, const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
RealtimeShockDecompositionStatement::checkPass(ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
if (auto opt = options_list.get_if<OptionsList::NumVal>("shock_decomp.with_epilogue");
opt && *opt == "true")
mod_file_struct.with_epilogue_option = true;
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: realtime_shock_decomposition: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
RealtimeShockDecompositionStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output);
output
<< "oo_ = realtime_shock_decomposition(M_,oo_,options_,var_list_,bayestopt_,estim_params_);"
<< endl;
}
void
RealtimeShockDecompositionStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "realtime_shock_decomposition")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
PlotShockDecompositionStatement::PlotShockDecompositionStatement(
SymbolList symbol_list_arg, OptionsList options_list_arg, const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
PlotShockDecompositionStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous, SymbolType::epilogue}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: plot_shock_decomposition: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
PlotShockDecompositionStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_ = set_default_plot_shock_decomposition_options(options_);" << endl;
options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output);
output << "oo_ = plot_shock_decomposition(M_, oo_, options_, var_list_);" << endl;
}
void
PlotShockDecompositionStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "plot_shock_decomposition")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
InitialConditionDecompositionStatement::InitialConditionDecompositionStatement(
SymbolList symbol_list_arg, OptionsList options_list_arg, const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
InitialConditionDecompositionStatement::checkPass(ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
if (auto opt = options_list.get_if<OptionsList::NumVal>("initial_condition_decomp.with_epilogue");
opt && *opt == "true")
mod_file_struct.with_epilogue_option = true;
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: initial_condition_decomposition: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
InitialConditionDecompositionStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_ = set_default_initial_condition_decomposition_options(options_);" << endl;
options_list.writeOutput(output);
symbol_list.writeOutput("var_list_", output);
output << "oo_ = initial_condition_decomposition(M_, oo_, options_, var_list_, bayestopt_, "
"estim_params_);"
<< endl;
}
void
InitialConditionDecompositionStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "initial_condition_decomposition")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
SqueezeShockDecompositionStatement::SqueezeShockDecompositionStatement(
SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)}, symbol_table {symbol_table_arg}
{
}
void
SqueezeShockDecompositionStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: squeeze_shock_decomposition: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
SqueezeShockDecompositionStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (symbol_list.empty())
output << "oo_ = squeeze_shock_decomposition(M_, oo_, options_);" << endl;
else
{
symbol_list.writeOutput("var_list_", output);
output << "oo_ = squeeze_shock_decomposition(M_, oo_, options_, var_list_);" << endl;
}
}
void
SqueezeShockDecompositionStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "squeeze_shock_decomposition")";
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
ConditionalForecastStatement::ConditionalForecastStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
ConditionalForecastStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (!options_list.contains("parameter_set"))
{
cerr << "ERROR: You must pass the `parameter_set` option to conditional_forecast" << endl;
exit(EXIT_FAILURE);
}
}
void
ConditionalForecastStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_cond_fcst_");
output << "oo_.conditional_forecast=conditional_forecasts.run(M_,options_,"
<< "oo_,bayestopt_,estim_params_,constrained_paths_, constrained_vars_,"
<< "options_cond_fcst_);" << endl;
}
void
ConditionalForecastStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "conditional_forecast")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
PlotConditionalForecastStatement::PlotConditionalForecastStatement(
const optional<int>& periods_arg, SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg) :
periods {periods_arg}, symbol_list {move(symbol_list_arg)}, symbol_table {symbol_table_arg}
{
}
void
PlotConditionalForecastStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
WarningConsolidation& warnings)
{
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: plot_conditional_forecast: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
PlotConditionalForecastStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
symbol_list.writeOutput("var_list_", output);
if (periods)
output << "conditional_forecasts.plot(var_list_, " << *periods << ",options_,oo_);" << endl;
else
output << "conditional_forecasts.plot(var_list_,[],options_,oo_);" << endl;
}
void
PlotConditionalForecastStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "plot_conditional_forecast")";
if (periods)
output << R"(, "periods": )" << *periods;
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
SvarIdentificationStatement::SvarIdentificationStatement(
svar_identification_restrictions_t restrictions_arg, bool upper_cholesky_present_arg,
bool lower_cholesky_present_arg, bool constants_exclusion_present_arg,
const SymbolTable& symbol_table_arg) :
restrictions {move(restrictions_arg)},
upper_cholesky_present {upper_cholesky_present_arg},
lower_cholesky_present {lower_cholesky_present_arg},
constants_exclusion_present {constants_exclusion_present_arg},
symbol_table {symbol_table_arg}
{
}
int
SvarIdentificationStatement::getMaxLag() const
{
int max_lag = 0;
for (const auto& restriction : restrictions)
max_lag = max(restriction.lag, max_lag);
return max_lag;
}
void
SvarIdentificationStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
// no equations OK with Svar Identification
mod_file_struct.bvar_present = true;
if (!mod_file_struct.svar_identification_present)
mod_file_struct.svar_identification_present = true;
else
{
cerr << "ERROR: You may only have one svar_identification block in your .mod file." << endl;
exit(EXIT_FAILURE);
}
if (upper_cholesky_present && lower_cholesky_present)
{
cerr << "ERROR: Within the svar_identification statement, you may only have one of "
<< "upper_cholesky and lower_cholesky." << endl;
exit(EXIT_FAILURE);
}
}
void
SvarIdentificationStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
assert(!(upper_cholesky_present && lower_cholesky_present));
output << "%" << endl << "% SVAR IDENTIFICATION" << endl << "%" << endl;
if (upper_cholesky_present)
output << "options_.ms.upper_cholesky=1;" << endl;
if (lower_cholesky_present)
output << "options_.ms.lower_cholesky=1;" << endl;
if (constants_exclusion_present)
output << "options_.ms.constants_exclusion=1;" << endl;
if (!upper_cholesky_present && !lower_cholesky_present)
{
int n = symbol_table.endo_nbr();
int m = 1; // this is the constant, not the shocks
int r = getMaxLag();
int k = r * n + m;
if (k < 1)
{
cerr << "ERROR: lag = " << r << ", number of endogenous variables = " << n
<< ", number of exogenous variables = " << m
<< ". If this is not a logical error in the specification"
<< " of the .mod file, please report it to the Dynare Team." << endl;
exit(EXIT_FAILURE);
}
if (n < 1)
{
cerr
<< "ERROR: Number of endogenous variables = " << n << "< 1. If this is not a logical "
<< "error in the specification of the .mod file, please report it to the Dynare Team."
<< endl;
exit(EXIT_FAILURE);
}
output << "options_.ms.Qi = cell(" << n << ",1);" << endl
<< "options_.ms.Ri = cell(" << n << ",1);" << endl;
for (auto& it : restrictions)
{
assert(it.lag >= 0);
if (it.lag == 0)
output << "options_.ms.Qi{" << it.equation << "}(" << it.restriction_nbr << ", "
<< it.variable + 1 << ") = ";
else
{
int col = (it.lag - 1) * n + it.variable + 1;
if (col > k)
{
cerr << "ERROR: lag =" << it.lag << ", num endog vars = " << n
<< "current endog var index = " << it.variable << ". Index "
<< "out of bounds. If the above does not represent a logical error, please "
"report this to the Dynare Team."
<< endl;
exit(EXIT_FAILURE);
}
output << "options_.ms.Ri{" << it.equation << "}(" << it.restriction_nbr << ", "
<< col << ") = ";
}
it.value->writeOutput(output);
output << ";" << endl;
}
output << "options_.ms.nlags = " << r << ";" << endl;
}
}
void
SvarIdentificationStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "svar_identification")";
if (upper_cholesky_present)
output << R"(, "upper_cholesky": 1)";
if (lower_cholesky_present)
output << R"(, "lower_cholesky": 1)";
if (constants_exclusion_present)
output << R"(, "constants_exclusion": 1)";
if (!upper_cholesky_present && !lower_cholesky_present)
{
output << R"(, "nlags": )" << getMaxLag() << R"(, "restrictions": [)";
for (bool printed_something {false}; const auto& it : restrictions)
{
if (exchange(printed_something, true))
output << ", ";
output << "{"
<< R"("equation_number": )" << it.equation << ", "
<< R"("restriction_number": )" << it.restriction_nbr << ", "
<< R"("variable": ")" << symbol_table.getName(it.variable) << R"(", )"
<< R"("expression": ")";
it.value->writeOutput(output);
output << R"("})";
}
output << "]";
}
output << "}";
}
MarkovSwitchingStatement::MarkovSwitchingStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
if (auto opt = options_list.get_if<vector<vector<string>>>("ms.restrictions"))
{
int num_regimes {stoi(options_list.get<OptionsList::NumVal>("ms.number_of_regimes"))};
for (const vector<string>& restriction : *opt)
{
if (restriction.size() != 3)
{
cerr
<< "ERROR: restrictions in the subsample statement must be specified in the form "
<< "[current_period_regime, next_period_regime, transition_probability]" << endl;
exit(EXIT_FAILURE);
}
try
{
auto from_regime = stoi(restriction[0]);
auto to_regime = stoi(restriction[1]);
if (from_regime > num_regimes || to_regime > num_regimes)
{
cerr << "ERROR: the regimes specified in the restrictions option must be "
<< "<= the number of regimes specified in the number_of_regimes option"
<< endl;
exit(EXIT_FAILURE);
}
if (restriction_map.contains({from_regime, to_regime}))
{
cerr << "ERROR: two restrictions were given for: " << from_regime << ", "
<< to_regime << endl;
exit(EXIT_FAILURE);
}
auto transition_probability = stod(restriction[2]);
if (transition_probability > 1.0)
{
cerr << "ERROR: the transition probability, " << transition_probability
<< " must be less than 1" << endl;
exit(EXIT_FAILURE);
}
restriction_map[{from_regime, to_regime}] = transition_probability;
}
catch (const invalid_argument&)
{
cerr << "ERROR: The first two arguments for a restriction must be integers "
<< "specifying the regime and the last must be a floating point specifying the "
<< "transition probability.";
exit(EXIT_FAILURE);
}
}
}
}
void
MarkovSwitchingStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
int chainNumber {stoi(options_list.get<OptionsList::NumVal>("ms.chain"))};
if (++mod_file_struct.last_markov_switching_chain != chainNumber)
{
cerr << "ERROR: The markov_switching chain option takes consecutive integers "
<< "beginning at 1." << endl;
exit(EXIT_FAILURE);
}
if (options_list.contains("ms.restrictions"))
{
int num_regimes {stoi(options_list.get<OptionsList::NumVal>("ms.number_of_regimes"))};
vector col_trans_prob_sum(num_regimes, 0.0);
vector row_trans_prob_sum(num_regimes, 0.0);
vector all_restrictions_in_row(num_regimes, true);
vector all_restrictions_in_col(num_regimes, true);
for (int row = 0; row < num_regimes; row++)
for (int col = 0; col < num_regimes; col++)
if (restriction_map.contains({row + 1, col + 1}))
{
row_trans_prob_sum[row] += restriction_map[{row + 1, col + 1}];
col_trans_prob_sum[col] += restriction_map[{row + 1, col + 1}];
}
else
{
all_restrictions_in_row[row] = false;
all_restrictions_in_col[col] = false;
}
for (int i = 0; i < num_regimes; i++)
{
if (all_restrictions_in_row[i])
{
if (row_trans_prob_sum[i] != 1.0)
{
cerr << "ERROR: When all transitions probabilities are specified for a certain "
<< "regime, they must sum to 1" << endl;
exit(EXIT_FAILURE);
}
}
else if (row_trans_prob_sum[i] >= 1.0)
{
cerr << "ERROR: When transition probabilites are not specified for every regime, "
<< "their sum must be < 1" << endl;
exit(EXIT_FAILURE);
}
if (all_restrictions_in_col[i])
{
if (col_trans_prob_sum[i] != 1.0)
{
cerr << "ERROR: When all transitions probabilities are specified for a certain "
<< "regime, they must sum to 1" << endl;
exit(EXIT_FAILURE);
}
}
else if (col_trans_prob_sum[i] >= 1.0)
{
cerr << "ERROR: When transition probabilites are not specified for every regime, "
<< "their sum must be < 1" << endl;
exit(EXIT_FAILURE);
}
}
}
if (options_list.contains("ms.parameters"))
mod_file_struct.ms_dsge_present = true;
}
void
MarkovSwitchingStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string chainNumber {options_list.get<OptionsList::NumVal>("ms.chain")};
assert(options_list.contains("ms.duration"));
output << "options_.ms.duration = ";
bool isDurationAVec {options_list.visit("ms.duration", [&]<class T>(const T& v) -> bool {
if constexpr (is_same_v<T, OptionsList::VecValueVal>)
{
output << "[";
for (bool printed_something {false}; const auto& it : v)
{
if (exchange(printed_something, true))
output << ", ";
output << it;
}
output << "]";
return true;
}
else if constexpr (is_same_v<T, OptionsList::NumVal>)
{
output << v;
return false;
}
else
{
cerr << "MarkovSwitchingStatement::writeOutput: incorrect value type for 'ms.duration' "
"option"
<< endl;
exit(EXIT_FAILURE);
}
})};
output << ";" << endl;
int NOR {stoi(options_list.get<OptionsList::NumVal>("ms.number_of_regimes"))};
for (int i {0}; i < NOR; i++)
{
output << "options_.ms.ms_chain(" << chainNumber << ").regime(" << i + 1
<< ").duration = options_.ms.duration";
if (isDurationAVec)
output << "(" << i + 1 << ")";
output << ";" << endl;
}
for (int restrictions_index {0}; const auto& [regimes, prob] : restriction_map)
output << "options_.ms.ms_chain(" << chainNumber << ").restrictions(" << ++restrictions_index
<< ") = {[" << regimes.first << ", " << regimes.second << ", " << prob << "]};" << endl;
}
void
MarkovSwitchingStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "markov_switching")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!restriction_map.empty())
output << ", {";
for (bool printed_something {false}; const auto& [regimes, prob] : restriction_map)
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"current_period_regime": )" << regimes.first << R"(, "next_period_regime": )"
<< regimes.second << R"(, "transition_probability": )" << prob << "}";
}
if (!restriction_map.empty())
output << "}";
output << "}";
}
SvarStatement::SvarStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
{
}
void
SvarStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
bool has_coefficients = options_list.contains("ms.coefficients"),
has_variances = options_list.contains("ms.variances"),
has_constants = options_list.contains("ms.constants");
assert((has_coefficients && !has_variances && !has_constants)
|| (!has_coefficients && has_variances && !has_constants)
|| (!has_coefficients && !has_variances && has_constants));
}
void
SvarStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "options_.ms.ms_chain(" << options_list.get<OptionsList::NumVal>("ms.chain") << ")";
if (auto opt1 = options_list.get_if<OptionsList::StringVal>("ms.coefficients"))
output << "." << *opt1;
else if (auto opt2 = options_list.get_if<OptionsList::StringVal>("ms.variances"))
output << "." << *opt2;
else
output << "." << options_list.get<OptionsList::StringVal>("ms.constants");
output << ".equations = ";
if (auto opt = options_list.get_if<vector<int>>("ms.equations"))
{
assert(opt->size() >= 1);
if (opt->size() > 1)
{
output << "[";
for (int viit : *opt)
output << viit << ";";
output << "];" << endl;
}
else
output << opt->front() << ";" << endl;
}
else
output << "'ALL';" << endl;
}
void
SvarStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "svar")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
void
SvarGlobalIdentificationCheckStatement::writeOutput(ostream& output,
[[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "svar_global_identification_check(options_);" << std::endl;
}
void
SvarGlobalIdentificationCheckStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "svar_global_identification"})";
}
SetTimeStatement::SetTimeStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
SetTimeStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
}
void
SetTimeStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "set_time")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
EstimationDataStatement::EstimationDataStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
EstimationDataStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.estimation_data_statement_present = true;
if (auto opt = options_list.get_if<OptionsList::NumVal>("nobs"))
if (stoi(*opt) <= 0)
{
cerr << "ERROR: The nobs option of the data statement only accepts positive integers."
<< endl;
exit(EXIT_FAILURE);
}
bool has_file = options_list.contains("file"), has_series = options_list.contains("series");
if (!has_file && !has_series)
{
cerr << "ERROR: The file or series option must be passed to the data statement." << endl;
exit(EXIT_FAILURE);
}
if (has_file && has_series)
{
cerr << "ERROR: The file and series options cannot be used simultaneously in the data "
"statement."
<< endl;
exit(EXIT_FAILURE);
}
}
void
EstimationDataStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_.dataset");
}
void
EstimationDataStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "estimation_data")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
SubsamplesStatement::SubsamplesStatement(string name1_arg, string name2_arg,
subsample_declaration_map_t subsample_declaration_map_arg,
const SymbolTable& symbol_table_arg) :
name1 {move(name1_arg)},
name2 {move(name2_arg)},
subsample_declaration_map {move(subsample_declaration_map_arg)},
symbol_table {symbol_table_arg}
{
}
void
SubsamplesStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "subsamples_indx = get_new_or_existing_ei_index('subsamples_index', '" << name1 << "','"
<< name2 << "');" << endl
<< "estimation_info.subsamples_index(subsamples_indx) = {'" << name1;
if (!name2.empty())
output << ":" << name2;
output << "'};" << endl
<< "estimation_info.subsamples(subsamples_indx).range = {};" << endl
<< "estimation_info.subsamples(subsamples_indx).range_index = {};" << endl;
for (int map_indx {1}; const auto& [range, dates] : subsample_declaration_map)
{
output << "estimation_info.subsamples(subsamples_indx).range_index(" << map_indx << ") = {'"
<< range << "'};" << endl
<< "estimation_info.subsamples(subsamples_indx).range(" << map_indx
<< ").date1 = " << dates.first << ";" << endl
<< "estimation_info.subsamples(subsamples_indx).range(" << map_indx
<< ").date2 = " << dates.second << ";" << endl;
map_indx++;
}
// Initialize associated subsample substructures in estimation_info
const SymbolType symb_type = symbol_table.getType(name1);
string lhs_field;
switch (symb_type)
{
case SymbolType::parameter:
lhs_field = "parameter";
break;
case SymbolType::exogenous:
lhs_field = "structural_innovation";
break;
case SymbolType::endogenous:
lhs_field = "measurement_error";
break;
default:
cerr << "subsamples: invalid symbol type for " << name1 << endl;
exit(EXIT_FAILURE);
}
output << "eifind = get_new_or_existing_ei_index('" << lhs_field;
if (!name2.empty())
output << "_corr";
output << "_prior_index', '" << name1 << "', '";
if (!name2.empty())
output << name2;
output << "');" << endl;
lhs_field = "estimation_info." + lhs_field;
if (!name2.empty())
lhs_field += "_corr";
output << lhs_field << "_prior_index(eifind) = {'" << name1;
if (!name2.empty())
output << ":" << name2;
output << "'};" << endl;
output << lhs_field << "(eifind).subsample_prior = estimation_info.empty_prior;" << endl
<< lhs_field << "(eifind).subsample_prior(1:" << subsample_declaration_map.size()
<< ") = estimation_info.empty_prior;" << endl
<< lhs_field
<< "(eifind).range_index = estimation_info.subsamples(subsamples_indx).range_index;"
<< endl;
}
void
SubsamplesStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "subsamples")"
<< R"(, "name1": ")" << name1 << R"(")";
if (!name2.empty())
output << R"(, "name2": ")" << name2 << R"(")";
output << R"(, "declarations": {)";
for (bool printed_something {false}; const auto& [range, dates] : subsample_declaration_map)
{
if (exchange(printed_something, true))
output << ",";
output << "{"
<< R"("range_index": ")" << range << R"(")"
<< R"(, "date1": ")" << dates.first << R"(")"
<< R"(, "date2": ")" << dates.second << R"(")"
<< "}";
}
output << "}"
<< "}";
}
SubsamplesEqualStatement::SubsamplesEqualStatement(string to_name1_arg, string to_name2_arg,
string from_name1_arg, string from_name2_arg,
const SymbolTable& symbol_table_arg) :
to_name1 {move(to_name1_arg)},
to_name2 {move(to_name2_arg)},
from_name1 {move(from_name1_arg)},
from_name2 {move(from_name2_arg)},
symbol_table {symbol_table_arg}
{
}
void
SubsamplesEqualStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "subsamples_to_indx = get_new_or_existing_ei_index('subsamples_index', '" << to_name1
<< "','" << to_name2 << "');" << endl
<< "estimation_info.subsamples_index(subsamples_to_indx) = {'" << to_name1;
if (!to_name2.empty())
output << ":" << to_name2;
output << "'};" << endl
<< "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','"
<< from_name2 << "');" << endl
<< "estimation_info.subsamples(subsamples_to_indx) = "
"estimation_info.subsamples(subsamples_from_indx);"
<< endl;
// Initialize associated subsample substructures in estimation_info
const SymbolType symb_type = symbol_table.getType(to_name1);
string lhs_field;
switch (symb_type)
{
case SymbolType::parameter:
lhs_field = "parameter";
break;
case SymbolType::exogenous:
lhs_field = "structural_innovation";
break;
case SymbolType::endogenous:
lhs_field = "measurement_error";
break;
default:
cerr << "subsamples: invalid symbol type for " << to_name1 << endl;
exit(EXIT_FAILURE);
}
output << "eifind = get_new_or_existing_ei_index('" << lhs_field;
if (!to_name2.empty())
output << "_corr";
output << "_prior_index', '" << to_name1 << "', '";
if (!to_name2.empty())
output << to_name2;
output << "');" << endl;
lhs_field = "estimation_info." + lhs_field;
if (!to_name2.empty())
lhs_field += "_corr";
output << lhs_field << "_prior_index(eifind) = {'" << to_name1;
if (!to_name2.empty())
output << ":" << to_name2;
output << "'};" << endl;
output << lhs_field << "(eifind).subsample_prior = estimation_info.empty_prior;" << endl
<< lhs_field
<< "(eifind).subsample_prior(1:size(estimation_info.subsamples(subsamples_to_indx).range_"
"index,2)) = estimation_info.empty_prior;"
<< endl
<< lhs_field
<< "(eifind).range_index = estimation_info.subsamples(subsamples_to_indx).range_index;"
<< endl;
}
void
SubsamplesEqualStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "subsamples_equal")"
<< R"(, "to_name1": ")" << to_name1 << R"(")";
if (!to_name2.empty())
output << R"(, "to_name2": ")" << to_name2 << R"(")";
output << R"(, "from_name1": ")" << from_name1 << R"(")";
if (!from_name2.empty())
output << R"(, "from_name2": ")" << from_name2 << R"(")";
output << "}";
}
JointPriorStatement::JointPriorStatement(vector<string> joint_parameters_arg,
PriorDistributions prior_shape_arg,
OptionsList options_list_arg) :
joint_parameters {move(joint_parameters_arg)},
prior_shape {prior_shape_arg},
options_list {move(options_list_arg)}
{
}
void
JointPriorStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (joint_parameters.size() < 2)
{
cerr << "ERROR: you must pass at least two parameters to the joint prior statement" << endl;
exit(EXIT_FAILURE);
}
if (prior_shape == PriorDistributions::noShape)
{
cerr << "ERROR: You must pass the shape option to the prior statement." << endl;
exit(EXIT_FAILURE);
}
if (!options_list.contains("mean") && !options_list.contains("mode"))
{
cerr << "ERROR: You must pass at least one of mean and mode to the prior statement." << endl;
exit(EXIT_FAILURE);
}
if (auto opt = options_list.get_if<OptionsList::VecValueVal>("domain"); opt && opt->size() != 4)
{
cerr << "ERROR: You must pass exactly four values to the domain option." << endl;
exit(EXIT_FAILURE);
}
}
void
JointPriorStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
for (const auto& joint_parameter : joint_parameters)
output << "eifind = get_new_or_existing_ei_index('joint_parameter_prior_index', '"
<< joint_parameter << "', '');" << endl
<< "estimation_info.joint_parameter_prior_index(eifind) = {'" << joint_parameter << "'};"
<< endl;
output << "key = {[";
for (const auto& joint_parameter : joint_parameters)
output << "get_new_or_existing_ei_index('joint_parameter_prior_index', '" << joint_parameter
<< "', '') ..." << endl
<< " ";
output << "]};" << endl;
string lhs_field("estimation_info.joint_parameter_tmp");
writeOutputHelper(output, "domain", lhs_field);
writeOutputHelper(output, "interval", lhs_field);
writeOutputHelper(output, "mean", lhs_field);
writeOutputHelper(output, "median", lhs_field);
writeOutputHelper(output, "mode", lhs_field);
assert(prior_shape != PriorDistributions::noShape);
output << lhs_field << ".shape = " << static_cast<int>(prior_shape) << ";" << endl;
writeOutputHelper(output, "shift", lhs_field);
writeOutputHelper(output, "stdev", lhs_field);
writeOutputHelper(output, "truncate", lhs_field);
writeOutputHelper(output, "variance", lhs_field);
output << "estimation_info.joint_parameter_tmp = [key, ..." << endl
<< " " << lhs_field << ".domain , ..." << endl
<< " " << lhs_field << ".interval , ..." << endl
<< " " << lhs_field << ".mean , ..." << endl
<< " " << lhs_field << ".median , ..." << endl
<< " " << lhs_field << ".mode , ..." << endl
<< " " << lhs_field << ".shape , ..." << endl
<< " " << lhs_field << ".shift , ..." << endl
<< " " << lhs_field << ".stdev , ..." << endl
<< " " << lhs_field << ".truncate , ..." << endl
<< " " << lhs_field << ".variance];" << endl
<< "estimation_info.joint_parameter = [estimation_info.joint_parameter; "
"estimation_info.joint_parameter_tmp];"
<< endl
<< "estimation_info=rmfield(estimation_info, 'joint_parameter_tmp');" << endl;
}
void
JointPriorStatement::writeOutputHelper(ostream& output, const string& field,
const string& lhs_field) const
{
output << lhs_field << "." << field << " = {";
if (options_list.contains(field))
options_list.visit(field, [&]<class T>(const T& v) {
if constexpr (is_same_v<T, OptionsList::NumVal>)
output << v;
else if constexpr (is_same_v<T, OptionsList::VecValueVal>)
{
output << "[";
for (bool printed_something {false}; const auto& it2 : v)
{
if (exchange(printed_something, true))
output << ", ";
output << it2;
}
output << "]";
}
else if constexpr (is_same_v<T, vector<vector<string>>>)
{
output << "{";
for (bool printed_something {false}; const auto& it2 : v)
{
if (exchange(printed_something, true))
output << ", ";
output << "[";
for (bool printed_something2 {false}; const auto& it3 : it2)
{
if (exchange(printed_something2, true))
output << ", ";
output << it3;
}
output << "]";
}
output << "}";
}
else
{
cerr << "JointPriorStatement::writeOutputHelper: unhandled alternative" << endl;
exit(EXIT_FAILURE);
}
});
else
output << "{}";
output << "};" << endl;
}
void
JointPriorStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "joint_prior")"
<< R"(, "key": [)";
for (bool printed_something {false}; const auto& it : joint_parameters)
{
if (exchange(printed_something, true))
output << ", ";
output << R"(")" << it << R"(")";
}
output << "]";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << R"(, "shape": )";
switch (prior_shape)
{
case PriorDistributions::beta:
output << R"("beta")";
break;
case PriorDistributions::gamma:
output << R"("gamma")";
break;
case PriorDistributions::normal:
output << R"("normal")";
break;
case PriorDistributions::invGamma:
output << R"("inv_gamma")";
break;
case PriorDistributions::uniform:
output << R"("uniform")";
break;
case PriorDistributions::invGamma2:
output << R"("inv_gamma2")";
break;
case PriorDistributions::dirichlet:
output << R"("dirichlet")";
break;
case PriorDistributions::weibull:
output << R"("weibull")";
break;
case PriorDistributions::noShape:
cerr << "Impossible case." << endl;
exit(EXIT_FAILURE);
}
output << "}";
}
BasicPriorStatement::BasicPriorStatement(string name_arg, string subsample_name_arg,
PriorDistributions prior_shape_arg, expr_t variance_arg,
OptionsList options_list_arg) :
name {move(name_arg)},
subsample_name {move(subsample_name_arg)},
prior_shape {prior_shape_arg},
variance {variance_arg},
options_list {move(options_list_arg)}
{
}
void
BasicPriorStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (prior_shape == PriorDistributions::noShape)
{
cerr << "ERROR: You must pass the shape option to the prior statement." << endl;
exit(EXIT_FAILURE);
}
if (!options_list.contains("mean") && !options_list.contains("mode"))
{
cerr << "ERROR: You must pass at least one of mean and mode to the prior statement." << endl;
exit(EXIT_FAILURE);
}
if (bool has_stdev = options_list.contains("stdev");
(!has_stdev && !variance) || (has_stdev && variance))
{
cerr << "ERROR: You must pass exactly one of stdev and variance to the prior statement."
<< endl;
exit(EXIT_FAILURE);
}
if (auto opt = options_list.get_if<OptionsList::VecValueVal>("domain"); opt && opt->size() != 2)
{
cerr << "ERROR: You must pass exactly two values to the domain option." << endl;
exit(EXIT_FAILURE);
}
}
bool
BasicPriorStatement::is_structural_innovation(const SymbolType symb_type) const
{
if (symb_type == SymbolType::exogenous)
return true;
return false;
}
void
BasicPriorStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const
{
if (symb_type == SymbolType::exogenous)
lhs_field = "structural_innovation";
else
lhs_field = "measurement_error";
}
void
BasicPriorStatement::writeCommonOutput(ostream& output, const string& lhs_field) const
{
output << lhs_field << " = estimation_info.empty_prior;" << endl;
writeCommonOutputHelper(output, "domain", lhs_field);
writeCommonOutputHelper(output, "interval", lhs_field);
writeCommonOutputHelper(output, "mean", lhs_field);
writeCommonOutputHelper(output, "median", lhs_field);
writeCommonOutputHelper(output, "mode", lhs_field);
assert(prior_shape != PriorDistributions::noShape);
output << lhs_field << ".shape = " << static_cast<int>(prior_shape) << ";" << endl;
writeCommonOutputHelper(output, "shift", lhs_field);
writeCommonOutputHelper(output, "stdev", lhs_field);
writeCommonOutputHelper(output, "truncate", lhs_field);
if (variance)
{
output << lhs_field << ".variance = ";
variance->writeOutput(output);
output << ";" << endl;
}
}
void
BasicPriorStatement::writeCommonOutputHelper(ostream& output, const string& field,
const string& lhs_field) const
{
if (options_list.contains(field))
options_list.visit(field, [&]<class T>(const T& v) {
if constexpr (is_same_v<T, OptionsList::NumVal>)
output << lhs_field << "." << field << " = " << v << ";" << endl;
// TODO: handle other variant types
});
}
void
BasicPriorStatement::writePriorOutput(ostream& output, string& lhs_field, const string& name2) const
{
if (subsample_name.empty())
lhs_field += ".prior(1)";
else
{
output << "subsamples_indx = get_existing_subsamples_indx('" << name << "','" << name2
<< "');" << endl
<< "eisind = get_subsamples_range_indx(subsamples_indx, '" << subsample_name << "');"
<< endl;
lhs_field += ".subsample_prior(eisind)";
}
writeCommonOutput(output, lhs_field);
}
void
BasicPriorStatement::writeJsonPriorOutput(ostream& output) const
{
output << R"(, "name": ")" << name << R"(")"
<< R"(, "subsample": ")" << subsample_name << R"(")"
<< ", ";
writeJsonShape(output);
if (variance)
{
output << R"(, "variance": ")";
variance->writeJsonOutput(output, {}, {});
output << R"(")";
}
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
}
void
BasicPriorStatement::writeJsonShape(ostream& output) const
{
output << R"("shape": )";
switch (prior_shape)
{
case PriorDistributions::beta:
output << R"("beta")";
break;
case PriorDistributions::gamma:
output << R"("gamma")";
break;
case PriorDistributions::normal:
output << R"("normal")";
break;
case PriorDistributions::invGamma:
output << R"("inv_gamma")";
break;
case PriorDistributions::uniform:
output << R"("uniform")";
break;
case PriorDistributions::invGamma2:
output << R"("inv_gamma2")";
break;
case PriorDistributions::dirichlet:
output << R"("dirichlet")";
break;
case PriorDistributions::weibull:
output << R"("weibull")";
break;
case PriorDistributions::noShape:
assert(prior_shape != PriorDistributions::noShape);
}
}
PriorStatement::PriorStatement(string name_arg, string subsample_name_arg,
PriorDistributions prior_shape_arg, expr_t variance_arg,
OptionsList options_list_arg) :
BasicPriorStatement {move(name_arg), move(subsample_name_arg), prior_shape_arg, variance_arg,
move(options_list_arg)}
{
}
void
PriorStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string lhs_field = "estimation_info.parameter(eifind)";
output << "eifind = get_new_or_existing_ei_index('parameter_prior_index', '" << name << "', '');"
<< endl
<< "estimation_info.parameter_prior_index(eifind) = {'" << name << "'};" << endl;
writePriorOutput(output, lhs_field, "");
}
void
PriorStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "prior")";
writeJsonPriorOutput(output);
output << "}";
}
StdPriorStatement::StdPriorStatement(string name_arg, string subsample_name_arg,
PriorDistributions prior_shape_arg, expr_t variance_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
BasicPriorStatement {move(name_arg), move(subsample_name_arg), prior_shape_arg, variance_arg,
move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
StdPriorStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string lhs_field;
get_base_name(symbol_table.getType(name), lhs_field);
output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_prior_index', '" << name
<< "', '');" << endl
<< "estimation_info." << lhs_field << "_prior_index(eifind) = {'" << name << "'};" << endl;
lhs_field = "estimation_info." + lhs_field + "(eifind)";
writePriorOutput(output, lhs_field, "");
}
void
StdPriorStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "std_prior")";
writeJsonPriorOutput(output);
output << "}";
}
CorrPriorStatement::CorrPriorStatement(string name_arg1, string name_arg2,
string subsample_name_arg,
PriorDistributions prior_shape_arg, expr_t variance_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
BasicPriorStatement {move(name_arg1), move(subsample_name_arg), prior_shape_arg, variance_arg,
move(options_list_arg)},
name1 {move(name_arg2)},
symbol_table {symbol_table_arg}
{
}
void
CorrPriorStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings)
{
BasicPriorStatement::checkPass(mod_file_struct, warnings);
if (symbol_table.getType(name) != symbol_table.getType(name1))
{
cerr << "ERROR: In the corr(A,B).prior statement, A and B must be of the same type. "
<< "In your case, " << name << " and " << name1 << " are of different "
<< "types." << endl;
exit(EXIT_FAILURE);
}
}
void
CorrPriorStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string lhs_field;
get_base_name(symbol_table.getType(name), lhs_field);
output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_corr_prior_index', '"
<< name << "', '" << name1 << "');" << endl
<< "estimation_info." << lhs_field << "_corr_prior_index(eifind) = {'" << name << ":"
<< name1 << "'};" << endl;
lhs_field = "estimation_info." + lhs_field + "_corr(eifind)";
writePriorOutput(output, lhs_field, name1);
}
void
CorrPriorStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "corr_prior")"
<< R"(, "name2": ")" << name1 << R"(")";
writeJsonPriorOutput(output);
output << "}";
}
PriorEqualStatement::PriorEqualStatement(string to_declaration_type_arg, string to_name1_arg,
string to_name2_arg, string to_subsample_name_arg,
string from_declaration_type_arg, string from_name1_arg,
string from_name2_arg, string from_subsample_name_arg,
const SymbolTable& symbol_table_arg) :
to_declaration_type {move(to_declaration_type_arg)},
to_name1 {move(to_name1_arg)},
to_name2 {move(to_name2_arg)},
to_subsample_name {move(to_subsample_name_arg)},
from_declaration_type {move(from_declaration_type_arg)},
from_name1 {move(from_name1_arg)},
from_name2 {move(from_name2_arg)},
from_subsample_name {move(from_subsample_name_arg)},
symbol_table {symbol_table_arg}
{
}
void
PriorEqualStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if ((to_declaration_type != "par" && to_declaration_type != "std"
&& to_declaration_type != "corr")
|| (from_declaration_type != "par" && from_declaration_type != "std"
&& from_declaration_type != "corr"))
{
cerr << "Internal Dynare Error" << endl;
exit(EXIT_FAILURE);
}
}
void
PriorEqualStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const
{
if (symb_type == SymbolType::exogenous)
lhs_field = "structural_innovation";
else
lhs_field = "measurement_error";
}
void
PriorEqualStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string lhs_field, rhs_field;
if (to_declaration_type == "par")
lhs_field = "parameter";
else
get_base_name(symbol_table.getType(to_name1), lhs_field);
if (from_declaration_type == "par")
rhs_field = "parameter";
else
get_base_name(symbol_table.getType(from_name1), rhs_field);
if (to_declaration_type == "corr")
lhs_field += "_corr";
if (from_declaration_type == "corr")
rhs_field += "_corr";
output << "ei_to_ind = get_new_or_existing_ei_index('" << lhs_field << "_prior_index', '"
<< to_name1 << "', '" << to_name2 << "');" << endl
<< "ei_from_ind = get_new_or_existing_ei_index('" << rhs_field << "_prior_index', '"
<< from_name1 << "', '" << from_name2 << "');" << endl
<< "estimation_info." << lhs_field << "_prior_index(ei_to_ind) = {'" << to_name1;
if (to_declaration_type == "corr")
output << ":" << to_name2;
output << "'};" << endl;
if (to_declaration_type == "par")
lhs_field = "parameter";
if (from_declaration_type == "par")
rhs_field = "parameter";
lhs_field = "estimation_info." + lhs_field + "(ei_to_ind)";
rhs_field = "estimation_info." + rhs_field + "(ei_from_ind)";
if (to_subsample_name.empty())
lhs_field += ".prior";
else
{
output << "subsamples_to_indx = get_existing_subsamples_indx('" << to_name1 << "','"
<< to_name2 << "');" << endl
<< "ei_to_ss_ind = get_subsamples_range_indx(subsamples_to_indx, '"
<< to_subsample_name << "');" << endl;
lhs_field += ".subsample_prior(ei_to_ss_ind)";
}
if (from_subsample_name.empty())
rhs_field += ".prior";
else
{
output << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','"
<< from_name2 << "');" << endl
<< "ei_from_ss_ind = get_subsamples_range_indx(subsamples_from_indx, '"
<< from_subsample_name << "');" << endl;
rhs_field += ".subsample_prior(ei_from_ss_ind)";
}
output << lhs_field << " = " << rhs_field << ";" << endl;
}
void
PriorEqualStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "prior_equal")"
<< R"(, "to_name1": ")" << to_name1 << R"(")";
if (to_declaration_type == "corr")
output << R"(, "to_name2": ")" << to_name2 << R"(")";
output << R"(, "to_subsample": ")" << to_subsample_name << R"(")"
<< R"(, "from_name1": ")" << from_name1 << R"(")";
if (to_declaration_type == "corr")
output << R"(, "from_name2": ")" << from_name2 << R"(")";
output << R"(, "from_subsample": ")" << from_subsample_name << R"(")"
<< "}";
}
BasicOptionsStatement::BasicOptionsStatement(string name_arg, string subsample_name_arg,
OptionsList options_list_arg) :
name {move(name_arg)},
subsample_name {move(subsample_name_arg)},
options_list {move(options_list_arg)}
{
}
bool
BasicOptionsStatement::is_structural_innovation(const SymbolType symb_type) const
{
return symb_type == SymbolType::exogenous;
}
void
BasicOptionsStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const
{
if (symb_type == SymbolType::exogenous)
lhs_field = "structural_innovation";
else
lhs_field = "measurement_error";
}
void
BasicOptionsStatement::writeCommonOutput(ostream& output, const string& lhs_field) const
{
output << lhs_field << " = estimation_info.empty_options;" << endl;
writeCommonOutputHelper(output, "bounds", lhs_field);
writeCommonOutputHelper(output, "init", lhs_field);
writeCommonOutputHelper(output, "jscale", lhs_field);
}
void
BasicOptionsStatement::writeCommonOutputHelper(ostream& output, const string& field,
const string& lhs_field) const
{
if (options_list.contains(field))
options_list.visit(field, [&]<class T>(const T& v) {
if constexpr (is_same_v<T, OptionsList::NumVal>)
output << lhs_field << "." << field << " = " << v << ";" << endl;
// TODO: handle other variant types
});
}
void
BasicOptionsStatement::writeOptionsOutput(ostream& output, string& lhs_field,
const string& name2) const
{
if (subsample_name.empty())
lhs_field += ".options(1)";
else
{
output << "subsamples_indx = get_existing_subsamples_indx('" << name << "','" << name2
<< "');" << endl
<< "eisind = get_subsamples_range_indx(subsamples_indx, '" << subsample_name << "');"
<< endl;
lhs_field += ".subsample_options(eisind)";
}
writeCommonOutput(output, lhs_field);
}
void
BasicOptionsStatement::writeJsonOptionsOutput(ostream& output) const
{
output << R"(, "name": ")" << name << R"(")";
if (!subsample_name.empty())
output << R"(, "subsample_name": ")" << subsample_name << R"(")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
}
OptionsStatement::OptionsStatement(string name_arg, string subsample_name_arg,
OptionsList options_list_arg) :
BasicOptionsStatement {move(name_arg), move(subsample_name_arg), move(options_list_arg)}
{
}
void
OptionsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string lhs_field = "estimation_info.parameter(eifind)";
output << "eifind = get_new_or_existing_ei_index('parameter_options_index', '" << name
<< "', '');" << endl
<< "estimation_info.parameter_options_index(eifind) = {'" << name << "'};" << endl;
writeOptionsOutput(output, lhs_field, "");
}
void
OptionsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "options")";
writeJsonOptionsOutput(output);
output << "}";
}
StdOptionsStatement::StdOptionsStatement(string name_arg, string subsample_name_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
BasicOptionsStatement {move(name_arg), move(subsample_name_arg), move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
StdOptionsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string lhs_field;
get_base_name(symbol_table.getType(name), lhs_field);
output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_options_index', '" << name
<< "', '');" << endl
<< "estimation_info." << lhs_field << "_options_index(eifind) = {'" << name << "'};"
<< endl;
lhs_field = "estimation_info." + lhs_field + "(eifind)";
writeOptionsOutput(output, lhs_field, "");
}
void
StdOptionsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "std_options")";
writeJsonOptionsOutput(output);
output << "}";
}
CorrOptionsStatement::CorrOptionsStatement(string name_arg1, string name_arg2,
string subsample_name_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
BasicOptionsStatement {move(name_arg1), move(subsample_name_arg), move(options_list_arg)},
name1 {move(name_arg2)},
symbol_table {symbol_table_arg}
{
}
void
CorrOptionsStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (symbol_table.getType(name) != symbol_table.getType(name1))
{
cerr << "ERROR: In the corr(A,B).options statement, A and B must be of the same type. "
<< "In your case, " << name << " and " << name1 << " are of different "
<< "types." << endl;
exit(EXIT_FAILURE);
}
}
void
CorrOptionsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string lhs_field;
get_base_name(symbol_table.getType(name), lhs_field);
output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_corr_options_index', '"
<< name << "', '" << name1 << "');" << endl
<< "estimation_info." << lhs_field << "_corr_options_index(eifind) = {'" << name << ":"
<< name1 << "'};" << endl;
lhs_field = "estimation_info." + lhs_field + "_corr(eifind)";
writeOptionsOutput(output, lhs_field, name1);
}
void
CorrOptionsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "corr_options")"
<< R"(, "name2": ")" << name1 << R"(")";
writeJsonOptionsOutput(output);
output << "}";
}
OptionsEqualStatement::OptionsEqualStatement(string to_declaration_type_arg, string to_name1_arg,
string to_name2_arg, string to_subsample_name_arg,
string from_declaration_type_arg,
string from_name1_arg, string from_name2_arg,
string from_subsample_name_arg,
const SymbolTable& symbol_table_arg) :
to_declaration_type {move(to_declaration_type_arg)},
to_name1 {move(to_name1_arg)},
to_name2 {move(to_name2_arg)},
to_subsample_name {move(to_subsample_name_arg)},
from_declaration_type {move(from_declaration_type_arg)},
from_name1 {move(from_name1_arg)},
from_name2 {move(from_name2_arg)},
from_subsample_name {move(from_subsample_name_arg)},
symbol_table {symbol_table_arg}
{
}
void
OptionsEqualStatement::checkPass([[maybe_unused]] ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if ((to_declaration_type != "par" && to_declaration_type != "std"
&& to_declaration_type != "corr")
|| (from_declaration_type != "par" && from_declaration_type != "std"
&& from_declaration_type != "corr"))
{
cerr << "Internal Dynare Error" << endl;
exit(EXIT_FAILURE);
}
}
void
OptionsEqualStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "options_equal")"
<< R"(, "to_name1": ")" << to_name1 << R"(")";
if (to_declaration_type == "corr")
output << R"(, "to_name2": ")" << to_name2 << R"(")";
output << R"(, "to_subsample": ")" << to_subsample_name << R"(")"
<< R"(, "from_name1": ")" << from_name1 << R"(")";
if (to_declaration_type == "corr")
output << R"(, "from_name2": ")" << from_name2 << R"(")";
output << R"(, "from_subsample": ")" << from_subsample_name << R"(")"
<< "}";
}
void
OptionsEqualStatement::get_base_name(const SymbolType symb_type, string& lhs_field) const
{
if (symb_type == SymbolType::exogenous)
lhs_field = "structural_innovation";
else
lhs_field = "measurement_error";
}
void
OptionsEqualStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
string lhs_field, rhs_field;
if (to_declaration_type == "par")
lhs_field = "parameter";
else
get_base_name(symbol_table.getType(to_name1), lhs_field);
if (from_declaration_type == "par")
rhs_field = "parameter";
else
get_base_name(symbol_table.getType(from_name1), rhs_field);
if (to_declaration_type == "corr")
lhs_field += "_corr";
if (from_declaration_type == "corr")
rhs_field += "_corr";
output << "ei_to_ind = get_new_or_existing_ei_index('" << lhs_field << "_options_index', '"
<< to_name1 << "', '" << to_name2 << "');" << endl
<< "ei_from_ind = get_new_or_existing_ei_index('" << rhs_field << "_options_index', '"
<< from_name1 << "', '" << from_name2 << "');" << endl
<< "estimation_info." << lhs_field << "_options_index(ei_to_ind) = {'" << to_name1;
if (to_declaration_type == "corr")
output << ":" << to_name2;
output << "'};" << endl;
if (to_declaration_type == "par")
lhs_field = "parameter";
if (from_declaration_type == "par")
rhs_field = "parameter";
lhs_field = "estimation_info." + lhs_field + "(ei_to_ind)";
rhs_field = "estimation_info." + rhs_field + "(ei_from_ind)";
if (to_subsample_name.empty())
lhs_field += ".options";
else
{
output << "subsamples_to_indx = get_existing_subsamples_indx('" << to_name1 << "','"
<< to_name2 << "');" << endl
<< "ei_to_ss_ind = get_subsamples_range_indx(subsamples_to_indx, '"
<< to_subsample_name << "');" << endl;
lhs_field += ".subsample_options(ei_to_ss_ind)";
}
if (from_subsample_name.empty())
rhs_field += ".options";
else
{
output << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','"
<< from_name2 << "');" << endl
<< "ei_from_ss_ind = get_subsamples_range_indx(subsamples_from_indx, '"
<< from_subsample_name << "');" << endl;
rhs_field += ".subsample_options(ei_from_ss_ind)";
}
output << lhs_field << " = " << rhs_field << ";" << endl;
}
CalibSmootherStatement::CalibSmootherStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg,
const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)},
options_list {move(options_list_arg)},
symbol_table {symbol_table_arg}
{
}
void
CalibSmootherStatement::checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings)
{
mod_file_struct.calib_smoother_present = true;
try
{
symbol_list.checkPass(warnings, {SymbolType::endogenous}, symbol_table);
}
catch (SymbolList::SymbolListException& e)
{
cerr << "ERROR: calib_smoother: " << e.message << endl;
exit(EXIT_FAILURE);
}
}
void
CalibSmootherStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
if (!options_list.contains("parameter_set"))
output << "options_.parameter_set = 'calibration';" << endl;
symbol_list.writeOutput("var_list_", output);
output << "options_.smoother = true;" << endl
<< "options_.order = 1;" << endl
<< "[oo_, M_, options_, bayestopt_] = evaluate_smoother(options_.parameter_set, "
"var_list_, M_, oo_, options_, bayestopt_, estim_params_);"
<< endl;
}
void
CalibSmootherStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "calib_smoother")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!symbol_list.empty())
{
output << ", ";
symbol_list.writeJsonOutput(output);
}
output << "}";
}
ExtendedPathStatement::ExtendedPathStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
ExtendedPathStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.extended_path_present = true;
if (!options_list.contains("periods"))
{
cerr << "ERROR: the 'periods' option of 'extended_path' is mandatory" << endl;
exit(EXIT_FAILURE);
}
}
void
ExtendedPathStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
// Beware: options do not have the same name in the interface and in the M code...
string periods {options_list.get<OptionsList::NumVal>("periods")};
OptionsList options_list_new {options_list};
options_list_new.erase("periods");
options_list_new.writeOutput(output);
output << "[Simulated_time_series, oo_] = extended_path([], " << periods
<< ", [], options_, M_, oo_);" << endl;
}
void
ExtendedPathStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "extended_path")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
void
ModelDiagnosticsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "model_diagnostics(M_,options_,oo_);" << endl;
}
void
ModelDiagnosticsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "model_diagnostics"})";
}
Smoother2histvalStatement::Smoother2histvalStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
Smoother2histvalStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_smoother2histval");
output << "smoother2histval(options_smoother2histval);" << endl;
}
void
Smoother2histvalStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "smoother_2_histval")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
MethodOfMomentsStatement::MethodOfMomentsStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)}
{
}
void
MethodOfMomentsStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
mod_file_struct.mom_estimation_present = true;
// Fill in option_order of mod_file_struct
if (auto opt = options_list.get_if<OptionsList::NumVal>("order"))
{
int order = stoi(*opt);
if (order > 2)
mod_file_struct.k_order_solver = true;
mod_file_struct.mom_order = order;
mod_file_struct.order_option = max(mod_file_struct.order_option, order);
}
if (!options_list.contains("mom.mom_method"))
{
cerr << "ERROR: The 'method_of_moments' statement requires a method to be supplied via the "
"'mom_method' option. Possible values are 'GMM', 'SMM', or 'IRF_MATCHING'."
<< endl;
exit(EXIT_FAILURE);
}
auto mom_method_value = options_list.get_if<OptionsList::StringVal>("mom.mom_method");
if ((mom_method_value == "GMM" || mom_method_value == "SMM")
&& !options_list.contains("datafile"))
{
cerr << "ERROR: The 'method_of_moments' statement requires a data file to be supplied via "
"the 'datafile' option."
<< endl;
exit(EXIT_FAILURE);
}
if (auto opt = options_list.get_if<OptionsList::StringVal>("mom.mom_method");
opt && *opt == "GMM")
mod_file_struct.GMM_present = true;
if (auto opt = options_list.get_if<OptionsList::NumVal>("mom.analytic_standard_errors");
opt && *opt == "true")
mod_file_struct.analytic_standard_errors_present = true;
if (!mod_file_struct.GMM_present && mod_file_struct.analytic_standard_errors_present)
{
cerr << "ERROR: The analytic_standard_errors statement requires the GMM option." << endl;
exit(EXIT_FAILURE);
}
if (auto opt = options_list.get_if<OptionsList::NumVal>("mom.analytic_jacobian");
opt && *opt == "true")
mod_file_struct.analytic_jacobian_present = true;
if (!mod_file_struct.GMM_present && mod_file_struct.analytic_jacobian_present)
{
cerr << "ERROR: The analytic_jacobian statement requires the GMM option." << endl;
exit(EXIT_FAILURE);
}
}
void
MethodOfMomentsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_mom_");
output << "[oo_, options_mom_, M_] = mom.run(bayestopt_, options_, oo_, estim_params_, M_, "
"options_mom_);"
<< endl;
}
void
MethodOfMomentsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "method_of_moments")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
GenerateIRFsStatement::GenerateIRFsStatement(
OptionsList options_list_arg, vector<string> generate_irf_names_arg,
vector<map<string, double>> generate_irf_elements_arg) :
options_list {move(options_list_arg)},
generate_irf_names {move(generate_irf_names_arg)},
generate_irf_elements {move(generate_irf_elements_arg)}
{
}
void
GenerateIRFsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output);
if (generate_irf_names.empty())
return;
output << "options_.irf_opt.irf_shock_graphtitles = { ";
for (const auto& generate_irf_name : generate_irf_names)
output << "'" << generate_irf_name << "'; ";
output << "};" << endl;
output << "options_.irf_opt.irf_shocks = zeros(M_.exo_nbr, " << generate_irf_names.size() << ");"
<< endl;
for (size_t i = 0; i < generate_irf_names.size(); i++)
for (auto& [exo_name, exo_value] : generate_irf_elements[i])
output << "options_.irf_opt.irf_shocks(M_.exo_names == '" << exo_name << "', " << i + 1
<< ") = " << exo_value << ";" << endl;
}
void
GenerateIRFsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "generate_irfs")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
if (!generate_irf_names.empty())
{
output << R"(, "irf_elements": [)";
for (size_t i = 0; i < generate_irf_names.size(); i++)
{
output << R"({"name": ")" << generate_irf_names[i] << R"(", "shocks": [)";
for (bool printed_something {false};
auto& [exo_name, exo_value] : generate_irf_elements[i])
{
if (exchange(printed_something, true))
output << ", ";
output << R"({"exogenous_variable": ")" << exo_name << R"(", )"
<< R"("exogenous_variable_value": ")" << exo_value << R"("})";
}
output << "]}";
if (i + 1 < generate_irf_names.size())
output << ", ";
}
output << "]";
}
output << "}";
}
MatchedMomentsStatement::MatchedMomentsStatement(
const SymbolTable& symbol_table_arg,
vector<tuple<vector<int>, vector<int>, vector<int>>> moments_arg) :
symbol_table {symbol_table_arg}, moments {move(moments_arg)}
{
}
void
MatchedMomentsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "M_.matched_moments = {" << endl;
for (const auto& [symb_ids, lags, powers] : moments)
{
output << " [";
for (int s : symb_ids)
output << symbol_table.getTypeSpecificID(s) + 1 << ',';
output << "], [";
for (int l : lags)
output << l << ',';
output << "], [";
for (int p : powers)
output << p << ',';
output << "]," << endl;
}
output << "};" << endl;
}
void
MatchedMomentsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "matched_moments", "moments": [)" << endl;
for (bool printed_something {false}; const auto& [symb_ids, lags, powers] : moments)
{
if (exchange(printed_something, true))
output << ',';
output << R"( { "endos": [)";
for (bool printed_something2 {false}; int s : symb_ids)
{
if (exchange(printed_something2, true))
output << ',';
output << symbol_table.getTypeSpecificID(s) + 1;
}
output << R"(], "lags": [)";
for (bool printed_something2 {false}; int l : lags)
{
if (exchange(printed_something2, true))
output << ',';
output << l;
}
output << R"(], "powers": [)";
for (bool printed_something2 {false}; int p : powers)
{
if (exchange(printed_something2, true))
output << ',';
output << p;
}
output << "]}" << endl;
}
output << "]}" << endl;
}
OccbinConstraintsStatement::OccbinConstraintsStatement(
const DataTree& data_tree_arg,
vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints_arg) :
data_tree {data_tree_arg}, constraints {move(constraints_arg)}
{
}
void
OccbinConstraintsStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings)
{
if (mod_file_struct.occbin_constraints_present)
{
cerr << "ERROR: Multiple 'occbin_constraints' blocks are not allowed" << endl;
exit(EXIT_FAILURE);
}
if (constraints.size() > 2)
{
cerr << "ERROR: only up to two constraints are supported in 'occbin_constraints' block"
<< endl;
exit(EXIT_FAILURE);
}
mod_file_struct.occbin_constraints_present = true;
}
void
OccbinConstraintsStatement::writeOutput(ostream& output, const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
output << "M_.occbin.constraint_nbr = " << constraints.size() << ';' << endl
<< "M_.occbin.pswitch = [" << endl;
for (const auto& [name, bind, relax, error_bind, error_relax] : constraints)
output << data_tree.symbol_table.getTypeSpecificID(
ParsingDriver::buildOccbinBindParamName(name))
+ 1
<< ' ';
output << "];" << endl
<< "options_.occbin = struct();" << endl
<< "options_.occbin = occbin.set_default_options(options_.occbin, M_);" << endl
<< "oo_.dr=set_state_space(oo_.dr,M_);" << endl;
filesystem::path filename {"+" + basename + "/occbin_difference.m"};
ofstream diff_output {filename, ios::out | ios::binary};
if (!diff_output.is_open())
{
cerr << "Error: Can't open file " << filename.string() << " for writing" << endl;
exit(EXIT_FAILURE);
}
diff_output
<< "function [binding, relax, err] = occbin_difference(zdatalinear, params, steady_state)"
<< endl;
for (int idx {1}; const auto& [name, bind, relax, error_bind, error_relax] : constraints)
{
diff_output << "binding.constraint_" << idx << " = ";
dynamic_cast<ExprNode*>(bind)->writeOutput(diff_output,
ExprNodeOutputType::occbinDifferenceFile);
diff_output << ';' << endl << "relax.constraint_" << idx << " = ";
if (relax)
dynamic_cast<ExprNode*>(relax)->writeOutput(diff_output,
ExprNodeOutputType::occbinDifferenceFile);
else
diff_output << "~binding.constraint_" << idx;
diff_output << ';' << endl << "err.binding_constraint_" << idx << " = ";
if (error_bind)
error_bind->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
else
{
diff_output << "abs((";
bind->arg1->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
diff_output << ")-(";
bind->arg2->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
diff_output << "))";
}
diff_output << ';' << endl << "err.relax_constraint_" << idx << " = ";
if (error_relax)
error_relax->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
else if (relax)
{
diff_output << "abs((";
relax->arg1->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
diff_output << ")-(";
relax->arg2->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
diff_output << "))";
}
else if (!error_bind)
/* If relax, error_relax and error_bind have not been specified, then
error_bind and error_relax have the same default value. */
diff_output << "err.binding_constraint_" << idx;
else
{
/* If relax and error_relax have not been specified, but error_bind
has been specified, then we need to compute the default value for
error_relax since it is different from error_bind. */
diff_output << "abs((";
bind->arg1->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
diff_output << ")-(";
bind->arg2->writeOutput(diff_output, ExprNodeOutputType::occbinDifferenceFile);
diff_output << "))";
}
diff_output << ';' << endl;
idx++;
}
diff_output << "end" << endl;
diff_output.close();
}
void
OccbinConstraintsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "occbin_constraints", "constraints": [)" << endl;
for (bool printed_something {false};
const auto& [name, bind, relax, error_bind, error_relax] : constraints)
{
if (exchange(printed_something, true))
output << ',';
output << R"({ "name": ")" << name << R"(", "bind": ")";
dynamic_cast<ExprNode*>(bind)->writeJsonOutput(output, {}, {});
output << R"(", "relax": ")";
if (relax)
dynamic_cast<ExprNode*>(relax)->writeJsonOutput(output, {}, {});
output << R"(", "error_bind": ")";
if (error_bind)
error_bind->writeJsonOutput(output, {}, {});
output << R"(", "error_relax": ")";
if (error_relax)
error_relax->writeJsonOutput(output, {}, {});
output << R"(" })" << endl;
}
output << "]}" << endl;
}
ResidStatement::ResidStatement(OptionsList options_list_arg) : options_list {move(options_list_arg)}
{
}
void
ResidStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
options_list.writeOutput(output, "options_resid_");
output << "display_static_residuals(M_, options_, oo_, options_resid_);" << endl;
}
void
ResidStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "resid")";
if (!options_list.empty())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << "}";
}
MatchedIrfsStatement::MatchedIrfsStatement(matched_irfs_t values_weights_arg, bool overwrite_arg) :
values_weights {move(values_weights_arg)}, overwrite {overwrite_arg}
{
}
void
MatchedIrfsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (overwrite)
output << "M_.matched_irfs = {};" << endl;
for (const auto& [key, vec] : values_weights)
{
const auto& [endo, exo] = key;
output << "M_.matched_irfs = [M_.matched_irfs; {'" << endo << "', '" << exo << "', {";
for (const auto& [p1, p2, value, weight] : vec)
{
output << p1 << ":" << p2 << ", ";
value->writeOutput(output);
output << ", ";
weight->writeOutput(output);
output << "; ";
}
output << "}}];" << endl;
}
}
void
MatchedIrfsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "matched_irfs")"
<< R"(, "overwrite": )" << boolalpha << overwrite << R"(, "contents": [)";
for (bool printed_something {false}; const auto& [key, vec] : values_weights)
{
if (exchange(printed_something, true))
output << ", ";
const auto& [endo, exo] = key;
output << R"({"var": ")" << endo << R"(", "varexo": ")" << exo
<< R"(", "periods_values_weights": [)";
for (bool printed_something2 {false}; const auto& [p1, p2, value, weight] : vec)
{
if (exchange(printed_something2, true))
output << ", ";
output << R"({"period1": )" << p1 << ", "
<< R"("period2": })" << p2 << ", "
<< R"("value": ")";
value->writeJsonOutput(output, {}, {});
output << R"(", "weight": ")";
weight->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}
output << "]}";
}
MatchedIrfsWeightsStatement::MatchedIrfsWeightsStatement(matched_irfs_weights_t weights_arg,
bool overwrite_arg) :
weights {move(weights_arg)}, overwrite {overwrite_arg}
{
}
void
MatchedIrfsWeightsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (overwrite)
output << "M_.matched_irfs_weights = {};" << endl;
for (const auto& [key, val] : weights)
{
const auto& [endo1, periods1, exo1, endo2, periods2, exo2] = key;
output << "M_.matched_irfs_weights = [M_.matched_irfs_weights; {'" << endo1 << "', "
<< periods1 << ", '" << exo1 << "', '" << endo2 << "', " << periods2 << ", '" << exo2
<< "', ";
val->writeOutput(output);
output << "}];" << endl;
}
}
void
MatchedIrfsWeightsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "matched_irfs_weights")"
<< R"(, "overwrite": )" << boolalpha << overwrite << R"(, "contents": [)";
for (bool printed_something {false}; const auto& [key, val] : weights)
{
const auto& [endo1, periods1, exo1, endo2, periods2, exo2] = key;
if (exchange(printed_something, true))
output << ", ";
output << R"({"endo1": ")" << endo1 << R"(", "periods1": ")" << periods1 << R"(", "exo1": )"
<< exo1 << R"(", "endo2": ")" << endo2 << R"(", "periods2": ")" << periods2
<< R"(", "exo2": )" << exo2 << R"(", "weight": ")";
val->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}