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: ...@@ -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{}; @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 (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 @descriptionhead
...@@ -910,7 +911,15 @@ trend. ...@@ -910,7 +911,15 @@ trend.
The expression used to detrend an endogenous variable. All trend The expression used to detrend an endogenous variable. All trend
variables, endogenous variables and parameters referenced in variables, endogenous variables and parameters referenced in
@var{MODEL_EXPRESSION} must already have been declared by the @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 @end table
@examplehead @examplehead
...@@ -1093,6 +1102,9 @@ model. @xref{Conventions}, for the syntax of @var{MODEL_EXPRESSION} and ...@@ -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 @var{VARIABLE_NAME}. Optionally it is possible to give a LaTeX name to
the variable. 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 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} nonstationary model in the @code{model} block. The @code{trend_var}
command must appear before the @code{var} command that references the command must appear before the @code{var} command that references the
...@@ -1117,6 +1129,17 @@ trend_var (growth_factor=gA) A; ...@@ -1117,6 +1129,17 @@ trend_var (growth_factor=gA) A;
@end deffn @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 @node Expressions
@section Expressions @section Expressions
......
/* /*
* Copyright (C) 2007-2011 Dynare Team * Copyright (C) 2007-2013 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -148,7 +148,8 @@ enum SymbolType ...@@ -148,7 +148,8 @@ enum SymbolType
eModFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded) eModFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded)
eExternalFunction = 12, //!< External (user-defined) function eExternalFunction = 12, //!< External (user-defined) function
eTrend = 13, //!< Trend variable 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 enum ExpressionType
......
...@@ -3532,6 +3532,7 @@ DynamicModel::computeDerivIDs() ...@@ -3532,6 +3532,7 @@ DynamicModel::computeDerivIDs()
equations[i]->collectVariables(eExogenousDet, dynvars); equations[i]->collectVariables(eExogenousDet, dynvars);
equations[i]->collectVariables(eParameter, dynvars); equations[i]->collectVariables(eParameter, dynvars);
equations[i]->collectVariables(eTrend, dynvars); equations[i]->collectVariables(eTrend, dynvars);
equations[i]->collectVariables(eLogTrend, dynvars);
} }
for (set<pair<int, int> >::const_iterator it = dynvars.begin(); for (set<pair<int, int> >::const_iterator it = dynvars.begin();
...@@ -3657,6 +3658,7 @@ DynamicModel::computeDynJacobianCols(bool jacobianExo) ...@@ -3657,6 +3658,7 @@ DynamicModel::computeDynJacobianCols(bool jacobianExo)
break; break;
case eParameter: case eParameter:
case eTrend: case eTrend:
case eLogTrend:
// We don't assign a dynamic jacobian column to parameters or trend variables // We don't assign a dynamic jacobian column to parameters or trend variables
break; break;
default: default:
...@@ -3692,21 +3694,21 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context ...@@ -3692,21 +3694,21 @@ DynamicModel::testTrendDerivativesEqualToZero(const eval_context_t &eval_context
{ {
for (deriv_id_table_t::const_iterator it = deriv_id_table.begin(); for (deriv_id_table_t::const_iterator it = deriv_id_table.begin();
it != deriv_id_table.end(); it++) 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++) for (int eq = 0; eq < (int) equations.size(); eq++)
{ {
expr_t testeq = AddLog(AddMinus(equations[eq]->get_arg1(), // F: a = b -> ln(a - b) expr_t testeq = AddLog(AddMinus(equations[eq]->get_arg1(), // F: a = b -> ln(a - b)
equations[eq]->get_arg2())); equations[eq]->get_arg2()));
assert(testeq != NULL);
testeq = testeq->getDerivative(it->second); // d F / d Trend testeq = testeq->getDerivative(it->second); // d F / d Trend
for (deriv_id_table_t::const_iterator endogit = deriv_id_table.begin(); for (deriv_id_table_t::const_iterator endogit = deriv_id_table.begin();
endogit != deriv_id_table.end(); endogit++) endogit != deriv_id_table.end(); endogit++)
if (symbol_table.getType(endogit->first.first) == eEndogenous) if (symbol_table.getType(endogit->first.first) == eEndogenous)
{ {
double nearZero = testeq->getDerivative(endogit->second)->eval(eval_context); // eval d F / d Trend d Endog 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(it->first.first) << " and endogenous variable "
<< symbol_table.getName(endogit->first.first) << " is not null. " << endl; << symbol_table.getName(endogit->first.first) << " is not null. " << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -4096,11 +4098,11 @@ DynamicModel::transformPredeterminedVariables() ...@@ -4096,11 +4098,11 @@ DynamicModel::transformPredeterminedVariables()
void void
DynamicModel::detrendEquations() 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++) it != nonstationary_symbols_map.end(); it++)
for (int i = 0; i < (int) equations.size(); i++) 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); assert(substeq != NULL);
equations[i] = dynamic_cast<BinaryOpNode *>(substeq); equations[i] = dynamic_cast<BinaryOpNode *>(substeq);
} }
......
...@@ -110,7 +110,7 @@ class ParsingDriver; ...@@ -110,7 +110,7 @@ class ParsingDriver;
%token INV_GAMMA_PDF INV_GAMMA1_PDF INV_GAMMA2_PDF IRF IRF_SHOCKS %token INV_GAMMA_PDF INV_GAMMA1_PDF INV_GAMMA2_PDF IRF IRF_SHOCKS
%token KALMAN_ALGO KALMAN_TOL SUBSAMPLES OPTIONS %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 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 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 MODE_CHECK MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS ABS SIGN
%token MODEL_DIAGNOSTICS MODIFIEDHARMONICMEAN MOMENTS_VARENDO DIFFUSE_FILTER SUB_DRAWS %token MODEL_DIAGNOSTICS MODIFIEDHARMONICMEAN MOMENTS_VARENDO DIFFUSE_FILTER SUB_DRAWS
...@@ -262,6 +262,7 @@ statement : parameters ...@@ -262,6 +262,7 @@ statement : parameters
| external_function | external_function
| steady_state_model | steady_state_model
| trend_var | trend_var
| log_trend_var
| ms_estimation | ms_estimation
| ms_simulation | ms_simulation
| ms_compute_mdd | ms_compute_mdd
...@@ -287,22 +288,42 @@ trend_var : TREND_VAR '(' GROWTH_FACTOR EQUAL { driver.begin_trend(); } hand_sid ...@@ -287,22 +288,42 @@ trend_var : TREND_VAR '(' GROWTH_FACTOR EQUAL { driver.begin_trend(); } hand_sid
; ;
trend_var_list : trend_var_list symbol trend_var_list : trend_var_list symbol
{ driver.declare_trend_var($2); } { driver.declare_trend_var(false, $2); }
| trend_var_list COMMA symbol | trend_var_list COMMA symbol
{ driver.declare_trend_var($3); } { driver.declare_trend_var(false, $3); }
| symbol | symbol
{ driver.declare_trend_var($1); } { driver.declare_trend_var(false, $1); }
| trend_var_list symbol TEX_NAME | 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 | trend_var_list COMMA symbol TEX_NAME
{ driver.declare_trend_var($3, $4); } { driver.declare_trend_var(false, $3, $4); }
| symbol TEX_NAME | 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 : VAR var_list ';'
| VAR '(' DEFLATOR EQUAL { driver.begin_trend(); } hand_side ')' nonstationary_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 nonstationary_var_list : nonstationary_var_list symbol
......
...@@ -103,6 +103,7 @@ string eofbuff; ...@@ -103,6 +103,7 @@ string eofbuff;
<INITIAL>varexo {BEGIN DYNARE_STATEMENT; return token::VAREXO;} <INITIAL>varexo {BEGIN DYNARE_STATEMENT; return token::VAREXO;}
<INITIAL>varexo_det {BEGIN DYNARE_STATEMENT; return token::VAREXO_DET;} <INITIAL>varexo_det {BEGIN DYNARE_STATEMENT; return token::VAREXO_DET;}
<INITIAL>trend_var {BEGIN DYNARE_STATEMENT; return token::TREND_VAR;} <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>predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;}
<INITIAL>parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;} <INITIAL>parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;}
<INITIAL>periods {BEGIN DYNARE_STATEMENT; return token::PERIODS;} <INITIAL>periods {BEGIN DYNARE_STATEMENT; return token::PERIODS;}
...@@ -467,6 +468,7 @@ string eofbuff; ...@@ -467,6 +468,7 @@ string eofbuff;
<DYNARE_STATEMENT>selected_variables_only {return token::SELECTED_VARIABLES_ONLY; } <DYNARE_STATEMENT>selected_variables_only {return token::SELECTED_VARIABLES_ONLY; }
<DYNARE_STATEMENT>pruning {return token::PRUNING; } <DYNARE_STATEMENT>pruning {return token::PRUNING; }
<DYNARE_STATEMENT>deflator {return token::DEFLATOR;} <DYNARE_STATEMENT>deflator {return token::DEFLATOR;}
<DYNARE_STATEMENT>log_deflator {return token::LOG_DEFLATOR;}
<DYNARE_STATEMENT>growth_factor {return token::GROWTH_FACTOR;} <DYNARE_STATEMENT>growth_factor {return token::GROWTH_FACTOR;}
<DYNARE_STATEMENT>cova_compute {return token::COVA_COMPUTE;} <DYNARE_STATEMENT>cova_compute {return token::COVA_COMPUTE;}
<DYNARE_STATEMENT>discretionary_tol {return token::DISCRETIONARY_TOL;} <DYNARE_STATEMENT>discretionary_tol {return token::DISCRETIONARY_TOL;}
......
...@@ -464,7 +464,7 @@ NumConstNode::replaceTrendVar() const ...@@ -464,7 +464,7 @@ NumConstNode::replaceTrendVar() const
} }
expr_t 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); return const_cast<NumConstNode *>(this);
} }
...@@ -505,6 +505,7 @@ VariableNode::prepareForDerivation() ...@@ -505,6 +505,7 @@ VariableNode::prepareForDerivation()
case eExogenousDet: case eExogenousDet:
case eParameter: case eParameter:
case eTrend: case eTrend:
case eLogTrend:
// For a variable or a parameter, the only non-null derivative is with respect to itself // 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)); non_null_derivatives.insert(datatree.getDerivID(symb_id, lag));
break; break;
...@@ -533,6 +534,7 @@ VariableNode::computeDerivative(int deriv_id) ...@@ -533,6 +534,7 @@ VariableNode::computeDerivative(int deriv_id)
case eExogenousDet: case eExogenousDet:
case eParameter: case eParameter:
case eTrend: case eTrend:
case eLogTrend:
if (deriv_id == datatree.getDerivID(symb_id, lag)) if (deriv_id == datatree.getDerivID(symb_id, lag))
return datatree.One; return datatree.One;
else else
...@@ -585,7 +587,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -585,7 +587,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << "\\bar{"; output << "\\bar{";
output << datatree.symbol_table.getTeXName(symb_id); output << datatree.symbol_table.getTeXName(symb_id);
if (output_type == oLatexDynamicModel 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"; output << "_{t";
if (lag != 0) if (lag != 0)
...@@ -757,6 +759,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -757,6 +759,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case eExternalFunction: case eExternalFunction:
case eTrend: case eTrend:
case eLogTrend:
case eStatementDeclaredVariable: case eStatementDeclaredVariable:
cerr << "Impossible case" << endl; cerr << "Impossible case" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
...@@ -910,6 +913,7 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recur ...@@ -910,6 +913,7 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recur
case eExogenousDet: case eExogenousDet:
case eParameter: case eParameter:
case eTrend: case eTrend:
case eLogTrend:
if (deriv_id == datatree.getDerivID(symb_id, lag)) if (deriv_id == datatree.getDerivID(symb_id, lag))
return datatree.One; return datatree.One;
else else
...@@ -1044,6 +1048,7 @@ VariableNode::decreaseLeadsLags(int n) const ...@@ -1044,6 +1048,7 @@ VariableNode::decreaseLeadsLags(int n) const
case eExogenous: case eExogenous:
case eExogenousDet: case eExogenousDet:
case eTrend: case eTrend:
case eLogTrend:
return datatree.AddVariable(symb_id, lag-n); return datatree.AddVariable(symb_id, lag-n);
case eModelLocalVariable: case eModelLocalVariable:
return datatree.local_variables_table[symb_id]->decreaseLeadsLags(n); return datatree.local_variables_table[symb_id]->decreaseLeadsLags(n);
...@@ -1248,43 +1253,76 @@ VariableNode::replaceTrendVar() const ...@@ -1248,43 +1253,76 @@ VariableNode::replaceTrendVar() const
{ {
if (get_type() == eTrend) if (get_type() == eTrend)
return datatree.One; return datatree.One;
else if (get_type() == eLogTrend)
return datatree.Zero;
else else
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
} }
expr_t 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) if (get_symb_id() != symb_id)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
if (get_lag() == 0) if (log_trend)
return datatree.AddTimes(const_cast<VariableNode *>(this), 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 else
return datatree.AddTimes(const_cast<VariableNode *>(this), trend->decreaseLeadsLags(-1*get_lag())); {
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 expr_t
VariableNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const 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); return const_cast<VariableNode *>(this);
map<int, expr_t>::const_iterator it = trend_symbols_map.find(symb_id); map<int, expr_t>::const_iterator it = trend_symbols_map.find(symb_id);
expr_t noTrendLeadLagNode = new VariableNode(datatree, it->first, 0); expr_t noTrendLeadLagNode = new VariableNode(datatree, it->first, 0);
bool log_trend = get_type() == eLogTrend;
expr_t trend = it->second;
if (get_lag() > 0) if (get_lag() > 0)
{ {
expr_t growthFactorSequence = it->second->decreaseLeadsLags(-1); expr_t growthFactorSequence = trend->decreaseLeadsLags(-1);
for (int i = 1; i < get_lag(); i++) if (log_trend)
growthFactorSequence = datatree.AddTimes(growthFactorSequence, it->second->decreaseLeadsLags(-1*(i+1))); {
return datatree.AddTimes(noTrendLeadLagNode, growthFactorSequence); for (int i = 1; i < get_lag(); i++)
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 else //get_lag < 0
{ {
expr_t growthFactorSequence = it->second; expr_t growthFactorSequence = trend;
for (int i = 1; i < abs(get_lag()); i++) if (log_trend)
growthFactorSequence = datatree.AddTimes(growthFactorSequence, it->second->decreaseLeadsLags(i)); {
return datatree.AddDivide(noTrendLeadLagNode, growthFactorSequence); for (int i = 1; i < abs(get_lag()); 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);
}
} }
} }
...@@ -2369,9 +2407,9 @@ UnaryOpNode::replaceTrendVar() const ...@@ -2369,9 +2407,9 @@ UnaryOpNode::replaceTrendVar() const
} }
expr_t 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); return buildSimilarUnaryOpNode(argsubst, datatree);
} }
...@@ -3665,10 +3703,10 @@ BinaryOpNode::replaceTrendVar() const ...@@ -3665,10 +3703,10 @@ BinaryOpNode::replaceTrendVar() const
} }
expr_t 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 arg1subst = arg1->detrend(symb_id, log_trend, trend);
expr_t arg2subst = arg2->detrend(symb_id, trend); expr_t arg2subst = arg2->detrend(symb_id, log_trend, trend);
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree); return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
} }
...@@ -4269,11 +4307,11 @@ TrinaryOpNode::replaceTrendVar() const ...@@ -4269,11 +4307,11 @@ TrinaryOpNode::replaceTrendVar() const
} }
expr_t 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 arg1subst = arg1->detrend(symb_id, log_trend, trend);
expr_t arg2subst = arg2->detrend(symb_id, trend); expr_t arg2subst = arg2->detrend(symb_id, log_trend, trend);
expr_t arg3subst = arg3->detrend(symb_id, trend); expr_t arg3subst = arg3->detrend(symb_id, log_trend, trend);
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree); return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
} }
...@@ -4855,11 +4893,11 @@ ExternalFunctionNode::replaceTrendVar() const ...@@ -4855,11 +4893,11 @@ ExternalFunctionNode::replaceTrendVar() const
} }
expr_t 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; vector<expr_t> arguments_subst;
for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++) 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); return buildSimilarExternalFunctionNode(arguments_subst, datatree);
} }
......
...@@ -389,10 +389,11 @@ public: ...@@ -389,10 +389,11 @@ public:
//! Constructs a new expression where the variable indicated by symb_id has been detrended //! 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] symb_id indicating the variable to be detrended
\param[in] expr_t indicating the trend \param[in] log_trend indicates if the trend is in log
\param[out] expr_t the new binary op pointing to a detrended variable \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 //! Add ExprNodes to the provided datatree
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const = 0; virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const = 0;
...@@ -452,7 +453,7 @@ public: ...@@ -452,7 +453,7 @@ public:
virtual bool containsEndogenous(void) const; virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const; virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() 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 cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const; virtual expr_t removeTrendLeadLag(map<int