Commit 5568e622 authored by sebastien's avatar sebastien
Browse files

preprocessor:

* fixed a bug with EXPECTATION operator: now handle model local variables
* substitute EXPECTATION operator even in deterministic models (for avoiding crashes, even if use of this operator doesn't make sense there)
* forbid the use of EXPECTATION and STEADY_STEATE outside model block
* minor implementation changes in EXPECTATION and STEADY_STATE operators

reference manual:
* documented EXPECTATION and STEADY_STATE operators
* added a note in write_latex_{static,dynamic}_model commands documentation about auxiliary variables and other model transformations


git-svn-id: https://www.dynare.org/svn/dynare/trunk@3145 ac1d8469-bf42-47a9-8791-bf33cf982152
parent 3fdeeca2
......@@ -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;
}
......@@ -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
{
};
......
......@@ -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
......
......@@ -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
......
......@@ -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);
}
}
}
......
......@@ -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;
......
......@@ -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();
......
......@@ -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
{
......
......@@ -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)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment