Preprocessor: added new 'steady_state_model' keyword for automatically creating steady state file

issue#70
Sébastien Villemot 2010-04-23 18:39:07 +02:00
parent a3398d3930
commit d68e984fd6
12 changed files with 246 additions and 15 deletions

View File

@ -119,7 +119,7 @@ class ParsingDriver;
%token <string_val> QUOTED_STRING
%token QZ_CRITERIUM FULL
%token RELATIVE_IRF REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE
%token SHOCKS SHOCK_DECOMPOSITION SIGMA_E SIMUL SIMUL_ALGO SIMUL_SEED SMOOTHER STACK_SOLVE_ALGO SOLVE_ALGO
%token SHOCKS SHOCK_DECOMPOSITION SIGMA_E SIMUL SIMUL_ALGO SIMUL_SEED SMOOTHER STACK_SOLVE_ALGO STEADY_STATE_MODEL SOLVE_ALGO
%token STDERR STEADY STOCH_SIMUL
%token TEX RAMSEY_POLICY PLANNER_DISCOUNT
%token <string_val> TEX_NAME
@ -240,6 +240,7 @@ statement : parameters
| markov_switching
| svar
| external_function
| steady_state_model
;
dsample : DSAMPLE INT_NUMBER ';'
@ -1649,6 +1650,18 @@ conditional_forecast_paths_shock_elem : VAR symbol ';' PERIODS period_list ';' V
{ driver.add_det_shock($2, true); }
;
steady_state_model : STEADY_STATE_MODEL ';' { driver.begin_steady_state_model(); }
steady_state_equation_list END { driver.reset_data_tree(); }
;
steady_state_equation_list : steady_state_equation_list steady_state_equation
| steady_state_equation
;
steady_state_equation : symbol EQUAL expression ';'
{ driver.add_steady_state_model_equal($1, $3); }
;
o_dr_algo : DR_ALGO EQUAL INT_NUMBER {
if (*$3 == string("0"))
driver.warning("dr_algo option is now deprecated, and may be removed in a future version of Dynare");

View File

@ -154,6 +154,7 @@ int sigma_e = 0;
/* Begin of a Dynare block */
<INITIAL>model {BEGIN DYNARE_BLOCK; return token::MODEL;}
<INITIAL>steady_state_model {BEGIN DYNARE_BLOCK; return token::STEADY_STATE_MODEL;}
<INITIAL>initval {BEGIN DYNARE_BLOCK; return token::INITVAL;}
<INITIAL>endval {BEGIN DYNARE_BLOCK; return token::ENDVAL;}
<INITIAL>histval {BEGIN DYNARE_BLOCK; return token::HISTVAL;}

View File

@ -523,14 +523,13 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
switch (type)
{
case eParameter:
if (output_type == oMatlabOutsideModel)
if (output_type == oMatlabOutsideModel || output_type == oSteadyStateFile)
output << "M_.params" << "(" << tsid + 1 << ")";
else
output << "params" << LEFT_ARRAY_SUBSCRIPT(output_type) << tsid + ARRAY_SUBSCRIPT_OFFSET(output_type) << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case eModelLocalVariable:
case eModFileLocalVariable:
if (output_type == oMatlabDynamicModelSparse || output_type == oMatlabStaticModelSparse || output_type == oMatlabDynamicModelSparseLocalTemporaryTerms)
{
output << "(";
@ -541,6 +540,10 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << datatree.symbol_table.getName(symb_id);
break;
case eModFileLocalVariable:
output << datatree.symbol_table.getName(symb_id);
break;
case eEndogenous:
switch (output_type)
{
@ -570,6 +573,9 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case oMatlabDynamicSteadyStateOperator:
output << "oo_.steady_state(" << tsid + 1 << ")";
break;
case oSteadyStateFile:
output << "ys_(" << tsid + 1 << ")";
break;
default:
assert(false);
}
@ -608,6 +614,9 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case oMatlabDynamicSteadyStateOperator:
output << "oo_.exo_steady_state(" << i << ")";
break;
case oSteadyStateFile:
output << "exo_(" << i << ")";
break;
default:
assert(false);
}
@ -646,6 +655,9 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case oMatlabDynamicSteadyStateOperator:
output << "oo_.exo_det_steady_state(" << tsid + 1 << ")";
break;
case oSteadyStateFile:
output << "exo_(" << i << ")";
break;
default:
assert(false);
}

View File

@ -71,7 +71,8 @@ enum ExprNodeOutputType
oLatexDynamicSteadyStateOperator, //!< LaTeX code, dynamic model steady state declarations
oMatlabDynamicSteadyStateOperator, //!< Matlab code, dynamic model steady state declarations
oMatlabDynamicModelSparseSteadyStateOperator, //!< Matlab code, dynamic block decomposed model steady state declarations
oMatlabDynamicModelSparseLocalTemporaryTerms //!< Matlab code, dynamic block decomposed model local temporary_terms
oMatlabDynamicModelSparseLocalTemporaryTerms, //!< Matlab code, dynamic block decomposed model local temporary_terms
oSteadyStateFile //!< Matlab code, in the generated steady state file
};
#define IS_MATLAB(output_type) ((output_type) == oMatlabStaticModel \
@ -81,7 +82,8 @@ enum ExprNodeOutputType
|| (output_type) == oMatlabDynamicModelSparse \
|| (output_type) == oMatlabDynamicModelSparseLocalTemporaryTerms \
|| (output_type) == oMatlabDynamicSteadyStateOperator \
|| (output_type) == oMatlabDynamicModelSparseSteadyStateOperator)
|| (output_type) == oMatlabDynamicModelSparseSteadyStateOperator \
|| (output_type) == oSteadyStateFile)
#define IS_C(output_type) ((output_type) == oCDynamicModel)

