diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc index fcf94a42..8f65bc0a 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 f6c19af0..ab209904 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -2798,7 +2798,7 @@ DynamicModel::writeBlockDriverOutput(ostream &output, const string &basename, } void -DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool block_decomposition, bool use_dll, bool estimation_present, bool compute_xrefs) const +DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool block_decomposition, bool use_dll, bool occbin, bool estimation_present, bool compute_xrefs) const { /* Writing initialisation for M_.lead_lag_incidence matrix M_.lead_lag_incidence is a matrix with as many columns as there are @@ -2895,7 +2895,8 @@ DynamicModel::writeDriverOutput(ostream &output, const string &basename, bool bl equation_tags.writeOutput(output); // Write Occbin tags - equation_tags.writeOccbinOutput(output); + if (occbin) + equation_tags.writeOccbinOutput(output); // Write mapping for variables and equations they are present in for (const auto &variable : variableMapping) diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index d98b13c5..c64ef062 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) const; + void writeDriverOutput(ostream &output, const string &basename, bool block, bool use_dll, bool occbin, bool estimation_present, bool compute_xrefs) const; //! Write JSON AST void writeJsonAST(ostream &output) const; diff --git a/src/DynareBison.yy b/src/DynareBison.yy index 68765865..6c47638a 100644 --- a/src/DynareBison.yy +++ b/src/DynareBison.yy @@ -107,7 +107,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 DETERMINISTIC_TRENDS OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS MAX_DIM_COVA_GROUP ADVANCED OUTFILE OUTVARS OVERWRITE DISCOUNT +%token DETERMINISTIC_TRENDS 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 PARTICLE_FILTER_OPTIONS @@ -131,7 +131,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 @@ -873,6 +873,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 @@ -2089,8 +2090,6 @@ estimation_options : o_datafile | o_emas_max_iter | o_stderr_multiples | o_diagonal_only - | o_occbin_likelihood - | o_occbin_smoother | o_no_init_estimation_check_first_obs | o_heteroskedastic_filter ; @@ -3518,8 +3517,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 b37ea326..feedb790 100644 --- a/src/DynareFlex.ll +++ b/src/DynareFlex.ll @@ -434,8 +434,6 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) rescale_prediction_error_covariance {return token::RESCALE_PREDICTION_ERROR_COVARIANCE;} use_penalized_objective_for_hessian {return token::USE_PENALIZED_OBJECTIVE_FOR_HESSIAN;} expression {return token::EXPRESSION;} -occbin_likelihood {return token::OCCBIN_LIKELIHOOD;} -occbin_smoother {return token::OCCBIN_SMOOTHER;} first_simulation_period {return token::FIRST_SIMULATION_PERIOD;} no_init_estimation_check_first_obs {return token::NO_INIT_ESTIMATION_CHECK_FIRST_OBS;} @@ -836,6 +834,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) no_static {return token::NO_STATIC;} differentiate_forward_vars {return token::DIFFERENTIATE_FORWARD_VARS;} parallel_local_files {return token::PARALLEL_LOCAL_FILES;} +occbin {return token::OCCBIN;} linear {return token::LINEAR;} diff --git a/src/EquationTags.cc b/src/EquationTags.cc index c86fd51a..18cacd5f 100644 --- a/src/EquationTags.cc +++ b/src/EquationTags.cc @@ -165,3 +165,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 d573f8c0..b983fbd4 100644 --- a/src/EquationTags.hh +++ b/src/EquationTags.hh @@ -115,6 +115,10 @@ public: void writeOccbinOutput(ostream &output) 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 d340903d..e72e5825 100644 --- a/src/ModFile.cc +++ b/src/ModFile.cc @@ -686,6 +686,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 @@ -1018,11 +1035,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); + dynamic_model.writeDriverOutput(mOutputFile, basename, block, use_dll, occbin, mod_file_struct.estimation_present, compute_xrefs); 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) { diff --git a/src/ModFile.hh b/src/ModFile.hh index 01e1a471..6ab993f7 100644 --- a/src/ModFile.hh +++ b/src/ModFile.hh @@ -99,6 +99,9 @@ public: with a lead */ vector 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 e6fc89d7..906c285c 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 6cfdfcf6..f295a04d 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -494,6 +494,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 4b0d9520..f25e0ef5 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 4402222e..46c3fde5 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -325,6 +325,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)