dynare/dynare++/src/forw_subst_builder.cpp

126 lines
4.2 KiB
C++

// Copyright (C) 2006-2011, Ondra Kamenik
#include "forw_subst_builder.h"
using namespace ogdyn;
ForwSubstBuilder::ForwSubstBuilder(DynareModel& m)
: model(m)
{
info.num_new_terms -= model.getParser().getTree().get_num_op();
// go through all equations
int neq = model.eqs.nformulas();
for (int i = 0; i < neq; i++) {
int ft = model.eqs.formula(i);
int mlead, mlag;
model.termspan(ft, mlead, mlag);
// if equation is too forward looking
if (mlead > 1) {
info.num_affected_equations++;
// break it to non-linear terms
unordered_set<int> nlt = model.get_nonlinear_subterms(ft);
int j = 0; // indexes subterms
// and make substitutions for all these non-linear subterms
for (unordered_set<int>::const_iterator it = nlt.begin();
it != nlt.end(); ++it, ++j)
substitute_for_term(*it, i, j);
}
}
// unassign all variables with lead greater than 1
unassign_gt_1_leads();
// forget the derivatives in the tree because some variables could
// have been unassigned
model.eqs.getTree().forget_derivative_maps();
info.num_new_terms += model.getParser().getTree().get_num_op();
}
void ForwSubstBuilder::substitute_for_term(int t, int i, int j)
{
int mlead, mlag;
model.termspan(t, mlead, mlag);
if (mlead > 1) {
info.num_subst_terms++;
// Example for comments: let t = f(x(+4))
// first make lagsubst be substitution setting f(x(+4)) to f(x(+1))
// this is lag = -3 (1-mlead)
map<int,int> lagsubst;
unordered_set<int> nult = model.eqs.nulary_of_term(t);// make copy of nult!
model.variable_shift_map(nult, 1-mlead, lagsubst);
int lagt = model.eqs.add_substitution(t, lagsubst);
// now maxlead of lagt is +1
// add AUXLD_*_*_1 = f(x(+1)) to the model
char name[100];
sprintf(name, "AUXLD_%d_%d_%d", i, j, 1);
model.atoms.register_uniq_endo(name);
info.num_aux_variables++;
const char* ss = model.atoms.get_name_storage().query(name);
int auxt = model.eqs.add_nulary(name);
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, auxt, lagt));
aux_map.insert(Tsubstmap::value_type(ss, lagt));
// now add variables and equations
// AUXLD_*_*_2 = AUXLD_*_*_1(+1) through
// AUXLD_*_*_{mlead-1} = AUXLD_*_*_{mlead-2}(+1)
for (int ll = 1; ll <= mlead-2; ll++) {
// create AUXLD_*_*_{ll}(+1)
sprintf(name, "AUXLD_%d_%d_%d(+1)", i, j, ll);
int lastauxt_lead = model.eqs.add_nulary(name);
// create AUXLD_*_*{ll+1}
sprintf(name, "AUXLD_%d_%d_%d", i, j, ll+1);
model.atoms.register_uniq_endo(name);
info.num_aux_variables++;
ss = model.atoms.get_name_storage().query(name);
auxt = model.eqs.add_nulary(name);
// add AUXLD_*_*_{ll+1} = AUXLD_*_*_{ll}(+1)
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, auxt, lastauxt_lead));
// add substitution to the map; todo: this
// works well because in the context where
// aux_map is used the timing doesn't matter,
// however, it is misleading, needs to be
// changed
aux_map.insert(Tsubstmap::value_type(ss, lagt));
}
// now we have to substitute AUXLD_*_*{mlead-1}(+1) for t
sprintf(name, "AUXLD_%d_%d_%d", i, j, mlead-1);
ss = model.atoms.get_name_storage().query(name);
model.substitute_atom_for_term(ss, +1, t);
}
}
void ForwSubstBuilder::unassign_gt_1_leads(const char* name)
{
const char* ss = model.atoms.get_name_storage().query(name);
int mlead, mlag;
model.atoms.varspan(name, mlead, mlag);
for (int ll = 2; ll <= mlead; ll++) {
int t = model.atoms.index(ss, ll);
if (t != -1)
model.atoms.unassign_variable(ss, ll, t);
}
}
void ForwSubstBuilder::unassign_gt_1_leads()
{
const vector<const char*>& endovars = model.atoms.get_endovars();
for (unsigned int i = 0; i < endovars.size(); i++)
unassign_gt_1_leads(endovars[i]);
const vector<const char*>& exovars = model.atoms.get_exovars();
for (unsigned int i = 0; i < exovars.size(); i++)
unassign_gt_1_leads(exovars[i]);
}
ForwSubstBuilder::ForwSubstBuilder(const ForwSubstBuilder& b, DynareModel& m)
: model(m)
{
for (Tsubstmap::const_iterator it = b.aux_map.begin();
it != b.aux_map.end(); ++it) {
const char* ss = m.atoms.get_name_storage().query((*it).first);
aux_map.insert(Tsubstmap::value_type(ss, (*it).second));
}
}