preprocessor: in stochastic mode, create auxiliary variables for exogenous with non-zero lead/lag

git-svn-id: https://www.dynare.org/svn/dynare/trunk@3026 ac1d8469-bf42-47a9-8791-bf33cf982152
time-shift
sebastien 2009-10-07 14:07:13 +00:00
parent f7d69ff58c
commit c84df1aace
8 changed files with 329 additions and 109 deletions

View File

@ -2831,7 +2831,25 @@ DynamicModel::hessianHelper(ostream &output, int row_nb, int col_nb, ExprNodeOut
} }
void void
DynamicModel::substituteLeadGreaterThanTwo() DynamicModel::substituteEndoLeadGreaterThanTwo()
{
substituteLeadLagInternal(0);
}
void
DynamicModel::substituteEndoLagGreaterThanTwo()
{
substituteLeadLagInternal(1);
}
void
DynamicModel::substituteExoLeadLag()
{
substituteLeadLagInternal(2);
}
void
DynamicModel::substituteLeadLagInternal(int vars)
{ {
ExprNode::subst_table_t subst_table; ExprNode::subst_table_t subst_table;
vector<BinaryOpNode *> neweqs; vector<BinaryOpNode *> neweqs;
@ -2839,12 +2857,40 @@ DynamicModel::substituteLeadGreaterThanTwo()
// Substitute in model local variables // Substitute in model local variables
for(map<int, NodeID>::iterator it = local_variables_table.begin(); for(map<int, NodeID>::iterator it = local_variables_table.begin();
it != local_variables_table.end(); it++) it != local_variables_table.end(); it++)
it->second = it->second->substituteLeadGreaterThanTwo(subst_table, neweqs); {
NodeID subst;
switch(vars)
{
case 0:
subst = it->second->substituteEndoLeadGreaterThanTwo(subst_table, neweqs);
break;
case 1:
subst = it->second->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
break;
case 2:
subst = it->second->substituteExoLeadLag(subst_table, neweqs);
break;
}
it->second = subst;
}
// Substitute in equations // Substitute in equations
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]->substituteLeadGreaterThanTwo(subst_table, neweqs)); NodeID subst;
switch(vars)
{
case 0:
subst = equations[i]->substituteEndoLeadGreaterThanTwo(subst_table, neweqs);
break;
case 1:
subst = equations[i]->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
break;
case 2:
subst = equations[i]->substituteExoLeadLag(subst_table, neweqs);
break;
}
BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(subst);
assert(substeq != NULL); assert(substeq != NULL);
equations[i] = substeq; equations[i] = substeq;
} }
@ -2857,37 +2903,22 @@ DynamicModel::substituteLeadGreaterThanTwo()
copy(neweqs.rbegin(), neweqs.rend(), front_inserter(aux_equations)); copy(neweqs.rbegin(), neweqs.rend(), front_inserter(aux_equations));
if (neweqs.size() > 0) if (neweqs.size() > 0)
cout << "Substitution of leads >= 2: added " << neweqs.size() << " auxiliary variables and equations." << endl;
}
void
DynamicModel::substituteLagGreaterThanTwo()
{
ExprNode::subst_table_t subst_table;
vector<BinaryOpNode *> neweqs;
// Substitute in model local variables
for(map<int, NodeID>::iterator it = local_variables_table.begin();
it != local_variables_table.end(); it++)
it->second = it->second->substituteLagGreaterThanTwo(subst_table, neweqs);
// Substitute in equations
for(int i = 0; i < (int) equations.size(); i++)
{ {
BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(equations[i]->substituteLagGreaterThanTwo(subst_table, neweqs)); cout << "Substitution of ";
assert(substeq != NULL); switch(vars)
equations[i] = substeq; {
case 0:
cout << "endo leads >= 2";
break;
case 1:
cout << "endo lags >= 2";
break;
case 2:
cout << "exo leads/lags >= 2";
break;
}
cout << ": added " << neweqs.size() << " auxiliary variables and equations." << endl;
} }
// Add new equations
for(int i = 0; i < (int) neweqs.size(); i++)
addEquation(neweqs[i]);
// Add the new set of equations at the *beginning* of aux_equations
copy(neweqs.rbegin(), neweqs.rend(), front_inserter(aux_equations));
if (neweqs.size() > 0)
cout << "Substitution of lags >= 2: added " << neweqs.size() << " auxiliary variables and equations." << endl;
} }
void void