View File

@ -47,7 +47,9 @@ dynare_m_SOURCES = \
CodeInterpreter.hh \
FlexLexer.h \
ExternalFunctionsTable.cc \
ExternalFunctionsTable.hh
ExternalFunctionsTable.hh \
SteadyStateModel.hh \
SteadyStateModel.cc
# The -I. is for <FlexLexer.h>
dynare_m_CPPFLAGS = $(BOOST_CPPFLAGS) -I.

View File

@ -24,8 +24,9 @@
#include "ModFile.hh"
ModFile::ModFile() : expressions_tree(symbol_table, num_constants, external_functions_table),
static_model(symbol_table, num_constants, external_functions_table),
steady_state_model(symbol_table, num_constants, external_functions_table),
dynamic_model(symbol_table, num_constants, external_functions_table),
static_model(symbol_table, num_constants, external_functions_table),
linear(false), block(false), byte_code(false),
use_dll(false), no_static(false)
{
@ -439,5 +440,8 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all
}
}
// Create steady state file
steady_state_model.writeSteadyStateFile(basename);
cout << "done" << endl;
}

View File

@ -30,6 +30,7 @@ using namespace std;
#include "NumericalInitialization.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "SteadyStateModel.hh"
#include "Statement.hh"
#include "ExternalFunctionsTable.hh"
@ -47,10 +48,12 @@ public:
NumericalConstants num_constants;
//! Expressions outside model block
DataTree expressions_tree;
//! Static Dll model
StaticModel static_model;
//! Dynamic model
//! Static model, as declared in the "steady_state_model" block if present
SteadyStateModel steady_state_model;
//! Dynamic model, as declared in the "model" block
DynamicModel dynamic_model;
//! Static model, as derived from the "model" block when leads and lags have been removed
StaticModel static_model;
//! Option linear
bool linear;

View File

@ -1391,17 +1391,27 @@ ParsingDriver::add_model_equal_with_zero_rhs(NodeID arg)
void
ParsingDriver::declare_and_init_model_local_variable(string *name, NodeID rhs)
{
int symb_id;
try
{
mod_file->symbol_table.addSymbol(*name, eModelLocalVariable);
symb_id = mod_file->symbol_table.addSymbol(*name, eModelLocalVariable);
}
catch (SymbolTable::AlreadyDeclaredException &e)
{
error("Local model variable " + *name + " declared twice.");
// It can have already been declared in a steady_state_model block, check that it is indeed a ModelLocalVariable
symb_id = mod_file->symbol_table.getID(*name);
if (mod_file->symbol_table.getType(symb_id) != eModelLocalVariable)
error(*name + " has wrong type, you cannot use it within as left-hand side of a pound ('#') expression");
}
int symb_id = mod_file->symbol_table.getID(*name);
model_tree->AddLocalVariable(symb_id, rhs);
try
{
model_tree->AddLocalVariable(symb_id, rhs);
}
catch (DataTree::LocalVariableException &e)
{
error("Local model variable " + *name + " declared twice.");
}
delete name;
}
@ -1834,3 +1844,43 @@ ParsingDriver::add_native(const char *s)
{
mod_file->addStatement(new NativeStatement(s));
}
void
ParsingDriver::begin_steady_state_model()
{
set_current_data_tree(&mod_file->steady_state_model);
}
void
ParsingDriver::add_steady_state_model_equal(string *varname, NodeID expr)
{
int id;
try
{
id = mod_file->symbol_table.getID(*varname);
}
catch (SymbolTable::UnknownSymbolNameException &e)
{
// Unknown symbol, declare it as a ModFileLocalVariable
id = mod_file->symbol_table.addSymbol(*varname, eModFileLocalVariable);
}
SymbolType type = mod_file->symbol_table.getType(id);
if (type != eEndogenous && type != eModFileLocalVariable)
error(*varname + " has incorrect type");
try
{
mod_file->steady_state_model.addDefinition(id, expr);
}
catch(SteadyStateModel::AlreadyDefinedException &e)
{
error(*varname + " has already been defined in the steady state block");
}
catch(SteadyStateModel::UndefinedVariableException &e)
{
error(e.varname + " is not yet initialized at this point");
}
delete varname;
}

