Now compute blocks[].first_equation from ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock
Also include various cosmetic changes.issue#70
parent
1886746581
commit
7f57821401
111
src/ModelTree.cc
111
src/ModelTree.cc
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue