Now compute blocks[].first_equation from ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock

Also include various cosmetic changes.
issue#70
Sébastien Villemot 2020-04-29 18:48:42 +02:00
parent 1886746581
commit 7f57821401
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
2 changed files with 53 additions and 62 deletions

View File

@ -673,7 +673,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock()
/* Identify the simultaneous blocks. Each simultaneous block is given an /* Identify the simultaneous blocks. Each simultaneous block is given an
index, starting from 0, in recursive order */ index, starting from 0, in recursive order */
auto [num_simblocks, endo2simblock] = G.sortedStronglyConnectedComponents(); auto [num_simblocks, simvar2simblock] = G.sortedStronglyConnectedComponents();
int num_blocks = prologue+num_simblocks+epilogue; int num_blocks = prologue+num_simblocks+epilogue;
@ -683,29 +683,23 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock()
eq2block.resize(nb_var); eq2block.resize(nb_var);
// Initialize size and mfs_size for prologue and epilogue, plus eq/endo→block mappings // Initialize size and mfs_size for prologue and epilogue, plus eq/endo→block mappings
for (int i = 0; i < prologue; i++) for (int blk = 0; blk < num_blocks; blk++)
{ if (blk < prologue || blk >= num_blocks-epilogue)
blocks[i].size = 1; {
blocks[i].mfs_size = 1; int var_eq = (blk < prologue ? blk : blk-num_simblocks+nb_simvars);
endo2block[endo_idx_block2orig[i]] = i; blocks[blk].size = 1;
eq2block[eq_idx_block2orig[i]] = i; blocks[blk].mfs_size = 1;
} blocks[blk].first_equation = var_eq;
for (int i = 0; i < epilogue; i++) endo2block[endo_idx_block2orig[var_eq]] = blk;
{ eq2block[eq_idx_block2orig[var_eq]] = blk;
int blk = prologue+num_simblocks+i; }
int var_eq = prologue+nb_simvars+i;
blocks[blk].size = 1;
blocks[blk].mfs_size = 1;
endo2block[endo_idx_block2orig[var_eq]] = blk;
eq2block[eq_idx_block2orig[var_eq]] = blk;
}
// Compute size and list of equations for simultaneous blocks // Initialize size for simultaneous blocks, plus eq/endo→block mappings
vector<vector<int>> eqs_in_simblock(num_simblocks); vector<vector<int>> simblock2simvars(num_simblocks);
for (int i = 0; i < static_cast<int>(endo2simblock.size()); i++) for (int i = 0; i < static_cast<int>(simvar2simblock.size()); i++)
{ {
eqs_in_simblock[endo2simblock[i]].push_back(i); simblock2simvars[simvar2simblock[i]].push_back(i);
int blk = prologue+endo2simblock[i]; int blk = prologue+simvar2simblock[i];
blocks[blk].size++; blocks[blk].size++;
endo2block[endo_idx_block2orig[prologue+i]] = blk; endo2block[endo_idx_block2orig[prologue+i]] = blk;
eq2block[eq_idx_block2orig[prologue+i]] = blk; eq2block[eq_idx_block2orig[prologue+i]] = blk;
@ -749,11 +743,12 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock()
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);
int ordidx = prologue; int ordidx = prologue;
for (int i = 0; i < num_simblocks; i++) for (int blk = prologue; blk < prologue+num_simblocks; blk++)
{ {
auto subG = G.extractSubgraph(eqs_in_simblock[i]); blocks[blk].first_equation = (blk == 0 ? 0 : blocks[blk-1].first_equation + blocks[blk-1].size);
auto subG = G.extractSubgraph(simblock2simvars[blk-prologue]);
auto feed_back_vertices = subG.minimalSetOfFeedbackVertices(); auto feed_back_vertices = subG.minimalSetOfFeedbackVertices();
blocks[prologue+i].mfs_size = feed_back_vertices.size(); blocks[blk].mfs_size = feed_back_vertices.size();
auto recursive_vertices = subG.reorderRecursiveVariables(feed_back_vertices); auto recursive_vertices = subG.reorderRecursiveVariables(feed_back_vertices);
auto v_index1 = get(boost::vertex_index1, subG); auto v_index1 = get(boost::vertex_index1, subG);
@ -816,19 +811,17 @@ ModelTree::printBlockDecomposition() const
void void
ModelTree::reduceBlocksAndTypeDetermination(bool linear_decomposition) ModelTree::reduceBlocksAndTypeDetermination(bool linear_decomposition)
{ {
for (int i = 0; i < static_cast<int>(blocks.size()); i++) for (int blk = 0; blk < static_cast<int>(blocks.size()); blk++)
{ {
int first_eq = (i == 0) ? 0 : blocks[i-1].first_equation+blocks[i-1].size;
/* Compute the maximum lead and lag across all endogenous that appear in /* Compute the maximum lead and lag across all endogenous that appear in
this block and that belong to it */ this block and that belong to it */
int max_lag = 0, max_lead = 0; int max_lag = 0, max_lead = 0;
for (int eq = first_eq; eq < first_eq+blocks[i].size; eq++) for (int eq = 0; eq < blocks[blk].size; eq++)
{ {
set<pair<int, int>> endos_and_lags; set<pair<int, int>> endos_and_lags;
equations[eq_idx_block2orig[eq]]->collectEndogenous(endos_and_lags); getBlockEquationExpr(blk, eq)->collectEndogenous(endos_and_lags);
for (const auto &[endo, lag] : endos_and_lags) for (const auto &[endo, lag] : endos_and_lags)
if (linear_decomposition || endo2block[endo] == i) if (linear_decomposition || endo2block[endo] == blk)
{ {
max_lead = max(lag, max_lead); max_lead = max(lag, max_lead);
max_lag = max(-lag, max_lag); max_lag = max(-lag, max_lag);
@ -839,12 +832,12 @@ ModelTree::reduceBlocksAndTypeDetermination(bool linear_decomposition)
BlockSimulationType Simulation_Type; BlockSimulationType Simulation_Type;
if (max_lag > 0 && max_lead > 0) if (max_lag > 0 && max_lead > 0)
{ {
if (blocks[i].size == 1) if (blocks[blk].size == 1)
Simulation_Type = BlockSimulationType::solveTwoBoundariesSimple; Simulation_Type = BlockSimulationType::solveTwoBoundariesSimple;
else else
Simulation_Type = BlockSimulationType::solveTwoBoundariesComplete; Simulation_Type = BlockSimulationType::solveTwoBoundariesComplete;
} }
else if (blocks[i].size > 1) else if (blocks[blk].size > 1)
{ {
if (max_lead > 0) if (max_lead > 0)
Simulation_Type = BlockSimulationType::solveBackwardComplete; Simulation_Type = BlockSimulationType::solveBackwardComplete;
@ -859,11 +852,11 @@ ModelTree::reduceBlocksAndTypeDetermination(bool linear_decomposition)
Simulation_Type = BlockSimulationType::solveForwardSimple; Simulation_Type = BlockSimulationType::solveForwardSimple;
} }
if (blocks[i].size == 1) if (blocks[blk].size == 1)
{ {
// Determine if the block can simply be evaluated // Determine if the block can simply be evaluated
if (equation_type_and_normalized_equation[eq_idx_block2orig[first_eq]].first == EquationType::evaluate if (getBlockEquationType(blk, 0) == EquationType::evaluate
|| equation_type_and_normalized_equation[eq_idx_block2orig[first_eq]].first == EquationType::evaluate_s) || getBlockEquationType(blk, 0) == EquationType::evaluate_s)
{ {
if (Simulation_Type == BlockSimulationType::solveBackwardSimple) if (Simulation_Type == BlockSimulationType::solveBackwardSimple)
Simulation_Type = BlockSimulationType::evaluateBackward; Simulation_Type = BlockSimulationType::evaluateBackward;
@ -875,19 +868,18 @@ ModelTree::reduceBlocksAndTypeDetermination(bool linear_decomposition)
This is only possible if the two blocks can simply be evaluated This is only possible if the two blocks can simply be evaluated
(in the same direction), and if the merge does not break the (in the same direction), and if the merge does not break the
restrictions on leads/lags. */ restrictions on leads/lags. */
if (i > 0) if (blk > 0)
{ {
set<pair<int, int>> endos_and_lags;
getBlockEquationExpr(blk, 0)->collectEndogenous(endos_and_lags);
bool is_lead = false, is_lag = false; bool is_lead = false, is_lag = false;
for (int j = blocks[i-1].first_equation; for (int var = 0; var < blocks[blk-1].size; var++)
j < blocks[i-1].first_equation+blocks[i-1].size; j++)
{ {
set<pair<int, int>> endos_and_lags; is_lag = endos_and_lags.find({ getBlockVariableID(blk-1, var), -1 }) != endos_and_lags.end();
equations[eq_idx_block2orig[first_eq]]->collectEndogenous(endos_and_lags); is_lead = endos_and_lags.find({ getBlockVariableID(blk-1, var), 1 }) != endos_and_lags.end();
is_lag = endos_and_lags.find({ endo_idx_block2orig[j], -1 }) != endos_and_lags.end();
is_lead = endos_and_lags.find({ endo_idx_block2orig[j], 1 }) != endos_and_lags.end();
} }
BlockSimulationType prev_Type = blocks[i-1].simulation_type; BlockSimulationType prev_Type = blocks[blk-1].simulation_type;
if ((prev_Type == BlockSimulationType::evaluateForward if ((prev_Type == BlockSimulationType::evaluateForward
&& Simulation_Type == BlockSimulationType::evaluateForward && Simulation_Type == BlockSimulationType::evaluateForward
&& !is_lead) && !is_lead)
@ -896,35 +888,34 @@ ModelTree::reduceBlocksAndTypeDetermination(bool linear_decomposition)
&& !is_lag)) && !is_lag))
{ {
// Merge the current block into the previous one // Merge the current block into the previous one
blocks[i-1].size++; blocks[blk-1].size++;
blocks[i-1].mfs_size = blocks[i-1].size; blocks[blk-1].mfs_size = blocks[blk-1].size;
/* For max lag/lead, the max of the two blocks is not enough. /* For max lag/lead, the max of the two blocks is not enough.
We need to consider the case where a variable of the We need to consider the case where a variable of the
previous block appears with a lag/lead in the current one previous block appears with a lag/lead in the current one
(the reverse case is excluded, by construction). */ (the reverse case is excluded, by construction). */
blocks[i-1].max_lag = is_lag ? 1 : max(blocks[i-1].max_lag, max_lag); blocks[blk-1].max_lag = is_lag ? 1 : max(blocks[blk-1].max_lag, max_lag);
blocks[i-1].max_lead = is_lead ? 1 : max(blocks[i-1].max_lead, max_lead); blocks[blk-1].max_lead = is_lead ? 1 : max(blocks[blk-1].max_lead, max_lead);
blocks[i-1].n_static += blocks[i].n_static; blocks[blk-1].n_static += blocks[blk].n_static;
blocks[i-1].n_forward += blocks[i].n_forward; blocks[blk-1].n_forward += blocks[blk].n_forward;
blocks[i-1].n_backward += blocks[i].n_backward; blocks[blk-1].n_backward += blocks[blk].n_backward;
blocks[i-1].n_mixed += blocks[i].n_mixed; blocks[blk-1].n_mixed += blocks[blk].n_mixed;
blocks.erase(blocks.begin()+i); blocks.erase(blocks.begin()+blk);
for (auto &b : endo2block) for (auto &b : endo2block)
if (b >= i) if (b >= blk)
b--; b--;
for (auto &b : eq2block) for (auto &b : eq2block)
if (b >= i) if (b >= blk)
b--; b--;
i--; blk--;
continue; continue;
} }
} }
} }
blocks[i].simulation_type = Simulation_Type; blocks[blk].simulation_type = Simulation_Type;
blocks[i].first_equation = first_eq; blocks[blk].max_lag = max_lag;
blocks[i].max_lag = max_lag; blocks[blk].max_lead = max_lead;
blocks[i].max_lead = max_lead;
} }
} }

View File

@ -301,7 +301,7 @@ protected:
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
Initializes the blocks structure, and fills the following fields: size, Initializes the blocks structure, and fills the following fields: size, first_equation,
mfs_size, n_static, n_forward, n_backward, n_mixed. mfs_size, n_static, n_forward, n_backward, n_mixed.
Also initializes the endo2block and eq2block structures. */ Also initializes the endo2block and eq2block structures. */
void computeBlockDecompositionAndFeedbackVariablesForEachBlock(); void computeBlockDecompositionAndFeedbackVariablesForEachBlock();
@ -309,7 +309,7 @@ protected:
prologue and the epilogue, and determine the type of each block. prologue and the epilogue, and determine the type of each block.
Fills the following fields of the blocks structure: simulation_type, Fills the following fields of the blocks structure: simulation_type,
first_equation, max_lead, max_lag. */ max_lead, max_lag. */
void reduceBlocksAndTypeDetermination(bool linear_decomposition); 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