2009-05-19 10:57:07 +02:00
|
|
|
/*
|
2010-12-13 14:23:04 +01:00
|
|
|
* Copyright (C) 2009-2010 Dynare Team
|
2009-05-19 10:57:07 +02:00
|
|
|
*
|
|
|
|
* This file is part of Dynare.
|
|
|
|
*
|
|
|
|
* Dynare is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Dynare is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2009-06-30 16:43:59 +02:00
|
|
|
#include <iostream>
|
|
|
|
|
2009-05-13 01:03:40 +02:00
|
|
|
#include "MinimumFeedbackSet.hh"
|
|
|
|
|
|
|
|
namespace MFS
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
|
|
|
void
|
2010-09-16 19:00:48 +02:00
|
|
|
Suppress(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G)
|
2009-05-13 01:03:40 +02:00
|
|
|
{
|
2009-12-16 18:13:23 +01:00
|
|
|
clear_vertex(vertex_to_eliminate, G);
|
|
|
|
remove_vertex(vertex_to_eliminate, G);
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
void
|
2010-09-16 19:00:48 +02:00
|
|
|
Suppress(int vertex_num, AdjacencyList_t &G)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
|
|
|
Suppress(vertex(vertex_num, G), G);
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
void
|
2010-09-16 19:00:48 +02:00
|
|
|
Eliminate(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
|
|
|
if (in_degree(vertex_to_eliminate, G) > 0 && out_degree(vertex_to_eliminate, G) > 0)
|
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
|
|
|
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(it_in, in_end) = in_edges(vertex_to_eliminate, G); it_in != in_end; ++it_in)
|
|
|
|
for (tie(it_out, out_end) = out_edges(vertex_to_eliminate, G); it_out != out_end; ++it_out)
|
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::edge_descriptor ed;
|
2009-12-16 18:13:23 +01:00
|
|
|
bool exist;
|
|
|
|
tie(ed, exist) = edge(source(*it_in, G), target(*it_out, G), G);
|
|
|
|
if (!exist)
|
|
|
|
add_edge(source(*it_in, G), target(*it_out, G), G);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Suppress(vertex_to_eliminate, G);
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
bool
|
2010-09-16 19:00:48 +02:00
|
|
|
has_cycle_dfs(AdjacencyList_t &g, AdjacencyList_t::vertex_descriptor u, color_t &color, vector<int> &circuit_stack)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, g);
|
2009-12-16 18:13:23 +01:00
|
|
|
color[u] = gray_color;
|
2010-09-16 19:00:48 +02:00
|
|
|
graph_traits<AdjacencyList_t>::out_edge_iterator vi, vi_end;
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(vi, vi_end) = out_edges(u, g); vi != vi_end; ++vi)
|
|
|
|
if (color[target(*vi, g)] == white_color && has_cycle_dfs(g, target(*vi, g), color, circuit_stack))
|
2009-05-13 01:03:40 +02:00
|
|
|
{
|
2009-12-16 18:13:23 +01:00
|
|
|
// cycle detected, return immediately
|
|
|
|
circuit_stack.push_back(v_index[target(*vi, g)]);
|
2009-06-30 16:43:59 +02:00
|
|
|
return true;
|
2009-05-13 01:03:40 +02:00
|
|
|
}
|
2009-12-16 18:13:23 +01:00
|
|
|
else if (color[target(*vi, g)] == gray_color)
|
2009-05-13 01:03:40 +02:00
|
|
|
{
|
2009-12-16 18:13:23 +01:00
|
|
|
// *vi is an ancestor!
|
|
|
|
circuit_stack.push_back(v_index[target(*vi, g)]);
|
|
|
|
return true;
|
2009-05-13 01:03:40 +02:00
|
|
|
}
|
2009-12-16 18:13:23 +01:00
|
|
|
color[u] = black_color;
|
|
|
|
return false;
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
bool
|
2010-09-16 19:00:48 +02:00
|
|
|
has_cycle(vector<int> &circuit_stack, AdjacencyList_t &g)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
|
|
|
// Initialize color map to white
|
2010-09-16 19:00:48 +02:00
|
|
|
color_t color;
|
|
|
|
graph_traits<AdjacencyList_t>::vertex_iterator vi, vi_end;
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
|
|
|
color[*vi] = white_color;
|
|
|
|
|
|
|
|
// Perform depth-first search
|
|
|
|
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
|
|
|
if (color[*vi] == white_color && has_cycle_dfs(g, *vi, color, circuit_stack))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
void
|
2010-09-16 19:00:48 +02:00
|
|
|
Print(AdjacencyList_t &G)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::vertex_iterator it, it_end;
|
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "Graph\n";
|
|
|
|
cout << "-----\n";
|
|
|
|
for (tie(it, it_end) = vertices(G); it != it_end; ++it)
|
|
|
|
{
|
|
|
|
cout << "vertex[" << v_index[*it] + 1 << "] <-";
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(it_in, in_end) = in_edges(*it, G); it_in != in_end; ++it_in)
|
|
|
|
cout << v_index[source(*it_in, G)] + 1 << " ";
|
|
|
|
cout << "\n ->";
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(it_out, out_end) = out_edges(*it, G); it_out != out_end; ++it_out)
|
|
|
|
cout << v_index[target(*it_out, G)] + 1 << " ";
|
|
|
|
cout << "\n";
|
|
|
|
}
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t
|
2009-12-16 18:13:23 +01:00
|
|
|
AM_2_AdjacencyList(bool *AM, unsigned int n)
|
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t G(n);
|
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
|
|
|
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
for (unsigned int i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
put(v_index, vertex(i, G), i);
|
|
|
|
put(v_index1, vertex(i, G), i);
|
|
|
|
}
|
|
|
|
for (unsigned int i = 0; i < n; i++)
|
|
|
|
for (unsigned int j = 0; j < n; j++)
|
|
|
|
if (AM[i*n+j])
|
|
|
|
add_edge(vertex(j, G), vertex(i, G), G);
|
|
|
|
return G;
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t
|
2010-12-13 14:23:04 +01:00
|
|
|
extract_subgraph(AdjacencyList_t &G1, set<int> select_index)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
|
|
|
unsigned int n = select_index.size();
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t G(n);
|
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
|
|
|
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
|
2010-12-13 14:23:04 +01:00
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v1_index = get(vertex_index, G1);
|
2009-12-16 18:13:23 +01:00
|
|
|
map<int, int> reverse_index;
|
2010-12-13 14:23:04 +01:00
|
|
|
set<int>::iterator it;
|
|
|
|
unsigned int i;
|
|
|
|
for (it = select_index.begin(), i = 0; i < n; i++, ++it)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
2010-12-13 14:23:04 +01:00
|
|
|
reverse_index[get(v1_index, vertex(*it, G1))] = i;
|
|
|
|
put(v_index, vertex(i, G), get(v1_index, vertex(*it, G1)));
|
2009-12-16 18:13:23 +01:00
|
|
|
put(v_index1, vertex(i, G), i);
|
|
|
|
}
|
|
|
|
for (it = select_index.begin(), i = 0; i < n; i++, ++it)
|
|
|
|
{
|
2010-12-13 14:23:04 +01:00
|
|
|
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
|
|
|
AdjacencyList_t::vertex_descriptor vi = vertex(*it, G1);
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(it_out, out_end) = out_edges(vi, G1); it_out != out_end; ++it_out)
|
|
|
|
{
|
2010-12-13 14:23:04 +01:00
|
|
|
int ii = v1_index[target(*it_out, G1)];
|
2009-12-16 18:13:23 +01:00
|
|
|
if (select_index.find(ii) != select_index.end())
|
2010-12-13 14:23:04 +01:00
|
|
|
add_edge(vertex(reverse_index[get(v1_index, source(*it_out, G1))], G), vertex(reverse_index[get(v1_index, target(*it_out, G1))], G), G);
|
2009-12-16 18:13:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return G;
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2010-09-16 19:00:48 +02:00
|
|
|
vector_vertex_descriptor_t
|
|
|
|
Collect_Doublet(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
|
|
|
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
|
|
|
vector<AdjacencyList_t::vertex_descriptor> Doublet;
|
2009-12-16 18:13:23 +01:00
|
|
|
if (in_degree(vertex, G) > 0 && out_degree(vertex, G) > 0)
|
|
|
|
for (tie(it_in, in_end) = in_edges(vertex, G); it_in != in_end; ++it_in)
|
|
|
|
for (tie(it_out, out_end) = out_edges(vertex, G); it_out != out_end; ++it_out)
|
|
|
|
if (source(*it_in, G) == target(*it_out, G) && source(*it_in, G) != target(*it_in, G)) // not a loop
|
|
|
|
Doublet.push_back(source(*it_in, G));
|
|
|
|
return Doublet;
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
bool
|
2010-09-16 19:00:48 +02:00
|
|
|
Vertex_Belong_to_a_Clique(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
vector<AdjacencyList_t::vertex_descriptor> liste;
|
2009-12-16 18:13:23 +01:00
|
|
|
bool agree = true;
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
|
|
|
AdjacencyList_t::out_edge_iterator it_out, out_end;
|
2009-12-16 18:13:23 +01:00
|
|
|
tie(it_in, in_end) = in_edges(vertex, G);
|
|
|
|
tie(it_out, out_end) = out_edges(vertex, G);
|
|
|
|
while (it_in != in_end && it_out != out_end && agree)
|
|
|
|
{
|
|
|
|
agree = (source(*it_in, G) == target(*it_out, G) && source(*it_in, G) != target(*it_in, G)); //not a loop
|
|
|
|
liste.push_back(source(*it_in, G));
|
|
|
|
++it_in;
|
|
|
|
++it_out;
|
|
|
|
}
|
|
|
|
if (agree)
|
|
|
|
{
|
|
|
|
if (it_in != in_end || it_out != out_end)
|
|
|
|
agree = false;
|
|
|
|
unsigned int i = 1;
|
|
|
|
while (i < liste.size() && agree)
|
|
|
|
{
|
|
|
|
unsigned int j = i + 1;
|
|
|
|
while (j < liste.size() && agree)
|
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::edge_descriptor ed;
|
2009-12-16 18:13:23 +01:00
|
|
|
bool exist1, exist2;
|
|
|
|
tie(ed, exist1) = edge(liste[i], liste[j], G);
|
|
|
|
tie(ed, exist2) = edge(liste[j], liste[i], G);
|
|
|
|
agree = (exist1 && exist2);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return agree;
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
bool
|
2010-09-16 19:00:48 +02:00
|
|
|
Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(AdjacencyList_t &G)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
|
|
|
bool something_has_been_done = false;
|
|
|
|
bool not_a_loop;
|
|
|
|
int i;
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::vertex_iterator it, it1, ita, it_end;
|
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
|
|
|
|
{
|
|
|
|
int in_degree_n = in_degree(*it, G);
|
|
|
|
int out_degree_n = out_degree(*it, G);
|
|
|
|
if (in_degree_n <= 1 || out_degree_n <= 1)
|
|
|
|
{
|
|
|
|
not_a_loop = true;
|
|
|
|
if (in_degree_n >= 1 && out_degree_n >= 1) // Do not eliminate a vertex if it loops on itself!
|
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::in_edge_iterator it_in, in_end;
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(it_in, in_end) = in_edges(*it, G); it_in != in_end; ++it_in)
|
|
|
|
if (source(*it_in, G) == target(*it_in, G))
|
|
|
|
{
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << v_index[source(*it_in, G)] << " == " << v_index[target(*it_in, G)] << "\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
2009-12-16 18:13:23 +01:00
|
|
|
not_a_loop = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (not_a_loop)
|
|
|
|
{
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2010-09-16 19:00:48 +02:00
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "->eliminate vertex[" << v_index[*it] + 1 << "]\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
2009-12-16 18:13:23 +01:00
|
|
|
Eliminate(*it, G);
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2009-12-16 18:13:23 +01:00
|
|
|
Print(G);
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
2009-12-16 18:13:23 +01:00
|
|
|
something_has_been_done = true;
|
|
|
|
if (i > 0)
|
|
|
|
it = ita;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tie(it, it_end) = vertices(G);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ita = it;
|
|
|
|
}
|
|
|
|
return something_has_been_done;
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
bool
|
2010-09-16 19:00:48 +02:00
|
|
|
Elimination_of_Vertex_belonging_to_a_clique_Step(AdjacencyList_t &G)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::vertex_iterator it, it1, ita, it_end;
|
2009-12-16 18:13:23 +01:00
|
|
|
bool something_has_been_done = false;
|
|
|
|
int i;
|
|
|
|
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
|
|
|
|
{
|
|
|
|
if (Vertex_Belong_to_a_Clique(*it, G))
|
|
|
|
{
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2010-09-16 19:00:48 +02:00
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "eliminate vertex[" << v_index[*it] + 1 << "]\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
2009-12-16 18:13:23 +01:00
|
|
|
Eliminate(*it, G);
|
|
|
|
something_has_been_done = true;
|
|
|
|
if (i > 0)
|
|
|
|
it = ita;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tie(it, it_end) = vertices(G);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ita = it;
|
|
|
|
}
|
|
|
|
return something_has_been_done;
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
bool
|
2010-09-16 19:00:48 +02:00
|
|
|
Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(set<int> &feed_back_vertices, AdjacencyList_t &G)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
|
|
|
bool something_has_been_done = false;
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::vertex_iterator it, it_end, ita;
|
2009-12-16 18:13:23 +01:00
|
|
|
int i = 0;
|
|
|
|
for (tie(it, it_end) = vertices(G); it != it_end; ++it, i++)
|
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::edge_descriptor ed;
|
2009-12-16 18:13:23 +01:00
|
|
|
bool exist;
|
|
|
|
tie(ed, exist) = edge(*it, *it, G);
|
|
|
|
if (exist)
|
|
|
|
{
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2010-09-16 19:00:48 +02:00
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "store v[*it] = " << v_index[*it]+1 << "\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
2010-09-16 19:00:48 +02:00
|
|
|
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
feed_back_vertices.insert(v_index1[*it]);
|
2010-09-16 19:00:48 +02:00
|
|
|
/*property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
2009-05-13 01:03:40 +02:00
|
|
|
feed_back_vertices.insert(v_index[*it] );*/
|
2009-12-16 18:13:23 +01:00
|
|
|
Suppress(*it, G);
|
|
|
|
something_has_been_done = true;
|
|
|
|
if (i > 0)
|
|
|
|
it = ita;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tie(it, it_end) = vertices(G);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ita = it;
|
|
|
|
}
|
|
|
|
return something_has_been_done;
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t
|
|
|
|
Minimal_set_of_feedback_vertex(set<int> &feed_back_vertices, const AdjacencyList_t &G1)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
|
|
|
bool something_has_been_done = true;
|
|
|
|
int cut_ = 0;
|
|
|
|
feed_back_vertices.clear();
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t G(G1);
|
2009-12-16 18:13:23 +01:00
|
|
|
while (num_vertices(G) > 0)
|
|
|
|
{
|
|
|
|
while (something_has_been_done && num_vertices(G) > 0)
|
|
|
|
{
|
|
|
|
//Rule 1
|
|
|
|
something_has_been_done = (Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(G) /*or something_has_been_done*/);
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "1 something_has_been_done=" << something_has_been_done << "\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
//Rule 2
|
|
|
|
something_has_been_done = (Elimination_of_Vertex_belonging_to_a_clique_Step(G) || something_has_been_done);
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "2 something_has_been_done=" << something_has_been_done << "\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
//Rule 3
|
|
|
|
something_has_been_done = (Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(feed_back_vertices, G) || something_has_been_done);
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "3 something_has_been_done=" << something_has_been_done << "\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
2009-12-16 18:13:23 +01:00
|
|
|
}
|
|
|
|
vector<int> circuit;
|
|
|
|
if (!has_cycle(circuit, G))
|
|
|
|
{
|
2009-06-30 16:43:59 +02:00
|
|
|
#ifdef verbose
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "has_cycle=false\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
2009-12-16 18:13:23 +01:00
|
|
|
//sort(feed_back_vertices.begin(), feed_back_vertices.end());
|
|
|
|
return G;
|
|
|
|
}
|
|
|
|
if (num_vertices(G) > 0)
|
|
|
|
{
|
|
|
|
/*if nothing has been done in the five previous rule then cut the vertex with the maximum in_degree+out_degree*/
|
|
|
|
unsigned int max_degree = 0, num = 0;
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::vertex_iterator it, it_end, max_degree_index;
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(it, it_end) = vertices(G); it != it_end; ++it, num++)
|
|
|
|
{
|
|
|
|
if (in_degree(*it, G) + out_degree(*it, G) > max_degree)
|
|
|
|
{
|
|
|
|
max_degree = in_degree(*it, G) + out_degree(*it, G);
|
|
|
|
max_degree_index = it;
|
|
|
|
}
|
|
|
|
}
|
2010-09-16 19:00:48 +02:00
|
|
|
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
feed_back_vertices.insert(v_index1[*max_degree_index]);
|
2010-09-16 19:00:48 +02:00
|
|
|
/*property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
2009-05-13 01:03:40 +02:00
|
|
|
feed_back_vertices.insert(v_index[*max_degree_index]);*/
|
2009-12-16 18:13:23 +01:00
|
|
|
//cout << "v_index1[*max_degree_index] = " << v_index1[*max_degree_index] << "\n";
|
|
|
|
cut_++;
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2010-09-16 19:00:48 +02:00
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "--> cut vertex " << v_index[*max_degree_index] + 1 << "\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
2009-12-16 18:13:23 +01:00
|
|
|
Suppress(*max_degree_index, G);
|
|
|
|
something_has_been_done = true;
|
|
|
|
}
|
|
|
|
}
|
2009-05-13 01:03:40 +02:00
|
|
|
#ifdef verbose
|
2009-12-16 18:13:23 +01:00
|
|
|
cout << "cut_=" << cut_ << "\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
#endif
|
2009-12-16 18:13:23 +01:00
|
|
|
//sort(feed_back_vertices.begin(), feed_back_vertices.end());
|
|
|
|
return G;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct rev
|
|
|
|
{
|
|
|
|
bool
|
|
|
|
operator()(const int a, const int b) const
|
|
|
|
{
|
|
|
|
return (a > b);
|
2009-05-13 01:03:40 +02:00
|
|
|
}
|
2009-12-16 18:13:23 +01:00
|
|
|
};
|
2009-05-13 01:03:40 +02:00
|
|
|
|
2009-12-16 18:13:23 +01:00
|
|
|
void
|
2010-09-16 19:00:48 +02:00
|
|
|
Reorder_the_recursive_variables(const AdjacencyList_t &G1, set<int> &feedback_vertices, vector< int> &Reordered_Vertices)
|
2009-12-16 18:13:23 +01:00
|
|
|
{
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t G(G1);
|
|
|
|
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
|
2009-12-16 18:13:23 +01:00
|
|
|
set<int>::iterator its, ita;
|
|
|
|
set<int, rev> fv;
|
|
|
|
for (its = feedback_vertices.begin(); its != feedback_vertices.end(); its++)
|
|
|
|
fv.insert(*its);
|
|
|
|
int i = 0;
|
|
|
|
for (its = fv.begin(); its != fv.end(); ++its, i++)
|
|
|
|
Suppress(*its, G);
|
|
|
|
bool something_has_been_done = true;
|
|
|
|
while (something_has_been_done)
|
2009-05-13 01:03:40 +02:00
|
|
|
{
|
2009-12-16 18:13:23 +01:00
|
|
|
something_has_been_done = false;
|
2010-09-16 19:00:48 +02:00
|
|
|
AdjacencyList_t::vertex_iterator it, it_end, ita;
|
2009-12-16 18:13:23 +01:00
|
|
|
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
|
2009-05-13 01:03:40 +02:00
|
|
|
{
|
2009-12-16 18:13:23 +01:00
|
|
|
if (in_degree(*it, G) == 0)
|
|
|
|
{
|
|
|
|
Reordered_Vertices.push_back(v_index[*it]);
|
|
|
|
Suppress(*it, G);
|
|
|
|
something_has_been_done = true;
|
|
|
|
if (i > 0)
|
|
|
|
it = ita;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tie(it, it_end) = vertices(G);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ita = it;
|
2009-05-13 01:03:40 +02:00
|
|
|
}
|
2009-12-16 18:13:23 +01:00
|
|
|
}
|
|
|
|
if (num_vertices(G))
|
|
|
|
cout << "Error in the computation of feedback vertex set\n";
|
2009-05-13 01:03:40 +02:00
|
|
|
}
|
2009-12-16 18:13:23 +01:00
|
|
|
}
|