trend_var, growth_factor, deflator: stationarize a nonstationary model and test

issue#70
Houtan Bastani 2010-10-15 19:05:16 +02:00
parent 0782dd57e3
commit a7fc3361ac
16 changed files with 559 additions and 10 deletions

View File

@ -136,7 +136,8 @@ enum SymbolType
eParameter = 4, //!< Parameter
eModelLocalVariable = 10, //!< Local variable whose scope is model (pound expression)
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
};
enum ExpressionType

View File

@ -213,6 +213,16 @@ public:
{
};
//! Raised when a trend is declared twice
class TrendException
{
public:
string name;
TrendException(const string &name_arg) : name(name_arg)
{
}
};
//! Returns the derivation ID, or throws an exception if the derivation ID does not exist
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
//! Returns the column of the dynamic Jacobian associated to a derivation ID

View File

@ -2411,6 +2411,13 @@ DynamicModel::collect_first_order_derivatives_endogenous()
return endo_derivatives;
}
void
DynamicModel::runTrendTest(const eval_context_t &eval_context)
{
computeDerivIDs();
testTrendDerivativesEqualToZero(eval_context);
}
void
DynamicModel::computingPass(bool jacobianExo, bool hessian, bool thirdDerivatives, bool paramsDerivatives,
const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool use_dll, bool bytecode)
@ -2832,6 +2839,29 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool bytecode
writeDynamicMFile(t_basename);
}
void
DynamicModel::cloneDynamic(DynamicModel &dynamic_model) const
{
/* Ensure that we are using the same symbol table, because at many places we manipulate
symbol IDs rather than strings */
assert(&symbol_table == &dynamic_model.symbol_table);
// Convert model local variables (need to be done first)
for (map<int, expr_t>::const_iterator it = local_variables_table.begin();
it != local_variables_table.end(); it++)
dynamic_model.AddLocalVariable(it->first, it->second->cloneDynamic(dynamic_model));
// Convert equations
for (vector<BinaryOpNode *>::const_iterator it = equations.begin();
it != equations.end(); it++)
dynamic_model.addEquation((*it)->cloneDynamic(dynamic_model));
// Convert auxiliary equations
for (deque<BinaryOpNode *>::const_iterator it = aux_equations.begin();
it != aux_equations.end(); it++)
dynamic_model.addAuxEquation((*it)->cloneDynamic(dynamic_model));
}
void
DynamicModel::toStatic(StaticModel &static_model) const
{
@ -2870,6 +2900,7 @@ DynamicModel::computeDerivIDs()
equations[i]->collectVariables(eExogenous, dynvars);
equations[i]->collectVariables(eExogenousDet, dynvars);
equations[i]->collectVariables(eParameter, dynvars);
equations[i]->collectVariables(eTrend, dynvars);
}
for (set<pair<int, int> >::const_iterator it = dynvars.begin();
@ -2982,7 +3013,8 @@ DynamicModel::computeDynJacobianCols(bool jacobianExo)
dyn_jacobian_cols_table[deriv_id] = dynJacobianColsNbr + symbol_table.exo_nbr() + tsid;
break;
case eParameter:
// We don't assign a dynamic jacobian column to parameters
case eTrend:
// We don't assign a dynamic jacobian column to parameters or trend variables
break;
default:
// Shut up GCC
@ -3012,6 +3044,34 @@ DynamicModel::getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDExcepti
return it->second;
}
void
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)
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)
{
cerr << "ERROR: 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);
}
}
}
}
void
DynamicModel::computeParamsDerivatives()
{
@ -3467,6 +3527,37 @@ DynamicModel::transformPredeterminedVariables()
}
}
void
DynamicModel::detrendEquations()
{
for (trend_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));
assert(substeq != NULL);
equations[i] = dynamic_cast<BinaryOpNode *>(substeq);
}
for (int i = 0; i < (int) equations.size(); i++)
{
BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(equations[i]->removeTrendLeadLag(trend_symbols_map));
assert(substeq != NULL);
equations[i] = dynamic_cast<BinaryOpNode *>(substeq);
}
}
void
DynamicModel::removeTrendVariableFromEquations()
{
for (int i = 0; i < (int) equations.size(); i++)
{
BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(equations[i]->replaceTrendVar());
assert(substeq != NULL);
equations[i] = dynamic_cast<BinaryOpNode *>(substeq);
}
}
void
DynamicModel::fillEvalContext(eval_context_t &eval_context) const
{
@ -3503,4 +3594,10 @@ DynamicModel::fillEvalContext(eval_context_t &eval_context) const
// Do nothing
}
}
//Third, trend variables
vector <int> trendVars = symbol_table.getTrendVarIds();
for (vector <int>::const_iterator it = trendVars.begin();
it != trendVars.end(); it++)
eval_context[*it] = 2; //not <= 0 bc of log, not 1 bc of powers
}