View File

@ -144,6 +144,9 @@ private:
//! Write chain rule derivative of a recursive equation w.r. to a variable //! Write chain rule derivative of a recursive equation w.r. to a variable
void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const; void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const;
//! Factorized code for substitutions of leads/lags
/*! \param[in] vars 0 for endo leads, 1 for endo lags, 2 for exo */
void substituteLeadLagInternal(int vars);
public: public:
DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants); DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants);
@ -199,11 +202,14 @@ public:
//! Returns true indicating that this is a dynamic model //! Returns true indicating that this is a dynamic model
virtual bool isDynamic() const { return true; }; virtual bool isDynamic() const { return true; };
//! Transforms the model by removing all leads greater or equal than 2 //! Transforms the model by removing all leads greater or equal than 2 on endos
void substituteLeadGreaterThanTwo(); void substituteEndoLeadGreaterThanTwo();
//! Transforms the model by removing all lags greater or equal than 2 //! Transforms the model by removing all lags greater or equal than 2 on endos
void substituteLagGreaterThanTwo(); void substituteEndoLagGreaterThanTwo();
//! Transforms the model by removing all leads and lags on exos
void substituteExoLeadLag();
//! Fills eval context with values of model local variables and auxiliary variables //! Fills eval context with values of model local variables and auxiliary variables
void fillEvalContext(eval_context_type &eval_context) const; void fillEvalContext(eval_context_type &eval_context) const;

View File

