diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc index 00f31006040cdc076fab7e7c61703e3e73597d57..73c4ab9d5e9c2f27ebfdd4ccd38ac26db6ec3c18 100644 --- a/src/ComputingTasks.cc +++ b/src/ComputingTasks.cc @@ -1019,20 +1019,6 @@ EstimationStatement::writeOutput(ostream &output, const string &basename, bool m { options_list.writeOutput(output); - bool occbin_option_present = false; - if (auto it = options_list.num_options.find("occbin_likelihood"); - it != options_list.num_options.end() && it->second == "true") - occbin_option_present = true; - - if (auto it = options_list.num_options.find("occbin_smoother"); - it != options_list.num_options.end() && it->second == "true") - occbin_option_present = true; - - if (occbin_option_present) - output << "options_ = set_default_occbin_options(options_, M_);" << endl - << "clear mr_runsim_occbin_fn" << endl - << "M_ = get_wish_list(M_);" << endl; - // Special treatment for order option and particle filter if (auto it = options_list.num_options.find("order"); it == options_list.num_options.end()) diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index e4b9fe6163d79539ce069389c0de62993ccbb405..089668260aa85602911e437d1d64060621afa620 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -2798,7 +2798,7 @@ DynamicModel::writeBlockDriverOutput(ostream &output, const string &basename, co } void -DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool block_decomposition, bool use_dll, bool estimation_present, bool compute_xrefs, bool julia) const +DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool block_decomposition, bool use_dll, bool occbin, bool estimation_present, bool compute_xrefs, bool julia) const { /* Writing initialisation for M_.lead_lag_incidence matrix M_.lead_lag_incidence is a matrix with as many columns as there are @@ -2909,7 +2909,8 @@ DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool bl equation_tags.writeOutput(output, modstruct, julia); // Write Occbin tags - equation_tags.writeOccbinOutput(output, modstruct, julia); + if (occbin) + equation_tags.writeOccbinOutput(output, modstruct, julia); // Write mapping for variables and equations they are present in if (!julia) diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index 1c68bb874dcf07e202b16473f7f154dc066a1a8f..6d046ddb9b6889406c5b4dbbcede6c18fbd2dfb0 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -300,7 +300,7 @@ public: void computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsOrder, const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool use_dll, bool bytecode); //! Writes information about the dynamic model to the driver file - void writeDriverOutput(ostream &output, const string &basename, bool block, bool use_dll, bool estimation_present, bool compute_xrefs, bool julia) const; + void writeDriverOutput(ostream &output, const string &basename, bool block, bool use_dll, bool occbin, bool estimation_present, bool compute_xrefs, bool julia) const; //! Write JSON AST void writeJsonAST(ostream &output) const; diff --git a/src/DynareBison.yy b/src/DynareBison.yy index 1a9c213e7f2dd5f03c3f28ed45a22044f1fa1144..212034a160e6d51e636731903ae89e24a0a8e54e 100644 --- a/src/DynareBison.yy +++ b/src/DynareBison.yy @@ -106,7 +106,7 @@ class ParsingDriver; %token USE_PENALIZED_OBJECTIVE_FOR_HESSIAN INIT_STATE FAST_REALTIME RESCALE_PREDICTION_ERROR_COVARIANCE GENERATE_IRFS %token NAN_CONSTANT NO_STATIC NOBS NOCONSTANT NODISPLAY NOCORR NODIAGNOSTIC NOFUNCTIONS NO_HOMOTOPY %token NOGRAPH POSTERIOR_NOGRAPH POSTERIOR_GRAPH NOMOMENTS NOPRINT NORMAL_PDF SAVE_DRAWS MODEL_NAME STDERR_MULTIPLES DIAGONAL_ONLY -%token OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS MAX_DIM_COVA_GROUP ADVANCED OUTFILE OUTVARS OVERWRITE DISCOUNT +%token OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS MAX_DIM_COVA_GROUP ADVANCED OUTFILE OUTVARS OVERWRITE DISCOUNT OCCBIN %token PARALLEL_LOCAL_FILES PARAMETERS PARAMETER_SET PARTIAL_INFORMATION PERIODS PERIOD PLANNER_OBJECTIVE PLOT_CONDITIONAL_FORECAST PLOT_PRIORS PREFILTER PRESAMPLE %token PERFECT_FORESIGHT_SETUP PERFECT_FORESIGHT_SOLVER NO_POSTERIOR_KERNEL_DENSITY FUNCTION %token PRINT PRIOR_MC PRIOR_TRUNC PRIOR_MODE PRIOR_MEAN POSTERIOR_MODE POSTERIOR_MEAN POSTERIOR_MEDIAN MLE_MODE PRUNING @@ -130,7 +130,7 @@ class ParsingDriver; %precedence UNARY %nonassoc POWER %token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN ERF DIFF ADL AUXILIARY_MODEL_NAME -%token SQRT CBRT NORMCDF NORMPDF STEADY_STATE EXPECTATION OCCBIN_LIKELIHOOD OCCBIN_SMOOTHER +%token SQRT CBRT NORMCDF NORMPDF STEADY_STATE EXPECTATION /* GSA analysis */ %token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU MORRIS_NLIV %token MORRIS_NTRA NSAM LOAD_REDFORM LOAD_RMSE LOAD_STAB ALPHA2_STAB LOGTRANS_REDFORM THRESHOLD_REDFORM @@ -866,6 +866,7 @@ model_options : BLOCK { driver.block(); } | o_linear | PARALLEL_LOCAL_FILES EQUAL '(' parallel_local_filename_list ')' | BALANCED_GROWTH_TEST_TOL EQUAL non_negative_number { driver.balanced_growth_test_tol($3); } + | OCCBIN { driver.occbin(); } ; model_options_list : model_options_list COMMA model_options @@ -2010,8 +2011,6 @@ estimation_options : o_datafile | o_emas_max_iter | o_stderr_multiples | o_diagonal_only - | o_occbin_likelihood - | o_occbin_smoother ; list_optim_option : QUOTED_STRING COMMA QUOTED_STRING @@ -3419,8 +3418,6 @@ o_proposal_approximation : PROPOSAL_APPROXIMATION EQUAL CUBATURE {driver.option_ o_distribution_approximation : DISTRIBUTION_APPROXIMATION EQUAL CUBATURE {driver.option_num("particle.distribution_approximation.cubature", "true"); driver.option_num("particle.distribution_approximation.unscented", "false"); driver.option_num("particle.distribution_approximation.montecarlo", "false");} | DISTRIBUTION_APPROXIMATION EQUAL UNSCENTED {driver.option_num("particle.distribution_approximation.cubature", "false"); driver.option_num("particle.distribution_approximation.unscented", "true"); driver.option_num("particle.distribution_approximation.montecarlo", "false");} | DISTRIBUTION_APPROXIMATION EQUAL MONTECARLO {driver.option_num("particle.distribution_approximation.cubature", "false"); driver.option_num("particle.distribution_approximation.unscented", "false"); driver.option_num("particle.distribution_approximation.montecarlo", "true");} ; -o_occbin_likelihood : OCCBIN_LIKELIHOOD { driver.option_num("occbin_likelihood", "true"); }; -o_occbin_smoother : OCCBIN_SMOOTHER { driver.option_num("occbin_smoother", "true"); }; o_gsa_identification : IDENTIFICATION EQUAL INT_NUMBER { driver.option_num("identification", $3); }; /*not in doc */ o_gsa_morris : MORRIS EQUAL INT_NUMBER { driver.option_num("morris", $3); }; o_gsa_stab : STAB EQUAL INT_NUMBER { driver.option_num("stab", $3); }; diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll index dda431955262b9f5b7a68a811face860eb610b3e..cdc7f6f0d8d3eaa8a80360d7f09ba52b3ef84c3b 100644 --- a/src/DynareFlex.ll +++ b/src/DynareFlex.ll @@ -432,8 +432,6 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) <DYNARE_STATEMENT>rescale_prediction_error_covariance {return token::RESCALE_PREDICTION_ERROR_COVARIANCE;} <DYNARE_STATEMENT>use_penalized_objective_for_hessian {return token::USE_PENALIZED_OBJECTIVE_FOR_HESSIAN;} <DYNARE_STATEMENT>expression {return token::EXPRESSION;} -<DYNARE_STATEMENT>occbin_likelihood {return token::OCCBIN_LIKELIHOOD;} -<DYNARE_STATEMENT>occbin_smoother {return token::OCCBIN_SMOOTHER;} <DYNARE_STATEMENT>first_simulation_period {return token::FIRST_SIMULATION_PERIOD;} <DYNARE_STATEMENT>alpha { @@ -825,6 +823,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) <DYNARE_BLOCK>no_static {return token::NO_STATIC;} <DYNARE_BLOCK>differentiate_forward_vars {return token::DIFFERENTIATE_FORWARD_VARS;} <DYNARE_BLOCK>parallel_local_files {return token::PARALLEL_LOCAL_FILES;} +<DYNARE_BLOCK>occbin {return token::OCCBIN;} <DYNARE_STATEMENT,DYNARE_BLOCK>linear {return token::LINEAR;} diff --git a/src/EquationTags.cc b/src/EquationTags.cc index d60772122ae827ff14966b3f61fb0c69a92af3b0..b1b61d415554e0dfb99918a263c8c481a2a89e89 100644 --- a/src/EquationTags.cc +++ b/src/EquationTags.cc @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Dynare Team + * Copyright © 2020-2021 Dynare Team * * This file is part of Dynare. * @@ -183,3 +183,16 @@ EquationTags::writeJsonAST(ostream &output, const int eqn) const } output << "}"; } + +bool +EquationTags::hasOccbinTags() const +{ + for (const auto & [eqn, tags] : eqn_tags) + for (const auto & [key, value] : tags) + if (key == "pswitch" + || key == "bind" + || key == "relax" + || key == "pcrit") + return true; + return false; +} diff --git a/src/EquationTags.hh b/src/EquationTags.hh index ddd1eec50734240ffa397c33a44f062a542029be..5738e12778588071bc253f958958820b26fd9ee3 100644 --- a/src/EquationTags.hh +++ b/src/EquationTags.hh @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Dynare Team + * Copyright © 2020-2021 Dynare Team * * This file is part of Dynare. * @@ -115,6 +115,10 @@ public: void writeOccbinOutput(ostream &output, const string &modstruct, bool julia) const; void writeLatexOutput(ostream &output, int eqn) const; void writeJsonAST(ostream &output, const int eq) const; + + /* Returns true if at least one equation has a tag associated to occbin + (bind/relax/pswitch/pcrit) */ + bool hasOccbinTags() const; }; #endif diff --git a/src/ModFile.cc b/src/ModFile.cc index 40a7b25f5fec59f4b3eaaa5e0a2c3a4fd9bb50a0..fcad0e87a56d718cfa911adc6e859fd024e0cbcc 100644 --- a/src/ModFile.cc +++ b/src/ModFile.cc @@ -679,6 +679,23 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool exit(EXIT_FAILURE); } + if (occbin && !dynamic_model.hasOccbinTags()) + { + cerr << "ERROR: the 'occbin' option is present, but there is no equation with the associated tags (bind/relax/pswitch/pcrit)" << endl; + exit(EXIT_FAILURE); + } + + if (occbin + && (mod_file_struct.stoch_simul_present || mod_file_struct.osr_present + || mod_file_struct.ramsey_model_present || mod_file_struct.ramsey_policy_present + || mod_file_struct.discretionary_policy_present || mod_file_struct.extended_path_present + || mod_file_struct.identification_present || mod_file_struct.sensitivity_present + || mod_file_struct.mom_estimation_present || mod_file_struct.calib_smoother_present)) + { + cerr << "ERROR: the 'occbin' option is not compatible with commands other than 'estimation'" << endl; + exit(EXIT_FAILURE); + } + if (!mod_file_struct.ramsey_model_present) cout << "Found " << dynamic_model.equation_number() << " equation(s)." << endl; else @@ -1011,11 +1028,16 @@ ModFile::writeMOutput(const string &basename, bool clear_all, bool clear_global, if (dynamic_model.equation_number() > 0) { - dynamic_model.writeDriverOutput(mOutputFile, basename, block, use_dll, mod_file_struct.estimation_present, compute_xrefs, false); + dynamic_model.writeDriverOutput(mOutputFile, basename, block, use_dll, occbin, mod_file_struct.estimation_present, compute_xrefs, false); if (!no_static) static_model.writeDriverOutput(mOutputFile, block); } + if (occbin) + mOutputFile << "options_ = set_default_occbin_options(options_, M_);" << endl + << "clear mr_runsim_occbin_fn" << endl + << "M_ = get_wish_list(M_);" << endl; + if (onlymodel || gui) for (const auto &statement : statements) { @@ -1219,7 +1241,7 @@ ModFile::writeJuliaOutput(const string &basename) const if (dynamic_model.equation_number() > 0) { - dynamic_model.writeDriverOutput(jlOutputFile, basename, false, false, + dynamic_model.writeDriverOutput(jlOutputFile, basename, false, false, false, mod_file_struct.estimation_present, false, true); if (!no_static) { diff --git a/src/ModFile.hh b/src/ModFile.hh index 01e1a471d1192d588533e5648efa8cdb7cb18740..6ab993f75b3716a952f2d46e84d677c22e8e1519 100644 --- a/src/ModFile.hh +++ b/src/ModFile.hh @@ -99,6 +99,9 @@ public: with a lead */ vector<string> differentiate_forward_vars_subset; + //! Whether “occbin” option is used + bool occbin{false}; + //! Are nonstationary variables present ? bool nonstationary_variables{false}; diff --git a/src/ModelTree.cc b/src/ModelTree.cc index b540bcb5b24281d7381ab75654e052dbd94ae71e..1197e2ec2a6910545ada91825b6e0f1396ad275a 100644 --- a/src/ModelTree.cc +++ b/src/ModelTree.cc @@ -2120,3 +2120,9 @@ ModelTree::updateReverseVariableEquationOrderings() eq_idx_orig2block[eq_idx_block2orig[i]] = i; } } + +bool +ModelTree::hasOccbinTags() const +{ + return equation_tags.hasOccbinTags(); +} diff --git a/src/ModelTree.hh b/src/ModelTree.hh index e075e612508333ee4ee05c6523a70a30ab0ce525..2b1c1b314a838b7299c8c85bcf26a280364cc053 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -480,6 +480,10 @@ public: return "UNKNOWN "; } } + + /* Returns true if at least one equation has a tag associated to occbin + (bind/relax/pswitch/pcrit) */ + bool hasOccbinTags() const; }; #endif diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc index 9b0695c732e54d639b32d0d9f9ce18e9d17cfdaa..a7a93a7e0409666dfd64c2f60919d1c4250ed527 100644 --- a/src/ParsingDriver.cc +++ b/src/ParsingDriver.cc @@ -634,6 +634,12 @@ ParsingDriver::bytecode() mod_file->bytecode = true; } +void +ParsingDriver::occbin() +{ + mod_file->occbin = true; +} + void ParsingDriver::differentiate_forward_vars_all() { diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh index ed4ef240175195191ffc8df6c4a8cc449323822c..cc33b0de792d0bd1d34ff2f23363c9ca152210dd 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -331,6 +331,8 @@ public: //! the model is stored in a binary file void bytecode(); + //! the model has occasional binding constraints + void occbin(); //! the static model is not computed void no_static(); //! the differentiate_forward_vars option is enabled (for all vars)