View File

@ -21,6 +21,7 @@
#define _DYNAMICMODEL_HH
using namespace std;
#define ZERO_BAND 1e-8
#include <fstream>
@ -156,6 +157,8 @@ private:
void computeDynJacobianCols(bool jacobianExo);
//! Computes derivatives of the Jacobian w.r. to parameters
void computeParamsDerivatives();
//! Computes derivatives of the Jacobian w.r. to trend vars and tests that they are equal to zero
void testTrendDerivativesEqualToZero(const eval_context_t &eval_context);
//! Computes temporary terms for the file containing parameters derivatives
void computeParamsDerivativesTemporaryTerms();
//! Collect only the first derivatives
@ -278,6 +281,10 @@ public:
/*! It assumes that the static model given in argument has just been allocated */
void toStatic(StaticModel &static_model) const;
//! Copies a dynamic model (only the equations)
/*! It assumes that the dynamic model given in argument has just been allocated */
void cloneDynamic(DynamicModel &dynamic_model) const;
//! Writes LaTeX file with the equations of the dynamic model
void writeLatexFile(const string &basename) const;
@ -294,6 +301,9 @@ public:
return true;
};
//! Drive test of detrended equations
void runTrendTest(const eval_context_t &eval_context);
//! Transforms the model by removing all leads greater or equal than 2 on endos
/*! Note that this can create new lags on endos and exos */
void substituteEndoLeadGreaterThanTwo(bool deterministic_model);
@ -314,6 +324,12 @@ public:
//! Transforms the model by decreasing the lead/lag of predetermined variables in model equations by one
void transformPredeterminedVariables();
//! Transforms the model by removing trends specified by the user
void detrendEquations();
//! Transforms the model by replacing trend variables with a 1
void removeTrendVariableFromEquations();
//! Fills eval context with values of model local variables and auxiliary variables
void fillEvalContext(eval_context_t &eval_context) const;

View File