View File

@ -493,6 +493,10 @@ public:
void add_native(const char *s);
//! Resets data_tree and model_tree pointers to default (i.e. mod_file->expressions_tree)
void reset_data_tree();
//! Begin a steady_state_model block
void begin_steady_state_model();
//! Add an assignment equation in steady_state_model block
void add_steady_state_model_equal(string *varname, NodeID expr);
};
#endif // ! PARSING_DRIVER_HH

View File

@ -26,7 +26,7 @@ using namespace std;
#include "ModelTree.hh"
//! Stores a static model
//! Stores a static model, as derived from the "model" block when leads and lags have been removed
class StaticModel : public ModelTree
{
private:

87
SteadyStateModel.cc Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2010 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <algorithm>
#include "SteadyStateModel.hh"
SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table_arg) :
DataTree(symbol_table_arg, num_constants, external_functions_table)
{
}
void
SteadyStateModel::addDefinition(int symb_id, NodeID expr) throw (UndefinedVariableException, AlreadyDefinedException)
{
assert(symbol_table.getType(symb_id) == eEndogenous
|| symbol_table.getType(symb_id) == eModFileLocalVariable);
// Check that symbol is not already defined
if (find(recursive_order.begin(), recursive_order.end(), symb_id)
!= recursive_order.end())
throw AlreadyDefinedException(symbol_table.getName(symb_id));
// Check that expression has no undefined symbol
set<pair<int, int> > used_symbols;
expr->collectVariables(eEndogenous, used_symbols);
expr->collectVariables(eModFileLocalVariable, used_symbols);
for(set<pair<int, int> >::const_iterator it = used_symbols.begin();
it != used_symbols.end(); it++)
if (find(recursive_order.begin(), recursive_order.end(), it->first)
== recursive_order.end())
throw UndefinedVariableException(symbol_table.getName(it->first));
// Add the variable
recursive_order.push_back(symb_id);
def_table[symb_id] = AddEqual(AddVariable(symb_id), expr);
}
void
SteadyStateModel::writeSteadyStateFile(const string &basename) const
{
if (recursive_order.size() == 0)
return;
string filename = basename + "_steadystate.m";
ofstream output;
output.open(filename.c_str(), ios::out | ios::binary);
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
exit(EXIT_FAILURE);
}
output << "function [ys_, check_] = " << basename << "_steadystate(ys_orig_, exo_)" << endl
<< "% Steady state generated by Dynare preprocessor" << endl
<< " global M_" << endl
<< " ys_=zeros(" << symbol_table.orig_endo_nbr() << ",1);" << endl;
for(size_t i = 0; i < recursive_order.size(); i++)
{
output << " ";
map<int, NodeID>::const_iterator it = def_table.find(recursive_order[i]);
it->second->writeOutput(output, oSteadyStateFile);
output << ";" << endl;
}
output << " check_=0;" << endl
<< "end" << endl;
}

53
SteadyStateModel.hh Normal file
View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2010 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _STEADY_STATE_MODEL_HH
#define _STEADY_STATE_MODEL_HH
#include "DataTree.hh"
class SteadyStateModel : public DataTree
{
private:
//! Associates a symbol ID to an expression of the form "var = expr"
map<int, NodeID> def_table;
vector<int> recursive_order;
public:
class AlreadyDefinedException
{
public:
const string &varname;
AlreadyDefinedException(const string &varname_arg) : varname(varname_arg) {}
};
class UndefinedVariableException
{
public:
const string &varname;
UndefinedVariableException(const string &varname_arg) : varname(varname_arg) {}
};
SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table_arg);
//! Add an expression of the form "var = expr;"
void addDefinition(int symb_id, NodeID expr) throw (UndefinedVariableException, AlreadyDefinedException);
//! Write the steady state file
void writeSteadyStateFile(const string &basename) const;
};
#endif