@ -148,7 +148,7 @@ ExprNode::writeOutput(ostream &output)
} }
VariableNode * VariableNode *
ExprNode::createLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const ExprNode::createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
int n = maxEndoLead(); int n = maxEndoLead();
assert(n >= 2); assert(n >= 2);
@ -168,7 +168,7 @@ ExprNode::createLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<Bin
it = subst_table.find(orig_expr); it = subst_table.find(orig_expr);
if (it == subst_table.end()) if (it == subst_table.end())
{ {
int symb_id = datatree.symbol_table.addLeadAuxiliaryVar(orig_expr->idx); int symb_id = datatree.symbol_table.addEndoLeadAuxiliaryVar(orig_expr->idx);
neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(symb_id, 0), substexpr))); neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(symb_id, 0), substexpr)));
substexpr = datatree.AddVariable(symb_id, +1); substexpr = datatree.AddVariable(symb_id, +1);
assert(dynamic_cast<VariableNode *>(substexpr) != NULL); assert(dynamic_cast<VariableNode *>(substexpr) != NULL);
@ -278,13 +278,19 @@ NumConstNode::decreaseLeadsLags(int n) const
} }
NodeID NodeID
NumConstNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const NumConstNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
return const_cast<NumConstNode *>(this); return const_cast<NumConstNode *>(this);
} }
NodeID NodeID
NumConstNode::substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const NumConstNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{
return const_cast<NumConstNode *>(this);
}
NodeID
NumConstNode::substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
return const_cast<NumConstNode *>(this); return const_cast<NumConstNode *>(this);
} }
@ -766,7 +772,7 @@ VariableNode::decreaseLeadsLags(int n) const
} }
NodeID NodeID
VariableNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const VariableNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
NodeID value; NodeID value;
switch(type) switch(type)
@ -775,20 +781,20 @@ VariableNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<Bi
if (lag <= 1) if (lag <= 1)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
else else
return createLeadAuxiliaryVarForMyself(subst_table, neweqs); return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
case eModelLocalVariable: case eModelLocalVariable:
value = datatree.local_variables_table[symb_id]; value = datatree.local_variables_table[symb_id];
if (value->maxEndoLead() <= 1) if (value->maxEndoLead() <= 1)
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
else else
return value->substituteLeadGreaterThanTwo(subst_table, neweqs); return value->substituteEndoLeadGreaterThanTwo(subst_table, neweqs);
default: default:
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
} }
} }
NodeID NodeID
VariableNode::substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const VariableNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
VariableNode *substexpr; VariableNode *substexpr;
subst_table_t::const_iterator it; subst_table_t::const_iterator it;
@ -814,7 +820,7 @@ VariableNode::substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<Bin
it = subst_table.find(orig_expr); it = subst_table.find(orig_expr);
if (it == subst_table.end()) if (it == subst_table.end())
{ {
int aux_symb_id = datatree.symbol_table.addLagAuxiliaryVar(symb_id, cur_lag+1); int aux_symb_id = datatree.symbol_table.addEndoLagAuxiliaryVar(symb_id, cur_lag+1);
neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(aux_symb_id, 0), substexpr))); neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(aux_symb_id, 0), substexpr)));
substexpr = datatree.AddVariable(aux_symb_id, -1); substexpr = datatree.AddVariable(aux_symb_id, -1);
subst_table[orig_expr] = substexpr; subst_table[orig_expr] = substexpr;
@ -827,7 +833,81 @@ VariableNode::substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<Bin
return substexpr; return substexpr;
case eModelLocalVariable: case eModelLocalVariable:
return datatree.local_variables_table[symb_id]->substituteLagGreaterThanTwo(subst_table, neweqs); return datatree.local_variables_table[symb_id]->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
default:
return const_cast<VariableNode *>(this);
}
}
NodeID
VariableNode::substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{
VariableNode *substexpr;
subst_table_t::const_iterator it;
int cur_lag;
switch(type)
{
case eExogenous:
if (lag == 0)
return const_cast<VariableNode *>(this);
it = subst_table.find(this);
if (it != subst_table.end())
return const_cast<VariableNode *>(it->second);
if (lag < 0)
{
substexpr = datatree.AddVariable(symb_id, 0);
cur_lag = -1;
// Each iteration tries to create an auxvar such that auxvar(-1)=curvar(cur_lag)
// At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to curvar(cur_lag+1) (resp. curvar(cur_lag))
while(cur_lag >= lag)
{
VariableNode *orig_expr = datatree.AddVariable(symb_id, cur_lag);
it = subst_table.find(orig_expr);
if (it == subst_table.end())
{
int aux_symb_id = datatree.symbol_table.addExoLagAuxiliaryVar(symb_id, cur_lag+1);
neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(aux_symb_id, 0), substexpr)));
substexpr = datatree.AddVariable(aux_symb_id, -1);
subst_table[orig_expr] = substexpr;
}
else
substexpr = const_cast<VariableNode *>(it->second);
cur_lag--;
}
return substexpr;
}
else
{
substexpr = datatree.AddVariable(symb_id, 0);
cur_lag = +1;
// Each iteration tries to create an auxvar such that auxvar(+1)=curvar(cur_lag)
// At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to curvar(cur_lag-1) (resp. curvar(cur_lag))
while(cur_lag <= lag)
{
VariableNode *orig_expr = datatree.AddVariable(symb_id, cur_lag);
it = subst_table.find(orig_expr);
if (it == subst_table.end())
{
int aux_symb_id = datatree.symbol_table.addExoLeadAuxiliaryVar(symb_id, cur_lag-1);
neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(aux_symb_id, 0), substexpr)));
substexpr = datatree.AddVariable(aux_symb_id, +1);
subst_table[orig_expr] = substexpr;
}
else
substexpr = const_cast<VariableNode *>(it->second);
cur_lag++;
}
return substexpr;
}
case eModelLocalVariable:
return datatree.local_variables_table[symb_id]->substituteExoLeadLag(subst_table, neweqs);
default: default:
return const_cast<VariableNode *>(this); return const_cast<VariableNode *>(this);
} }
@ -1471,26 +1551,33 @@ UnaryOpNode::decreaseLeadsLags(int n) const
} }
NodeID NodeID
UnaryOpNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const UnaryOpNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
if (op_code == oUminus) if (op_code == oUminus)
{ {
NodeID argsubst = arg->substituteLeadGreaterThanTwo(subst_table, neweqs); NodeID argsubst = arg->substituteEndoLeadGreaterThanTwo(subst_table, neweqs);
return buildSimilarUnaryOpNode(argsubst, datatree); return buildSimilarUnaryOpNode(argsubst, datatree);
} }
else else
{ {
if (maxEndoLead() >= 2) if (maxEndoLead() >= 2)
return createLeadAuxiliaryVarForMyself(subst_table, neweqs); return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
else else
return const_cast<UnaryOpNode *>(this); return const_cast<UnaryOpNode *>(this);
} }
} }
NodeID NodeID
UnaryOpNode::substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const UnaryOpNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
NodeID argsubst = arg->substituteLagGreaterThanTwo(subst_table, neweqs); NodeID argsubst = arg->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
return buildSimilarUnaryOpNode(argsubst, datatree);
}
NodeID
UnaryOpNode::substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{
NodeID argsubst = arg->substituteExoLeadLag(subst_table, neweqs);
return buildSimilarUnaryOpNode(argsubst, datatree); return buildSimilarUnaryOpNode(argsubst, datatree);
} }
@ -2365,7 +2452,7 @@ BinaryOpNode::decreaseLeadsLags(int n) const
} }
NodeID NodeID
BinaryOpNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const BinaryOpNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
NodeID arg1subst, arg2subst; NodeID arg1subst, arg2subst;
int maxlead1 = arg1->maxEndoLead(), maxlead2 = arg2->maxEndoLead(); int maxlead1 = arg1->maxEndoLead(), maxlead2 = arg2->maxEndoLead();
@ -2378,32 +2465,40 @@ BinaryOpNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<Bi
case oPlus: case oPlus:
case oMinus: case oMinus:
case oEqual: case oEqual:
arg1subst = maxlead1 >= 2 ? arg1->substituteLeadGreaterThanTwo(subst_table, neweqs) : arg1; arg1subst = maxlead1 >= 2 ? arg1->substituteEndoLeadGreaterThanTwo(subst_table, neweqs) : arg1;
arg2subst = maxlead2 >= 2 ? arg2->substituteLeadGreaterThanTwo(subst_table, neweqs) : arg2; arg2subst = maxlead2 >= 2 ? arg2->substituteEndoLeadGreaterThanTwo(subst_table, neweqs) : arg2;
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree); return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
case oTimes: case oTimes:
case oDivide: case oDivide:
if (maxlead1 >= 2 && maxlead2 == 0) if (maxlead1 >= 2 && maxlead2 == 0)
{ {
arg1subst = arg1->substituteLeadGreaterThanTwo(subst_table, neweqs); arg1subst = arg1->substituteEndoLeadGreaterThanTwo(subst_table, neweqs);
return buildSimilarBinaryOpNode(arg1subst, arg2, datatree); return buildSimilarBinaryOpNode(arg1subst, arg2, datatree);
} }
if (maxlead1 == 0 && maxlead2 >= 2 && op_code == oTimes) if (maxlead1 == 0 && maxlead2 >= 2 && op_code == oTimes)
{ {
arg2subst = arg2->substituteLeadGreaterThanTwo(subst_table, neweqs); arg2subst = arg2->substituteEndoLeadGreaterThanTwo(subst_table, neweqs);
return buildSimilarBinaryOpNode(arg1, arg2subst, datatree); return buildSimilarBinaryOpNode(arg1, arg2subst, datatree);
} }
return createLeadAuxiliaryVarForMyself(subst_table, neweqs); return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
default: default:
return createLeadAuxiliaryVarForMyself(subst_table, neweqs); return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
} }
} }
NodeID NodeID
BinaryOpNode::substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const BinaryOpNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
NodeID arg1subst = arg1->substituteLagGreaterThanTwo(subst_table, neweqs); NodeID arg1subst = arg1->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
NodeID arg2subst = arg2->substituteLagGreaterThanTwo(subst_table, neweqs); NodeID arg2subst = arg2->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
}
NodeID
BinaryOpNode::substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{
NodeID arg1subst = arg1->substituteExoLeadLag(subst_table, neweqs);
NodeID arg2subst = arg2->substituteExoLeadLag(subst_table, neweqs);
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree); return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
} }
@ -2766,20 +2861,29 @@ TrinaryOpNode::decreaseLeadsLags(int n) const
} }
NodeID NodeID
TrinaryOpNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const TrinaryOpNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
if (maxEndoLead() < 2) if (maxEndoLead() < 2)
return const_cast<TrinaryOpNode *>(this); return const_cast<TrinaryOpNode *>(this);
else else
return createLeadAuxiliaryVarForMyself(subst_table, neweqs); return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
} }
NodeID NodeID
TrinaryOpNode::substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const TrinaryOpNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
NodeID arg1subst = arg1->substituteLagGreaterThanTwo(subst_table, neweqs); NodeID arg1subst = arg1->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
NodeID arg2subst = arg2->substituteLagGreaterThanTwo(subst_table, neweqs); NodeID arg2subst = arg2->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
NodeID arg3subst = arg3->substituteLagGreaterThanTwo(subst_table, neweqs); NodeID arg3subst = arg3->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
}
NodeID
TrinaryOpNode::substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{
NodeID arg1subst = arg1->substituteExoLeadLag(subst_table, neweqs);
NodeID arg2subst = arg2->substituteExoLeadLag(subst_table, neweqs);
NodeID arg3subst = arg3->substituteExoLeadLag(subst_table, neweqs);
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree); return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
} }
@ -2932,15 +3036,22 @@ UnknownFunctionNode::decreaseLeadsLags(int n) const
} }
NodeID NodeID
UnknownFunctionNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const UnknownFunctionNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
cerr << "UnknownFunctionNode::substituteLeadGreaterThanTwo: not implemented!" << endl; cerr << "UnknownFunctionNode::substituteEndoLeadGreaterThanTwo: not implemented!" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
NodeID NodeID
UnknownFunctionNode::substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const UnknownFunctionNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{ {
cerr << "UnknownFunctionNode::substituteLagGreaterThanTwo: not implemented!" << endl; cerr << "UnknownFunctionNode::substituteEndoLagGreaterThanTwo: not implemented!" << endl;
exit(EXIT_FAILURE);
}
NodeID
UnknownFunctionNode::substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{
cerr << "UnknownFunctionNode::substituteExoLeadLag: not implemented!" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -240,14 +240,14 @@ public:
//! Type for the substitution map used in the process of creating auxiliary vars for leads >= 2 //! Type for the substitution map used in the process of creating auxiliary vars for leads >= 2
typedef map<const ExprNode *, const VariableNode *> subst_table_t; typedef map<const ExprNode *, const VariableNode *> subst_table_t;
//! Creates auxiliary lead variables corresponding to this expression //! Creates auxiliary endo lead variables corresponding to this expression
/*! /*!
If maximum endogenous lead >= 3, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table. If maximum endogenous lead >= 3, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table.
\pre This expression is assumed to have maximum endogenous lead >= 2 \pre This expression is assumed to have maximum endogenous lead >= 2
\param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added \param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added
\return The new variable node corresponding to the current expression \return The new variable node corresponding to the current expression
*/ */
VariableNode *createLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; VariableNode *createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
//! Constructs a new expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables //! Constructs a new expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables
/*! /*!
@ -260,14 +260,21 @@ public:
\return A new equivalent expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables \return A new equivalent expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables
*/ */
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0; virtual NodeID substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
//! Constructs a new expression where endo variables with max endo lag >= 2 have been replaced by auxiliary variables //! Constructs a new expression where endo variables with max endo lag >= 2 have been replaced by auxiliary variables
/*! /*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr. \param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables. \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
*/ */
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0; virtual NodeID substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
//! Constructs a new expression where endo variables with max exo lag >= 2 or max exo lag >= 2 have been replaced by auxiliary variables
/*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
*/
virtual NodeID substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
}; };
//! Object used to compare two nodes (using their indexes) //! Object used to compare two nodes (using their indexes)
@ -300,8 +307,9 @@ public:
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables); virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
virtual int maxEndoLead() const; virtual int maxEndoLead() const;
virtual NodeID decreaseLeadsLags(int n) const; virtual NodeID decreaseLeadsLags(int n) const;
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
virtual NodeID substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
}; };
//! Symbol or variable node //! Symbol or variable node
@ -334,8 +342,9 @@ public:
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables); virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
virtual int maxEndoLead() const; virtual int maxEndoLead() const;
virtual NodeID decreaseLeadsLags(int n) const; virtual NodeID decreaseLeadsLags(int n) const;
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
virtual NodeID substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
}; };
//! Unary operator node //! Unary operator node
@ -374,10 +383,11 @@ public:
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables); virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
virtual int maxEndoLead() const; virtual int maxEndoLead() const;
virtual NodeID decreaseLeadsLags(int n) const; virtual NodeID decreaseLeadsLags(int n) const;
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
//! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and argument //! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and argument
NodeID buildSimilarUnaryOpNode(NodeID alt_arg, DataTree &alt_datatree) const; NodeID buildSimilarUnaryOpNode(NodeID alt_arg, DataTree &alt_datatree) const;
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
virtual NodeID substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
}; };
//! Binary operator node //! Binary operator node
@ -421,10 +431,11 @@ public:
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables); virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
virtual int maxEndoLead() const; virtual int maxEndoLead() const;
virtual NodeID decreaseLeadsLags(int n) const; virtual NodeID decreaseLeadsLags(int n) const;
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
//! Creates another BinaryOpNode with the same opcode, but with a possibly different datatree and arguments //! Creates another BinaryOpNode with the same opcode, but with a possibly different datatree and arguments
NodeID buildSimilarBinaryOpNode(NodeID alt_arg1, NodeID alt_arg2, DataTree &alt_datatree) const; NodeID buildSimilarBinaryOpNode(NodeID alt_arg1, NodeID alt_arg2, DataTree &alt_datatree) const;
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
virtual NodeID substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
}; };
//! Trinary operator node //! Trinary operator node
@ -462,10 +473,11 @@ public:
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables); virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
virtual int maxEndoLead() const; virtual int maxEndoLead() const;
virtual NodeID decreaseLeadsLags(int n) const; virtual NodeID decreaseLeadsLags(int n) const;
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
//! Creates another TrinaryOpNode with the same opcode, but with a possibly different datatree and arguments //! Creates another TrinaryOpNode with the same opcode, but with a possibly different datatree and arguments
NodeID buildSimilarTrinaryOpNode(NodeID alt_arg1, NodeID alt_arg2, NodeID alt_arg3, DataTree &alt_datatree) const; NodeID buildSimilarTrinaryOpNode(NodeID alt_arg1, NodeID alt_arg2, NodeID alt_arg3, DataTree &alt_datatree) const;
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
virtual NodeID substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
}; };
//! Unknown function node //! Unknown function node
@ -497,8 +509,9 @@ public:
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables); virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
virtual int maxEndoLead() const; virtual int maxEndoLead() const;
virtual NodeID decreaseLeadsLags(int n) const; virtual NodeID decreaseLeadsLags(int n) const;
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const; virtual NodeID substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
virtual NodeID substituteExoLeadLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
}; };
#endif #endif

