Remove some limitations of steady state model:

- allow recursive definitions (Closes #554)
- allow a variable to be defined twice, simply emit a warning (Ref #556)
time-shift
Sébastien Villemot 2014-02-24 16:40:28 +01:00
parent 711a4f62a2
commit 8fddca92a2
3 changed files with 27 additions and 29 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2006-2013 Dynare Team * Copyright (C) 2006-2014 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
@ -113,7 +113,7 @@ ModFile::checkPass()
(*it)->checkPass(mod_file_struct, warnings); (*it)->checkPass(mod_file_struct, warnings);
// Check the steady state block // Check the steady state block
steady_state_model.checkPass(mod_file_struct.ramsey_policy_present); steady_state_model.checkPass(mod_file_struct.ramsey_policy_present, warnings);
// If order option has not been set, default to 2 // If order option has not been set, default to 2
if (!mod_file_struct.order_option) if (!mod_file_struct.order_option)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2010-2011 Dynare Team * Copyright (C) 2010-2014 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
@ -39,8 +39,7 @@ SteadyStateModel::addDefinition(int symb_id, expr_t expr)
// Add the variable // Add the variable
vector<int> v; vector<int> v;
v.push_back(symb_id); v.push_back(symb_id);
recursive_order.push_back(v); def_table.push_back(make_pair(v, expr));
def_table[v] = expr;
} }
void void
@ -53,33 +52,32 @@ SteadyStateModel::addMultipleDefinitions(const vector<int> &symb_ids, expr_t exp
|| symbol_table.getType(symb_ids[i]) == eModFileLocalVariable || symbol_table.getType(symb_ids[i]) == eModFileLocalVariable
|| symbol_table.getType(symb_ids[i]) == eParameter); || symbol_table.getType(symb_ids[i]) == eParameter);
} }
recursive_order.push_back(symb_ids); def_table.push_back(make_pair(symb_ids, expr));
def_table[symb_ids] = expr;
} }
void void
SteadyStateModel::checkPass(bool ramsey_policy) const SteadyStateModel::checkPass(bool ramsey_policy, WarningConsolidation &warnings) const
{ {
if (ramsey_policy)
return;
vector<int> so_far_defined; vector<int> so_far_defined;
for (size_t i = 0; i < recursive_order.size(); i++) for (size_t i = 0; i < def_table.size(); i++)
{ {
const vector<int> &symb_ids = recursive_order[i]; const vector<int> &symb_ids = def_table[i].first;
// Check that symbols are not already defined // Check that symbols are not already defined
for (size_t j = 0; j < symb_ids.size(); j++) for (size_t j = 0; j < symb_ids.size(); j++)
if (find(so_far_defined.begin(), so_far_defined.end(), symb_ids[j]) if (find(so_far_defined.begin(), so_far_defined.end(), symb_ids[j])
!= so_far_defined.end()) != so_far_defined.end())
{ warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(symb_ids[j]) << "' is declared twice" << endl;
cerr << "ERROR: in the 'steady_state' block, variable '" << symbol_table.getName(symb_ids[j]) << "' is declared twice" << endl;
exit(EXIT_FAILURE);
}
// Check that expression has no undefined symbol // Check that expression has no undefined symbol
if (!ramsey_policy) if (!ramsey_policy)
{ {
set<int> used_symbols; set<int> used_symbols;
expr_t expr = def_table.find(symb_ids)->second; const expr_t &expr = def_table[i].second;
expr->collectVariables(eEndogenous, used_symbols); expr->collectVariables(eEndogenous, used_symbols);
expr->collectVariables(eModFileLocalVariable, used_symbols); expr->collectVariables(eModFileLocalVariable, used_symbols);
for (set<int>::const_iterator it = used_symbols.begin(); for (set<int>::const_iterator it = used_symbols.begin();
@ -87,7 +85,7 @@ SteadyStateModel::checkPass(bool ramsey_policy) const
if (find(so_far_defined.begin(), so_far_defined.end(), *it) if (find(so_far_defined.begin(), so_far_defined.end(), *it)
== so_far_defined.end()) == so_far_defined.end())
{ {
cerr << "ERROR: in the 'steady_state' block, variable '" << symbol_table.getName(*it) cerr << "ERROR: in the 'steady_state_model' block, variable '" << symbol_table.getName(*it)
<< "' is undefined in the declaration of variable '" << symbol_table.getName(symb_ids[0]) << "'" << endl; << "' is undefined in the declaration of variable '" << symbol_table.getName(symb_ids[0]) << "'" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -100,7 +98,7 @@ SteadyStateModel::checkPass(bool ramsey_policy) const
void void
SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_policy) const SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_policy) const
{ {
if (recursive_order.size() == 0) if (def_table.size() == 0)
return; return;
string filename = basename + "_steadystate2.m"; string filename = basename + "_steadystate2.m";
@ -118,9 +116,9 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_polic
<< "% Steady state generated by Dynare preprocessor" << endl << "% Steady state generated by Dynare preprocessor" << endl
<< " info = 0;" << endl; << " info = 0;" << endl;
for (size_t i = 0; i < recursive_order.size(); i++) for (size_t i = 0; i < def_table.size(); i++)
{ {
const vector<int> &symb_ids = recursive_order[i]; const vector<int> &symb_ids = def_table[i].first;
output << " "; output << " ";
if (symb_ids.size() > 1) if (symb_ids.size() > 1)
output << "["; output << "[";
@ -136,7 +134,7 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_polic
output << "]"; output << "]";
output << "="; output << "=";
def_table.find(symb_ids)->second->writeOutput(output, oSteadyStateFile); def_table[i].second->writeOutput(output, oSteadyStateFile);
output << ";" << endl; output << ";" << endl;
} }
output << " % Auxiliary equations" << endl; output << " % Auxiliary equations" << endl;
@ -169,16 +167,16 @@ SteadyStateModel::writeSteadyStateFileCC(const string &basename, bool ramsey_pol
<< "{" << endl << "{" << endl
<< " *info = 0;" << endl; << " *info = 0;" << endl;
if (recursive_order.size() == 0) if (def_table.size() == 0)
{ {
output << " return;" << endl output << " return;" << endl
<< "}" << endl; << "}" << endl;
return; return;
} }
for (size_t i = 0; i < recursive_order.size(); i++) for (size_t i = 0; i < def_table.size(); i++)
{ {
const vector<int> &symb_ids = recursive_order[i]; const vector<int> &symb_ids = def_table[i].first;
output << " "; output << " ";
if (symb_ids.size() > 1) if (symb_ids.size() > 1)
std::cout << "Error: in C, multiple returns are not permitted in steady_state_model" << std::endl; std::cout << "Error: in C, multiple returns are not permitted in steady_state_model" << std::endl;
@ -188,7 +186,7 @@ SteadyStateModel::writeSteadyStateFileCC(const string &basename, bool ramsey_pol
output << "double "; output << "double ";
dynamic_cast<ExprNode *>(it->second)->writeOutput(output, oCSteadyStateFile); dynamic_cast<ExprNode *>(it->second)->writeOutput(output, oCSteadyStateFile);
output << "="; output << "=";
def_table.find(symb_ids)->second->writeOutput(output, oCSteadyStateFile); def_table[i].second->writeOutput(output, oCSteadyStateFile);
output << ";" << endl; output << ";" << endl;
} }
output << " // Auxiliary equations" << endl; output << " // Auxiliary equations" << endl;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2010-2011 Dynare Team * Copyright (C) 2010-2014 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
@ -22,13 +22,13 @@
#include "DataTree.hh" #include "DataTree.hh"
#include "StaticModel.hh" #include "StaticModel.hh"
#include "WarningConsolidation.hh"
class SteadyStateModel : public DataTree class SteadyStateModel : public DataTree
{ {
private: private:
//! Associates a set of symbol IDs (the variable(s) assigned in a given statement) to an expression (their assigned value) //! Associates a set of symbol IDs (the variable(s) assigned in a given statement) to an expression (their assigned value)
map<vector<int>, expr_t> def_table; vector<pair<vector<int>, expr_t> > def_table;
vector<vector<int> > recursive_order;
//! Reference to static model (for writing auxiliary equations) //! Reference to static model (for writing auxiliary equations)
const StaticModel &static_model; const StaticModel &static_model;
@ -43,7 +43,7 @@ public:
/*! /*!
\param[in] ramsey_policy Is there a ramsey_policy statement in the MOD file? If yes, then disable the check on the recursivity of the declarations \param[in] ramsey_policy Is there a ramsey_policy statement in the MOD file? If yes, then disable the check on the recursivity of the declarations
*/ */
void checkPass(bool ramsey_policy) const; void checkPass(bool ramsey_policy, WarningConsolidation &warnings) const;
//! Write the steady state file //! Write the steady state file
/*! /*!
\param[in] ramsey_policy Is there a ramsey_policy statement in the MOD file? If yes, then use the "ys" in argument of the steady state file as initial values \param[in] ramsey_policy Is there a ramsey_policy statement in the MOD file? If yes, then use the "ys" in argument of the steady state file as initial values