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.
*
@ -113,7 +113,7 @@ ModFile::checkPass()
(*it)->checkPass(mod_file_struct, warnings);
// 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 (!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.
*
@ -39,8 +39,7 @@ SteadyStateModel::addDefinition(int symb_id, expr_t expr)
// Add the variable
vector<int> v;
v.push_back(symb_id);
recursive_order.push_back(v);
def_table[v] = expr;
def_table.push_back(make_pair(v, expr));
}
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]) == eParameter);
}
recursive_order.push_back(symb_ids);
def_table[symb_ids] = expr;
def_table.push_back(make_pair(symb_ids, expr));
}
void
SteadyStateModel::checkPass(bool ramsey_policy) const
SteadyStateModel::checkPass(bool ramsey_policy, WarningConsolidation &warnings) const
{
if (ramsey_policy)
return;
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
for (size_t j = 0; j < symb_ids.size(); j++)
if (find(so_far_defined.begin(), so_far_defined.end(), symb_ids[j])
!= so_far_defined.end())
{
cerr << "ERROR: in the 'steady_state' block, variable '" << symbol_table.getName(symb_ids[j]) << "' is declared twice" << endl;
exit(EXIT_FAILURE);
}
warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(symb_ids[j]) << "' is declared twice" << endl;
// Check that expression has no undefined symbol
if (!ramsey_policy)
{
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(eModFileLocalVariable, used_symbols);
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)
== 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;
exit(EXIT_FAILURE);
}
@ -100,7 +98,7 @@ SteadyStateModel::checkPass(bool ramsey_policy) const
void
SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_policy) const
{
if (recursive_order.size() == 0)
if (def_table.size() == 0)
return;
string filename = basename + "_steadystate2.m";
@ -118,9 +116,9 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_polic
<< "% Steady state generated by Dynare preprocessor" << 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 << " ";
if (symb_ids.size() > 1)
output << "[";
@ -136,7 +134,7 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_polic
output << "]";
output << "=";
def_table.find(symb_ids)->second->writeOutput(output, oSteadyStateFile);
def_table[i].second->writeOutput(output, oSteadyStateFile);
output << ";" << endl;
}
output << " % Auxiliary equations" << endl;
@ -169,16 +167,16 @@ SteadyStateModel::writeSteadyStateFileCC(const string &basename, bool ramsey_pol
<< "{" << endl
<< " *info = 0;" << endl;
if (recursive_order.size() == 0)
if (def_table.size() == 0)
{
output << " return;" << endl
<< "}" << endl;
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 << " ";
if (symb_ids.size() > 1)
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 ";
dynamic_cast<ExprNode *>(it->second)->writeOutput(output, oCSteadyStateFile);
output << "=";
def_table.find(symb_ids)->second->writeOutput(output, oCSteadyStateFile);
def_table[i].second->writeOutput(output, oCSteadyStateFile);
output << ";" << 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.
*
@ -22,13 +22,13 @@
#include "DataTree.hh"
#include "StaticModel.hh"
#include "WarningConsolidation.hh"
class SteadyStateModel : public DataTree
{
private:
//! 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<vector<int> > recursive_order;
vector<pair<vector<int>, expr_t> > def_table;
//! Reference to static model (for writing auxiliary equations)
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
*/
void checkPass(bool ramsey_policy) const;
void checkPass(bool ramsey_policy, WarningConsolidation &warnings) const;
//! 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