Block decomposition: reorganize data structures storing block information

issue#70
Sébastien Villemot 2020-04-21 18:10:46 +02:00
parent 8eafd9ab4f
commit 118ceab85b
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
4 changed files with 221 additions and 254 deletions

View File

@ -1249,7 +1249,7 @@ DynamicModel::writeModelEquationsCode_Block(const string &basename, const map_id
block_size, block_size,
endo_idx_block2orig, endo_idx_block2orig,
eq_idx_block2orig, eq_idx_block2orig,
blocks_linear[block], blocks[block].linear,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
block_max_lag, block_max_lag,
block_max_lead, block_max_lead,
@ -2083,7 +2083,7 @@ DynamicModel::writeSparseDynamicMFile(const string &basename) const
<< " end;" << endl << " end;" << endl
<< " y = solve_one_boundary('" << basename << ".block.dynamic_" << block + 1 << "'" << " y = solve_one_boundary('" << basename << ".block.dynamic_" << block + 1 << "'"
<< ", y, x, params, steady_state, y_index, " << nze << ", y, x, params, steady_state, y_index, " << nze
<< ", options_.periods, " << blocks_linear[block] << ", options_.periods, " << blocks[block].linear
<< ", blck_num, y_kmin, options_.simul.maxit, options_.solve_tolf, options_.slowc, " << cutoff << ", options_.stack_solve_algo, 1, 1, 0, M_, options_, oo_);" << endl << ", blck_num, y_kmin, options_.simul.maxit, options_.solve_tolf, options_.slowc, " << cutoff << ", options_.stack_solve_algo, 1, 1, 0, M_, options_, oo_);" << endl
<< " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);" << endl << " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);" << endl
<< " if any(isnan(tmp) | isinf(tmp))" << endl << " if any(isnan(tmp) | isinf(tmp))" << endl
@ -2115,7 +2115,7 @@ DynamicModel::writeSparseDynamicMFile(const string &basename) const
<< " end;" << endl << " end;" << endl
<< " y = solve_one_boundary('" << basename << ".block.dynamic_" << block + 1 << "'" << " y = solve_one_boundary('" << basename << ".block.dynamic_" << block + 1 << "'"
<<", y, x, params, steady_state, y_index, " << nze <<", y, x, params, steady_state, y_index, " << nze
<<", options_.periods, " << blocks_linear[block] <<", options_.periods, " << blocks[block].linear
<<", blck_num, y_kmin, options_.simul.maxit, options_.solve_tolf, options_.slowc, " << cutoff << ", options_.stack_solve_algo, 1, 1, 0, M_, options_, oo_);" << endl <<", blck_num, y_kmin, options_.simul.maxit, options_.solve_tolf, options_.slowc, " << cutoff << ", options_.stack_solve_algo, 1, 1, 0, M_, options_, oo_);" << endl
<< " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);" << endl << " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);" << endl
<< " if any(isnan(tmp) | isinf(tmp))" << endl << " if any(isnan(tmp) | isinf(tmp))" << endl
@ -2147,7 +2147,7 @@ DynamicModel::writeSparseDynamicMFile(const string &basename) const
<<", y, x, params, steady_state, y_index, " << nze <<", y, x, params, steady_state, y_index, " << nze
<<", options_.periods, " << max_leadlag_block[block].first <<", options_.periods, " << max_leadlag_block[block].first
<<", " << max_leadlag_block[block].second <<", " << max_leadlag_block[block].second
<<", " << blocks_linear[block] <<", " << blocks[block].linear
<<", blck_num, y_kmin, options_.simul.maxit, options_.solve_tolf, options_.slowc, " << cutoff << ", options_.stack_solve_algo, options_, M_, oo_);" << endl <<", blck_num, y_kmin, options_.simul.maxit, options_.solve_tolf, options_.slowc, " << cutoff << ", options_.stack_solve_algo, options_, M_, oo_);" << endl
<< " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);" << endl << " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);" << endl
<< " if any(isnan(tmp) | isinf(tmp))" << endl << " if any(isnan(tmp) | isinf(tmp))" << endl
@ -4793,30 +4793,22 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
computeParamsDerivatives(paramsDerivsOrder); computeParamsDerivatives(paramsDerivsOrder);
} }
jacob_map_t contemporaneous_jacobian, static_jacobian;
map<tuple<int, int, int>, expr_t> first_order_endo_derivatives;
// For each simultaneous block contains pair<Size, Num_Feedback_variable>
vector<pair<int, int>> simblock_size;
vector<int> n_static, n_forward, n_backward, n_mixed;
if (linear_decomposition) if (linear_decomposition)
{ {
first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous(); auto first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous();
is_equation_linear = equationLinear(first_order_endo_derivatives); equationLinear(first_order_endo_derivatives);
tie(contemporaneous_jacobian, static_jacobian) = evaluateAndReduceJacobian(eval_context, cutoff, false); auto [contemporaneous_jacobian, static_jacobian] = evaluateAndReduceJacobian(eval_context, cutoff, false);
if (!computeNaturalNormalization()) if (!computeNaturalNormalization())
computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian); computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian);
tie(simblock_size, n_static, n_forward, n_backward, n_mixed) select_non_linear_equations_and_variables();
= select_non_linear_equations_and_variables(is_equation_linear);
equationTypeDetermination(first_order_endo_derivatives, 0); equationTypeDetermination(first_order_endo_derivatives, 0);
prologue = 0;
epilogue = 0;
reduceBlocksAndTypeDetermination(simblock_size, equation_type_and_normalized_equation, n_static, n_forward, n_backward, n_mixed, linear_decomposition); reduceBlocksAndTypeDetermination(linear_decomposition);
computeChainRuleJacobian(); computeChainRuleJacobian();
@ -4830,26 +4822,23 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
if (!no_tmp_terms) if (!no_tmp_terms)
computeTemporaryTermsOrdered(); computeTemporaryTermsOrdered();
} }
else if (block)
if (block)
{ {
tie(contemporaneous_jacobian, static_jacobian) = evaluateAndReduceJacobian(eval_context, cutoff, false); auto [contemporaneous_jacobian, static_jacobian] = evaluateAndReduceJacobian(eval_context, cutoff, false);
computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian); computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian);
computePrologueAndEpilogue(static_jacobian); computePrologueAndEpilogue(static_jacobian);
first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous(); auto first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous();
equationTypeDetermination(first_order_endo_derivatives, mfs); equationTypeDetermination(first_order_endo_derivatives, mfs);
cout << "Finding the optimal block decomposition of the model ..." << endl; cout << "Finding the optimal block decomposition of the model ..." << endl;
lag_lead_vector_t variable_lag_lead; auto variable_lag_lead = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, false);
tie(simblock_size, variable_lag_lead, n_static, n_forward, n_backward, n_mixed) = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, equation_type_and_normalized_equation, false); reduceBlocksAndTypeDetermination(linear_decomposition);
reduceBlocksAndTypeDetermination(simblock_size, equation_type_and_normalized_equation, n_static, n_forward, n_backward, n_mixed, linear_decomposition);
printBlockDecomposition(); printBlockDecomposition();

