diff --git a/DataTree.cc b/DataTree.cc index e0559d702b813be95d20a07558027d2331265cc2..c116adfba710a65f2517016f1ff19086c5d1720a 100644 --- a/DataTree.cc +++ b/DataTree.cc @@ -39,8 +39,6 @@ DataTree::DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_consta MinusInfinity = AddUMinus(Infinity); Pi = AddNumConstant("3.141592653589793"); - - steady_state_found = false; } DataTree::~DataTree() @@ -418,7 +416,6 @@ DataTree::AddNormcdf(NodeID iArg1, NodeID iArg2, NodeID iArg3) NodeID DataTree::AddSteadyState(NodeID iArg1) { - steady_state_found = true; return AddUnaryOp(oSteadyState, iArg1); } @@ -484,3 +481,14 @@ DataTree::getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException) { throw UnknownDerivIDException(); } + +bool +DataTree::containsSteadyStateOperator() const +{ + for(unary_op_node_map_type::const_iterator it = unary_op_node_map.begin(); + it != unary_op_node_map.end(); it++) + if (it->first.second == oSteadyState) + return true; + + return false; +} diff --git a/DataTree.hh b/DataTree.hh index 66b76129ff5a6a952c1df110beb7aa83783e7cbc..1bd4b40d82ea3db8589dcbf08dfc3cc927d293c1 100644 --- a/DataTree.hh +++ b/DataTree.hh @@ -54,22 +54,22 @@ protected: //! Pair (symbol_id, lag) used as key typedef map<pair<int, int>, VariableNode *> variable_node_map_type; variable_node_map_type variable_node_map; - typedef map<pair<NodeID, int>, UnaryOpNode *> unary_op_node_map_type; + typedef map<pair<NodeID, UnaryOpcode>, UnaryOpNode *> unary_op_node_map_type; unary_op_node_map_type unary_op_node_map; - typedef map<pair<pair<NodeID, NodeID>, int>, BinaryOpNode *> binary_op_node_map_type; + typedef map<pair<pair<NodeID, NodeID>, BinaryOpcode>, BinaryOpNode *> binary_op_node_map_type; binary_op_node_map_type binary_op_node_map; - typedef map<pair<pair<pair<NodeID, NodeID>,NodeID>, int>, TrinaryOpNode *> trinary_op_node_map_type; + typedef map<pair<pair<pair<NodeID, NodeID>,NodeID>, TrinaryOpcode>, TrinaryOpNode *> trinary_op_node_map_type; trinary_op_node_map_type trinary_op_node_map; //! Stores local variables value (maps symbol ID to corresponding node) map<int, NodeID> local_variables_table; - //! true when oSteadyState is encountered in a dynamic model - bool steady_state_found; - //! Internal implementation of AddVariable(), without the check on the lag VariableNode *AddVariableInternal(int symb_id, int lag); + //! Is there a steady state operator in the tree? + bool containsSteadyStateOperator() const; + private: typedef list<NodeID> node_list_type; //! The list of nodes @@ -180,8 +180,6 @@ public: //! Checks if a given symbol is used somewhere in the data tree bool isSymbolUsed(int symb_id) const; //! Thrown when trying to access an unknown variable by deriv_id - bool containsSteadyStateOperator() const { return steady_state_found; }; - //! Thrown when trying to access an unknown variable by deriv_id class UnknownDerivIDException { }; diff --git a/DynamicModel.cc b/DynamicModel.cc index 532261f9b6868b9ccbed07b1dfae67803e03272c..ce95029dbd6535176e9e9788f8b748ac2427a5b2 100644 --- a/DynamicModel.cc +++ b/DynamicModel.cc @@ -3051,10 +3051,10 @@ DynamicModel::substituteExpectation(bool partial_information_model) ExprNode::subst_table_t subst_table; vector<BinaryOpNode *> neweqs; - // Substitute in model binary op node map - for(unary_op_node_map_type::reverse_iterator it = unary_op_node_map.rbegin(); - it != unary_op_node_map.rend(); it++) - it->second->substituteExpectation(subst_table, neweqs, partial_information_model); + // Substitute in model local variables + for(map<int, NodeID>::iterator it = local_variables_table.begin(); + it != local_variables_table.end(); it++) + it->second = it->second->substituteExpectation(subst_table, neweqs, partial_information_model); // Substitute in equations for(int i = 0; i < (int) equations.size(); i++) @@ -3072,10 +3072,12 @@ DynamicModel::substituteExpectation(bool partial_information_model) copy(neweqs.rbegin(), neweqs.rend(), front_inserter(aux_equations)); if (neweqs.size() > 0) - if (partial_information_model) - cout << "Substitution of Expectation operator: added " << subst_table.size() << " auxiliary variables and " << neweqs.size() << " auxiliary equations." << endl; - else - cout << "Substitution of Expectation operator: added " << neweqs.size() << " auxiliary variables and equations." << endl; + { + if (partial_information_model) + cout << "Substitution of Expectation operator: added " << subst_table.size() << " auxiliary variables and " << neweqs.size() << " auxiliary equations." << endl; + else + cout << "Substitution of Expectation operator: added " << neweqs.size() << " auxiliary variables and equations." << endl; + } } void diff --git a/DynareBison.yy b/DynareBison.yy index 81eafe0ef0a6134f0b1aa4b85596ea76c5b28c05..5cc425fc89b92ed8733f87212d7b7b7bd8907c17 100644 --- a/DynareBison.yy +++ b/DynareBison.yy @@ -375,8 +375,6 @@ expression : '(' expression ')' { $$ = driver.add_equal_equal($1, $3); } | expression EXCLAMATION_EQUAL expression { $$ = driver.add_different($1, $3); } - | EXPECTATION '(' signed_integer ')''(' expression ')' - { $$ = driver.add_expectation($3, $6); } | MINUS expression %prec UMINUS { $$ = driver.add_uminus($2); } | PLUS expression %prec UPLUS @@ -413,8 +411,6 @@ expression : '(' expression ')' { $$ = driver.add_normcdf($3, $5, $7); } | NORMCDF '(' expression ')' { $$ = driver.add_normcdf($3); } - | STEADY_STATE '(' expression ')' - { $$ = driver.add_steady_state($3); } | NAN_CONSTANT { $$ = driver.add_nan_constant(); } | INF_CONSTANT diff --git a/ExprNode.cc b/ExprNode.cc index 0a861ec0fdddbb686ef06bef5349abfaf932dd59..705254e34057b8348229ca25440162543a397108 100644 --- a/ExprNode.cc +++ b/ExprNode.cc @@ -1704,45 +1704,41 @@ UnaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNo { subst_table_t::iterator it = subst_table.find(const_cast<UnaryOpNode *>(this)); - //This if statement should evaluate to true when substituting Exp operators out of equations in second pass if (it != subst_table.end()) return const_cast<VariableNode *>(it->second); //Arriving here, we need to create an auxiliary variable for this Expectation Operator: int symb_id = datatree.symbol_table.addExpectationAuxiliaryVar(expectation_information_set, arg->idx); //AUXE_period_arg.idx NodeID newAuxE = datatree.AddVariable(symb_id, 0); - assert(dynamic_cast<VariableNode *>(newAuxE) != NULL); if (partial_information_model && expectation_information_set==0) { //Ensure x is a single variable as opposed to an expression if (dynamic_cast<VariableNode *>(arg) == NULL) { - cerr << "In Partial Information models, EXPECTATION(0)(X) can only be used when X is a single variable." << endl; + cerr << "ERROR: In Partial Information models, EXPECTATION(0)(X) can only be used when X is a single variable." << endl; exit(EXIT_FAILURE); } } else { - //take care of any nested expectation operators by calling arg->substituteExpectation(.), then decreaseLeadsLags for this oExp operator + //take care of any nested expectation operators by calling arg->substituteExpectation(.), then decreaseLeadsLags for this oExpectation operator //arg(lag-period) (holds entire subtree of arg(lag-period) NodeID substexpr = (arg->substituteExpectation(subst_table, neweqs, partial_information_model))->decreaseLeadsLags(expectation_information_set); assert(substexpr != NULL); neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(newAuxE, substexpr))); //AUXE_period_arg.idx = arg(lag-period) - newAuxE = newAuxE->decreaseLeadsLags(-1*expectation_information_set); - assert(dynamic_cast<VariableNode *>(newAuxE) != NULL); + newAuxE = datatree.AddVariable(symb_id, expectation_information_set); } + assert(dynamic_cast<VariableNode *>(newAuxE) != NULL); subst_table[this] = dynamic_cast<VariableNode *>(newAuxE); return newAuxE; } default: - { NodeID argsubst = arg->substituteExpectation(subst_table, neweqs, partial_information_model); return buildSimilarUnaryOpNode(argsubst, datatree); - } } } diff --git a/ExprNode.hh b/ExprNode.hh index 2bc611c4c4b60bc9bbe462b965b3c2f899920fca..6349e39dacb38eae917ff8cffdf6c0f838000b13 100644 --- a/ExprNode.hh +++ b/ExprNode.hh @@ -301,6 +301,7 @@ public: /*! \param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. + \param[in] partial_information_model Are we substituting in a partial information model? */ virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const = 0; diff --git a/ModFile.cc b/ModFile.cc index 93cf96ff8dc23f283a4ac8178d6cf970951e3f53..005cb5c63c9dc97f981d8bcb9898d51b7fc1f3f8 100644 --- a/ModFile.cc +++ b/ModFile.cc @@ -137,14 +137,14 @@ ModFile::transformPass() if (symbol_table.predeterminedNbr() > 0) dynamic_model.transformPredeterminedVariables(); + // Create auxiliary vars for Expectation operator + dynamic_model.substituteExpectation(mod_file_struct.partial_information); + if (mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present || mod_file_struct.osr_present || mod_file_struct.ramsey_policy_present) { - // In stochastic models, create auxiliary vars for Expecatation operator - dynamic_model.substituteExpectation(mod_file_struct.partial_information); - // In stochastic models, create auxiliary vars for leads and lags greater than 2 dynamic_model.substituteEndoLeadGreaterThanTwo(); dynamic_model.substituteExoLead(); diff --git a/SymbolTable.cc b/SymbolTable.cc index 4dd13629d4ff872890a8cc2aea8d62d9be2f3d82..8dd000d620b738a40b69499fe0e88a21b837e871 100644 --- a/SymbolTable.cc +++ b/SymbolTable.cc @@ -211,6 +211,7 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException) { case avEndoLead: case avExoLead: + case avExpectation: break; case avEndoLag: case avExoLag: @@ -314,10 +315,11 @@ SymbolTable::addExoLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (Frozen } int -SymbolTable::addExpectationAuxiliaryVar(int arg1, int arg2) throw (FrozenException) +SymbolTable::addExpectationAuxiliaryVar(int information_set, int index) throw (FrozenException) { ostringstream varname; - varname << "AUXE_" << arg1 << "_" << arg2; + varname << "AUX_EXPECT_" << (information_set < 0 ? "LAG" : "LEAD") << "_" + << abs(information_set) << "_" << index; int symb_id; try { diff --git a/SymbolTable.hh b/SymbolTable.hh index 4f11bb2ecc975e6870b25bf1eacfe3a7a1d1be82..4eded1bc1bfd261301345d0086e6d99edb876cb7 100644 --- a/SymbolTable.hh +++ b/SymbolTable.hh @@ -176,11 +176,13 @@ public: \param[in] orig_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lag) \return the symbol ID of the new symbol */ int addExoLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException); - //! Adds an auxiliary variable for the expectations operator + //! Adds an auxiliary variable for the expectation operator /*! - \param[in] indeces Used to construct the variable name - \return the symbol ID of the new symbol */ - int addExpectationAuxiliaryVar(int arg1, int arg2) throw (FrozenException); + \param[in] information_set information set (possibly negative) of the expectation operator + \param[in] index Used to construct the variable name + \return the symbol ID of the new symbol + */ + int addExpectationAuxiliaryVar(int information_set, int index) throw (FrozenException); //! Tests if symbol already exists inline bool exists(const string &name) const; //! Get symbol name (by ID)