@ -154,7 +154,7 @@ class ParsingDriver;
%token COMPUTE_MDD COMPUTE_PROBABILITIES PRINT_DRAWS N_DRAWS THINNING_FACTOR PROPOSAL_DRAWS MARKOV_FILE
%token MHM_FILE OUTPUT_FILE_TAG DRAWS_NBR_BURN_IN_1 DRAWS_NBR_BURN_IN_2 DRAWS_NBR_MEAN_VAR_ESTIMATE
%token DRAWS_NBR_MODIFIED_HARMONIC_MEAN DIRICHLET_SCALE
%token SBVAR MS_SBVAR
%token SBVAR MS_SBVAR TREND_VAR DEFLATOR GROWTH_FACTOR
%token SVAR_IDENTIFICATION EQUATION EXCLUSION LAG UPPER_CHOLESKY LOWER_CHOLESKY
%token MARKOV_SWITCHING CHAIN STATE DURATION NUMBER_OF_STATES
%token SVAR COEFFICIENTS VARIANCES CONSTANTS EQUATIONS
@ -241,6 +241,7 @@ statement : parameters
| svar
| external_function
| steady_state_model
| trend_var
;
dsample : DSAMPLE INT_NUMBER ';'
@ -251,7 +252,42 @@ dsample : DSAMPLE INT_NUMBER ';'
rplot : RPLOT symbol_list ';' { driver.rplot(); };
var : VAR var_list ';';
trend_var : TREND_VAR '(' GROWTH_FACTOR EQUAL { driver.begin_trend(); } hand_side ')' trend_var_list ';'
{ driver.end_trend_var($6); }
;
trend_var_list : trend_var_list symbol
{ driver.declare_trend_var($2); }
| trend_var_list COMMA symbol
{ driver.declare_trend_var($3); }
| symbol
{ driver.declare_trend_var($1); }
| trend_var_list symbol TEX_NAME
{ driver.declare_trend_var($2, $3); }
| trend_var_list COMMA symbol TEX_NAME
{ driver.declare_trend_var($3, $4); }
| symbol TEX_NAME
{ driver.declare_trend_var($1, $2); }
;
var : VAR var_list ';'
| VAR '(' DEFLATOR EQUAL { driver.begin_trend(); } hand_side ')' nonstationary_var_list ';'
{ driver.end_nonstationary_var($6); }
;
nonstationary_var_list : nonstationary_var_list symbol
{ driver.declare_nonstationary_var($2); }
| nonstationary_var_list COMMA symbol
{ driver.declare_nonstationary_var($3); }
| symbol
{ driver.declare_nonstationary_var($1); }
| nonstationary_var_list symbol TEX_NAME
{ driver.declare_nonstationary_var($2, $3); }
| nonstationary_var_list COMMA symbol TEX_NAME
{ driver.declare_nonstationary_var($3, $4); }
| symbol TEX_NAME
{ driver.declare_nonstationary_var($1, $2); }
;
varexo : VAREXO varexo_list ';';
@ -702,7 +738,6 @@ period_list : period_list COMMA INT_NUMBER
{ driver.add_period($1); }
;
sigma_e : SIGMA_E EQUAL '[' triangular_matrix ']' ';' { driver.do_sigma_e(); };
value_list

View File