View File

@ -162,19 +162,16 @@ ModelTree::ModelTree(const ModelTree &m) :
eq_idx_orig2block{m.eq_idx_orig2block}, eq_idx_orig2block{m.eq_idx_orig2block},
endo_idx_orig2block{m.endo_idx_orig2block}, endo_idx_orig2block{m.endo_idx_orig2block},
map_idx{m.map_idx}, 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}, endo_max_leadlag_block{m.endo_max_leadlag_block},
other_endo_max_leadlag_block{m.other_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_max_leadlag_block{m.exo_max_leadlag_block},
exo_det_max_leadlag_block{m.exo_det_max_leadlag_block}, exo_det_max_leadlag_block{m.exo_det_max_leadlag_block},
max_leadlag_block{m.max_leadlag_block}, max_leadlag_block{m.max_leadlag_block},
blocks{m.blocks},
is_equation_linear{m.is_equation_linear}, is_equation_linear{m.is_equation_linear},
endo2eq{m.endo2eq}, endo2eq{m.endo2eq},
epilogue{m.epilogue}, epilogue{m.epilogue},
prologue{m.prologue}, prologue{m.prologue},
block_lag_lead{m.block_lag_lead},
cutoff{m.cutoff}, cutoff{m.cutoff},
mfs{m.mfs} mfs{m.mfs}
{ {
@ -215,25 +212,21 @@ ModelTree::operator=(const ModelTree &m)
first_chain_rule_derivatives.clear(); first_chain_rule_derivatives.clear();
map_idx = m.map_idx; map_idx = m.map_idx;
equation_type_and_normalized_equation.clear(); equation_type_and_normalized_equation.clear();
block_type_firstequation_size_mfs = m.block_type_firstequation_size_mfs;
blocks_derivatives.clear(); blocks_derivatives.clear();
blocks_linear = m.blocks_linear;
derivative_endo.clear(); derivative_endo.clear();
derivative_other_endo.clear(); derivative_other_endo.clear();
derivative_exo.clear(); derivative_exo.clear();
derivative_exo_det.clear(); derivative_exo_det.clear();
block_col_type = m.block_col_type;
endo_max_leadlag_block = m.endo_max_leadlag_block; endo_max_leadlag_block = m.endo_max_leadlag_block;
other_endo_max_leadlag_block = m.other_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_max_leadlag_block = m.exo_max_leadlag_block;
exo_det_max_leadlag_block = m.exo_det_max_leadlag_block; exo_det_max_leadlag_block = m.exo_det_max_leadlag_block;
max_leadlag_block = m.max_leadlag_block; max_leadlag_block = m.max_leadlag_block;
blocks = m.blocks;
is_equation_linear = m.is_equation_linear; is_equation_linear = m.is_equation_linear;
endo2eq = m.endo2eq; endo2eq = m.endo2eq;
epilogue = m.epilogue; epilogue = m.epilogue;
prologue = m.prologue; prologue = m.prologue;
block_lag_lead = m.block_lag_lead;
cutoff = m.cutoff; cutoff = m.cutoff;
mfs = m.mfs; mfs = m.mfs;
@ -456,43 +449,46 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context, double
return { contemporaneous_jacobian, static_jacobian }; return { contemporaneous_jacobian, static_jacobian };
} }
tuple<vector<pair<int, int>>, vector<int>, vector<int>, vector<int>, vector<int>> void
ModelTree::select_non_linear_equations_and_variables(const vector<bool> &is_equation_linear) ModelTree::select_non_linear_equations_and_variables()
{ {
vector<int> eq2endo(equations.size(), 0); prologue = 0;
int num = 0; epilogue = 0;
for (auto it : endo2eq)
if (!is_equation_linear[it]) vector<int> endo2block(endo2eq.size(), 1); // The 1 is a dummy value, distinct from 0
num++; int i = 0;
vector<int> endo2block(endo2eq.size(), 1); for (int endo = 0; endo < static_cast<int>(endo2eq.size()); endo++)
int i = 0, j = 0;
for (auto it : endo2eq)
if (!is_equation_linear[it])
{
eq_idx_block2orig[i] = it;
endo_idx_block2orig[i] = j;
endo2block[j] = 0;
i++;
j++;
}
auto [equation_lag_lead, variable_lag_lead] = getVariableLeadLagByBlock(endo2block);
vector<int> n_static(endo2eq.size(), 0), n_forward(endo2eq.size(), 0),
n_backward(endo2eq.size(), 0), n_mixed(endo2eq.size(), 0);
for (int i = 0; i < static_cast<int>(endo2eq.size()); i++)
{ {
if (variable_lag_lead[endo_idx_block2orig[i]].first != 0 && variable_lag_lead[endo_idx_block2orig[i]].second != 0) int eq = endo2eq[endo];
n_mixed[i]++; if (!is_equation_linear[eq])
else if (variable_lag_lead[endo_idx_block2orig[i]].first == 0 && variable_lag_lead[endo_idx_block2orig[i]].second != 0) {
n_forward[i]++; eq_idx_block2orig[i] = eq;
else if (variable_lag_lead[endo_idx_block2orig[i]].first != 0 && variable_lag_lead[endo_idx_block2orig[i]].second == 0) endo_idx_block2orig[i] = endo;
n_backward[i]++; endo2block[i] = 0;
else if (variable_lag_lead[endo_idx_block2orig[i]].first == 0 && variable_lag_lead[endo_idx_block2orig[i]].second == 0) i++;
n_static[i]++; }
} }
cout.flush();
vector<pair<int, int>> simblock_size(1, {i, i});
updateReverseVariableEquationOrderings(); updateReverseVariableEquationOrderings();
return { simblock_size, n_static, n_forward, n_backward, n_mixed };
blocks.clear();
blocks.resize(1);
blocks[0].size = i;
blocks[0].mfs_size = i;
auto [equation_lag_lead, variable_lag_lead] = getVariableLeadLagByBlock(endo2block);
for (int i = 0; i < blocks[0].size; i++)
{
auto [max_lag, max_lead] = variable_lag_lead[endo_idx_block2orig[i]];
if (max_lag != 0 && max_lead != 0)
blocks[0].n_mixed++;
else if (max_lag == 0 && max_lead != 0)
blocks[0].n_forward++;
else if (max_lag != 0 && max_lead == 0)
blocks[0].n_backward++;
else
blocks[0].n_static++;
}
} }
bool bool
@ -701,9 +697,8 @@ ModelTree::getVariableLeadLagByBlock(const vector<int> &endo2simblock) const
return { equation_lag_lead, variable_lag_lead }; return { equation_lag_lead, variable_lag_lead };
} }
tuple<vector<pair<int, int>>, lag_lead_vector_t, lag_lead_vector_t
vector<int>, vector<int>, vector<int>, vector<int>> ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, bool verbose_)
ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_)
{ {
int nb_var = symbol_table.endo_nbr(); int nb_var = symbol_table.endo_nbr();
int nb_simvars = nb_var - prologue - epilogue; int nb_simvars = nb_var - prologue - epilogue;
@ -731,13 +726,28 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
index, starting from 0, in recursive order */ index, starting from 0, in recursive order */
auto [num_simblocks, endo2simblock] = G.sortedStronglyConnectedComponents(); auto [num_simblocks, endo2simblock] = G.sortedStronglyConnectedComponents();
vector<pair<int, int>> simblock_size(num_simblocks, { 0, 0 }); int num_blocks = prologue+num_simblocks+epilogue;
// equations belonging to the block blocks.clear();
blocks.resize(num_blocks);
// Initialize size and mfs_size for prologue and epilogue
for (int i = 0; i < prologue; i++)
{
blocks[i].size = 1;
blocks[i].mfs_size = 1;
}
for (int i = 0; i < epilogue; i++)
{
blocks[prologue+num_simblocks+i].size = 1;
blocks[prologue+num_simblocks+i].mfs_size = 1;
}
// Compute size and list of equations for simultaneous blocks
vector<set<int>> eqs_in_simblock(num_simblocks); vector<set<int>> eqs_in_simblock(num_simblocks);
for (int i = 0; i < static_cast<int>(endo2simblock.size()); i++) for (int i = 0; i < static_cast<int>(endo2simblock.size()); i++)
{ {
simblock_size[endo2simblock[i]].first++; blocks[prologue+endo2simblock[i]].size++;
eqs_in_simblock[endo2simblock[i]].insert(i); eqs_in_simblock[endo2simblock[i]].insert(i);
} }
@ -746,7 +756,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
/* Add a loop on vertices which could not be normalized or vertices related /* Add a loop on vertices which could not be normalized or vertices related
to lead/lag variables. This forces those vertices to belong to the feedback set */ to lead/lag variables. This forces those vertices to belong to the feedback set */
for (int i = 0; i < nb_simvars; i++) for (int i = 0; i < nb_simvars; i++)
if (Equation_Type[eq_idx_block2orig[i+prologue]].first == EquationType::solve if (equation_type_and_normalized_equation[eq_idx_block2orig[i+prologue]].first == EquationType::solve
|| variable_lag_lead[endo_idx_block2orig[i+prologue]].first > 0 || variable_lag_lead[endo_idx_block2orig[i+prologue]].first > 0
|| variable_lag_lead[endo_idx_block2orig[i+prologue]].second > 0 || variable_lag_lead[endo_idx_block2orig[i+prologue]].second > 0
|| equation_lag_lead[eq_idx_block2orig[i+prologue]].first > 0 || equation_lag_lead[eq_idx_block2orig[i+prologue]].first > 0
@ -754,23 +764,19 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
|| mfs == 0) || mfs == 0)
add_edge(vertex(i, G), vertex(i, G), G); add_edge(vertex(i, G), vertex(i, G), G);
int num_blocks = prologue+num_simblocks+epilogue;
// Determines the dynamic structure of each equation // Determines the dynamic structure of each equation
vector<int> n_static(num_blocks, 0), n_forward(num_blocks, 0),
n_backward(num_blocks, 0), n_mixed(num_blocks, 0);
const vector<int> old_eq_idx_block2orig(eq_idx_block2orig), old_endo_idx_block2orig(endo_idx_block2orig); const vector<int> old_eq_idx_block2orig(eq_idx_block2orig), old_endo_idx_block2orig(endo_idx_block2orig);
for (int i = 0; i < prologue; i++) for (int i = 0; i < prologue; i++)
{ {
auto [max_lag, max_lead] = variable_lag_lead[old_endo_idx_block2orig[i]]; auto [max_lag, max_lead] = variable_lag_lead[old_endo_idx_block2orig[i]];
if (max_lag != 0 && max_lead != 0) if (max_lag != 0 && max_lead != 0)
n_mixed[i]++; blocks[i].n_mixed++;
else if (max_lag == 0 && max_lead != 0) else if (max_lag == 0 && max_lead != 0)
n_forward[i]++; blocks[i].n_forward++;
else if (max_lag != 0 && max_lead == 0) else if (max_lag != 0 && max_lead == 0)
n_backward[i]++; blocks[i].n_backward++;
else else
n_static[i]++; blocks[i].n_static++;
} }
/* For each block, the minimum set of feedback variable is computed and the /* For each block, the minimum set of feedback variable is computed and the
@ -783,7 +789,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
auto subG = G.extractSubgraph(eqs_in_simblock[i]); auto subG = G.extractSubgraph(eqs_in_simblock[i]);
auto feed_back_vertices = subG.minimalSetOfFeedbackVertices(); auto feed_back_vertices = subG.minimalSetOfFeedbackVertices();
auto v_index1 = get(boost::vertex_index1, subG); auto v_index1 = get(boost::vertex_index1, subG);
simblock_size[i].second = feed_back_vertices.size(); blocks[prologue+i].mfs_size = feed_back_vertices.size();
auto reordered_vertices = subG.reorderRecursiveVariables(feed_back_vertices); auto reordered_vertices = subG.reorderRecursiveVariables(feed_back_vertices);
// First we have the recursive equations conditional on feedback variables // First we have the recursive equations conditional on feedback variables
@ -799,22 +805,22 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
}; };
if (j == 2 && max_lag != 0 && max_lead != 0) if (j == 2 && max_lag != 0 && max_lead != 0)
{ {
n_mixed[prologue+i]++; blocks[prologue+i].n_mixed++;
reorder(); reorder();
} }
else if (j == 3 && max_lag == 0 && max_lead != 0) else if (j == 3 && max_lag == 0 && max_lead != 0)
{ {
n_forward[prologue+i]++; blocks[prologue+i].n_forward++;
reorder(); reorder();
} }
else if (j == 1 && max_lag != 0 && max_lead == 0) else if (j == 1 && max_lag != 0 && max_lead == 0)
{ {
n_backward[prologue+i]++; blocks[prologue+i].n_backward++;
reorder(); reorder();
} }
else if (j == 0 && max_lag == 0 && max_lead == 0) else if (j == 0 && max_lag == 0 && max_lead == 0)
{ {
n_static[prologue+i]++; blocks[prologue+i].n_static++;
reorder(); reorder();
} }
} }
@ -833,22 +839,22 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
}; };
if (j == 2 && max_lag != 0 && max_lead != 0) if (j == 2 && max_lag != 0 && max_lead != 0)
{ {
n_mixed[prologue+i]++; blocks[prologue+i].n_mixed++;
reorder(); reorder();
} }
else if (j == 3 && max_lag == 0 && max_lead != 0) else if (j == 3 && max_lag == 0 && max_lead != 0)
{ {
n_forward[prologue+i]++; blocks[prologue+i].n_forward++;
reorder(); reorder();
} }
else if (j == 1 && max_lag != 0 && max_lead == 0) else if (j == 1 && max_lag != 0 && max_lead == 0)
{ {
n_backward[prologue+i]++; blocks[prologue+i].n_backward++;
reorder(); reorder();
} }
else if (j == 0 && max_lag == 0 && max_lead == 0) else if (j == 0 && max_lag == 0 && max_lead == 0)
{ {
n_static[prologue+i]++; blocks[prologue+i].n_static++;
reorder(); reorder();
} }
} }
@ -858,18 +864,18 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
{ {
auto [max_lag, max_lead] = variable_lag_lead[old_endo_idx_block2orig[prologue+nb_simvars+i]]; auto [max_lag, max_lead] = variable_lag_lead[old_endo_idx_block2orig[prologue+nb_simvars+i]];
if (max_lag != 0 && max_lead != 0) if (max_lag != 0 && max_lead != 0)
n_mixed[prologue+num_simblocks+i]++; blocks[prologue+num_simblocks+i].n_mixed++;
else if (max_lag == 0 && max_lead != 0) else if (max_lag == 0 && max_lead != 0)
n_forward[prologue+num_simblocks+i]++; blocks[prologue+num_simblocks+i].n_forward++;
else if (max_lag != 0 && max_lead == 0) else if (max_lag != 0 && max_lead == 0)
n_backward[prologue+num_simblocks+i]++; blocks[prologue+num_simblocks+i].n_backward++;
else else
n_static[prologue+num_simblocks+i]++; blocks[prologue+num_simblocks+i].n_static++;
} }
updateReverseVariableEquationOrderings(); updateReverseVariableEquationOrderings();
return { simblock_size, variable_lag_lead, n_static, n_forward, n_backward, n_mixed }; return variable_lag_lead;
} }
void void
@ -904,185 +910,152 @@ ModelTree::printBlockDecomposition() const
} }
void void
ModelTree::reduceBlocksAndTypeDetermination(const vector<pair<int, int>> &simblock_size, const equation_type_and_normalized_equation_t &Equation_Type, const vector<int> &n_static, const vector<int> &n_forward, const vector<int> &n_backward, const vector<int> &n_mixed, bool linear_decomposition) ModelTree::reduceBlocksAndTypeDetermination(bool linear_decomposition)
{ {
int count_equ = 0, simblock_counter = 0; for (int i = 0; i < static_cast<int>(blocks.size()); i++)
block_type_firstequation_size_mfs.clear();
BlockSimulationType prev_Type = BlockSimulationType::unknown;
int eq = 0;
int num_simblocks = simblock_size.size();
for (int i = 0; i < prologue+num_simblocks+epilogue; i++)
{ {
int Blck_Size, MFS_Size; int first_eq = (i == 0) ? 0 : blocks[i-1].first_equation+blocks[i-1].size;
int first_count_equ = count_equ;
if (i < prologue)
{
Blck_Size = 1;
MFS_Size = 1;
}
else if (i < prologue+num_simblocks)
{
Blck_Size = simblock_size[simblock_counter].first;
MFS_Size = simblock_size[simblock_counter].second;
simblock_counter++;
}
else if (i < prologue+num_simblocks+epilogue)
{
Blck_Size = 1;
MFS_Size = 1;
}
int Lag = 0, Lead = 0; /* Compute the maximum lead and lag across all endogenous that appear in
for (count_equ = first_count_equ; count_equ < Blck_Size+first_count_equ; count_equ++) this block and that belong to it */
int max_lag = 0, max_lead = 0;
for (int eq = first_eq; eq < first_eq+blocks[i].size; eq++)
{ {
set<pair<int, int>> endos_and_lags; set<pair<int, int>> endos_and_lags;
equations[eq_idx_block2orig[count_equ]]->collectEndogenous(endos_and_lags); equations[eq_idx_block2orig[eq]]->collectEndogenous(endos_and_lags);
for (const auto &[curr_variable, curr_lag] : endos_and_lags) for (const auto &[endo, lag] : endos_and_lags)
{ {
if (linear_decomposition) if (linear_decomposition)
{ {
if (dynamic_jacobian.find({ curr_lag, eq_idx_block2orig[count_equ], curr_variable }) != dynamic_jacobian.end()) if (dynamic_jacobian.find({ lag, eq_idx_block2orig[eq], endo })
!= dynamic_jacobian.end())
{ {
if (curr_lag > Lead) max_lead = max(lag, max_lead);
Lead = curr_lag; max_lag = max(-lag, max_lag);
else if (-curr_lag > Lag)
Lag = -curr_lag;
} }
} }
else else
{ {
if (find(endo_idx_block2orig.begin()+first_count_equ, endo_idx_block2orig.begin()+(first_count_equ+Blck_Size), curr_variable) if (find(endo_idx_block2orig.begin()+first_eq,
!= endo_idx_block2orig.begin()+(first_count_equ+Blck_Size) endo_idx_block2orig.begin()+first_eq+blocks[i].size, endo)
&& dynamic_jacobian.find({ curr_lag, eq_idx_block2orig[count_equ], curr_variable }) != dynamic_jacobian.end()) != endo_idx_block2orig.begin()+first_eq+blocks[i].size
&& dynamic_jacobian.find({ lag, eq_idx_block2orig[eq], endo })
!= dynamic_jacobian.end())
{ {
if (curr_lag > Lead) max_lead = max(lag, max_lead);
Lead = curr_lag; max_lag = max(-lag, max_lag);
else if (-curr_lag > Lag)
Lag = -curr_lag;
} }
} }
} }
} }
// Determine the block type
BlockSimulationType Simulation_Type; BlockSimulationType Simulation_Type;
if (Lag > 0 && Lead > 0) if (max_lag > 0 && max_lead > 0)
{ {
if (Blck_Size == 1) if (blocks[i].size == 1)
Simulation_Type = BlockSimulationType::solveTwoBoundariesSimple; Simulation_Type = BlockSimulationType::solveTwoBoundariesSimple;
else else
Simulation_Type = BlockSimulationType::solveTwoBoundariesComplete; Simulation_Type = BlockSimulationType::solveTwoBoundariesComplete;
} }
else if (Blck_Size > 1) else if (blocks[i].size > 1)
{ {
if (Lead > 0) if (max_lead > 0)
Simulation_Type = BlockSimulationType::solveBackwardComplete; Simulation_Type = BlockSimulationType::solveBackwardComplete;
else else
Simulation_Type = BlockSimulationType::solveForwardComplete; Simulation_Type = BlockSimulationType::solveForwardComplete;
} }
else else
{ {
if (Lead > 0) if (max_lead > 0)
Simulation_Type = BlockSimulationType::solveBackwardSimple; Simulation_Type = BlockSimulationType::solveBackwardSimple;
else else
Simulation_Type = BlockSimulationType::solveForwardSimple; Simulation_Type = BlockSimulationType::solveForwardSimple;
} }
int l_n_static = n_static[i];
int l_n_forward = n_forward[i]; if (blocks[i].size == 1)
int l_n_backward = n_backward[i];
int l_n_mixed = n_mixed[i];
if (Blck_Size == 1)
{ {
if (Equation_Type[eq_idx_block2orig[eq]].first == EquationType::evaluate // Determine if the block can simply be evaluated
|| Equation_Type[eq_idx_block2orig[eq]].first == EquationType::evaluate_s) if (equation_type_and_normalized_equation[eq_idx_block2orig[first_eq]].first == EquationType::evaluate
|| equation_type_and_normalized_equation[eq_idx_block2orig[first_eq]].first == EquationType::evaluate_s)
{ {
if (Simulation_Type == BlockSimulationType::solveBackwardSimple) if (Simulation_Type == BlockSimulationType::solveBackwardSimple)
Simulation_Type = BlockSimulationType::evaluateBackward; Simulation_Type = BlockSimulationType::evaluateBackward;
else if (Simulation_Type == BlockSimulationType::solveForwardSimple) else if (Simulation_Type == BlockSimulationType::solveForwardSimple)
Simulation_Type = BlockSimulationType::evaluateForward; Simulation_Type = BlockSimulationType::evaluateForward;
} }
/* Try to merge this block with the previous one.
This is only possible if the two blocks can simply be evaluated
(in the same direction), and if the merge does not break the
restrictions on leads/lags. */
if (i > 0) if (i > 0)
{ {
bool is_lead = false, is_lag = false; bool is_lead = false, is_lag = false;
int c_Size = get<2>(block_type_firstequation_size_mfs[block_type_firstequation_size_mfs.size()-1]); for (int j = blocks[i-1].first_equation;
int first_equation = get<1>(block_type_firstequation_size_mfs[block_type_firstequation_size_mfs.size()-1]); j < blocks[i-1].first_equation+blocks[i-1].size; j++)
if (c_Size > 0
&& ((prev_Type == BlockSimulationType::evaluateForward && Simulation_Type == BlockSimulationType::evaluateForward && !is_lead)
|| (prev_Type == BlockSimulationType::evaluateBackward && Simulation_Type == BlockSimulationType::evaluateBackward && !is_lag)))
{ {
for (int j = first_equation; j < first_equation+c_Size; j++) if (dynamic_jacobian.find({ -1, eq_idx_block2orig[first_eq], endo_idx_block2orig[j] })
{ != dynamic_jacobian.end())
if (dynamic_jacobian.find({ -1, eq_idx_block2orig[eq], endo_idx_block2orig[j] }) is_lag = true;
!= dynamic_jacobian.end()) if (dynamic_jacobian.find({ +1, eq_idx_block2orig[first_eq], endo_idx_block2orig[j] })
is_lag = true; != dynamic_jacobian.end())
if (dynamic_jacobian.find({ +1, eq_idx_block2orig[eq], endo_idx_block2orig[j] }) is_lead = true;
!= dynamic_jacobian.end())
is_lead = true;
}
} }
if ((prev_Type == BlockSimulationType::evaluateForward && Simulation_Type == BlockSimulationType::evaluateForward && !is_lead)
|| (prev_Type == BlockSimulationType::evaluateBackward && Simulation_Type == BlockSimulationType::evaluateBackward && !is_lag)) BlockSimulationType prev_Type = blocks[i-1].simulation_type;
if ((prev_Type == BlockSimulationType::evaluateForward
&& Simulation_Type == BlockSimulationType::evaluateForward
&& !is_lead)
|| (prev_Type == BlockSimulationType::evaluateBackward
&& Simulation_Type == BlockSimulationType::evaluateBackward
&& !is_lag))
{ {
//merge the current block with the previous one // Merge the current block into the previous one
BlockSimulationType c_Type = get<0>(block_type_firstequation_size_mfs[block_type_firstequation_size_mfs.size()-1]); blocks[i-1].size++;
c_Size++; blocks[i-1].mfs_size = blocks[i-1].size;
block_type_firstequation_size_mfs[block_type_firstequation_size_mfs.size()-1] = { c_Type, first_equation, c_Size, c_Size }; blocks[i-1].max_lag = max(blocks[i-1].max_lag, max_lag);
if (block_lag_lead[block_type_firstequation_size_mfs.size()-1].first > Lag) blocks[i-1].max_lead = max(blocks[i-1].max_lead, max_lead);
Lag = block_lag_lead[block_type_firstequation_size_mfs.size()-1].first; blocks[i-1].n_static += blocks[i].n_static;
if (block_lag_lead[block_type_firstequation_size_mfs.size()-1].second > Lead) blocks[i-1].n_forward += blocks[i].n_forward;
Lead = block_lag_lead[block_type_firstequation_size_mfs.size()-1].second; blocks[i-1].n_backward += blocks[i].n_backward;
block_lag_lead[block_type_firstequation_size_mfs.size()-1] = { Lag, Lead }; blocks[i-1].n_mixed += blocks[i].n_mixed;
auto tmp = block_col_type[block_col_type.size()-1]; blocks.erase(blocks.begin()+i);
block_col_type[block_col_type.size()-1] = { get<0>(tmp)+l_n_static, get<1>(tmp)+l_n_forward, get<2>(tmp)+l_n_backward, get<3>(tmp)+l_n_mixed }; i--;
} continue;
else
{
block_type_firstequation_size_mfs.emplace_back(Simulation_Type, eq, Blck_Size, MFS_Size);
block_lag_lead.emplace_back(Lag, Lead);
block_col_type.emplace_back(l_n_static, l_n_forward, l_n_backward, l_n_mixed);
} }
} }
else
{
block_type_firstequation_size_mfs.emplace_back(Simulation_Type, eq, Blck_Size, MFS_Size);
block_lag_lead.emplace_back(Lag, Lead);
block_col_type.emplace_back(l_n_static, l_n_forward, l_n_backward, l_n_mixed);
}
} }
else
{ blocks[i].simulation_type = Simulation_Type;
block_type_firstequation_size_mfs.emplace_back(Simulation_Type, eq, Blck_Size, MFS_Size); blocks[i].first_equation = first_eq;
block_lag_lead.emplace_back(Lag, Lead); blocks[i].max_lag = max_lag;
block_col_type.emplace_back(l_n_static, l_n_forward, l_n_backward, l_n_mixed); blocks[i].max_lead = max_lead;
}
prev_Type = Simulation_Type;
eq += Blck_Size;
} }
} }
vector<bool> void
ModelTree::equationLinear(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives) const ModelTree::equationLinear(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives)
{ {
vector<bool> is_linear(symbol_table.endo_nbr(), true); is_equation_linear.clear();
for (const auto &it : first_order_endo_derivatives) is_equation_linear.resize(symbol_table.endo_nbr(), true);
for (const auto &[indices, expr] : first_order_endo_derivatives)
{ {
expr_t Id = it.second;
set<pair<int, int>> endogenous; set<pair<int, int>> endogenous;
Id->collectEndogenous(endogenous); expr->collectEndogenous(endogenous);
if (endogenous.size() > 0) if (endogenous.size() > 0)
{ {
int eq = get<0>(it.first); int eq = get<0>(indices);
is_linear[eq] = false; is_equation_linear[eq] = false;
} }
} }
return is_linear;
} }
void void
ModelTree::determineLinearBlocks() ModelTree::determineLinearBlocks()
{ {
int nb_blocks = getNbBlocks(); // Note that field “linear” in class BlockInfo defaults to true
blocks_linear.clear(); for (int block = 0; block < getNbBlocks(); block++)
blocks_linear.resize(nb_blocks, true);
for (int block = 0; block < nb_blocks; block++)
{ {
BlockSimulationType simulation_type = getBlockSimulationType(block); BlockSimulationType simulation_type = getBlockSimulationType(block);
int block_size = getBlockSize(block); int block_size = getBlockSize(block);
@ -1100,7 +1073,7 @@ ModelTree::determineLinearBlocks()
for (int l = 0; l < block_size; l++) for (int l = 0; l < block_size; l++)
if (endogenous.find({ endo_idx_block2orig[first_variable_position+l], 0 }) != endogenous.end()) if (endogenous.find({ endo_idx_block2orig[first_variable_position+l], 0 }) != endogenous.end())
{ {
blocks_linear[block] = false; blocks[block].linear = false;
goto the_end; goto the_end;
} }
} }
@ -1115,7 +1088,7 @@ ModelTree::determineLinearBlocks()
for (int l = 0; l < block_size; l++) for (int l = 0; l < block_size; l++)
if (endogenous.find({ endo_idx_block2orig[first_variable_position+l], lag }) != endogenous.end()) if (endogenous.find({ endo_idx_block2orig[first_variable_position+l], lag }) != endogenous.end())
{ {
blocks_linear[block] = false; blocks[block].linear = false;
goto the_end; goto the_end;
} }
} }