View File

@ -141,8 +141,9 @@ ModFile::transformPass()
|| mod_file_struct.osr_present || mod_file_struct.osr_present
|| mod_file_struct.ramsey_policy_present) || mod_file_struct.ramsey_policy_present)
{ {
dynamic_model.substituteLeadGreaterThanTwo(); dynamic_model.substituteEndoLeadGreaterThanTwo();
dynamic_model.substituteLagGreaterThanTwo(); dynamic_model.substituteEndoLagGreaterThanTwo();
dynamic_model.substituteExoLeadLag();
} }
// Freeze the symbol table // Freeze the symbol table

View File

@ -192,9 +192,6 @@ ParsingDriver::add_model_variable(string *name, string *olag)
if (type == eUnknownFunction) if (type == eUnknownFunction)
error("Symbol " + *name + " is a function name unknown to Dynare. It cannot be used inside model."); error("Symbol " + *name + " is a function name unknown to Dynare. It cannot be used inside model.");
if (type == eExogenous && lag != 0 && !mod_file->block)
warning("Exogenous variable " + *name + " has lead/lag " + *olag);
if (type == eModelLocalVariable && lag != 0) if (type == eModelLocalVariable && lag != 0)
error("Model local variable " + *name + " cannot be given a lead or a lag."); error("Model local variable " + *name + " cannot be given a lead or a lag.");