@ -102,6 +102,7 @@ string eofbuff;
<INITIAL>var {BEGIN DYNARE_STATEMENT; return token::VAR;}
<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>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;}
@ -360,7 +361,9 @@ string eofbuff;
<DYNARE_STATEMENT>filter_covariance {return token::FILTER_COVARIANCE; }
<DYNARE_STATEMENT>filter_decomposition {return token::FILTER_DECOMPOSITION; }
<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>growth_factor {return token::GROWTH_FACTOR;}
<DYNARE_STATEMENT>[\$][^$]*[\$] {
strtok(yytext+1, "$");

View File

@ -329,6 +329,12 @@ NumConstNode::toStatic(DataTree &static_datatree) const
return static_datatree.AddNumConstant(datatree.num_constants.get(id));
}
expr_t
NumConstNode::cloneDynamic(DataTree &dynamic_datatree) const
{
return dynamic_datatree.AddNumConstant(datatree.num_constants.get(id));
}
int
NumConstNode::maxEndoLead() const
{
@ -424,6 +430,24 @@ NumConstNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int la
return false;
}
expr_t
NumConstNode::replaceTrendVar() const
{
return const_cast<NumConstNode *>(this);
}
expr_t
NumConstNode::detrend(int symb_id, expr_t trend) const
{
return const_cast<NumConstNode *>(this);
}
expr_t
NumConstNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
{
return const_cast<NumConstNode *>(this);
}
void
VariableNode::prepareForDerivation()
{
@ -439,6 +463,7 @@ VariableNode::prepareForDerivation()
case eExogenous:
case eExogenousDet:
case eParameter:
case eTrend:
// 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;
@ -465,6 +490,7 @@ VariableNode::computeDerivative(int deriv_id)
case eExogenous:
case eExogenousDet:
case eParameter:
case eTrend:
if (deriv_id == datatree.getDerivID(symb_id, lag))
return datatree.One;
else
@ -514,7 +540,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 == eEndogenous || type == eExogenous || type == eExogenousDet || type == eModelLocalVariable || type == eTrend))
{
output << "_{t";
if (lag != 0)
@ -677,6 +703,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
break;
case eExternalFunction:
case eTrend:
cerr << "Impossible case" << endl;
exit(EXIT_FAILURE);
}
@ -812,6 +839,7 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recur
case eExogenous:
case eExogenousDet:
case eParameter:
case eTrend:
if (deriv_id == datatree.getDerivID(symb_id, lag))
return datatree.One;
else
@ -856,6 +884,12 @@ VariableNode::toStatic(DataTree &static_datatree) const
return static_datatree.AddVariable(symb_id);
}
expr_t
VariableNode::cloneDynamic(DataTree &dynamic_datatree) const
{
return dynamic_datatree.AddVariable(symb_id, lag);
}
int
VariableNode::maxEndoLead() const
{
@ -920,6 +954,7 @@ VariableNode::decreaseLeadsLags(int n) const
case eEndogenous:
case eExogenous:
case eExogenousDet:
case eTrend:
return datatree.AddVariable(symb_id, lag-n);
case eModelLocalVariable:
return datatree.local_variables_table[symb_id]->decreaseLeadsLags(n);
@ -1104,6 +1139,51 @@ VariableNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int la
return false;
}
expr_t
VariableNode::replaceTrendVar() const
{
if (get_type() == eTrend)
return datatree.One;
else
return const_cast<VariableNode *>(this);
}
expr_t
VariableNode::detrend(int symb_id, expr_t trend) const
{
if (get_symb_id() != symb_id)
return const_cast<VariableNode *>(this);
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)
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);
if (get_lag() > 0)
{
expr_t growthFactorSequence = it->second->decreaseLeadsLags(-1);
for (int i=1; i<get_lag(); i++)
growthFactorSequence = datatree.AddTimes(growthFactorSequence, it->second->decreaseLeadsLags(-1*(i+1)));
return datatree.AddTimes(noTrendLeadLagNode, growthFactorSequence);
}
else //get_lag < 0
{
expr_t growthFactorSequence = it->second;
for (int i=1; i<abs(get_lag()); i++)
growthFactorSequence = datatree.AddTimes(growthFactorSequence, it->second->decreaseLeadsLags(i));
return datatree.AddDivide(noTrendLeadLagNode, growthFactorSequence);
}
}
UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, const int expectation_information_set_arg, const string &expectation_information_set_name_arg) :
ExprNode(datatree_arg),
arg(arg_arg),
@ -1779,6 +1859,13 @@ UnaryOpNode::toStatic(DataTree &static_datatree) const
return buildSimilarUnaryOpNode(sarg, static_datatree);
}
expr_t
UnaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const
{
expr_t substarg = arg->cloneDynamic(dynamic_datatree);
return buildSimilarUnaryOpNode(substarg, dynamic_datatree);
}
int
UnaryOpNode::maxEndoLead() const
{
@ -1948,6 +2035,27 @@ UnaryOpNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag
return false;
}
expr_t
UnaryOpNode::replaceTrendVar() const
{
expr_t argsubst = arg->replaceTrendVar();
return buildSimilarUnaryOpNode(argsubst, datatree);
}
expr_t
UnaryOpNode::detrend(int symb_id, expr_t trend) const
{
expr_t argsubst = arg->detrend(symb_id, trend);
return buildSimilarUnaryOpNode(argsubst, datatree);
}
expr_t
UnaryOpNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
{
expr_t argsubst = arg->removeTrendLeadLag(trend_symbols_map);
return buildSimilarUnaryOpNode(argsubst, datatree);
}
BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
BinaryOpcode op_code_arg, const expr_t arg2_arg) :
ExprNode(datatree_arg),
@ -2817,6 +2925,14 @@ BinaryOpNode::toStatic(DataTree &static_datatree) const
return buildSimilarBinaryOpNode(sarg1, sarg2, static_datatree);
}
expr_t
BinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const
{
expr_t substarg1 = arg1->cloneDynamic(dynamic_datatree);
expr_t substarg2 = arg2->cloneDynamic(dynamic_datatree);
return buildSimilarBinaryOpNode(substarg1, substarg2, dynamic_datatree);
}
int
BinaryOpNode::maxEndoLead() const
{
@ -2899,7 +3015,6 @@ BinaryOpNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vecto
return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
}
}
}
expr_t
@ -2982,6 +3097,30 @@ BinaryOpNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int la
return false;
}
expr_t
BinaryOpNode::replaceTrendVar() const
{
expr_t arg1subst = arg1->replaceTrendVar();
expr_t arg2subst = arg2->replaceTrendVar();
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
}
expr_t
BinaryOpNode::detrend(int symb_id, expr_t trend) const
{
expr_t arg1subst = arg1->detrend(symb_id, trend);
expr_t arg2subst = arg2->detrend(symb_id, trend);
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
}
expr_t
BinaryOpNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
{
expr_t arg1subst = arg1->removeTrendLeadLag(trend_symbols_map);
expr_t arg2subst = arg2->removeTrendLeadLag(trend_symbols_map);
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
}
TrinaryOpNode::TrinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg) :
ExprNode(datatree_arg),
@ -3403,6 +3542,15 @@ TrinaryOpNode::toStatic(DataTree &static_datatree) const
return buildSimilarTrinaryOpNode(sarg1, sarg2, sarg3, static_datatree);
}
expr_t
TrinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const
{
expr_t substarg1 = arg1->cloneDynamic(dynamic_datatree);
expr_t substarg2 = arg2->cloneDynamic(dynamic_datatree);
expr_t substarg3 = arg3->cloneDynamic(dynamic_datatree);
return buildSimilarTrinaryOpNode(substarg1, substarg2, substarg3, dynamic_datatree);
}
int
TrinaryOpNode::maxEndoLead() const
{
@ -3516,6 +3664,33 @@ TrinaryOpNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int l
return false;
}
expr_t
TrinaryOpNode::replaceTrendVar() const
{
expr_t arg1subst = arg1->replaceTrendVar();
expr_t arg2subst = arg2->replaceTrendVar();
expr_t arg3subst = arg3->replaceTrendVar();
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
}
expr_t
TrinaryOpNode::detrend(int symb_id, 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);
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
}
expr_t
TrinaryOpNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
{
expr_t arg1subst = arg1->removeTrendLeadLag(trend_symbols_map);
expr_t arg2subst = arg2->removeTrendLeadLag(trend_symbols_map);
expr_t arg3subst = arg3->removeTrendLeadLag(trend_symbols_map);
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
}
ExternalFunctionNode::ExternalFunctionNode(DataTree &datatree_arg,
int symb_id_arg,
const vector<expr_t> &arguments_arg) :
@ -3797,6 +3972,16 @@ ExternalFunctionNode::toStatic(DataTree &static_datatree) const
return static_datatree.AddExternalFunction(symb_id, static_arguments);
}
expr_t
ExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const
{
vector<expr_t> dynamic_arguments;
for (vector<expr_t>::const_iterator it = arguments.begin();
it != arguments.end(); it++)
dynamic_arguments.push_back((*it)->cloneDynamic(dynamic_datatree));
return dynamic_datatree.AddExternalFunction(symb_id, dynamic_arguments);
}
int
ExternalFunctionNode::maxEndoLead() const
{
@ -3936,6 +4121,33 @@ ExternalFunctionNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id
return false;
}
expr_t
ExternalFunctionNode::replaceTrendVar() const
{
vector<expr_t> arguments_subst;
for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
arguments_subst.push_back((*it)->replaceTrendVar());
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
}
expr_t
ExternalFunctionNode::detrend(int symb_id, 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));
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
}
expr_t
ExternalFunctionNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
{
vector<expr_t> arguments_subst;
for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
arguments_subst.push_back((*it)->removeTrendLeadLag(trend_symbols_map));
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
}
FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatree_arg,
int top_level_symb_id_arg,
const vector<expr_t> &arguments_arg,