View File

@ -55,9 +55,6 @@ using equation_type_and_normalized_equation_t = vector<pair<EquationType, expr_t
//! Vector describing variables: max_lag in the block, max_lead in the block //! Vector describing variables: max_lag in the block, max_lead in the block
using lag_lead_vector_t = vector<pair<int, int>>; using lag_lead_vector_t = vector<pair<int, int>>;
//! for each block contains tuple<Simulation_Type, first_equation, Block_Size, Recursive_part_Size>
using block_type_firstequation_size_mfs_t = vector<tuple<BlockSimulationType, int, int, int>>;
//! for a block contains derivatives tuple<block_equation_number, block_variable_number, lead_lag, expr_t> //! for a block contains derivatives tuple<block_equation_number, block_variable_number, lead_lag, expr_t>
using block_derivatives_equation_variable_laglead_nodeid_t = vector<tuple<int, int, int, expr_t>>; using block_derivatives_equation_variable_laglead_nodeid_t = vector<tuple<int, int, int, expr_t>>;
@ -190,27 +187,32 @@ protected:
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation //! 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; equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
//! For each block contains tuple<Simulation_Type, first_equation, Block_Size, Recursive_part_Size>
block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
//! for all blocks derivatives description //! for all blocks derivatives description
blocks_derivatives_t blocks_derivatives; 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> //! Map the derivatives for a block tuple<lag, eq, var>
using derivative_t = map<tuple<int, int, int>, expr_t>; using derivative_t = map<tuple<int, int, int>, expr_t>;
//! Vector of derivative for each blocks //! Vector of derivative for each blocks
vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det; 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 //!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; 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;
class BlockInfo
{
public:
BlockSimulationType simulation_type;
int first_equation; // Stores a block-ordered equation ID
int size{0};
int mfs_size{0}; // Size of the minimal feedback set
bool linear{true}; // Whether the block is linear in endogenous variable
int n_static{0}, n_forward{0}, n_backward{0}, n_mixed{0};
int max_lag{0}, max_lead{0};
};
// Stores various informations on the blocks
vector<BlockInfo> blocks;
//! the file containing the model and the derivatives code //! the file containing the model and the derivatives code
ofstream code_file; ofstream code_file;
@ -270,9 +272,6 @@ protected:
//! number of equation in the prologue and in the epilogue //! number of equation in the prologue and in the epilogue
int epilogue, prologue; int epilogue, prologue;
//! for each block contains pair< max_lag, max_lead>
lag_lead_vector_t block_lag_lead;
/* Compute a pseudo-Jacobian whose all elements are either zero or one, /* Compute a pseudo-Jacobian whose all elements are either zero or one,
depending on whether the variable symbolically appears in the equation */ depending on whether the variable symbolically appears in the equation */
jacob_map_t computeSymbolicJacobian() const; jacob_map_t computeSymbolicJacobian() const;
@ -302,17 +301,22 @@ protected:
dynamic_jacobian. Elements below the cutoff are discarded. External functions are evaluated to 1. */ dynamic_jacobian. Elements below the cutoff are discarded. External functions are evaluated to 1. */
pair<jacob_map_t, jacob_map_t> evaluateAndReduceJacobian(const eval_context_t &eval_context, double cutoff, bool verbose); pair<jacob_map_t, jacob_map_t> evaluateAndReduceJacobian(const eval_context_t &eval_context, double cutoff, bool verbose);
//! Select and reorder the non linear equations of the model //! Select and reorder the non linear equations of the model
/*! Returns a tuple (blocks, n_static, n_forward, n_backward, n_mixed) */ void select_non_linear_equations_and_variables();
tuple<vector<pair<int, int>>, vector<int>, vector<int>, vector<int>, vector<int>> select_non_linear_equations_and_variables(const vector<bool> &is_equation_linear);
//! Search the equations and variables belonging to the prologue and the epilogue of the model //! Search the equations and variables belonging to the prologue and the epilogue of the model
void computePrologueAndEpilogue(const jacob_map_t &static_jacobian); void computePrologueAndEpilogue(const jacob_map_t &static_jacobian);
//! Determine the type of each equation of model and try to normalize the unnormalized equation //! Determine the type of each equation of model and try to normalize the unnormalized equation
void equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives, int mfs); void equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives, int mfs);
//! Compute the block decomposition and for a non-recusive block find the minimum feedback set /* Compute the block decomposition and for a non-recusive block find the minimum feedback set
/*! Returns a tuple (blocks, variable_lag_lead, n_static, n_forward, n_backward, n_mixed) */
tuple<vector<pair<int, int>>, lag_lead_vector_t, vector<int>, vector<int>, vector<int>, vector<int>> computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_); Initializes the blocks structure, and fills the following fields: size,
//! Reduce the number of block merging the same type equation in the prologue and the epilogue and determine the type of each block mfs_size, n_static, n_forward, n_backward, n_mixed. */
void reduceBlocksAndTypeDetermination(const vector<pair<int, int>> &simblock_size, const equation_type_and_normalized_equation_t &Equation_Type, const vector<int> &n_static, const vector<int> &n_forward, const vector<int> &n_backward, const vector<int> &n_mixed, bool linear_decomposition); lag_lead_vector_t computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, bool verbose_);
/* Reduce the number of block by merging the same type of equations in the
prologue and the epilogue, and determine the type of each block.
Fills the following fields of the blocks structure: simulation_type,
first_equation, max_lead, max_lag. */
void reduceBlocksAndTypeDetermination(bool linear_decomposition);
/* The 1st output gives, for each equation (in original order) the (max_lag, /* The 1st output gives, for each equation (in original order) the (max_lag,
max_lead) across all endogenous that appear in the equation and that max_lead) across all endogenous that appear in the equation and that
belong to the same block (i.e. those endogenous are solved in the same belong to the same block (i.e. those endogenous are solved in the same
@ -323,7 +327,7 @@ protected:
which it belongs. */ which it belongs. */
pair<lag_lead_vector_t, lag_lead_vector_t> getVariableLeadLagByBlock(const vector<int> &endo2simblock) const; pair<lag_lead_vector_t, lag_lead_vector_t> getVariableLeadLagByBlock(const vector<int> &endo2simblock) const;
//! For each equation determine if it is linear or not //! For each equation determine if it is linear or not
vector<bool> equationLinear(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives) const; void equationLinear(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives);
//! Print an abstract of the block structure of the model //! Print an abstract of the block structure of the model
void printBlockDecomposition() const; void printBlockDecomposition() const;
//! Determine for each block if it is linear or not //! Determine for each block if it is linear or not
@ -337,25 +341,25 @@ protected:
int int
getNbBlocks() const getNbBlocks() const
{ {
return block_type_firstequation_size_mfs.size(); return blocks.size();
}; };
//! Determine the simulation type of each block //! Determine the simulation type of each block
BlockSimulationType BlockSimulationType
getBlockSimulationType(int block_number) const getBlockSimulationType(int block_number) const
{ {
return get<0>(block_type_firstequation_size_mfs[block_number]); return blocks[block_number].simulation_type;
}; };
//! Return the first equation number of a block //! Return the first equation number of a block
int int
getBlockFirstEquation(int block_number) const getBlockFirstEquation(int block_number) const
{ {
return get<1>(block_type_firstequation_size_mfs[block_number]); return blocks[block_number].first_equation;
}; };
//! Return the size of the block block_number //! Return the size of the block block_number
int int
getBlockSize(int block_number) const getBlockSize(int block_number) const
{ {
return get<2>(block_type_firstequation_size_mfs[block_number]); return blocks[block_number].size;
}; };
//! Return the number of exogenous variable in the block block_number //! Return the number of exogenous variable in the block block_number
virtual int getBlockExoSize(int block_number) const = 0; virtual int getBlockExoSize(int block_number) const = 0;
@ -365,61 +369,62 @@ protected:
int int
getBlockMfs(int block_number) const getBlockMfs(int block_number) const
{ {
return get<3>(block_type_firstequation_size_mfs[block_number]); return blocks[block_number].mfs_size;
}; };
//! Return the maximum lag in a block //! Return the maximum lag in a block
int int
getBlockMaxLag(int block_number) const getBlockMaxLag(int block_number) const
{ {
return block_lag_lead[block_number].first; return blocks[block_number].max_lag;
}; };
//! Return the maximum lead in a block //! Return the maximum lead in a block
int int
getBlockMaxLead(int block_number) const getBlockMaxLead(int block_number) const
{ {
return block_lag_lead[block_number].second; return blocks[block_number].max_lead;
}; };
inline void inline void
setBlockLeadLag(int block, int max_lag, int max_lead) setBlockLeadLag(int block, int max_lag, int max_lead)
{ {
block_lag_lead[block] = { max_lag, max_lead }; blocks[block].max_lag = max_lag;
blocks[block].max_lead = max_lead;
}; };
//! Return the type of equation (equation_number) belonging to the block block_number //! Return the type of equation (equation_number) belonging to the block block_number
EquationType EquationType
getBlockEquationType(int block_number, int equation_number) const getBlockEquationType(int block_number, int equation_number) const
{ {
return equation_type_and_normalized_equation[eq_idx_block2orig[get<1>(block_type_firstequation_size_mfs[block_number])+equation_number]].first; return equation_type_and_normalized_equation[eq_idx_block2orig[getBlockFirstEquation(block_number)+equation_number]].first;
}; };
//! Return true if the equation has been normalized //! Return true if the equation has been normalized
bool bool
isBlockEquationRenormalized(int block_number, int equation_number) const isBlockEquationRenormalized(int block_number, int equation_number) const
{ {
return equation_type_and_normalized_equation[eq_idx_block2orig[get<1>(block_type_firstequation_size_mfs[block_number])+equation_number]].first == EquationType::evaluate_s; return equation_type_and_normalized_equation[eq_idx_block2orig[getBlockFirstEquation(block_number)+equation_number]].first == EquationType::evaluate_s;
}; };
//! Return the expr_t of the equation equation_number belonging to the block block_number //! Return the expr_t of the equation equation_number belonging to the block block_number
expr_t expr_t
getBlockEquationExpr(int block_number, int equation_number) const getBlockEquationExpr(int block_number, int equation_number) const
{ {
return equations[eq_idx_block2orig[get<1>(block_type_firstequation_size_mfs[block_number])+equation_number]]; return equations[eq_idx_block2orig[getBlockFirstEquation(block_number)+equation_number]];
}; };
//! Return the expr_t of the renormalized equation equation_number belonging to the block block_number //! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
expr_t expr_t
getBlockEquationRenormalizedExpr(int block_number, int equation_number) const getBlockEquationRenormalizedExpr(int block_number, int equation_number) const
{ {
return equation_type_and_normalized_equation[eq_idx_block2orig[get<1>(block_type_firstequation_size_mfs[block_number])+equation_number]].second; return equation_type_and_normalized_equation[eq_idx_block2orig[getBlockFirstEquation(block_number)+equation_number]].second;
}; };
//! Return the original number of equation equation_number belonging to the block block_number //! Return the original number of equation equation_number belonging to the block block_number
int int
getBlockEquationID(int block_number, int equation_number) const getBlockEquationID(int block_number, int equation_number) const
{ {
return eq_idx_block2orig[get<1>(block_type_firstequation_size_mfs[block_number])+equation_number]; return eq_idx_block2orig[getBlockFirstEquation(block_number)+equation_number];
}; };
//! Return the original number of variable variable_number belonging to the block block_number //! Return the original number of variable variable_number belonging to the block block_number
int int
getBlockVariableID(int block_number, int variable_number) const getBlockVariableID(int block_number, int variable_number) const
{ {
return endo_idx_block2orig[get<1>(block_type_firstequation_size_mfs[block_number])+variable_number]; return endo_idx_block2orig[getBlockFirstEquation(block_number)+variable_number];
}; };
//! Return the original number of the exogenous variable varexo_number belonging to the block block_number //! Return the original number of the exogenous variable varexo_number belonging to the block block_number
virtual int getBlockVariableExoID(int block_number, int variable_number) const = 0; virtual int getBlockVariableExoID(int block_number, int variable_number) const = 0;
@ -427,13 +432,13 @@ protected:
int int
getBlockInitialEquationID(int block_number, int equation_number) const getBlockInitialEquationID(int block_number, int equation_number) const
{ {
return eq_idx_orig2block[equation_number] - get<1>(block_type_firstequation_size_mfs[block_number]); return eq_idx_orig2block[equation_number] - getBlockFirstEquation(block_number);
}; };
//! Return the position of variable_number in the block number belonging to the block block_number //! Return the position of variable_number in the block number belonging to the block block_number
int int
getBlockInitialVariableID(int block_number, int variable_number) const getBlockInitialVariableID(int block_number, int variable_number) const
{ {
return endo_idx_orig2block[variable_number] - get<1>(block_type_firstequation_size_mfs[block_number]); return endo_idx_orig2block[variable_number] - getBlockFirstEquation(block_number);
}; };
//! Return the position of variable_number in the block number belonging to the block block_number //! Return the position of variable_number in the block number belonging to the block block_number
virtual int getBlockInitialExogenousID(int block_number, int variable_number) const = 0; virtual int getBlockInitialExogenousID(int block_number, int variable_number) const = 0;

View File

@ -703,7 +703,7 @@ StaticModel::writeModelEquationsCode_Block(const string &basename, map_idx_t map
block_size, block_size,
endo_idx_block2orig, endo_idx_block2orig,
eq_idx_block2orig, eq_idx_block2orig,
blocks_linear[block], blocks[block].linear,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
0, 0,
0, 0,
@ -1142,9 +1142,9 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
cout << "Finding the optimal block decomposition of the model ..." << endl; cout << "Finding the optimal block decomposition of the model ..." << endl;
auto [blocks, variable_lag_lead, n_static, n_forward, n_backward, n_mixed] = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, equation_type_and_normalized_equation, false); auto variable_lag_lead = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, false);
reduceBlocksAndTypeDetermination(blocks, equation_type_and_normalized_equation, n_static, n_forward, n_backward, n_mixed, false); reduceBlocksAndTypeDetermination(false);
printBlockDecomposition(); printBlockDecomposition();