Commit a0b71789 authored by Sébastien Villemot's avatar Sébastien Villemot
Browse files

Automatic detrending engine can now handle models written in logs (ref. #309)

 - new command `log_trend_var'
 - new option `log_deflator' to `var' command
parent c681b5e4
......@@ -884,6 +884,7 @@ Declarations of variables and parameters are made with the following commands:
@deffn Command var @var{VARIABLE_NAME} [$@var{LATEX_NAME}$]@dots{};
@deffnx Command var (deflator = @var{MODEL_EXPRESSION}) @var{VARIABLE_NAME} [$@var{LATEX_NAME}$]@dots{};
@deffnx Command var (log_deflator = @var{MODEL_EXPRESSION}) @var{VARIABLE_NAME} [$@var{LATEX_NAME}$]@dots{};
@descriptionhead
......@@ -910,7 +911,15 @@ trend.
The expression used to detrend an endogenous variable. All trend
variables, endogenous variables and parameters referenced in
@var{MODEL_EXPRESSION} must already have been declared by the
@code{trend_var}, @code{var} and @code{parameters} commands.
@code{trend_var}, @code{log_trend_var}, @code{var} and
@code{parameters} commands. The deflator is assumed to be
multiplicative; for an additive deflator, use @code{log_deflator}.
@item log_deflator = @var{MODEL_EXPRESSION}
Same as @code{deflator}, except that the deflator is assumed to be
additive instead of multiplicative (or, to put it otherwise, the
declared variable is equal to the log of a variable with a
multiplicative trend).
@end table
@examplehead
......@@ -1093,6 +1102,9 @@ model. @xref{Conventions}, for the syntax of @var{MODEL_EXPRESSION} and
@var{VARIABLE_NAME}. Optionally it is possible to give a LaTeX name to
the variable.
The variable is assumed to have a multiplicative growth trend. For an
additive growth trend, use @code{log_trend_var} instead.
Trend variables are required if the user wants to be able to write a
nonstationary model in the @code{model} block. The @code{trend_var}
command must appear before the @code{var} command that references the
......@@ -1117,6 +1129,17 @@ trend_var (growth_factor=gA) A;
@end deffn
@deffn Command log_trend_var (growth_factor = @var{MODEL_EXPRESSION}) @var{VARIABLE_NAME} [$@var{LATEX_NAME}$]@dots{};
@descriptionhead
Same as @code{trend_var}, except that the variable is supposed to have
an additive trend (or, to put it otherwise, to be equal to the log of
a variable with a multiplicative trend).
@end deffn
@node Expressions
@section Expressions
......
/*
* Copyright (C) 2007-2011 Dynare Team
* Copyright (C) 2007-2013 Dynare Team
*
* This file is part of Dynare.
*
......@@ -148,7 +148,8 @@ enum SymbolType
eModFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded)
eExternalFunction = 12, //!< External (user-defined) function
eTrend = 13, //!< Trend variable
eStatementDeclaredVariable = 14 //!< Local variable assigned within a Statement (see subsample statement for example)
eStatementDeclaredVariable = 14, //!< Local variable assigned within a Statement (see subsample statement for example)
eLogTrend = 15 //!< Log-trend variable
};
enum ExpressionType
......
......@@ -3532,6 +3532,7 @@ DynamicModel::computeDerivIDs()
equations[i]->collectVariables(eExogenousDet, dynvars);
equations[i]->collectVariables(eParameter, dynvars);
equations[i]->collectVariables(eTrend, dynvars);
equations[i]->collectVariables(eLogTrend, dynvars);
}
for (set<pair<int, int> >::const_iterator it = dynvars.begin();
......@@ -3657,6 +3658,7 @@ DynamicModel::computeDynJacobianCols(bool jacobianExo)
break;
case eParameter:
case eTrend:
case eLogTrend:
// We don't assign a dynamic jacobian column to parameters or trend variables
break;
default:
......@@ -3692,21 +3694,21 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context
{
for (deriv_id_table_t::const_iterator it = deriv_id_table.begin();
it != deriv_id_table.end(); it++)
if (symbol_table.getType(it->first.first) == eTrend)
if (symbol_table.getType(it->first.first) == eTrend
|| symbol_table.getType(it->first.first) == eLogTrend)
for (int eq = 0; eq < (int) equations.size(); eq++)
{
expr_t testeq = AddLog(AddMinus(equations[eq]->get_arg1(), // F: a = b -> ln(a - b)
equations[eq]->get_arg2()));
assert(testeq != NULL);
testeq = testeq->getDerivative(it->second); // d F / d Trend
for (deriv_id_table_t::const_iterator endogit = deriv_id_table.begin();
endogit != deriv_id_table.end(); endogit++)
if (symbol_table.getType(endogit->first.first) == eEndogenous)
{
double nearZero = testeq->getDerivative(endogit->second)->eval(eval_context); // eval d F / d Trend d Endog
if (nearZero < -ZERO_BAND || nearZero > ZERO_BAND)
if (fabs(nearZero) > ZERO_BAND)
{
cerr << "ERROR: the second-order cross partial of equation " << eq + 1 << " w.r.t. trend variable "
cerr << "ERROR: trends not compatible with balanced growth path; the second-order cross partial of equation " << eq + 1 << " w.r.t. trend variable "
<< symbol_table.getName(it->first.first) << " and endogenous variable "
<< symbol_table.getName(endogit->first.first) << " is not null. " << endl;
exit(EXIT_FAILURE);
......@@ -4096,11 +4098,11 @@ DynamicModel::transformPredeterminedVariables()
void
DynamicModel::detrendEquations()
{
for (trend_symbols_map_t::const_iterator it = nonstationary_symbols_map.begin();
for (nonstationary_symbols_map_t::const_iterator it = nonstationary_symbols_map.begin();
it != nonstationary_symbols_map.end(); it++)
for (int i = 0; i < (int) equations.size(); i++)
{
BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(equations[i]->detrend(it->first, it->second));
BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(equations[i]->detrend(it->first, it->second.first, it->second.second));
assert(substeq != NULL);
equations[i] = dynamic_cast<BinaryOpNode *>(substeq);
}
......
......@@ -110,7 +110,7 @@ class ParsingDriver;
%token INV_GAMMA_PDF INV_GAMMA1_PDF INV_GAMMA2_PDF IRF IRF_SHOCKS
%token KALMAN_ALGO KALMAN_TOL SUBSAMPLES OPTIONS
%token LABELS LAPLACE LIK_ALGO LIK_INIT LINEAR LOAD_IDENT_FILES LOAD_MH_FILE LOAD_PARAMS_AND_STEADY_STATE LOGLINEAR LYAPUNOV
%token LYAPUNOV_FIXED_POINT_TOL LYAPUNOV_DOUBLING_TOL LYAPUNOV_SQUARE_ROOT_SOLVER_TOL MARKOWITZ MARGINAL_DENSITY MAX MAXIT
%token LYAPUNOV_FIXED_POINT_TOL LYAPUNOV_DOUBLING_TOL LYAPUNOV_SQUARE_ROOT_SOLVER_TOL LOG_DEFLATOR LOG_TREND_VAR MARKOWITZ MARGINAL_DENSITY MAX MAXIT
%token MFS MH_DROP MH_INIT_SCALE MH_JSCALE MH_MODE MH_NBLOCKS MH_REPLIC MH_RECOVER MIN MINIMAL_SOLVING_PERIODS SOLVE_MAXIT
%token MODE_CHECK MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS ABS SIGN
%token MODEL_DIAGNOSTICS MODIFIEDHARMONICMEAN MOMENTS_VARENDO DIFFUSE_FILTER SUB_DRAWS
......@@ -262,6 +262,7 @@ statement : parameters
| external_function
| steady_state_model
| trend_var
| log_trend_var
| ms_estimation
| ms_simulation
| ms_compute_mdd
......@@ -287,22 +288,42 @@ trend_var : TREND_VAR '(' GROWTH_FACTOR EQUAL { driver.begin_trend(); } hand_sid
;
trend_var_list : trend_var_list symbol
{ driver.declare_trend_var($2); }
{ driver.declare_trend_var(false, $2); }
| trend_var_list COMMA symbol
{ driver.declare_trend_var($3); }
{ driver.declare_trend_var(false, $3); }
| symbol
{ driver.declare_trend_var($1); }
{ driver.declare_trend_var(false, $1); }
| trend_var_list symbol TEX_NAME
{ driver.declare_trend_var($2, $3); }
{ driver.declare_trend_var(false, $2, $3); }
| trend_var_list COMMA symbol TEX_NAME
{ driver.declare_trend_var($3, $4); }
{ driver.declare_trend_var(false, $3, $4); }
| symbol TEX_NAME
{ driver.declare_trend_var($1, $2); }
{ driver.declare_trend_var(false, $1, $2); }
;
log_trend_var : LOG_TREND_VAR '(' GROWTH_FACTOR EQUAL { driver.begin_trend(); } hand_side ')' log_trend_var_list ';'
{ driver.end_trend_var($6); }
;
log_trend_var_list : log_trend_var_list symbol
{ driver.declare_trend_var(true, $2); }
| log_trend_var_list COMMA symbol
{ driver.declare_trend_var(true, $3); }
| symbol
{ driver.declare_trend_var(true, $1); }
| log_trend_var_list symbol TEX_NAME
{ driver.declare_trend_var(true, $2, $3); }
| log_trend_var_list COMMA symbol TEX_NAME
{ driver.declare_trend_var(true, $3, $4); }
| symbol TEX_NAME
{ driver.declare_trend_var(true, $1, $2); }
;
var : VAR var_list ';'
| VAR '(' DEFLATOR EQUAL { driver.begin_trend(); } hand_side ')' nonstationary_var_list ';'
{ driver.end_nonstationary_var($6); }
{ driver.end_nonstationary_var(false, $6); }
| VAR '(' LOG_DEFLATOR EQUAL { driver.begin_trend(); } hand_side ')' nonstationary_var_list ';'
{ driver.end_nonstationary_var(true, $6); }
;
nonstationary_var_list : nonstationary_var_list symbol
......
......@@ -103,6 +103,7 @@ string eofbuff;
<INITIAL>varexo {BEGIN DYNARE_STATEMENT; return token::VAREXO;}
<INITIAL>varexo_det {BEGIN DYNARE_STATEMENT; return token::VAREXO_DET;}
<INITIAL>trend_var {BEGIN DYNARE_STATEMENT; return token::TREND_VAR;}
<INITIAL>log_trend_var {BEGIN DYNARE_STATEMENT; return token::LOG_TREND_VAR;}
<INITIAL>predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;}
<INITIAL>parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;}
<INITIAL>periods {BEGIN DYNARE_STATEMENT; return token::PERIODS;}
......@@ -467,6 +468,7 @@ string eofbuff;
<DYNARE_STATEMENT>selected_variables_only {return token::SELECTED_VARIABLES_ONLY; }
<DYNARE_STATEMENT>pruning {return token::PRUNING; }
<DYNARE_STATEMENT>deflator {return token::DEFLATOR;}
<DYNARE_STATEMENT>log_deflator {return token::LOG_DEFLATOR;}
<DYNARE_STATEMENT>growth_factor {return token::GROWTH_FACTOR;}
<DYNARE_STATEMENT>cova_compute {return token::COVA_COMPUTE;}
<DYNARE_STATEMENT>discretionary_tol {return token::DISCRETIONARY_TOL;}
......
......@@ -464,7 +464,7 @@ NumConstNode::replaceTrendVar() const
}
expr_t
NumConstNode::detrend(int symb_id, expr_t trend) const
NumConstNode::detrend(int symb_id, bool log_trend, expr_t trend) const
{
return const_cast<NumConstNode *>(this);
}
......@@ -505,6 +505,7 @@ VariableNode::prepareForDerivation()
case eExogenousDet:
case eParameter:
case eTrend:
case eLogTrend:
// For a variable or a parameter, the only non-null derivative is with respect to itself
non_null_derivatives.insert(datatree.getDerivID(symb_id, lag));
break;
......@@ -533,6 +534,7 @@ VariableNode::computeDerivative(int deriv_id)
case eExogenousDet:
case eParameter:
case eTrend:
case eLogTrend:
if (deriv_id == datatree.getDerivID(symb_id, lag))
return datatree.One;
else
......@@ -585,7 +587,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << "\\bar{";
output << datatree.symbol_table.getTeXName(symb_id);
if (output_type == oLatexDynamicModel
&& (type == eEndogenous || type == eExogenous || type == eExogenousDet || type == eModelLocalVariable || type == eTrend))
&& (type == eEndogenous || type == eExogenous || type == eExogenousDet || type == eModelLocalVariable || type == eTrend || type == eLogTrend))
{
output << "_{t";
if (lag != 0)
......@@ -757,6 +759,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case eExternalFunction:
case eTrend:
case eLogTrend:
case eStatementDeclaredVariable:
cerr << "Impossible case" << endl;
exit(EXIT_FAILURE);
......@@ -910,6 +913,7 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recur
case eExogenousDet:
case eParameter:
case eTrend:
case eLogTrend:
if (deriv_id == datatree.getDerivID(symb_id, lag))
return datatree.One;
else
......@@ -1044,6 +1048,7 @@ VariableNode::decreaseLeadsLags(int n) const
case eExogenous:
case eExogenousDet:
case eTrend:
case eLogTrend:
return datatree.AddVariable(symb_id, lag-n);
case eModelLocalVariable:
return datatree.local_variables_table[symb_id]->decreaseLeadsLags(n);
......@@ -1248,44 +1253,77 @@ VariableNode::replaceTrendVar() const
{
if (get_type() == eTrend)
return datatree.One;
else if (get_type() == eLogTrend)
return datatree.Zero;
else
return const_cast<VariableNode *>(this);
}
expr_t
VariableNode::detrend(int symb_id, expr_t trend) const
VariableNode::detrend(int symb_id, bool log_trend, expr_t trend) const
{
if (get_symb_id() != symb_id)
return const_cast<VariableNode *>(this);
if (log_trend)
{
if (get_lag() == 0)
return datatree.AddPlus(const_cast<VariableNode *>(this), trend);
else
return datatree.AddPlus(const_cast<VariableNode *>(this), trend->decreaseLeadsLags(-1*get_lag()));
}
else
{
if (get_lag() == 0)
return datatree.AddTimes(const_cast<VariableNode *>(this), trend);
else
return datatree.AddTimes(const_cast<VariableNode *>(this), trend->decreaseLeadsLags(-1*get_lag()));
}
}
expr_t
VariableNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
{
if (get_type() != eTrend || get_lag() == 0)
if ((get_type() != eTrend && get_type() != eLogTrend) || get_lag() == 0)
return const_cast<VariableNode *>(this);
map<int, expr_t>::const_iterator it = trend_symbols_map.find(symb_id);
expr_t noTrendLeadLagNode = new VariableNode(datatree, it->first, 0);
bool log_trend = get_type() == eLogTrend;
expr_t trend = it->second;
if (get_lag() > 0)
{
expr_t growthFactorSequence = it->second->decreaseLeadsLags(-1);
expr_t growthFactorSequence = trend->decreaseLeadsLags(-1);
if (log_trend)
{
for (int i = 1; i < get_lag(); i++)
growthFactorSequence = datatree.AddTimes(growthFactorSequence, it->second->decreaseLeadsLags(-1*(i+1)));
growthFactorSequence = datatree.AddPlus(growthFactorSequence, trend->decreaseLeadsLags(-1*(i+1)));
return datatree.AddPlus(noTrendLeadLagNode, growthFactorSequence);
}
else
{
for (int i = 1; i < get_lag(); i++)
growthFactorSequence = datatree.AddTimes(growthFactorSequence, trend->decreaseLeadsLags(-1*(i+1)));
return datatree.AddTimes(noTrendLeadLagNode, growthFactorSequence);
}
}
else //get_lag < 0
{
expr_t growthFactorSequence = it->second;
expr_t growthFactorSequence = trend;
if (log_trend)
{
for (int i = 1; i < abs(get_lag()); i++)
growthFactorSequence = datatree.AddTimes(growthFactorSequence, it->second->decreaseLeadsLags(i));
growthFactorSequence = datatree.AddPlus(growthFactorSequence, trend->decreaseLeadsLags(i));
return datatree.AddMinus(noTrendLeadLagNode, growthFactorSequence);
}
else
{
for (int i = 1; i < abs(get_lag()); i++)
growthFactorSequence = datatree.AddTimes(growthFactorSequence, trend->decreaseLeadsLags(i));
return datatree.AddDivide(noTrendLeadLagNode, growthFactorSequence);
}
}
}
UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg) :
......@@ -2369,9 +2407,9 @@ UnaryOpNode::replaceTrendVar() const
}
expr_t
UnaryOpNode::detrend(int symb_id, expr_t trend) const
UnaryOpNode::detrend(int symb_id, bool log_trend, expr_t trend) const
{
expr_t argsubst = arg->detrend(symb_id, trend);
expr_t argsubst = arg->detrend(symb_id, log_trend, trend);
return buildSimilarUnaryOpNode(argsubst, datatree);
}
......@@ -3665,10 +3703,10 @@ BinaryOpNode::replaceTrendVar() const
}
expr_t
BinaryOpNode::detrend(int symb_id, expr_t trend) const
BinaryOpNode::detrend(int symb_id, bool log_trend, expr_t trend) const
{
expr_t arg1subst = arg1->detrend(symb_id, trend);
expr_t arg2subst = arg2->detrend(symb_id, trend);
expr_t arg1subst = arg1->detrend(symb_id, log_trend, trend);
expr_t arg2subst = arg2->detrend(symb_id, log_trend, trend);
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
}
......@@ -4269,11 +4307,11 @@ TrinaryOpNode::replaceTrendVar() const
}
expr_t
TrinaryOpNode::detrend(int symb_id, expr_t trend) const
TrinaryOpNode::detrend(int symb_id, bool log_trend, expr_t trend) const
{
expr_t arg1subst = arg1->detrend(symb_id, trend);
expr_t arg2subst = arg2->detrend(symb_id, trend);
expr_t arg3subst = arg3->detrend(symb_id, trend);
expr_t arg1subst = arg1->detrend(symb_id, log_trend, trend);
expr_t arg2subst = arg2->detrend(symb_id, log_trend, trend);
expr_t arg3subst = arg3->detrend(symb_id, log_trend, trend);
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
}
......@@ -4855,11 +4893,11 @@ ExternalFunctionNode::replaceTrendVar() const
}
expr_t
ExternalFunctionNode::detrend(int symb_id, expr_t trend) const
ExternalFunctionNode::detrend(int symb_id, bool log_trend, expr_t trend) const
{
vector<expr_t> arguments_subst;
for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
arguments_subst.push_back((*it)->detrend(symb_id, trend));
arguments_subst.push_back((*it)->detrend(symb_id, log_trend, trend));
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
}
......
......@@ -389,10 +389,11 @@ public:
//! Constructs a new expression where the variable indicated by symb_id has been detrended
/*!
\param[in] symb_id indicating the variable to be detrended
\param[in] expr_t indicating the trend
\param[out] expr_t the new binary op pointing to a detrended variable
\param[in] log_trend indicates if the trend is in log
\param[in] trend indicating the trend
\return the new binary op pointing to a detrended variable
*/
virtual expr_t detrend(int symb_id, expr_t trend) const = 0;
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const = 0;
//! Add ExprNodes to the provided datatree
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const = 0;
......@@ -452,7 +453,7 @@ public:
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
......@@ -513,7 +514,7 @@ public:
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
......@@ -589,7 +590,7 @@ public:
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
......@@ -678,7 +679,7 @@ public:
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
//! Function to write out the oPowerNode in expr_t terms as opposed to writing out the function itself
......@@ -747,7 +748,7 @@ public:
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
......@@ -821,7 +822,7 @@ public:
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual void writePrhs(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const string &ending) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
......
......@@ -1413,14 +1413,14 @@ ModelTree::addTrendVariables(vector<int> trend_vars, expr_t growth_factor) throw
}
void
ModelTree::addNonstationaryVariables(vector<int> nonstationary_vars, expr_t deflator) throw (TrendException)
ModelTree::addNonstationaryVariables(vector<int> nonstationary_vars, bool log_deflator, expr_t deflator) throw (TrendException)
{
while (!nonstationary_vars.empty())
if (nonstationary_symbols_map.find(nonstationary_vars.back()) != nonstationary_symbols_map.end())
throw TrendException(symbol_table.getName(nonstationary_vars.back()));
else
{
nonstationary_symbols_map[nonstationary_vars.back()] = deflator;
nonstationary_symbols_map[nonstationary_vars.back()] = make_pair(log_deflator, deflator);
nonstationary_vars.pop_back();
}
}
......
......@@ -45,9 +45,6 @@ typedef vector< pair<pair<int, int>, pair< int, expr_t > > > block_derivatives_e
//! for all blocks derivatives description
typedef vector<block_derivatives_equation_variable_laglead_nodeid_t> blocks_derivatives_t;
//! for all trends
typedef map<int, expr_t> trend_symbols_map_t;
//! Shared code for static and dynamic models
class ModelTree : public DataTree
{
......@@ -136,9 +133,13 @@ protected:
//! Trend variables and their growth factors
trend_symbols_map_t trend_symbols_map;
map<int, expr_t> trend_symbols_map;
//! for all trends; the boolean is true if this is a log-trend, false otherwise
typedef map<int, pair<bool, expr_t> > nonstationary_symbols_map_t;
//! Nonstationary variables and their deflators
trend_symbols_map_t nonstationary_symbols_map;
nonstationary_symbols_map_t nonstationary_symbols_map;
//! vector of block reordered variables and equations
vector<int> equation_reordered, variable_reordered, inv_equation_reordered, inv_variable_reordered;
......@@ -304,8 +305,8 @@ public:
int equation_number() const;
//! Adds a trend variable with its growth factor
void addTrendVariables(vector<int> trend_vars, expr_t growth_factor) throw (TrendException);
//! Adds a nonstationary variable with its deflator
void addNonstationaryVariables(vector<int> nonstationary_vars, expr_t deflator) throw (TrendException);
//! Adds a nonstationary variables with their (common) deflator
void addNonstationaryVariables(vector<int> nonstationary_vars, bool log_deflator, expr_t deflator) throw (TrendException);
void set_cutoff_to_zero();
//! Helper for writing the Jacobian elements in MATLAB and C
/*! Writes either (i+1,j+1) or [i+j*no_eq] */
......
......@@ -204,9 +204,9 @@ ParsingDriver::begin_trend()
}
void
ParsingDriver::declare_trend_var(string *name, string *tex_name)
ParsingDriver::declare_trend_var(bool log_trend, string *name, string *tex_name)
{
declare_symbol(name, eTrend, tex_name);
declare_symbol(name, log_trend ? eLogTrend : eTrend, tex_name);
declared_trend_vars.push_back(mod_file->symbol_table.getID(*name));
delete name;
if (tex_name != NULL)
......@@ -339,11 +339,11 @@ ParsingDriver::declare_nonstationary_var(string *name, string *tex_name)
}
void
ParsingDriver::end_nonstationary_var(expr_t deflator)
ParsingDriver::end_nonstationary_var(bool log_deflator, expr_t deflator)
{
try
{
dynamic_model->addNonstationaryVariables(declared_nonstationary_vars, deflator);
dynamic_model->addNonstationaryVariables(declared_nonstationary_vars, log_deflator, deflator);
}
catch (DataTree::TrendException &e)
{
......
......@@ -631,13 +631,13 @@ public:
//! Switches datatree
void begin_trend();
//! Declares a trend variable with its growth factor
void declare_trend_var(string *name, string *tex_name = NULL);
void declare_trend_var(bool log_trend, string *name, string *tex_name = NULL);
//! Ends declaration of trend variable
void end_trend_var(expr_t growth_factor);
//! Declares a nonstationary variable with its deflator
void declare_nonstationary_var(string *name, string *tex_name = NULL);
//! Ends declaration of nonstationary variable
void end_nonstationary_var(expr_t deflator);
void end_nonstationary_var(bool log_deflator, expr_t deflator);
//! Add a graph format to the list of formats requested
void add_graph_format(const string &name);
//! Add the graph_format option to the OptionsList structure
......
......@@ -502,7 +502,7 @@ SymbolTable::getTrendVarIds() const
vector <int> trendVars;
for (symbol_table_type::const_iterator it = symbol_table.begin();
it != symbol_table.end(); it++)
if (getType(it->second) == eTrend)
if (getType(it->second) == eTrend || getType(it->second) == eLogTrend)
trendVars.push_back(it->second);
return trendVars;
}
......
......@@ -146,7 +146,9 @@ MODFILES = \
deterministic_simulations/rbc_det4.mod \
deterministic_simulations/rbc_det5.mod \
walsh.mod \
measurement_errors/fs2000_corr_me_ml_mcmc/fs2000_corr_ME.mod
measurement_errors/fs2000_corr_me_ml_mcmc/fs2000_corr_ME.mod \
trend_var/fs2000_nonstationary.mod \
trend_var/fs2000_log_nonstationary.mod
XFAIL_MODFILES = ramst_xfail.mod
......
/*
* This file is a modified version of 'fs2000.mod'.
*
* The difference is that, here, the equations are written in non-stationary form,
* all variables are taken in logs, and Dynare automatically does the detrending.
*
* Also note that "m" and "dA" in 'fs2000.mod' are here called "gM" and "gA"
*/
/*
* Copyright (C) 2004-2013 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/>.
*/
var gM gA;