Block decomposition: various refactorings
parent
1d92adacf4
commit
8eafd9ab4f
|
@ -4809,9 +4809,7 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
|
|||
if (!computeNaturalNormalization())
|
||||
computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian);
|
||||
|
||||
lag_lead_vector_t equation_lag_lead, variable_lag_lead;
|
||||
|
||||
tie(simblock_size, equation_lag_lead, variable_lag_lead, n_static, n_forward, n_backward, n_mixed)
|
||||
tie(simblock_size, n_static, n_forward, n_backward, n_mixed)
|
||||
= select_non_linear_equations_and_variables(is_equation_linear);
|
||||
|
||||
equationTypeDetermination(first_order_endo_derivatives, 0);
|
||||
|
@ -4847,9 +4845,9 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
|
|||
|
||||
cout << "Finding the optimal block decomposition of the model ..." << endl;
|
||||
|
||||
lag_lead_vector_t equation_lag_lead, variable_lag_lead;
|
||||
lag_lead_vector_t variable_lag_lead;
|
||||
|
||||
tie(simblock_size, equation_lag_lead, variable_lag_lead, n_static, n_forward, n_backward, n_mixed) = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, equation_type_and_normalized_equation, false, true);
|
||||
tie(simblock_size, variable_lag_lead, n_static, n_forward, n_backward, n_mixed) = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, equation_type_and_normalized_equation, false);
|
||||
|
||||
reduceBlocksAndTypeDetermination(simblock_size, equation_type_and_normalized_equation, n_static, n_forward, n_backward, n_mixed, linear_decomposition);
|
||||
|
||||
|
|
123
src/ModelTree.cc
123
src/ModelTree.cc
|
@ -456,8 +456,7 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context, double
|
|||
return { contemporaneous_jacobian, static_jacobian };
|
||||
}
|
||||
|
||||
tuple<vector<pair<int, int>>, lag_lead_vector_t, lag_lead_vector_t,
|
||||
vector<int>, vector<int>, vector<int>, vector<int>>
|
||||
tuple<vector<pair<int, int>>, vector<int>, vector<int>, vector<int>, vector<int>>
|
||||
ModelTree::select_non_linear_equations_and_variables(const vector<bool> &is_equation_linear)
|
||||
{
|
||||
vector<int> eq2endo(equations.size(), 0);
|
||||
|
@ -476,7 +475,7 @@ ModelTree::select_non_linear_equations_and_variables(const vector<bool> &is_equa
|
|||
i++;
|
||||
j++;
|
||||
}
|
||||
auto [equation_lag_lead, variable_lag_lead] = getVariableLeadLagByBlock(endo2block, endo2block.size());
|
||||
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++)
|
||||
|
@ -493,8 +492,7 @@ ModelTree::select_non_linear_equations_and_variables(const vector<bool> &is_equa
|
|||
cout.flush();
|
||||
vector<pair<int, int>> simblock_size(1, {i, i});
|
||||
updateReverseVariableEquationOrderings();
|
||||
return { simblock_size, equation_lag_lead, variable_lag_lead,
|
||||
n_static, n_forward, n_backward, n_mixed };
|
||||
return { simblock_size, n_static, n_forward, n_backward, n_mixed };
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -530,18 +528,14 @@ ModelTree::computePrologueAndEpilogue(const jacob_map_t &static_jacobian)
|
|||
{
|
||||
const int n = equations.size();
|
||||
|
||||
/* Compute reverse map (eq→endo) of normalization. Also initialize
|
||||
“eq_idx_block2orig” and “endo_idx_block2orig” to the identity
|
||||
/* Initialize “eq_idx_block2orig” and “endo_idx_block2orig” to the identity
|
||||
permutation. */
|
||||
vector<int> eq2endo(n);
|
||||
eq_idx_block2orig.resize(n);
|
||||
endo_idx_block2orig.resize(n);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int it = endo2eq[i];
|
||||
eq2endo[it] = i;
|
||||
eq_idx_block2orig[i] = i;
|
||||
endo_idx_block2orig[it] = i;
|
||||
endo_idx_block2orig[endo2eq[i]] = i;
|
||||
}
|
||||
|
||||
/* Compute incidence matrix, equations in rows, variables in columns. Row
|
||||
|
@ -677,53 +671,42 @@ ModelTree::equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &fi
|
|||
}
|
||||
|
||||
pair<lag_lead_vector_t, lag_lead_vector_t>
|
||||
ModelTree::getVariableLeadLagByBlock(const vector<int> &endo2simblock, int num_simblocks) const
|
||||
ModelTree::getVariableLeadLagByBlock(const vector<int> &endo2simblock) const
|
||||
{
|
||||
int nb_endo = symbol_table.endo_nbr();
|
||||
lag_lead_vector_t variable_lead_lag(nb_endo, { 0, 0 }), equation_lead_lag(nb_endo, { 0, 0 });
|
||||
vector<int> variable_blck(nb_endo), equation_blck(nb_endo);
|
||||
for (int i = 0; i < nb_endo; i++)
|
||||
{
|
||||
if (i < prologue)
|
||||
{
|
||||
variable_blck[endo_idx_block2orig[i]] = i;
|
||||
equation_blck[eq_idx_block2orig[i]] = i;
|
||||
}
|
||||
else if (i < static_cast<int>(endo2simblock.size()) + prologue)
|
||||
{
|
||||
variable_blck[endo_idx_block2orig[i]] = endo2simblock[i-prologue] + prologue;
|
||||
equation_blck[eq_idx_block2orig[i]] = endo2simblock[i-prologue] + prologue;
|
||||
}
|
||||
else
|
||||
{
|
||||
variable_blck[endo_idx_block2orig[i]] = i - (nb_endo - num_simblocks - prologue - epilogue);
|
||||
equation_blck[eq_idx_block2orig[i]] = i - (nb_endo - num_simblocks - prologue - epilogue);
|
||||
}
|
||||
}
|
||||
|
||||
auto belong_to_same_block = [&](int endo, int eq)
|
||||
{
|
||||
int endo2 = endo_idx_orig2block[endo];
|
||||
int eq2 = eq_idx_orig2block[eq];
|
||||
if (endo2 < prologue || endo2 >= nb_endo-epilogue
|
||||
|| eq2 < prologue || eq2 >= nb_endo-epilogue)
|
||||
return endo2 == eq2;
|
||||
else
|
||||
return endo2simblock[endo2-prologue] == endo2simblock[eq2-prologue];
|
||||
};
|
||||
|
||||
lag_lead_vector_t variable_lag_lead(nb_endo, { 0, 0 }), equation_lag_lead(nb_endo, { 0, 0 });
|
||||
for (const auto &[key, value] : dynamic_jacobian)
|
||||
{
|
||||
auto [lag, j_1, i_1] = key;
|
||||
if (variable_blck[i_1] == equation_blck[j_1])
|
||||
auto [lag, eq, endo] = key;
|
||||
if (belong_to_same_block(endo, eq))
|
||||
{
|
||||
if (lag > variable_lead_lag[i_1].second)
|
||||
variable_lead_lag[i_1] = { variable_lead_lag[i_1].first, lag };
|
||||
if (lag < -variable_lead_lag[i_1].first)
|
||||
variable_lead_lag[i_1] = { -lag, variable_lead_lag[i_1].second };
|
||||
if (lag > equation_lead_lag[j_1].second)
|
||||
equation_lead_lag[j_1] = { equation_lead_lag[j_1].first, lag };
|
||||
if (lag < -equation_lead_lag[j_1].first)
|
||||
equation_lead_lag[j_1] = { -lag, equation_lead_lag[j_1].second };
|
||||
variable_lag_lead[endo].first = max(variable_lag_lead[endo].first, -lag);
|
||||
variable_lag_lead[endo].second = max(variable_lag_lead[endo].second, lag);
|
||||
equation_lag_lead[eq].first = max(equation_lag_lead[eq].first, -lag);
|
||||
equation_lag_lead[eq].second = max(equation_lag_lead[eq].second, lag);
|
||||
}
|
||||
}
|
||||
return { equation_lead_lag, variable_lead_lag };
|
||||
return { equation_lag_lead, variable_lag_lead };
|
||||
}
|
||||
|
||||
tuple<vector<pair<int, int>>, lag_lead_vector_t, lag_lead_vector_t,
|
||||
tuple<vector<pair<int, int>>, lag_lead_vector_t,
|
||||
vector<int>, vector<int>, vector<int>, vector<int>>
|
||||
ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_, bool select_feedback_variable)
|
||||
ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_)
|
||||
{
|
||||
int nb_var = endo_idx_block2orig.size();
|
||||
int n = nb_var - prologue - epilogue;
|
||||
int nb_var = symbol_table.endo_nbr();
|
||||
int nb_simvars = nb_var - prologue - epilogue;
|
||||
|
||||
/* Construct the graph representing the dependencies between all
|
||||
variables that do not belong to the prologue or the epilogue.
|
||||
|
@ -731,7 +714,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
|
|||
For detecting dependencies between variables, use the static jacobian,
|
||||
except when the cutoff is zero, in which case use the symbolic adjacency
|
||||
matrix */
|
||||
VariableDependencyGraph G(n);
|
||||
VariableDependencyGraph G(nb_simvars);
|
||||
for (const auto &[key, value] : cutoff == 0 ? computeSymbolicJacobian() : static_jacobian)
|
||||
{
|
||||
auto [eq, endo] = key;
|
||||
|
@ -758,25 +741,18 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
|
|||
eqs_in_simblock[endo2simblock[i]].insert(i);
|
||||
}
|
||||
|
||||
auto [equation_lag_lead, variable_lag_lead] = getVariableLeadLagByBlock(endo2simblock, num_simblocks);
|
||||
auto [equation_lag_lead, variable_lag_lead] = getVariableLeadLagByBlock(endo2simblock);
|
||||
|
||||
/* Add a loop on vertices which could not be normalized or vertices related
|
||||
to lead variables. This forces those vertices to belong to the feedback set */
|
||||
if (select_feedback_variable)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
if (Equation_Type[eq_idx_block2orig[i+prologue]].first == EquationType::solve
|
||||
|| variable_lag_lead[endo_idx_block2orig[i+prologue]].second > 0
|
||||
|| variable_lag_lead[endo_idx_block2orig[i+prologue]].first > 0
|
||||
|| equation_lag_lead[eq_idx_block2orig[i+prologue]].second > 0
|
||||
|| equation_lag_lead[eq_idx_block2orig[i+prologue]].first > 0
|
||||
|| mfs == 0)
|
||||
add_edge(vertex(i, G), vertex(i, G), G);
|
||||
}
|
||||
else
|
||||
for (int i = 0; i < n; i++)
|
||||
if (Equation_Type[eq_idx_block2orig[i+prologue]].first == EquationType::solve || mfs == 0)
|
||||
add_edge(vertex(i, G), vertex(i, G), G);
|
||||
to lead/lag variables. This forces those vertices to belong to the feedback set */
|
||||
for (int i = 0; i < nb_simvars; i++)
|
||||
if (Equation_Type[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]].second > 0
|
||||
|| equation_lag_lead[eq_idx_block2orig[i+prologue]].first > 0
|
||||
|| equation_lag_lead[eq_idx_block2orig[i+prologue]].second > 0
|
||||
|| mfs == 0)
|
||||
add_edge(vertex(i, G), vertex(i, G), G);
|
||||
|
||||
int num_blocks = prologue+num_simblocks+epilogue;
|
||||
// Determines the dynamic structure of each equation
|
||||
|
@ -786,8 +762,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
|
|||
const vector<int> old_eq_idx_block2orig(eq_idx_block2orig), old_endo_idx_block2orig(endo_idx_block2orig);
|
||||
for (int i = 0; i < prologue; i++)
|
||||
{
|
||||
int max_lag = variable_lag_lead[old_endo_idx_block2orig[i]].first;
|
||||
int max_lead = variable_lag_lead[old_endo_idx_block2orig[i]].second;
|
||||
auto [max_lag, max_lead] = variable_lag_lead[old_endo_idx_block2orig[i]];
|
||||
if (max_lag != 0 && max_lead != 0)
|
||||
n_mixed[i]++;
|
||||
else if (max_lag == 0 && max_lead != 0)
|
||||
|
@ -806,7 +781,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
|
|||
for (int i = 0; i < num_simblocks; i++)
|
||||
{
|
||||
auto subG = G.extractSubgraph(eqs_in_simblock[i]);
|
||||
auto [G1, feed_back_vertices] = subG.minimalSetOfFeedbackVertices();
|
||||
auto feed_back_vertices = subG.minimalSetOfFeedbackVertices();
|
||||
auto v_index1 = get(boost::vertex_index1, subG);
|
||||
simblock_size[i].second = feed_back_vertices.size();
|
||||
auto reordered_vertices = subG.reorderRecursiveVariables(feed_back_vertices);
|
||||
|
@ -815,8 +790,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
|
|||
for (int j = 0; j < 4; j++)
|
||||
for (int its : reordered_vertices)
|
||||
{
|
||||
int max_lag = variable_lag_lead[old_endo_idx_block2orig[its+prologue]].first;
|
||||
int max_lead = variable_lag_lead[old_endo_idx_block2orig[its+prologue]].second;
|
||||
auto [max_lag, max_lead] = variable_lag_lead[old_endo_idx_block2orig[its+prologue]];
|
||||
auto reorder = [&]()
|
||||
{
|
||||
eq_idx_block2orig[ordidx] = old_eq_idx_block2orig[its+prologue];
|
||||
|
@ -850,8 +824,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
|
|||
for (int fbvertex : feed_back_vertices)
|
||||
{
|
||||
int idx = v_index1[vertex(fbvertex, subG)];
|
||||
int max_lag = variable_lag_lead[old_endo_idx_block2orig[idx+prologue]].first;
|
||||
int max_lead = variable_lag_lead[old_endo_idx_block2orig[idx+prologue]].second;
|
||||
auto [max_lag, max_lead] = variable_lag_lead[old_endo_idx_block2orig[idx+prologue]];
|
||||
auto reorder = [&]()
|
||||
{
|
||||
eq_idx_block2orig[ordidx] = old_eq_idx_block2orig[idx+prologue];
|
||||
|
@ -883,8 +856,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
|
|||
|
||||
for (int i = 0; i < epilogue; i++)
|
||||
{
|
||||
int max_lag = variable_lag_lead[old_endo_idx_block2orig[prologue+n+i]].first;
|
||||
int max_lead = variable_lag_lead[old_endo_idx_block2orig[prologue+n+i]].second;
|
||||
auto [max_lag, max_lead] = variable_lag_lead[old_endo_idx_block2orig[prologue+nb_simvars+i]];
|
||||
if (max_lag != 0 && max_lead != 0)
|
||||
n_mixed[prologue+num_simblocks+i]++;
|
||||
else if (max_lag == 0 && max_lead != 0)
|
||||
|
@ -897,8 +869,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob
|
|||
|
||||
updateReverseVariableEquationOrderings();
|
||||
|
||||
return { simblock_size, equation_lag_lead, variable_lag_lead,
|
||||
n_static, n_forward, n_backward, n_mixed };
|
||||
return { simblock_size, variable_lag_lead, n_static, n_forward, n_backward, n_mixed };
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -302,22 +302,26 @@ protected:
|
|||
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);
|
||||
//! Select and reorder the non linear equations of the model
|
||||
/*! Returns a tuple (blocks, equation_lag_lead, variable_lag_lead, n_static,
|
||||
n_forward, n_backward, n_mixed) */
|
||||
tuple<vector<pair<int, int>>, lag_lead_vector_t, lag_lead_vector_t, vector<int>, vector<int>, vector<int>, vector<int>> select_non_linear_equations_and_variables(const vector<bool> &is_equation_linear);
|
||||
/*! Returns a tuple (blocks, n_static, n_forward, n_backward, n_mixed) */
|
||||
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
|
||||
void computePrologueAndEpilogue(const jacob_map_t &static_jacobian);
|
||||
//! 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);
|
||||
//! Compute the block decomposition and for a non-recusive block find the minimum feedback set
|
||||
/*! Returns a tuple (blocks, equation_lag_lead, variable_lag_lead, n_static,
|
||||
n_forward, n_backward, n_mixed) */
|
||||
tuple<vector<pair<int, int>>, lag_lead_vector_t, 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_, bool select_feedback_variable);
|
||||
/*! 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_);
|
||||
//! Reduce the number of block merging the same type equation in the prologue and the epilogue and determine the type of each block
|
||||
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);
|
||||
//! Determine the maximum number of lead and lag for the endogenous variable in a bloc
|
||||
/*! Returns a pair { equation_lead,lag, variable_lead_lag } */
|
||||
pair<lag_lead_vector_t, lag_lead_vector_t> getVariableLeadLagByBlock(const vector<int> &endo2simblock, int num_simblocks) const;
|
||||
/* 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
|
||||
belong to the same block (i.e. those endogenous are solved in the same
|
||||
block).
|
||||
|
||||
The 2nd output gives, for each type-specific endo IDs, its (max_lag,
|
||||
max_lead) across all its occurences inside the equations of the block to
|
||||
which it belongs. */
|
||||
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
|
||||
vector<bool> equationLinear(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives) const;
|
||||
//! Print an abstract of the block structure of the model
|
||||
|
|
|
@ -1142,7 +1142,7 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
|
|||
|
||||
cout << "Finding the optimal block decomposition of the model ..." << endl;
|
||||
|
||||
auto [blocks, equation_lag_lead, variable_lag_lead, n_static, n_forward, n_backward, n_mixed] = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, equation_type_and_normalized_equation, false, false);
|
||||
auto [blocks, variable_lag_lead, n_static, n_forward, n_backward, n_mixed] = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, equation_type_and_normalized_equation, false);
|
||||
|
||||
reduceBlocksAndTypeDetermination(blocks, equation_type_and_normalized_equation, n_static, n_forward, n_backward, n_mixed, false);
|
||||
|
||||
|
|
|
@ -320,7 +320,7 @@ VariableDependencyGraph::suppressionOfVerticesWithLoop(set<int> &feed_back_verti
|
|||
return something_has_been_done;
|
||||
}
|
||||
|
||||
pair<VariableDependencyGraph, set<int>>
|
||||
set<int>
|
||||
VariableDependencyGraph::minimalSetOfFeedbackVertices() const
|
||||
{
|
||||
bool something_has_been_done = true;
|
||||
|
@ -354,7 +354,7 @@ VariableDependencyGraph::minimalSetOfFeedbackVertices() const
|
|||
#ifdef verbose
|
||||
cout << "has_cycle=false\n";
|
||||
#endif
|
||||
return { G, feed_back_vertices };
|
||||
return feed_back_vertices;
|
||||
}
|
||||
if (num_vertices(G) > 0)
|
||||
{
|
||||
|
@ -383,7 +383,7 @@ VariableDependencyGraph::minimalSetOfFeedbackVertices() const
|
|||
#ifdef verbose
|
||||
cout << "cut_=" << cut_ << "\n";
|
||||
#endif
|
||||
return { G, feed_back_vertices };
|
||||
return feed_back_vertices;
|
||||
}
|
||||
|
||||
vector<int>
|
||||
|
|
|
@ -56,7 +56,7 @@ public:
|
|||
*/
|
||||
VariableDependencyGraph extractSubgraph(const set<int> &select_index) const;
|
||||
//! Return the feedback set
|
||||
pair<VariableDependencyGraph, set<int>> minimalSetOfFeedbackVertices() const;
|
||||
set<int> minimalSetOfFeedbackVertices() const;
|
||||
//! Reorder the recursive variables
|
||||
/*! They appear first in a quasi triangular form and they are followed by the feedback variables */
|
||||
vector<int> reorderRecursiveVariables(const set<int> &feedback_vertices) const;
|
||||
|
@ -65,6 +65,8 @@ public:
|
|||
Returns the number of SCCs, and a mapping of vertex indices to sorted SCC
|
||||
indices. */
|
||||
pair<int, vector<int>> sortedStronglyConnectedComponents() const;
|
||||
// Print on stdout a description of the graph
|
||||
void print() const;
|
||||
private:
|
||||
// Remove a vertex (including all edges to and from it); takes a vertex descriptor
|
||||
void suppress(vertex_descriptor vertex_to_eliminate);
|
||||
|
@ -78,8 +80,6 @@ private:
|
|||
bool hasCycleDFS(vertex_descriptor u, color_t &color, vector<int> &circuit_stack) const;
|
||||
// Determine whether the graph has a cycle
|
||||
bool hasCycle() const;
|
||||
// Print on stdout a description of the graph
|
||||
void print() const;
|
||||
bool vertexBelongsToAClique(vertex_descriptor vertex) const;
|
||||
bool eliminationOfVerticesWithOneOrLessIndegreeOrOutdegree();
|
||||
bool eliminationOfVerticesBelongingToAClique();
|
||||
|
|
Loading…
Reference in New Issue