Block decomposition: factorize data structures between StaticModel and DynamicModel

issue#70
Sébastien Villemot 2020-03-17 18:58:34 +01:00
parent 7aea50b988
commit 76c2e87c3b
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
6 changed files with 118 additions and 238 deletions

View File

@ -34,55 +34,6 @@ DynamicModel::copyHelper(const DynamicModel &m)
for (const auto &it : m.static_only_equations)
static_only_equations.push_back(dynamic_cast<BinaryOpNode *>(f(it)));
auto convert_vector_tt = [f](vector<temporary_terms_t> vtt)
{
vector<temporary_terms_t> vtt2;
for (const auto &tt : vtt)
{
temporary_terms_t tt2;
for (const auto &it : tt)
tt2.insert(f(it));
vtt2.push_back(tt2);
}
return vtt2;
};
for (const auto &it : m.v_temporary_terms)
v_temporary_terms.push_back(convert_vector_tt(it));
for (const auto &it : m.first_chain_rule_derivatives)
first_chain_rule_derivatives[it.first] = f(it.second);
for (const auto &it : m.equation_type_and_normalized_equation)
equation_type_and_normalized_equation.emplace_back(it.first, f(it.second));
for (const auto &it : m.blocks_derivatives)
{
block_derivatives_equation_variable_laglead_nodeid_t v;
for (const auto &it2 : it)
v.emplace_back(get<0>(it2), get<1>(it2), get<2>(it2), f(get<3>(it2)));
blocks_derivatives.push_back(v);
}
for (const auto &it : m.dynamic_jacobian)
dynamic_jacobian[it.first] = f(it.second);
auto convert_derivative_t = [f](derivative_t dt)
{
derivative_t dt2;
for (const auto &it : dt)
dt2[it.first] = f(it.second);
return dt2;
};
for (const auto &it : m.derivative_endo)
derivative_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_other_endo)
derivative_other_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo)
derivative_exo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo_det)
derivative_exo_det.push_back(convert_derivative_t(it));
}
DynamicModel::DynamicModel(SymbolTable &symbol_table_arg,
@ -129,11 +80,7 @@ DynamicModel::DynamicModel(const DynamicModel &m) :
xref_exo{m.xref_exo},
xref_exo_det{m.xref_exo_det},
nonzero_hessian_eqs{m.nonzero_hessian_eqs},
v_temporary_terms_inuse{m.v_temporary_terms_inuse},
map_idx{m.map_idx},
global_temporary_terms{m.global_temporary_terms},
block_type_firstequation_size_mfs{m.block_type_firstequation_size_mfs},
blocks_linear{m.blocks_linear},
other_endo_block{m.other_endo_block},
exo_block{m.exo_block},
exo_det_block{m.exo_det_block},
@ -141,15 +88,9 @@ DynamicModel::DynamicModel(const DynamicModel &m) :
block_exo_index{m.block_exo_index},
block_det_exo_index{m.block_det_exo_index},
block_other_endo_index{m.block_other_endo_index},
block_col_type{m.block_col_type},
variable_block_lead_lag{m.variable_block_lead_lag},
equation_block{m.equation_block},
var_expectation_functions_to_write{m.var_expectation_functions_to_write},
endo_max_leadlag_block{m.endo_max_leadlag_block},
other_endo_max_leadlag_block{m.other_endo_max_leadlag_block},
exo_max_leadlag_block{m.exo_max_leadlag_block},
exo_det_max_leadlag_block{m.exo_det_max_leadlag_block},
max_leadlag_block{m.max_leadlag_block}
var_expectation_functions_to_write{m.var_expectation_functions_to_write}
{
copyHelper(m);
}
@ -192,29 +133,8 @@ DynamicModel::operator=(const DynamicModel &m)
xref_exo_det = m.xref_exo_det;
nonzero_hessian_eqs = m.nonzero_hessian_eqs;
v_temporary_terms.clear();
v_temporary_terms_inuse = m.v_temporary_terms_inuse;
first_chain_rule_derivatives.clear();
map_idx = m.map_idx;
global_temporary_terms = m.global_temporary_terms;
equation_type_and_normalized_equation.clear();
block_type_firstequation_size_mfs = m.block_type_firstequation_size_mfs;
blocks_derivatives.clear();
dynamic_jacobian.clear();
blocks_linear = m.blocks_linear;
derivative_endo.clear();
derivative_other_endo.clear();
derivative_exo.clear();
derivative_exo_det.clear();
other_endo_block = m.other_endo_block;
exo_block = m.exo_block;
exo_det_block = m.exo_det_block;
@ -222,17 +142,10 @@ DynamicModel::operator=(const DynamicModel &m)
block_exo_index = m.block_exo_index;
block_det_exo_index = m.block_det_exo_index;
block_other_endo_index = m.block_other_endo_index;
block_col_type = m.block_col_type;
variable_block_lead_lag = m.variable_block_lead_lag;
equation_block = m.equation_block;
var_expectation_functions_to_write = m.var_expectation_functions_to_write;
endo_max_leadlag_block = m.endo_max_leadlag_block;
other_endo_max_leadlag_block = m.other_endo_max_leadlag_block;
exo_max_leadlag_block = m.exo_max_leadlag_block;
exo_det_max_leadlag_block = m.exo_det_max_leadlag_block;
max_leadlag_block = m.max_leadlag_block;
copyHelper(m);
return *this;

View File

@ -100,18 +100,10 @@ private:
//! Number of columns of dynamic jacobian
/*! Set by computeDerivID()s and computeDynJacobianCols() */
int dynJacobianColsNbr{0};
//! Temporary terms for block decomposed models
vector<vector<temporary_terms_t>> v_temporary_terms;
vector<temporary_terms_inuse_t> v_temporary_terms_inuse;
//! Creates mapping for variables and equations they are present in
map<int, set<int>> variableMapping;
//! Store the derivatives or the chainrule derivatives:map<tuple<equation, variable, lead_lag>, expr_t>
using first_chain_rule_derivatives_t = map<tuple<int, int, int>, expr_t>;
first_chain_rule_derivatives_t first_chain_rule_derivatives;
//! Writes dynamic model file (Matlab version)
void writeDynamicMFile(const string &basename) const;
//! Writes dynamic model file (Julia version)
@ -149,7 +141,6 @@ private:
void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives);
string reform(const string &name) const;
map_idx_t map_idx;
//! sorts the temporary terms in the blocks order
void computeTemporaryTermsOrdered();
@ -194,26 +185,6 @@ private:
//! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
bool global_temporary_terms{true};
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
//! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size >>
block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
//! for all blocks derivatives description
blocks_derivatives_t blocks_derivatives;
//! The jacobian without the elements below the cutoff
dynamic_jacob_map_t dynamic_jacobian;
//! Vector indicating if the block is linear in endogenous variable (true) or not (false)
vector<bool> blocks_linear;
//! Map the derivatives for a block tuple<lag, eq, var>
using derivative_t = map<tuple<int, int, int>, expr_t>;
//! Vector of derivative for each blocks
vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det;
//!List for each block and for each lag-lead all the other endogenous variables and exogenous variables
using var_t = set<int>;
using lag_var_t = map<int, var_t>;
@ -224,10 +195,6 @@ private:
map< int, map<int, int>> block_exo_index, block_det_exo_index, block_other_endo_index;
//! for each block described the number of static, forward, backward and mixed variables in the block
/*! tuple<static, forward, backward, mixed> */
vector<tuple<int, int, int, int>> block_col_type;
//! Help computeXrefs to compute the reverse references (i.e. param->eqs, endo->eqs, etc)
void computeRevXref(map<pair<int, int>, set<int>> &xrefset, const set<pair<int, int>> &eiref, int eqn);
@ -242,9 +209,6 @@ private:
//! Used for var_expectation and var_model
map<string, set<int>> var_expectation_functions_to_write;
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
vector<pair<int, int>> endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
void writeWrapperFunctions(const string &name, const string &ending) const;
void writeDynamicModelHelper(const string &basename,
const string &name, const string &retvalname,

View File

@ -39,6 +39,18 @@ void
ModelTree::copyHelper(const ModelTree &m)
{
auto f = [this](expr_t e) { return e->clone(*this); };
auto convert_vector_tt = [f](vector<temporary_terms_t> vtt)
{
vector<temporary_terms_t> vtt2;
for (const auto &tt : vtt)
{
temporary_terms_t tt2;
for (const auto &it : tt)
tt2.insert(f(it));
vtt2.push_back(tt2);
}
return vtt2;
};
// Equations
for (const auto &it : m.equations)
@ -77,6 +89,8 @@ ModelTree::copyHelper(const ModelTree &m)
temporary_terms_derivatives.push_back(convert_temporary_terms_t(it));
for (const auto &it : m.temporary_terms_idxs)
temporary_terms_idxs[f(it.first)] = it.second;
for (const auto &it : m.v_temporary_terms)
v_temporary_terms.push_back(convert_vector_tt(it));
for (const auto &it : m.params_derivs_temporary_terms)
params_derivs_temporary_terms[it.first] = convert_temporary_terms_t(it.second);
for (const auto &it : m.params_derivs_temporary_terms_idxs)
@ -87,6 +101,37 @@ ModelTree::copyHelper(const ModelTree &m)
trend_symbols_map[it.first] = f(it.second);
for (const auto &it : m.nonstationary_symbols_map)
nonstationary_symbols_map[it.first] = {it.second.first, f(it.second.second)};
for (const auto &it : m.dynamic_jacobian)
dynamic_jacobian[it.first] = f(it.second);
for (const auto &it : m.first_chain_rule_derivatives)
first_chain_rule_derivatives[it.first] = f(it.second);
for (const auto &it : m.equation_type_and_normalized_equation)
equation_type_and_normalized_equation.emplace_back(it.first, f(it.second));
for (const auto &it : m.blocks_derivatives)
{
block_derivatives_equation_variable_laglead_nodeid_t v;
for (const auto &it2 : it)
v.emplace_back(get<0>(it2), get<1>(it2), get<2>(it2), f(get<3>(it2)));
blocks_derivatives.push_back(v);
}
auto convert_derivative_t = [f](derivative_t dt)
{
derivative_t dt2;
for (const auto &it : dt)
dt2[it.first] = f(it.second);
return dt2;
};
for (const auto &it : m.derivative_endo)
derivative_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_other_endo)
derivative_other_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo)
derivative_exo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo_det)
derivative_exo_det.push_back(convert_derivative_t(it));
}
ModelTree::ModelTree(SymbolTable &symbol_table_arg,
@ -111,10 +156,20 @@ ModelTree::ModelTree(const ModelTree &m) :
equation_tags{m.equation_tags},
computed_derivs_order{m.computed_derivs_order},
NNZDerivatives{m.NNZDerivatives},
v_temporary_terms_inuse{m.v_temporary_terms_inuse},
equation_reordered{m.equation_reordered},
variable_reordered{m.variable_reordered},
inv_equation_reordered{m.inv_equation_reordered},
inv_variable_reordered{m.inv_variable_reordered},
map_idx{m.map_idx},
block_type_firstequation_size_mfs{m.block_type_firstequation_size_mfs},
blocks_linear{m.blocks_linear},
block_col_type{m.block_col_type},
endo_max_leadlag_block{m.endo_max_leadlag_block},
other_endo_max_leadlag_block{m.other_endo_max_leadlag_block},
exo_max_leadlag_block{m.exo_max_leadlag_block},
exo_det_max_leadlag_block{m.exo_det_max_leadlag_block},
max_leadlag_block{m.max_leadlag_block},
is_equation_linear{m.is_equation_linear},
endo2eq{m.endo2eq},
epilogue{m.epilogue},
@ -144,16 +199,36 @@ ModelTree::operator=(const ModelTree &m)
temporary_terms.clear();
temporary_terms_mlv.clear();
temporary_terms_derivatives.clear();
v_temporary_terms.clear();
v_temporary_terms_inuse = m.v_temporary_terms_inuse;
params_derivs_temporary_terms.clear();
params_derivs_temporary_terms_idxs.clear();
trend_symbols_map.clear();
nonstationary_symbols_map.clear();
dynamic_jacobian.clear();
equation_reordered = m.equation_reordered;
variable_reordered = m.variable_reordered;
inv_equation_reordered = m.inv_equation_reordered;
inv_variable_reordered = m.inv_variable_reordered;
first_chain_rule_derivatives.clear();
map_idx = m.map_idx;
equation_type_and_normalized_equation.clear();
block_type_firstequation_size_mfs = m.block_type_firstequation_size_mfs;
blocks_derivatives.clear();
blocks_linear = m.blocks_linear;
derivative_endo.clear();
derivative_other_endo.clear();
derivative_exo.clear();
derivative_exo_det.clear();
block_col_type = m.block_col_type;
endo_max_leadlag_block = m.endo_max_leadlag_block;
other_endo_max_leadlag_block = m.other_endo_max_leadlag_block;
exo_max_leadlag_block = m.exo_max_leadlag_block;
exo_det_max_leadlag_block = m.exo_det_max_leadlag_block;
max_leadlag_block = m.max_leadlag_block;
is_equation_linear = m.is_equation_linear;
endo2eq = m.endo2eq;
epilogue = m.epilogue;

View File

@ -144,6 +144,10 @@ protected:
//! Stores, for each temporary term, its index in the MATLAB/Julia vector
temporary_terms_idxs_t temporary_terms_idxs;
//! Temporary terms for block decomposed models
vector<vector<temporary_terms_t>> v_temporary_terms;
vector<temporary_terms_inuse_t> v_temporary_terms_inuse;
//! Temporary terms for parameter derivatives, under a disaggregated form
/*! The pair of integers is to be interpreted as in param_derivatives */
map<pair<int, int>, temporary_terms_t> params_derivs_temporary_terms;
@ -160,9 +164,46 @@ protected:
//! Nonstationary variables and their deflators
nonstationary_symbols_map_t nonstationary_symbols_map;
//! Sparse matrix of double to store the values of the Jacobian
/*! First index is lag, second index is equation number, third index is endogenous type specific ID */
using dynamic_jacob_map_t = map<tuple<int, int, int>, expr_t>;
//! The jacobian without the elements below the cutoff
dynamic_jacob_map_t dynamic_jacobian;
//! vector of block reordered variables and equations
vector<int> equation_reordered, variable_reordered, inv_equation_reordered, inv_variable_reordered;
//! Store the derivatives or the chainrule derivatives:map<tuple<equation, variable, lead_lag>, expr_t>
using first_chain_rule_derivatives_t = map<tuple<int, int, int>, expr_t>;
first_chain_rule_derivatives_t first_chain_rule_derivatives;
map_idx_t map_idx;
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
//! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size >>
block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
//! for all blocks derivatives description
blocks_derivatives_t blocks_derivatives;
//! Vector indicating if the block is linear in endogenous variable (true) or not (false)
vector<bool> blocks_linear;
//! Map the derivatives for a block tuple<lag, eq, var>
using derivative_t = map<tuple<int, int, int>, expr_t>;
//! Vector of derivative for each blocks
vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det;
//! for each block described the number of static, forward, backward and mixed variables in the block
/*! tuple<static, forward, backward, mixed> */
vector<tuple<int, int, int, int>> block_col_type;
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
vector<pair<int, int>> endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
//! the file containing the model and the derivatives code
ofstream code_file;
@ -215,10 +256,6 @@ protected:
/*! First index is equation number, second index is endogenous type specific ID */
using jacob_map_t = map<pair<int, int>, double>;
//! Sparse matrix of double to store the values of the Jacobian
/*! First index is lag, second index is equation number, third index is endogenous type specific ID */
using dynamic_jacob_map_t = map<tuple<int, int, int>, expr_t>;
//! Normalization of equations
/*! Maps endogenous type specific IDs to equation numbers */
vector<int> endo2eq;

View File

@ -44,43 +44,9 @@ StaticModel::copyHelper(const StaticModel &m)
return vtt2;
};
for (const auto &it : m.v_temporary_terms)
v_temporary_terms.push_back(convert_vector_tt(it));
for (const auto &it : m.v_temporary_terms_local)
v_temporary_terms_local.push_back(convert_vector_tt(it));
for (const auto &it : m.first_chain_rule_derivatives)
first_chain_rule_derivatives[it.first] = f(it.second);
for (const auto &it : m.equation_type_and_normalized_equation)
equation_type_and_normalized_equation.emplace_back(it.first, f(it.second));
for (const auto &it : m.blocks_derivatives)
{
block_derivatives_equation_variable_laglead_nodeid_t v;
for (const auto &it2 : it)
v.emplace_back(get<0>(it2), get<1>(it2), get<2>(it2), f(get<3>(it2)));
blocks_derivatives.push_back(v);
}
for (const auto &it : m.dynamic_jacobian)
dynamic_jacobian[it.first] = f(it.second);
auto convert_derivative_t = [f](derivative_t dt)
{
derivative_t dt2;
for (const auto &it : dt)
dt2[it.first] = f(it.second);
return dt2;
};
for (const auto &it : m.derivative_endo)
derivative_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_other_endo)
derivative_other_endo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo)
derivative_exo.push_back(convert_derivative_t(it));
for (const auto &it : m.derivative_exo_det)
derivative_exo_det.push_back(convert_derivative_t(it));
}
StaticModel::StaticModel(SymbolTable &symbol_table_arg,
@ -92,18 +58,8 @@ StaticModel::StaticModel(SymbolTable &symbol_table_arg,
StaticModel::StaticModel(const StaticModel &m) :
ModelTree{m},
v_temporary_terms_inuse{m.v_temporary_terms_inuse},
map_idx{m.map_idx},
map_idx2{m.map_idx2},
global_temporary_terms{m.global_temporary_terms},
block_type_firstequation_size_mfs{m.block_type_firstequation_size_mfs},
blocks_linear{m.blocks_linear},
block_col_type{m.block_col_type},
endo_max_leadlag_block{m.endo_max_leadlag_block},
other_endo_max_leadlag_block{m.other_endo_max_leadlag_block},
exo_max_leadlag_block{m.exo_max_leadlag_block},
exo_det_max_leadlag_block{m.exo_det_max_leadlag_block},
max_leadlag_block{m.max_leadlag_block}
global_temporary_terms{m.global_temporary_terms}
{
copyHelper(m);
}
@ -113,38 +69,10 @@ StaticModel::operator=(const StaticModel &m)
{
ModelTree::operator=(m);
v_temporary_terms.clear();
v_temporary_terms_local.clear();
v_temporary_terms_inuse = m.v_temporary_terms_inuse;
first_chain_rule_derivatives.clear();
map_idx = m.map_idx;
map_idx2 = m.map_idx2;
global_temporary_terms = m.global_temporary_terms;
equation_type_and_normalized_equation.clear();
block_type_firstequation_size_mfs = m.block_type_firstequation_size_mfs;
blocks_derivatives.clear();
dynamic_jacobian.clear();
blocks_linear = m.blocks_linear;
derivative_endo.clear();
derivative_other_endo.clear();
derivative_exo.clear();
derivative_exo_det.clear();
block_col_type = m.block_col_type;
endo_max_leadlag_block = m.endo_max_leadlag_block;
other_endo_max_leadlag_block = m.other_endo_max_leadlag_block;
exo_max_leadlag_block = m.exo_max_leadlag_block;
exo_det_max_leadlag_block = m.exo_det_max_leadlag_block;
max_leadlag_block = m.max_leadlag_block;
copyHelper(m);
return *this;

View File

@ -33,17 +33,9 @@ class DynamicModel;
class StaticModel : public ModelTree
{
private:
//! global temporary terms for block decomposed models
vector<vector<temporary_terms_t>> v_temporary_terms;
//! local temporary terms for block decomposed models
vector<vector<temporary_terms_t>> v_temporary_terms_local;
vector<temporary_terms_inuse_t> v_temporary_terms_inuse;
using first_chain_rule_derivatives_t = map<tuple<int, int, int>, expr_t>;
first_chain_rule_derivatives_t first_chain_rule_derivatives;
//! Writes static model file (standard Matlab version)
void writeStaticMFile(const string &basename) const;
@ -75,8 +67,6 @@ private:
*/
void evaluateJacobian(const eval_context_t &eval_context, jacob_map_t *j_m, bool dynamic);
map_idx_t map_idx;
vector<map_idx_t> map_idx2;
//! sorts the temporary terms in the blocks order
@ -110,37 +100,10 @@ private:
//! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
bool global_temporary_terms{true};
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
//! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size >>
block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
//! for all blocks derivatives description
blocks_derivatives_t blocks_derivatives;
//! The jacobian without the elements below the cutoff
dynamic_jacob_map_t dynamic_jacobian;
//! Vector indicating if the block is linear in endogenous variable (true) or not (false)
vector<bool> blocks_linear;
//! Map the derivatives for a block tuple<lag, eq, var>
using derivative_t = map<tuple<int, int, int>, expr_t>;
//! Vector of derivative for each blocks
vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det;
//!List for each block and for each lag-leag all the other endogenous variables and exogenous variables
using var_t = set<int>;
using lag_var_t = map<int, var_t>;
//! for each block described the number of static, forward, backward and mixed variables in the block
/*! tuple<static, forward, backward, mixed> */
vector<tuple<int, int, int, int>> block_col_type;
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
vector<pair<int, int>> endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
//! Helper functions for writeStaticModel
void writeStaticModelHelper(const string &basename,
const string &name, const string &retvalname,