diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc index 0bbf6e5bd..5a97ef2a5 100644 --- a/preprocessor/DynamicModel.cc +++ b/preprocessor/DynamicModel.cc @@ -1995,6 +1995,15 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll) const void DynamicModel::writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll) const { + // Write list of predetermined variables in M_.predetermined_variables + if (predetermined_variables_vec.size() > 0) + { + output << "M_.predetermined_variables = '';" << endl; + for(vector ::const_iterator it = predetermined_variables_vec.begin(); + it != predetermined_variables_vec.end(); it++) + output << "M_.predetermined_variables = strvcat(M_.predetermined_variables, '" << *it << "');" << endl; + } + /* Writing initialisation for M_.lead_lag_incidence matrix M_.lead_lag_incidence is a matrix with as many columns as there are endogenous variables and as many rows as there are periods in the @@ -3078,6 +3087,40 @@ DynamicModel::substituteExpectation(bool partial_information_model) cout << "Substitution of Expectation operator: added " << neweqs.size() << " auxiliary variables and equations." << endl; } +void +DynamicModel::transformPredeterminedVariables() +{ + for(vector ::const_iterator it = predetermined_variables_vec.begin(); + it != predetermined_variables_vec.end(); it++) + { + try + { + if(symbol_table.getType(*it)!=eEndogenous) + { + cerr << "Error: You must declare predetermined variable " << *it << " as an endogenous variable." << endl; + exit(EXIT_FAILURE); + } + } + catch(SymbolTable::UnknownSymbolNameException &e) + { + cerr << "Error: predetermind variable " << *it << " has not been declared." << endl; + exit(EXIT_FAILURE); + } + catch(...) + { + cerr << "error in DynamicModel::transformPredeterminedVariables(), should not arrive here" << endl; + exit(EXIT_FAILURE); + } + + for(int i = 0; i < (int) equations.size(); i++) + { + BinaryOpNode *substeq = dynamic_cast(equations[i]->decreaseLeadsLagsPredeterminedVariables(*it)); + assert(substeq != NULL); + equations[i] = substeq; + } + } +} + void DynamicModel::fillEvalContext(eval_context_type &eval_context) const { diff --git a/preprocessor/DynamicModel.hh b/preprocessor/DynamicModel.hh index a17fab51c..785f06e61 100644 --- a/preprocessor/DynamicModel.hh +++ b/preprocessor/DynamicModel.hh @@ -165,6 +165,8 @@ public: int mfs; //! the file containing the model and the derivatives code ofstream code_file; + //! Stores variables declared to be predetermined by "predetermined_variables" statement + vector predetermined_variables_vec; //! Execute computations (variable sorting + derivation) /*! \param jacobianExo whether derivatives w.r. to exo and exo_det should be in the Jacobian (derivatives w.r. to endo are always computed) @@ -220,6 +222,9 @@ public: //! Transforms the model by removing all oExpectation void substituteExpectation(bool partial_information_model); + //! Transforms the model by decreasing the lead/lag of predetermined variables in model equations by one + void transformPredeterminedVariables(); + //! Fills eval context with values of model local variables and auxiliary variables void fillEvalContext(eval_context_type &eval_context) const; }; diff --git a/preprocessor/DynareBison.yy b/preprocessor/DynareBison.yy index 74afd2d00..81eafe0ef 100644 --- a/preprocessor/DynareBison.yy +++ b/preprocessor/DynareBison.yy @@ -123,7 +123,7 @@ class ParsingDriver; %token TEX RAMSEY_POLICY PLANNER_DISCOUNT %token TEX_NAME %token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL USEAUTOCORR -%token VALUES VAR VAREXO VAREXO_DET VAROBS +%token VALUES VAR VAREXO VAREXO_DET VAROBS PREDETERMINED_VARIABLES %token WRITE_LATEX_DYNAMIC_MODEL WRITE_LATEX_STATIC_MODEL %token XLS_SHEET XLS_RANGE %left COMMA @@ -177,6 +177,7 @@ statement : parameters | var | varexo | varexo_det + | predetermined_variables | change_type | periods | model @@ -246,6 +247,8 @@ varexo : VAREXO varexo_list ';'; varexo_det : VAREXO_DET varexo_det_list ';'; +predetermined_variables : PREDETERMINED_VARIABLES predetermined_variables_list ';'; + parameters : PARAMETERS parameter_list ';'; var_list : var_list symbol @@ -304,6 +307,14 @@ parameter_list : parameter_list symbol { driver.declare_parameter($1, $2); } ; +predetermined_variables_list : predetermined_variables_list symbol + { driver.add_predetermined_variable($2); } + | predetermined_variables_list COMMA symbol + { driver.add_predetermined_variable($3); } + | symbol + { driver.add_predetermined_variable($1); } + ; + change_type : CHANGE_TYPE '(' change_type_arg ')' change_type_var_list ';' { driver.change_type($3, $5); } ; diff --git a/preprocessor/DynareFlex.ll b/preprocessor/DynareFlex.ll index 35bf2b848..d91c0e119 100644 --- a/preprocessor/DynareFlex.ll +++ b/preprocessor/DynareFlex.ll @@ -98,6 +98,7 @@ int sigma_e = 0; var {BEGIN DYNARE_STATEMENT; return token::VAR;} varexo {BEGIN DYNARE_STATEMENT; return token::VAREXO;} varexo_det {BEGIN DYNARE_STATEMENT; return token::VAREXO_DET;} +predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;} parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;} periods {BEGIN DYNARE_STATEMENT; return token::PERIODS;} model_info {BEGIN DYNARE_STATEMENT; return token::MODEL_INFO;} @@ -317,6 +318,7 @@ int sigma_e = 0; varexo { return token::VAREXO; } varexo_det { return token::VAREXO_DET; } parameters { return token::PARAMETERS; } +predetermined_variables { return token::PREDETERMINED_VARIABLES; } bvar_prior_tau { return token::BVAR_PRIOR_TAU; } bvar_prior_decay { return token::BVAR_PRIOR_DECAY; } diff --git a/preprocessor/ExprNode.cc b/preprocessor/ExprNode.cc index 9e997ebf1..7715ca5e4 100644 --- a/preprocessor/ExprNode.cc +++ b/preprocessor/ExprNode.cc @@ -318,6 +318,12 @@ NumConstNode::decreaseLeadsLags(int n) const return const_cast(this); } +NodeID +NumConstNode::decreaseLeadsLagsPredeterminedVariables(const string pv_name) const +{ + return decreaseLeadsLags(1); +} + NodeID NumConstNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector &neweqs) const { @@ -824,6 +830,15 @@ VariableNode::decreaseLeadsLags(int n) const } } +NodeID +VariableNode::decreaseLeadsLagsPredeterminedVariables(const string pv_name) const +{ + if(datatree.symbol_table.getName(symb_id).compare(pv_name)==0) + return decreaseLeadsLags(1); + else + return const_cast(this); +} + NodeID VariableNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector &neweqs) const { @@ -1625,6 +1640,13 @@ UnaryOpNode::decreaseLeadsLags(int n) const return buildSimilarUnaryOpNode(argsubst, datatree); } +NodeID +UnaryOpNode::decreaseLeadsLagsPredeterminedVariables(const string pv_name) const +{ + NodeID argsubst = arg->decreaseLeadsLagsPredeterminedVariables(pv_name); + return buildSimilarUnaryOpNode(argsubst, datatree); +} + NodeID UnaryOpNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector &neweqs) const { @@ -2603,6 +2625,14 @@ BinaryOpNode::decreaseLeadsLags(int n) const return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree); } +NodeID +BinaryOpNode::decreaseLeadsLagsPredeterminedVariables(const string pv_name) const +{ + NodeID arg1subst = arg1->decreaseLeadsLagsPredeterminedVariables(pv_name); + NodeID arg2subst = arg2->decreaseLeadsLagsPredeterminedVariables(pv_name); + return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree); +} + NodeID BinaryOpNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector &neweqs) const { @@ -3066,6 +3096,15 @@ TrinaryOpNode::decreaseLeadsLags(int n) const return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree); } +NodeID +TrinaryOpNode::decreaseLeadsLagsPredeterminedVariables(const string pv_name) const +{ + NodeID arg1subst = arg1->decreaseLeadsLagsPredeterminedVariables(pv_name); + NodeID arg2subst = arg2->decreaseLeadsLagsPredeterminedVariables(pv_name); + NodeID arg3subst = arg3->decreaseLeadsLagsPredeterminedVariables(pv_name); + return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree); +} + NodeID TrinaryOpNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector &neweqs) const { @@ -3269,6 +3308,13 @@ UnknownFunctionNode::decreaseLeadsLags(int n) const exit(EXIT_FAILURE); } +NodeID +UnknownFunctionNode::decreaseLeadsLagsPredeterminedVariables(const string pv_name) const +{ + cerr << "UnknownFunctionNode::decreaseLeadsLagsPredeterminedVariables: not implemented!" << endl; + exit(EXIT_FAILURE); +} + NodeID UnknownFunctionNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector &neweqs) const { diff --git a/preprocessor/ExprNode.hh b/preprocessor/ExprNode.hh index 9091d33ae..5ba198f9a 100644 --- a/preprocessor/ExprNode.hh +++ b/preprocessor/ExprNode.hh @@ -303,6 +303,9 @@ public: \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. */ virtual NodeID substituteExpectation(subst_table_t &subst_table, vector &neweqs, bool partial_information_model) const = 0; + + virtual NodeID decreaseLeadsLagsPredeterminedVariables(const string pv_name) const = 0; + }; //! Object used to compare two nodes (using their indexes) @@ -342,6 +345,7 @@ public: virtual NodeID substituteExoLead(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExoLag(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExpectation(subst_table_t &subst_table, vector &neweqs, bool partial_information_model) const; + virtual NodeID decreaseLeadsLagsPredeterminedVariables(const string pv_name) const; }; //! Symbol or variable node @@ -380,6 +384,7 @@ public: virtual NodeID substituteExoLead(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExoLag(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExpectation(subst_table_t &subst_table, vector &neweqs, bool partial_information_model) const; + virtual NodeID decreaseLeadsLagsPredeterminedVariables(const string pv_name) const; }; //! Unary operator node @@ -428,6 +433,7 @@ public: virtual NodeID substituteExoLead(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExoLag(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExpectation(subst_table_t &subst_table, vector &neweqs, bool partial_information_model) const; + virtual NodeID decreaseLeadsLagsPredeterminedVariables(const string pv_name) const; }; //! Binary operator node @@ -479,6 +485,7 @@ public: virtual NodeID substituteExoLead(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExoLag(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExpectation(subst_table_t &subst_table, vector &neweqs, bool partial_information_model) const; + virtual NodeID decreaseLeadsLagsPredeterminedVariables(const string pv_name) const; }; //! Trinary operator node @@ -524,6 +531,7 @@ public: virtual NodeID substituteExoLead(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExoLag(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExpectation(subst_table_t &subst_table, vector &neweqs, bool partial_information_model) const; + virtual NodeID decreaseLeadsLagsPredeterminedVariables(const string pv_name) const; }; //! Unknown function node @@ -561,6 +569,7 @@ public: virtual NodeID substituteExoLead(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExoLag(subst_table_t &subst_table, vector &neweqs) const; virtual NodeID substituteExpectation(subst_table_t &subst_table, vector &neweqs, bool partial_information_model) const; + virtual NodeID decreaseLeadsLagsPredeterminedVariables(const string pv_name) const; }; #endif diff --git a/preprocessor/ModFile.cc b/preprocessor/ModFile.cc index c9ac4e540..125f193a3 100644 --- a/preprocessor/ModFile.cc +++ b/preprocessor/ModFile.cc @@ -134,6 +134,8 @@ ModFile::checkPass() void ModFile::transformPass() { + dynamic_model.transformPredeterminedVariables(); + if (mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present || mod_file_struct.osr_present @@ -172,9 +174,6 @@ ModFile::transformPass() void ModFile::computingPass(bool no_tmp_terms) { - - // expressions_tree.replace_oExpectation_in_datatree(); - // Mod file may have no equation (for example in a standalone BVAR estimation) bool dynamic_model_needed = mod_file_struct.simul_present || mod_file_struct.check_present || mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present|| mod_file_struct.osr_present diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc index 45d3b2ea7..0be4a6d5a 100644 --- a/preprocessor/ParsingDriver.cc +++ b/preprocessor/ParsingDriver.cc @@ -144,6 +144,13 @@ ParsingDriver::declare_parameter(string *name, string *tex_name) declare_symbol(name, eParameter, tex_name); } +void +ParsingDriver::add_predetermined_variable(string *name) +{ + mod_file->dynamic_model.predetermined_variables_vec.push_back(*name); + delete name; +} + void ParsingDriver::add_equation_tags(string *key, string *value) { diff --git a/preprocessor/ParsingDriver.hh b/preprocessor/ParsingDriver.hh index e2e35a91d..7ad71f27d 100644 --- a/preprocessor/ParsingDriver.hh +++ b/preprocessor/ParsingDriver.hh @@ -193,6 +193,8 @@ public: void declare_exogenous_det(string *name, string *tex_name = NULL); //! Declares a parameter void declare_parameter(string *name, string *tex_name = NULL); + //! Adds a predetermined_variable + void add_predetermined_variable(string *name); //! Declares and initializes a local parameter void declare_and_init_model_local_variable(string *name, NodeID rhs); //! Changes type of a symbol