View File

@ -356,6 +356,22 @@ public:
*/
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const = 0;
//! Replaces the Trend var with datatree.One
virtual expr_t replaceTrendVar() const = 0;
//! 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
*/
virtual expr_t detrend(int symb_id, expr_t trend) const = 0;
//! Add ExprNodes to the provided datatree
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const = 0;
//! Move a trend variable with lag/lead to time t by dividing/multiplying by its growth factor
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const = 0;
};
//! Object used to compare two nodes (using their indexes)
@ -405,6 +421,10 @@ public:
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) 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 cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
//! Symbol or variable node
@ -458,6 +478,10 @@ public:
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) 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 cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
//! Unary operator node
@ -523,6 +547,10 @@ public:
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) 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 cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
//! Binary operator node
@ -593,6 +621,10 @@ public:
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) 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 cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
//! Trinary operator node
@ -645,6 +677,10 @@ public:
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) 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 cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
//! External function node
@ -703,6 +739,10 @@ public:
virtual bool isNumConstNodeEqualTo(double value) const;
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 cloneDynamic(DataTree &dynamic_datatree) const;
virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
};
class FirstDerivExternalFunctionNode : public ExternalFunctionNode

View File

@ -25,10 +25,11 @@
ModFile::ModFile() : expressions_tree(symbol_table, num_constants, external_functions_table),
dynamic_model(symbol_table, num_constants, external_functions_table),
trend_dynamic_model(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, static_model),
linear(false), block(false), byte_code(false),
use_dll(false), no_static(false)
use_dll(false), no_static(false), nonstationary_variables(false)
{
}
@ -212,6 +213,13 @@ ModFile::transformPass()
if (symbol_table.predeterminedNbr() > 0)
dynamic_model.transformPredeterminedVariables();
if (nonstationary_variables)
{
dynamic_model.detrendEquations();
dynamic_model.cloneDynamic(trend_dynamic_model);
dynamic_model.removeTrendVariableFromEquations();
}
// Create auxiliary vars for Expectation operator
dynamic_model.substituteExpectation(mod_file_struct.partial_information);
@ -295,6 +303,9 @@ ModFile::computingPass(bool no_tmp_terms)
|| mod_file_struct.ramsey_policy_present || mod_file_struct.identification_present;
if (dynamic_model.equation_number() > 0)
{
if (nonstationary_variables)
trend_dynamic_model.runTrendTest(global_eval_context);
// Compute static model and its derivatives
dynamic_model.toStatic(static_model);
if(!no_static)

View File

@ -50,6 +50,8 @@ public:
DataTree expressions_tree;
//! Dynamic model, as declared in the "model" block
DynamicModel dynamic_model;
//! A copy of Dynamic model, for testing trends declared by user
DynamicModel trend_dynamic_model;
//! Static model, as derived from the "model" block when leads and lags have been removed
StaticModel static_model;
//! Static model, as declared in the "steady_state_model" block if present
@ -69,6 +71,9 @@ public:
//! Is the static model have to computed (no_static=false) or not (no_static=true). Option of 'model'
bool no_static;
//! Are nonstationary variables present ?
bool nonstationary_variables;
//! Global evaluation context
/*! Filled using initval blocks and parameters initializations */
eval_context_t global_eval_context;

View File

@ -1362,3 +1362,29 @@ ModelTree::addAuxEquation(expr_t eq)
aux_equations.push_back(beq);
}
void
ModelTree::addTrendVariables(vector<int> trend_vars, expr_t growth_factor) throw (TrendException)
{
while (!trend_vars.empty())
if (trend_symbols_map.find(trend_vars.back()) != trend_symbols_map.end())
throw TrendException(symbol_table.getName(trend_vars.back()));
else
{
trend_symbols_map[trend_vars.back()] = growth_factor;
trend_vars.pop_back();
}
}
void
ModelTree::addNonstationaryVariables(vector<int> nonstationary_vars, 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_vars.pop_back();
}
}