View File

@ -208,9 +208,11 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
<< "M_.aux_vars(" << i+1 << ").type = " << aux_vars[i].type << ";" << endl; << "M_.aux_vars(" << i+1 << ").type = " << aux_vars[i].type << ";" << endl;
switch(aux_vars[i].type) switch(aux_vars[i].type)
{ {
case avLead: case avEndoLead:
break; break;
case avLag: case avEndoLag:
case avExoLead:
case avExoLag:
output << "M_.aux_vars(" << i+1 << ").orig_endo_index = " << getTypeSpecificID(aux_vars[i].orig_symb_id)+1 << ";" << endl output << "M_.aux_vars(" << i+1 << ").orig_endo_index = " << getTypeSpecificID(aux_vars[i].orig_symb_id)+1 << ";" << endl
<< "M_.aux_vars(" << i+1 << ").orig_lag = " << aux_vars[i].orig_lag << ";" << endl; << "M_.aux_vars(" << i+1 << ").orig_lag = " << aux_vars[i].orig_lag << ";" << endl;
break; break;
@ -219,10 +221,10 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
} }
int int
SymbolTable::addLeadAuxiliaryVar(int index) throw (FrozenException) SymbolTable::addEndoLeadAuxiliaryVar(int index) throw (FrozenException)
{ {
ostringstream varname; ostringstream varname;
varname << "AUXLEAD_" << index; varname << "AUX_ENDO_LEAD_" << index;
int symb_id; int symb_id;
try try
{ {
@ -236,17 +238,32 @@ SymbolTable::addLeadAuxiliaryVar(int index) throw (FrozenException)
AuxVarInfo avi; AuxVarInfo avi;
avi.symb_id = symb_id; avi.symb_id = symb_id;
avi.type = avLead; avi.type = avEndoLead;
aux_vars.push_back(avi); aux_vars.push_back(avi);
return symb_id; return symb_id;
} }
int int
SymbolTable::addLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException) SymbolTable::addLeadLagAuxiliaryVarInternal(aux_var_t type, int orig_symb_id, int orig_lag) throw (FrozenException)
{ {
ostringstream varname; ostringstream varname;
varname << "AUXLAG_" << orig_symb_id << "_" << -orig_lag; switch(type)
{
case avEndoLag:
varname << "AUX_ENDO_LAG_" << orig_symb_id << "_" << -orig_lag;
break;
case avExoLead:
varname << "AUX_EXO_LEAD_" << orig_symb_id << "_" << orig_lag;
break;
case avExoLag:
varname << "AUX_EXO_LAG_" << orig_symb_id << "_" << -orig_lag;
break;
default:
cerr << "Impossible case!" << endl;
exit(EXIT_FAILURE);
}
int symb_id; int symb_id;
try try
{ {
@ -260,10 +277,28 @@ SymbolTable::addLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenExc
AuxVarInfo avi; AuxVarInfo avi;
avi.symb_id = symb_id; avi.symb_id = symb_id;
avi.type = avLag; avi.type = type;
avi.orig_symb_id = orig_symb_id; avi.orig_symb_id = orig_symb_id;
avi.orig_lag = orig_lag; avi.orig_lag = orig_lag;
aux_vars.push_back(avi); aux_vars.push_back(avi);
return symb_id; return symb_id;
} }
int
SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException)
{
return addLeadLagAuxiliaryVarInternal(avEndoLag, orig_symb_id, orig_lag);
}
int
SymbolTable::addExoLeadAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException)
{
return addLeadLagAuxiliaryVarInternal(avExoLead, orig_symb_id, orig_lag);
}
int
SymbolTable::addExoLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException)
{
return addLeadLagAuxiliaryVarInternal(avExoLag, orig_symb_id, orig_lag);
}

