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
time-shift
sebastien 2009-11-09 15:13:47 +00:00
parent 09f1b60e22
commit 76e691c651
10 changed files with 64 additions and 40 deletions

View File

@ -729,6 +729,12 @@ end;
<listitem><para>binary comparison operators (which evaluate to either <literal>0</literal> or <literal>1</literal>): <literal>&lt;</literal>, <literal>&gt;</literal>, <literal>&lt;=</literal>, <literal>&gt;=</literal>, <literal>==</literal>, <literal>!=</literal></para></listitem>
</itemizedlist>
</para>
<para>The following operators are allowed in <replaceable>MODEL_EXPRESSION</replaceable>:
<itemizedlist>
<listitem><para>steady state operator: <literal>STEADY_STATE(</literal><replaceable>MODEL_EXPRESSION</replaceable><literal>)</literal>. This operator is used to take the value of the enclosed expression at the steady state. A typical usage is in the Taylor rule, where you may want to use the value of GDP at steady state to compute the output gap.</para></listitem>
<listitem id="expectation_operator"><para>expectation operator: <literal>EXPECTATION(</literal><replaceable>INTEGER</replaceable><literal>)(</literal><replaceable>MODEL_EXPRESSION</replaceable><literal>)</literal>. This operator is used to take the expectation of some expression using a different information set than the information available at current period. For example, <literal>EXPECTATION(-1)(x(+1))</literal> is equal to the expected value of variable <literal>x</literal> at next period, using the information set available at the previous period. In practice, Dynare solves this by creating an auxiliary variable equal to <literal>AUX = x(+2)</literal>, and by replacing the expectation operator by <literal>AUX(-1)</literal>. Note that a value of <literal>0</literal> for the time shift component is reserved for partial information models (not yet fully implemented).</para></listitem>
</itemizedlist>
</para>
</sect2>
<sect2><title>Functions</title>
@ -914,6 +920,16 @@ end;
</para>
<para>If LaTeX names were given for variables and parameters (see <xref linkend="var"/>, <xref linkend="varexo"/>, <xref linkend="varexo_det"/>, <xref linkend="parameters"/>), then those will be used; otherwise, the plain text names will be used.</para>
<para>Time subscripts (<literal>t</literal>, <literal>t+1</literal>, <literal>t-1</literal>, ...) will be appended to the variable names, as LaTeX subscripts.</para>
<para>
Note that the model written in the TeX file will differ from the model declared by the user in the following dimensions:
<itemizedlist>
<listitem><para>the timing convention of <xref linkend="predetermined_variables"/> will have been changed to the default Dynare timing convention; in other words, variables declared as predetermined will be lagged on period back,</para></listitem>
<listitem><para>the <link linkend="expectation_operator">expectation operators</link> will have been removed, replaced by auxiliary variables and new equations as explained in the documentation of the operator,</para></listitem>
<listitem><para>for stochastic models, variables with leads or lags greater or equal than two will have been removed, replaced by new auxiliary variables and equations.</para></listitem>
</itemizedlist>
</para>
</refsect1>
</refentry>
@ -937,6 +953,9 @@ end;
<para>If your <filename class="extension">.mod</filename> file is <filename><replaceable>FILENAME</replaceable>.mod</filename>, then Dynare will create a file called <filename><replaceable>FILENAME</replaceable>_static.tex</filename>, containing the list of all the equations of the steady state model.
</para>
<para>If LaTeX names were given for variables and parameters (see <xref linkend="var"/>, <xref linkend="varexo"/>, <xref linkend="varexo_det"/>, <xref linkend="parameters"/>), then those will be used; otherwise, the plain text names will be used.</para>
<para>
Note that the model written in the TeX file will differ from the model declared by the user in the some dimensions, see <xref linkend="write_latex_dynamic_model"/>.
</para>
</refsect1>
</refentry>

View File

@ -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;
}

View File

@ -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
{
};

View File

@ -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

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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();

View File

@ -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
{

View File

@ -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)