View File

@ -45,12 +45,14 @@ 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
{
friend class DynamicModel;
friend class StaticModel;
protected:
//! Stores declared and generated auxiliary equations
vector<BinaryOpNode *> equations;
@ -92,6 +94,10 @@ protected:
//! Temporary terms (those which will be noted Txxxx)
temporary_terms_t temporary_terms;
//! Trend variables and their growth factors
trend_symbols_map_t trend_symbols_map;
//! Nonstationary variables and their deflators
trend_symbols_map_t nonstationary_symbols_map;
//! Computes 1st derivatives
/*! \param vars the derivation IDs w.r. to which compute the derivatives */
@ -233,6 +239,10 @@ public:
void addAuxEquation(expr_t eq);
//! Returns the number of equations in the model
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);
inline static std::string
c_Equation_Type(int type)

View File

@ -164,6 +164,37 @@ ParsingDriver::declare_parameter(string *name, string *tex_name)
delete tex_name;
}
void
ParsingDriver::begin_trend()
{
set_current_data_tree(&mod_file->dynamic_model);
}
void
ParsingDriver::declare_trend_var(string *name, string *tex_name)
{
declare_symbol(name, eTrend, tex_name);
declared_trend_vars.push_back(mod_file->symbol_table.getID(*name));
delete name;
if (tex_name != NULL)
delete tex_name;
}
void
ParsingDriver::end_trend_var(expr_t growth_factor)
{
try
{
dynamic_model->addTrendVariables(declared_trend_vars, growth_factor);
}
catch (DataTree::TrendException &e)
{
error("Trend variable " + e.name + " was declared twice.");
}
declared_trend_vars.clear();
reset_data_tree();
}
void
ParsingDriver::add_predetermined_variable(string *name)
{
@ -260,6 +291,32 @@ ParsingDriver::add_expression_variable(string *name)
return id;
}
void
ParsingDriver::declare_nonstationary_var(string *name, string *tex_name)
{
declare_endogenous(new string(*name), tex_name);
declared_nonstationary_vars.push_back(mod_file->symbol_table.getID(*name));
mod_file->nonstationary_variables = true;
delete name;
if (tex_name != NULL)
delete tex_name;
}
void
ParsingDriver::end_nonstationary_var(expr_t deflator)
{
try
{
dynamic_model->addNonstationaryVariables(declared_nonstationary_vars, deflator);
}
catch (DataTree::TrendException &e)
{
error("Variable " + e.name + " was listed more than once as following a trend.");
}
declared_nonstationary_vars.clear();
reset_data_tree();
}
void
ParsingDriver::periods(string *periods)
{

View File

@ -163,6 +163,10 @@ private:
int current_external_function_id;
//! Temporary storage for option list provided to external_function()
ExternalFunctionsTable::external_function_options current_external_function_options;
//! Temporary storage for declaring trend variables
vector<int> declared_trend_vars;
//! Temporary storage for declaring nonstationary variables
vector<int> declared_nonstationary_vars;
//! reset the values for temporary storage
void reset_current_external_function_options();
//! Adds a model lagged variable to ModelTree and VariableTable
@ -502,6 +506,16 @@ public:
void begin_steady_state_model();
//! Add an assignment equation in steady_state_model block
void add_steady_state_model_equal(string *varname, expr_t expr);
//! Switches datatree
void begin_trend();
//! Declares a trend variable with its growth factor
void declare_trend_var(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);
};
#endif // ! PARSING_DRIVER_HH

View File

@ -433,3 +433,14 @@ SymbolTable::getObservedVariableIndex(int symb_id) const
assert(it != varobs.end());
return (int) (it - varobs.begin());
}
vector <int>
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)
trendVars.push_back(it->second);
return trendVars;
}

View File

@ -261,6 +261,7 @@ public:
bool isObservedVariable(int symb_id) const;
//! Return the index of a given observed variable in the vector of all observed variables
int getObservedVariableIndex(int symb_id) const;
vector <int> getTrendVarIds() const;
};
inline bool