View File

@ -32,8 +32,10 @@ using namespace std;
//! Types of auxiliary variables //! Types of auxiliary variables
enum aux_var_t enum aux_var_t
{ {
avLead = 0, //!< Substitute for leads >= 2 avEndoLead = 0, //!< Substitute for endo leads >= 2
avLag = 1 //!< Substitute for lags >= 2 avEndoLag = 1, //!< Substitute for endo lags >= 2
avExoLead = 2, //!< Substitute for exo leads >= 2
avExoLag = 3, //!< Substitute for exo lags >= 2
}; };
//! Information on some auxiliary variables //! Information on some auxiliary variables
@ -41,8 +43,8 @@ struct AuxVarInfo
{ {
int symb_id; //!< Symbol ID of the auxiliary variable int symb_id; //!< Symbol ID of the auxiliary variable
aux_var_t type; //!< Its type aux_var_t type; //!< Its type
int orig_symb_id; //!< Symbol ID of the endo of the original model represented by this aux var. Only for avLag int orig_symb_id; //!< Symbol ID of the endo of the original model represented by this aux var. Not used for avEndoLead
int orig_lag; //!< Lag of the endo of the original model represented by this aux var. Only for avLag int orig_lag; //!< Lead/lag of the endo of the original model represented by this aux var. Not used for avEndoLead
}; };
//! Stores the symbol table //! Stores the symbol table
@ -88,6 +90,7 @@ private:
vector<int> param_ids; vector<int> param_ids;
//! Information about auxiliary variables //! Information about auxiliary variables
vector<AuxVarInfo> aux_vars; vector<AuxVarInfo> aux_vars;
public: public:
SymbolTable(); SymbolTable();
//! Thrown when trying to access an unknown symbol (by name) //! Thrown when trying to access an unknown symbol (by name)
@ -132,17 +135,40 @@ public:
class NotYetFrozenException class NotYetFrozenException
{ {
}; };
private:
int addLeadLagAuxiliaryVarInternal(aux_var_t type, int orig_symb_id, int orig_lag) throw (FrozenException);
public:
//! Add a symbol //! Add a symbol
/*! Returns the symbol ID */ /*! Returns the symbol ID */
int addSymbol(const string &name, SymbolType type, const string &tex_name) throw (AlreadyDeclaredException, FrozenException); int addSymbol(const string &name, SymbolType type, const string &tex_name) throw (AlreadyDeclaredException, FrozenException);
//! Add a symbol without its TeX name (will be equal to its name) //! Add a symbol without its TeX name (will be equal to its name)
/*! Returns the symbol ID */ /*! Returns the symbol ID */
int addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException); int addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException);
//! Adds an auxiliary variable for leads >=2 //! Adds an auxiliary variable for endogenous with lead >= 2
/*! Uses the given argument to construct the variable name. /*!
Will exit the preprocessor with an error message if the variable name already declared by the user. Returns the symbol ID. */ \param[in] index Used to construct the variable name
int addLeadAuxiliaryVar(int index) throw (FrozenException); \return the symbol ID of the new symbol */
int addLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException); int addEndoLeadAuxiliaryVar(int index) throw (FrozenException);
//! Adds an auxiliary variable for endogenous with lag >= 2
/*!
\param[in] orig_symb_id symbol ID of the endogenous declared by the user that this new variable will represent
\param[in] orig_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lag)
\return the symbol ID of the new symbol */
int addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException);
//! Adds an auxiliary variable for endogenous with lead >= 1
/*!
\param[in] orig_symb_id symbol ID of the exogenous declared by the user that this new variable will represent
\param[in] orig_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lag)
\return the symbol ID of the new symbol */
int addExoLeadAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException);
//! Adds an auxiliary variable for exogenous with lag >= 1
/*!
\param[in] orig_symb_id symbol ID of the exogenous declared by the user that this new variable will represent
\param[in] orig_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lag)
\return the symbol ID of the new symbol */
int addExoLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException);
//! Tests if symbol already exists //! Tests if symbol already exists
inline bool exists(const string &name) const; inline bool exists(const string &name) const;
//! Get symbol name (by ID) //! Get symbol name (by ID)