diff --git a/ComputingTasks.cc b/ComputingTasks.cc index c7a29788..47910592 100644 --- a/ComputingTasks.cc +++ b/ComputingTasks.cc @@ -174,11 +174,13 @@ PriorPosteriorFunctionStatement::writeOutput(ostream &output, const string &base VarModelStatement::VarModelStatement(const SymbolList &symbol_list_arg, const OptionsList &options_list_arg, const string &name_arg, - const SymbolTable &symbol_table_arg) : + const SymbolTable &symbol_table_arg, + const DynamicModel &dynamic_model_arg) : symbol_list(symbol_list_arg), options_list(options_list_arg), name(name_arg), - symbol_table(symbol_table_arg) + symbol_table(symbol_table_arg), + dynamic_model(dynamic_model_arg) { } @@ -214,6 +216,7 @@ VarModelStatement::writeOutput(ostream &output, const string &basename, bool min symbol_list.writeOutput("options_.var.var_list_", output); output << "M_.var." << name << " = options_.var;" << endl << "clear options_.var;" << endl; + dynamic_model.writeVarExpectationFunctions(output, name); } StochSimulStatement::StochSimulStatement(const SymbolList &symbol_list_arg, diff --git a/ComputingTasks.hh b/ComputingTasks.hh index bba0efbf..e76ba3ae 100644 --- a/ComputingTasks.hh +++ b/ComputingTasks.hh @@ -117,11 +117,13 @@ private: const OptionsList options_list; const string &name; const SymbolTable &symbol_table; + const DynamicModel &dynamic_model; public: VarModelStatement(const SymbolList &symbol_list_arg, const OptionsList &options_list_arg, const string &name_arg, - const SymbolTable &symbol_table_arg); + const SymbolTable &symbol_table_arg, + const DynamicModel &dynamic_model_arg); virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings); virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const; }; diff --git a/DynamicModel.cc b/DynamicModel.cc index ce3ea113..bb9d0ba9 100644 --- a/DynamicModel.cc +++ b/DynamicModel.cc @@ -3141,6 +3141,14 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de output << "];" << endl; } +void +DynamicModel::writeVarExpectationFunctions(ostream &output, const string &var_model_name) const +{ + // Write Var Forecast files + for (int eq = 0; eq < (int) equations.size(); eq++) + equations[eq]->writeVarExpectationFunction(output, var_model_name); +} + map >, expr_t> DynamicModel::collect_first_order_derivatives_endogenous() { diff --git a/DynamicModel.hh b/DynamicModel.hh index 7f0177fb..9f0f2994 100644 --- a/DynamicModel.hh +++ b/DynamicModel.hh @@ -236,6 +236,9 @@ public: //! Writes model initialization and lead/lag incidence matrix to output void writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const; + //! Writes calls to functions that write functions that forecast VARs + void writeVarExpectationFunctions(ostream &output, const string &var_model_name) const; + //! Return true if the hessian is equal to zero inline bool checkHessianZero() const; diff --git a/DynareBison.yy b/DynareBison.yy index 0b56a4a3..55c05855 100644 --- a/DynareBison.yy +++ b/DynareBison.yy @@ -771,7 +771,7 @@ hand_side : '(' hand_side ')' { $$ = driver.add_power($1, $3); } | EXPECTATION '(' signed_integer ')''(' hand_side ')' { $$ = driver.add_expectation($3, $6); } - | VAR_EXPECTATION '(' hand_side COMMA MODEL_NAME EQUAL NAME ')' + | VAR_EXPECTATION '(' symbol COMMA MODEL_NAME EQUAL NAME ')' { $$ = driver.add_var_expectation($3, $7); } | MINUS hand_side %prec UMINUS { $$ = driver.add_uminus($2); } diff --git a/ExprNode.cc b/ExprNode.cc index fc768c5e..97be9eb1 100644 --- a/ExprNode.cc +++ b/ExprNode.cc @@ -194,6 +194,12 @@ ExprNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &inst // Nothing to do } +void +ExprNode::writeVarExpectationFunction(ostream &output, const string &var_model_name) const +{ + // Nothing to do +} + VariableNode * ExprNode::createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector &neweqs) const { @@ -349,6 +355,11 @@ NumConstNode::collectDynamicVariables(SymbolType type_arg, set > { } +void +NumConstNode::writeVarExpectationFunction(ostream &output, const string &var_model_name) const +{ +} + pair NumConstNode::normalizeEquation(int var_endo, vector > > &List_of_Op_RHS) const { @@ -1394,6 +1405,11 @@ VariableNode::isNumConstNodeEqualTo(double value) const return false; } +void +VariableNode::writeVarExpectationFunction(ostream &output, const string &var_model_name) const +{ +} + bool VariableNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const { @@ -1668,6 +1684,17 @@ UnaryOpNode::composeDerivatives(expr_t darg, int deriv_id) exit(EXIT_FAILURE); } +void +UnaryOpNode::writeVarExpectationFunction(ostream &output, const string &var_model_name) const +{ + if (op_code == oVarExpectation && var_model_name == var_expectation_model_name) + { + VariableNode *varg = dynamic_cast(arg); + output << "writeVarExpectationFunction('" << var_expectation_model_name << "', '" + << datatree.symbol_table.getName(varg->symb_id) << "');" << endl; + } +} + expr_t UnaryOpNode::computeDerivative(int deriv_id) { @@ -2017,15 +2044,13 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, break; case oVarExpectation: VariableNode *varg = dynamic_cast(arg); - assert(varg != NULL); - assert(datatree.symbol_table.getType(varg->symb_id) == eEndogenous); if (IS_LATEX(output_type)) output << "VAR" << LEFT_PAR(output_type) << datatree.symbol_table.getTeXName(varg->symb_id) << "_{t+1}" << RIGHT_PAR(output_type); else - output << "var_forecast('" << var_expectation_model_name << "', 1, y, '" - << datatree.symbol_table.getName(varg->symb_id) << "')"; + output << "var_forecast_" << var_expectation_model_name << "_" + << datatree.symbol_table.getName(varg->symb_id) << "(y)"; return; } @@ -2385,6 +2410,9 @@ UnaryOpNode::buildSimilarUnaryOpNode(expr_t alt_arg, DataTree &alt_datatree) con expr_t UnaryOpNode::toStatic(DataTree &static_datatree) const { + if (op_code == oVarExpectation) + return static_datatree.AddVariable((dynamic_cast(arg))->symb_id); + expr_t sarg = arg->toStatic(static_datatree); return buildSimilarUnaryOpNode(sarg, static_datatree); } @@ -3095,6 +3123,13 @@ BinaryOpNode::containsExternalFunction() const || arg2->containsExternalFunction(); } +void +BinaryOpNode::writeVarExpectationFunction(ostream &output, const string &var_model_name) const +{ + arg1->writeVarExpectationFunction(output, var_model_name); + arg2->writeVarExpectationFunction(output, var_model_name); +} + void BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, @@ -4234,6 +4269,14 @@ TrinaryOpNode::containsExternalFunction() const || arg3->containsExternalFunction(); } +void +TrinaryOpNode::writeVarExpectationFunction(ostream &output, const string &var_model_name) const +{ + arg1->writeVarExpectationFunction(output, var_model_name); + arg2->writeVarExpectationFunction(output, var_model_name); + arg3->writeVarExpectationFunction(output, var_model_name); +} + void TrinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, @@ -4899,6 +4942,14 @@ AbstractExternalFunctionNode::normalizeEquation(int var_endo, vector::const_iterator it = arguments.begin(); + it != arguments.end(); it++) + (*it)->writeVarExpectationFunction(output, var_model_name); +} + void AbstractExternalFunctionNode::writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, diff --git a/ExprNode.hh b/ExprNode.hh index 8f6d3560..19a2494b 100644 --- a/ExprNode.hh +++ b/ExprNode.hh @@ -212,6 +212,9 @@ public: //! returns true if the expr node contains an external function virtual bool containsExternalFunction() const = 0; + //! Writes the matlab/C function for a Var Expectation Node + virtual void writeVarExpectationFunction(ostream &output, const string &var_model_name) const = 0; + //! Writes output of node (with no temporary terms and with "outside model" output type) void writeOutput(ostream &output) const; @@ -501,6 +504,7 @@ public: virtual expr_t decreaseLeadsLagsPredeterminedVariables() const; virtual expr_t differentiateForwardVars(const vector &subset, subst_table_t &subst_table, vector &neweqs) const; virtual bool isNumConstNodeEqualTo(double value) const; + virtual void writeVarExpectationFunction(ostream &output, const string &var_model_name) const; virtual bool containsEndogenous(void) const; virtual bool containsExogenous() const; virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const; @@ -567,6 +571,7 @@ public: virtual expr_t decreaseLeadsLagsPredeterminedVariables() const; virtual expr_t differentiateForwardVars(const vector &subset, subst_table_t &subst_table, vector &neweqs) const; virtual bool isNumConstNodeEqualTo(double value) const; + virtual void writeVarExpectationFunction(ostream &output, const string &var_model_name) const; virtual bool containsEndogenous(void) const; virtual bool containsExogenous() const; virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const; @@ -655,6 +660,7 @@ public: virtual expr_t decreaseLeadsLagsPredeterminedVariables() const; virtual expr_t differentiateForwardVars(const vector &subset, subst_table_t &subst_table, vector &neweqs) const; virtual bool isNumConstNodeEqualTo(double value) const; + virtual void writeVarExpectationFunction(ostream &output, const string &var_model_name) const; virtual bool containsEndogenous(void) const; virtual bool containsExogenous() const; virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const; @@ -754,6 +760,7 @@ public: virtual expr_t decreaseLeadsLagsPredeterminedVariables() const; virtual expr_t differentiateForwardVars(const vector &subset, subst_table_t &subst_table, vector &neweqs) const; virtual bool isNumConstNodeEqualTo(double value) const; + virtual void writeVarExpectationFunction(ostream &output, const string &var_model_name) const; virtual bool containsEndogenous(void) const; virtual bool containsExogenous() const; virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const; @@ -835,6 +842,7 @@ public: virtual expr_t decreaseLeadsLagsPredeterminedVariables() const; virtual expr_t differentiateForwardVars(const vector &subset, subst_table_t &subst_table, vector &neweqs) const; virtual bool isNumConstNodeEqualTo(double value) const; + virtual void writeVarExpectationFunction(ostream &output, const string &var_model_name) const; virtual bool containsEndogenous(void) const; virtual bool containsExogenous() const; virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const; @@ -916,6 +924,7 @@ public: virtual expr_t decreaseLeadsLagsPredeterminedVariables() const; virtual expr_t differentiateForwardVars(const vector &subset, subst_table_t &subst_table, vector &neweqs) const; virtual bool isNumConstNodeEqualTo(double value) const; + virtual void writeVarExpectationFunction(ostream &output, const string &var_model_name) const; virtual bool containsEndogenous(void) const; virtual bool containsExogenous() const; virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const; diff --git a/ModFile.cc b/ModFile.cc index 5719d019..975b0d8a 100644 --- a/ModFile.cc +++ b/ModFile.cc @@ -809,9 +809,20 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo } // Print statements + // Print var_model statements first so that the forecast functions can be used by following statements + // for (vector::const_iterator it = statements.begin(); + // it != statements.end(); it++) + // if (dynamic_cast(*it) != NULL) + // (*it)->writeOutput(mOutputFile, basename, minimal_workspace); + // dynamic_model.writeVarExpectationFunctions(mOutputFile); + for (vector::const_iterator it = statements.begin(); it != statements.end(); it++) { + // Don't print var_model statements again as they were already printed + // if (dynamic_cast(*it) != NULL) + // continue; + (*it)->writeOutput(mOutputFile, basename, minimal_workspace); /* Special treatment for initval block: insert initial values for the diff --git a/ParsingDriver.cc b/ParsingDriver.cc index 6e03325c..250c328b 100644 --- a/ParsingDriver.cc +++ b/ParsingDriver.cc @@ -1286,7 +1286,7 @@ ParsingDriver::var_model() if (it == options_list.string_options.end()) error("You must pass the model_name option to the var_model statement."); const string *name = new string(it->second); - mod_file->addStatement(new VarModelStatement(symbol_list, options_list, *name, mod_file->symbol_table)); + mod_file->addStatement(new VarModelStatement(symbol_list, options_list, *name, mod_file->symbol_table, mod_file->dynamic_model)); symbol_list.clear(); options_list.clear(); } @@ -1628,6 +1628,15 @@ ParsingDriver::copy_options(string *to_declaration_type, string *to_name1, strin delete from_subsample_name; } +void +ParsingDriver::check_symbol_is_endogenous(string *name) +{ + check_symbol_existence(*name); + int symb_id = mod_file->symbol_table.getID(*name); + if (mod_file->symbol_table.getType(symb_id) != eEndogenous) + error(*name + " is not endogenous"); +} + void ParsingDriver::check_symbol_is_endogenous_or_exogenous(string *name) { @@ -2387,9 +2396,10 @@ ParsingDriver::add_expectation(string *arg1, expr_t arg2) } expr_t -ParsingDriver::add_var_expectation(expr_t arg1, string *arg2) +ParsingDriver::add_var_expectation(string *arg1, string *arg2) { - expr_t varExpectationNode = data_tree->AddVarExpectation(arg1, *arg2); + check_symbol_is_endogenous(arg1); + expr_t varExpectationNode = data_tree->AddVarExpectation(add_model_variable(arg1), *arg2); return varExpectationNode; } diff --git a/ParsingDriver.hh b/ParsingDriver.hh index 9d5736db..a66d2d33 100644 --- a/ParsingDriver.hh +++ b/ParsingDriver.hh @@ -87,6 +87,9 @@ private: //! Checks that a given symbol exists and is a parameter, and stops with an error message if it isn't void check_symbol_is_parameter(string *name); + //! Checks that a given symbol exists and is endogenous, and stops with an error message if it isn't + void check_symbol_is_endogenous(string *name); + //! Checks that a given symbol was assigned within a Statement void check_symbol_is_statement_variable(string *name); @@ -639,7 +642,7 @@ public: //! Writes token "E(arg1)(arg2)" to model tree expr_t add_expectation(string *arg1, expr_t arg2); //! Writes token "VAR_EXPECTATION(arg1,arg2)" to model tree - expr_t add_var_expectation(expr_t arg1, string *arg2); + expr_t add_var_expectation(string *arg1, string *arg2); //! Writes token "exp(arg1)" to model tree expr_t add_exp(expr_t arg1); //! Writes token "log(arg1)" to model tree