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-bf33cf982152time-shift
parent
f7d69ff58c
commit
c84df1aace
|
@ -2831,37 +2831,25 @@ DynamicModel::hessianHelper(ostream &output, int row_nb, int col_nb, ExprNodeOut
|
|||
}
|
||||
|
||||
void
|
||||
DynamicModel::substituteLeadGreaterThanTwo()
|
||||
DynamicModel::substituteEndoLeadGreaterThanTwo()
|
||||
{
|
||||
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->substituteLeadGreaterThanTwo(subst_table, neweqs);
|
||||
|
||||
// Substitute in equations
|
||||
for(int i = 0; i < (int) equations.size(); i++)
|
||||
{
|
||||
BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(equations[i]->substituteLeadGreaterThanTwo(subst_table, neweqs));
|
||||
assert(substeq != NULL);
|
||||
equations[i] = substeq;
|
||||
}
|
||||
|
||||
// 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 leads >= 2: added " << neweqs.size() << " auxiliary variables and equations." << endl;
|
||||
substituteLeadLagInternal(0);
|
||||
}
|
||||
|
||||
void
|
||||
DynamicModel::substituteLagGreaterThanTwo()
|
||||
DynamicModel::substituteEndoLagGreaterThanTwo()
|
||||
{
|
||||
substituteLeadLagInternal(1);
|
||||
}
|
||||
|
||||
void
|
||||
DynamicModel::substituteExoLeadLag()
|
||||
{
|
||||
substituteLeadLagInternal(2);
|
||||
}
|
||||
|
||||
void
|
||||
DynamicModel::substituteLeadLagInternal(int vars)
|
||||
{
|
||||
ExprNode::subst_table_t subst_table;
|
||||
vector<BinaryOpNode *> neweqs;
|
||||
|
@ -2869,12 +2857,40 @@ DynamicModel::substituteLagGreaterThanTwo()
|
|||
// 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);
|
||||
{
|
||||
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
|
||||
for(int i = 0; i < (int) equations.size(); i++)
|
||||
{
|
||||
BinaryOpNode *substeq = dynamic_cast<BinaryOpNode *>(equations[i]->substituteLagGreaterThanTwo(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);
|
||||
equations[i] = substeq;
|
||||
}
|
||||
|
@ -2887,7 +2903,22 @@ DynamicModel::substituteLagGreaterThanTwo()
|
|||
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;
|
||||
{
|
||||
cout << "Substitution of ";
|
||||
switch(vars)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -144,6 +144,9 @@ private:
|
|||
//! 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;
|
||||
|
||||
//! 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:
|
||||
DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants);
|
||||
|
@ -199,11 +202,14 @@ public:
|
|||
//! Returns true indicating that this is a dynamic model
|
||||
virtual bool isDynamic() const { return true; };
|
||||
|
||||
//! Transforms the model by removing all leads greater or equal than 2
|
||||
void substituteLeadGreaterThanTwo();
|
||||
//! Transforms the model by removing all leads greater or equal than 2 on endos
|
||||
void substituteEndoLeadGreaterThanTwo();
|
||||
|
||||
//! Transforms the model by removing all lags greater or equal than 2
|
||||
void substituteLagGreaterThanTwo();
|
||||
//! Transforms the model by removing all lags greater or equal than 2 on endos
|
||||
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
|
||||
void fillEvalContext(eval_context_type &eval_context) const;
|
||||
|
|
|
@ -148,7 +148,7 @@ ExprNode::writeOutput(ostream &output)
|
|||
}
|
||||
|
||||
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();
|
||||
assert(n >= 2);
|
||||
|
@ -168,7 +168,7 @@ ExprNode::createLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<Bin
|
|||
it = subst_table.find(orig_expr);
|
||||
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)));
|
||||
substexpr = datatree.AddVariable(symb_id, +1);
|
||||
assert(dynamic_cast<VariableNode *>(substexpr) != NULL);
|
||||
|
@ -278,13 +278,19 @@ NumConstNode::decreaseLeadsLags(int n) const
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -766,7 +772,7 @@ VariableNode::decreaseLeadsLags(int n) const
|
|||
}
|
||||
|
||||
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;
|
||||
switch(type)
|
||||
|
@ -775,20 +781,20 @@ VariableNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<Bi
|
|||
if (lag <= 1)
|
||||
return const_cast<VariableNode *>(this);
|
||||
else
|
||||
return createLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
case eModelLocalVariable:
|
||||
value = datatree.local_variables_table[symb_id];
|
||||
if (value->maxEndoLead() <= 1)
|
||||
return const_cast<VariableNode *>(this);
|
||||
else
|
||||
return value->substituteLeadGreaterThanTwo(subst_table, neweqs);
|
||||
return value->substituteEndoLeadGreaterThanTwo(subst_table, neweqs);
|
||||
default:
|
||||
return const_cast<VariableNode *>(this);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
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)));
|
||||
substexpr = datatree.AddVariable(aux_symb_id, -1);
|
||||
subst_table[orig_expr] = substexpr;
|
||||
|
@ -827,7 +833,81 @@ VariableNode::substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<Bin
|
|||
return substexpr;
|
||||
|
||||
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:
|
||||
return const_cast<VariableNode *>(this);
|
||||
}
|
||||
|
@ -1471,26 +1551,33 @@ UnaryOpNode::decreaseLeadsLags(int n) const
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
NodeID argsubst = arg->substituteLeadGreaterThanTwo(subst_table, neweqs);
|
||||
NodeID argsubst = arg->substituteEndoLeadGreaterThanTwo(subst_table, neweqs);
|
||||
return buildSimilarUnaryOpNode(argsubst, datatree);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (maxEndoLead() >= 2)
|
||||
return createLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
else
|
||||
return const_cast<UnaryOpNode *>(this);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2365,7 +2452,7 @@ BinaryOpNode::decreaseLeadsLags(int n) const
|
|||
}
|
||||
|
||||
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;
|
||||
int maxlead1 = arg1->maxEndoLead(), maxlead2 = arg2->maxEndoLead();
|
||||
|
@ -2378,32 +2465,40 @@ BinaryOpNode::substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<Bi
|
|||
case oPlus:
|
||||
case oMinus:
|
||||
case oEqual:
|
||||
arg1subst = maxlead1 >= 2 ? arg1->substituteLeadGreaterThanTwo(subst_table, neweqs) : arg1;
|
||||
arg2subst = maxlead2 >= 2 ? arg2->substituteLeadGreaterThanTwo(subst_table, neweqs) : arg2;
|
||||
arg1subst = maxlead1 >= 2 ? arg1->substituteEndoLeadGreaterThanTwo(subst_table, neweqs) : arg1;
|
||||
arg2subst = maxlead2 >= 2 ? arg2->substituteEndoLeadGreaterThanTwo(subst_table, neweqs) : arg2;
|
||||
return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
|
||||
case oTimes:
|
||||
case oDivide:
|
||||
if (maxlead1 >= 2 && maxlead2 == 0)
|
||||
{
|
||||
arg1subst = arg1->substituteLeadGreaterThanTwo(subst_table, neweqs);
|
||||
arg1subst = arg1->substituteEndoLeadGreaterThanTwo(subst_table, neweqs);
|
||||
return buildSimilarBinaryOpNode(arg1subst, arg2, datatree);
|
||||
}
|
||||
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 createLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
default:
|
||||
return createLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
}
|
||||
}
|
||||
|
||||
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 arg2subst = arg2->substituteLagGreaterThanTwo(subst_table, neweqs);
|
||||
NodeID arg1subst = arg1->substituteEndoLagGreaterThanTwo(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);
|
||||
}
|
||||
|
||||
|
@ -2766,20 +2861,29 @@ TrinaryOpNode::decreaseLeadsLags(int n) const
|
|||
}
|
||||
|
||||
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)
|
||||
return const_cast<TrinaryOpNode *>(this);
|
||||
else
|
||||
return createLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs);
|
||||
}
|
||||
|
||||
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 arg2subst = arg2->substituteLagGreaterThanTwo(subst_table, neweqs);
|
||||
NodeID arg3subst = arg3->substituteLagGreaterThanTwo(subst_table, neweqs);
|
||||
NodeID arg1subst = arg1->substituteEndoLagGreaterThanTwo(subst_table, neweqs);
|
||||
NodeID arg2subst = arg2->substituteEndoLagGreaterThanTwo(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);
|
||||
}
|
||||
|
||||
|
@ -2932,15 +3036,22 @@ UnknownFunctionNode::decreaseLeadsLags(int n) const
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -240,14 +240,14 @@ public:
|
|||
//! 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;
|
||||
|
||||
//! 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.
|
||||
\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
|
||||
\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
|
||||
/*!
|
||||
|
@ -260,14 +260,21 @@ public:
|
|||
|
||||
\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
|
||||
/*!
|
||||
\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 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)
|
||||
|
@ -300,8 +307,9 @@ public:
|
|||
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
|
||||
virtual int maxEndoLead() const;
|
||||
virtual NodeID decreaseLeadsLags(int n) const;
|
||||
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||
virtual NodeID substituteEndoLeadGreaterThanTwo(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
|
||||
|
@ -334,8 +342,9 @@ public:
|
|||
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
|
||||
virtual int maxEndoLead() const;
|
||||
virtual NodeID decreaseLeadsLags(int n) const;
|
||||
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||
virtual NodeID substituteEndoLeadGreaterThanTwo(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
|
||||
|
@ -374,10 +383,11 @@ public:
|
|||
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
|
||||
virtual int maxEndoLead() 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
|
||||
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
|
||||
|
@ -421,10 +431,11 @@ public:
|
|||
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
|
||||
virtual int maxEndoLead() 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
|
||||
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
|
||||
|
@ -462,10 +473,11 @@ public:
|
|||
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
|
||||
virtual int maxEndoLead() 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
|
||||
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
|
||||
|
@ -497,8 +509,9 @@ public:
|
|||
virtual NodeID getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables);
|
||||
virtual int maxEndoLead() const;
|
||||
virtual NodeID decreaseLeadsLags(int n) const;
|
||||
virtual NodeID substituteLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||
virtual NodeID substituteLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||
virtual NodeID substituteEndoLeadGreaterThanTwo(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
|
||||
|
|
|
@ -141,8 +141,9 @@ ModFile::transformPass()
|
|||
|| mod_file_struct.osr_present
|
||||
|| mod_file_struct.ramsey_policy_present)
|
||||
{
|
||||
dynamic_model.substituteLeadGreaterThanTwo();
|
||||
dynamic_model.substituteLagGreaterThanTwo();
|
||||
dynamic_model.substituteEndoLeadGreaterThanTwo();
|
||||
dynamic_model.substituteEndoLagGreaterThanTwo();
|
||||
dynamic_model.substituteExoLeadLag();
|
||||
}
|
||||
|
||||
// Freeze the symbol table
|
||||
|
|
|
@ -192,9 +192,6 @@ ParsingDriver::add_model_variable(string *name, string *olag)
|
|||
if (type == eUnknownFunction)
|
||||
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)
|
||||
error("Model local variable " + *name + " cannot be given a lead or a lag.");
|
||||
|
||||
|
|
|
@ -208,9 +208,11 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
|
|||
<< "M_.aux_vars(" << i+1 << ").type = " << aux_vars[i].type << ";" << endl;
|
||||
switch(aux_vars[i].type)
|
||||
{
|
||||
case avLead:
|
||||
case avEndoLead:
|
||||
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
|
||||
<< "M_.aux_vars(" << i+1 << ").orig_lag = " << aux_vars[i].orig_lag << ";" << endl;
|
||||
break;
|
||||
|
@ -219,10 +221,10 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
|
|||
}
|
||||
|
||||
int
|
||||
SymbolTable::addLeadAuxiliaryVar(int index) throw (FrozenException)
|
||||
SymbolTable::addEndoLeadAuxiliaryVar(int index) throw (FrozenException)
|
||||
{
|
||||
ostringstream varname;
|
||||
varname << "AUXLEAD_" << index;
|
||||
varname << "AUX_ENDO_LEAD_" << index;
|
||||
int symb_id;
|
||||
try
|
||||
{
|
||||
|
@ -236,17 +238,32 @@ SymbolTable::addLeadAuxiliaryVar(int index) throw (FrozenException)
|
|||
|
||||
AuxVarInfo avi;
|
||||
avi.symb_id = symb_id;
|
||||
avi.type = avLead;
|
||||
avi.type = avEndoLead;
|
||||
aux_vars.push_back(avi);
|
||||
|
||||
return symb_id;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
try
|
||||
{
|
||||
|
@ -260,10 +277,28 @@ SymbolTable::addLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenExc
|
|||
|
||||
AuxVarInfo avi;
|
||||
avi.symb_id = symb_id;
|
||||
avi.type = avLag;
|
||||
avi.type = type;
|
||||
avi.orig_symb_id = orig_symb_id;
|
||||
avi.orig_lag = orig_lag;
|
||||
aux_vars.push_back(avi);
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,10 @@ using namespace std;
|
|||
//! Types of auxiliary variables
|
||||
enum aux_var_t
|
||||
{
|
||||
avLead = 0, //!< Substitute for leads >= 2
|
||||
avLag = 1 //!< Substitute for lags >= 2
|
||||
avEndoLead = 0, //!< Substitute for endo leads >= 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
|
||||
|
@ -41,8 +43,8 @@ struct AuxVarInfo
|
|||
{
|
||||
int symb_id; //!< Symbol ID of the auxiliary variable
|
||||
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_lag; //!< Lag 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; //!< Lead/lag of the endo of the original model represented by this aux var. Not used for avEndoLead
|
||||
};
|
||||
|
||||
//! Stores the symbol table
|
||||
|
@ -88,6 +90,7 @@ private:
|
|||
vector<int> param_ids;
|
||||
//! Information about auxiliary variables
|
||||
vector<AuxVarInfo> aux_vars;
|
||||
|
||||
public:
|
||||
SymbolTable();
|
||||
//! Thrown when trying to access an unknown symbol (by name)
|
||||
|
@ -132,17 +135,40 @@ public:
|
|||
class NotYetFrozenException
|
||||
{
|
||||
};
|
||||
|
||||
private:
|
||||
int addLeadLagAuxiliaryVarInternal(aux_var_t type, int orig_symb_id, int orig_lag) throw (FrozenException);
|
||||
|
||||
public:
|
||||
//! Add a symbol
|
||||
/*! Returns the symbol ID */
|
||||
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)
|
||||
/*! Returns the symbol ID */
|
||||
int addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException);
|
||||
//! Adds an auxiliary variable for leads >=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. */
|
||||
int addLeadAuxiliaryVar(int index) throw (FrozenException);
|
||||
int addLagAuxiliaryVar(int orig_symb_id, int orig_lag) throw (FrozenException);
|
||||
//! Adds an auxiliary variable for endogenous with lead >= 2
|
||||
/*!
|
||||
\param[in] index Used to construct the variable name
|
||||
\return the symbol ID of the new symbol */
|
||||
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
|
||||
inline bool exists(const string &name) const;
|
||||
//! Get symbol name (by ID)
|
||||
|
|
Loading…
Reference in New Issue