Block decomposition: reorganize data structures storing block information
parent
8eafd9ab4f
commit
118ceab85b
|
@ -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();
|
||||||
|
|
||||||
|
|
345
src/ModelTree.cc
345
src/ModelTree.cc
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue