4
#include "Common/Options.h"
5
#include "DepthFirstSearch.h"
7
#include <boost/unordered_map.hpp>
15
/** Record a topological order of the vertices. */
16
template <typename OutIt>
17
struct TopoVisitor : public boost::default_dfs_visitor
19
TopoVisitor(OutIt it) : m_it(it) { }
21
template <typename Vertex, typename Graph>
22
void finish_vertex(const Vertex& u, Graph&) { *m_it++ = u; }
28
/** Record a topological order of the vertices. */
29
template <typename Graph, typename It>
30
void topologicalSort(const Graph& g, It it)
32
using boost::default_color_type;
33
using boost::vector_property_map;
34
typedef vector_property_map<
35
default_color_type, ContigNodeIndexMap> ColorMap;
36
depthFirstSearch(g, TopoVisitor<It>(it),
37
ColorMap(num_vertices(g)));
40
/** Return true if the specified sequence of vertices is a bubble. */
41
template <typename Graph, typename It>
42
bool isBubble(const Graph& g, It first, It last)
44
typedef typename graph_traits<Graph>::adjacency_iterator Ait;
45
typedef typename graph_traits<Graph>::vertex_descriptor V;
46
assert(last - first > 1);
47
if (last - first == 2)
48
return false; // unambiguous edge
49
if (*first == ~last[-1])
50
return false; // palindrome
51
std::set<V> targets(first, first + 1);
52
for (It it = first; it != last - 1; ++it) {
53
std::pair<Ait, Ait> adj = adjacent_vertices(*it, g);
54
targets.insert(adj.first, adj.second);
56
std::set<V> sources(last - 1, last);
57
for (It it = first + 1; it != last; ++it) {
58
std::pair<Ait, Ait> adj = adjacent_vertices(~*it, g);
59
transform(adj.first, adj.second,
60
inserter(sources, sources.end()),
61
std::mem_fun_ref(&V::operator~));
63
std::set<V> bubble(first, last);
64
return sources == bubble && targets == bubble;
67
typedef std::vector<ContigNode> Bubble;
68
typedef std::vector<Bubble> Bubbles;
70
/** Discover bubbles. */
71
template <typename Graph>
72
Bubbles discoverBubbles(const Graph& g)
74
typedef typename graph_traits<Graph>::vertex_descriptor V;
76
std::vector<V> topo(num_vertices(g));
77
topologicalSort(g, topo.rbegin());
80
typedef typename std::vector<V>::const_iterator It;
81
for (It first = topo.begin(); first != topo.end(); ++first) {
82
int sum = out_degree(*first, g);
86
std::cerr << "* " << *first << '\n';
87
for (It it = first + 1; it != topo.end(); ++it) {
88
unsigned indeg = in_degree(*it, g);
89
unsigned outdeg = out_degree(*it, g);
93
std::cerr << *it << '\t' << indeg << '\t' << outdeg
95
<< '\t' << sum + (int)outdeg << '\n';
97
if (indeg == 0 || sum < 0)
101
if (isBubble(g, first, last)) {
102
if (opt::verbose > 3)
103
std::cerr << "good\n";
104
bubbles.push_back(Bubble(first, last));
118
/** Return the length of the longest path through the bubble. */
119
template <typename Graph>
120
int longestPath(const Graph& g, const Bubble& topo)
123
typedef graph_traits<Graph> GTraits;
124
typedef typename GTraits::edge_descriptor E;
125
typedef typename GTraits::out_edge_iterator Eit;
126
typedef typename GTraits::vertex_descriptor V;
128
EdgeWeightMap<Graph> weight(g);
129
/* GCC 4.4.6 has a bug that prevents ContigNode being used as the
130
* key of a std::map. Possibly related to
131
* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39390
133
boost::unordered_map<V, int> distance;
134
distance[topo.front()] = 0;
135
for (Bubble::const_iterator it = topo.begin();
136
it != topo.end(); ++it) {
139
for (tie(eit, elast) = out_edges(u, g); eit != elast; ++eit) {
142
distance[v] = std::max(
143
distance[v], distance[u] + weight[e]);
147
return distance[v] - g[v].length;
150
/** Scaffold over the bubble between vertices u and w.
151
* Add an edge (u,w) with the distance property set to the length of
152
* the largest branch of the bubble.
154
template <typename Graph>
155
void scaffoldBubble(Graph& g, const Bubble& bubble)
157
typedef graph_traits<Graph> GTraits;
158
typedef typename GTraits::adjacency_iterator Ait;
159
typedef typename GTraits::vertex_descriptor V;
160
assert(bubble.size() > 2);
162
V u = bubble.front(), w = bubble.back();
163
if (edge(u, w, g).second) {
164
// Already scaffolded.
167
assert(isBubble(g, bubble.begin(), bubble.end()));
169
add_edge(u, w, std::max(longestPath(g, bubble), 1), g);
172
/** Replace each bubble in the graph with a single edge.
173
* Remove the vertices in the bubbles from the graph.
174
* @return the vertices that were removed from the graph
176
template <typename Graph>
177
std::vector<typename graph_traits<Graph>::vertex_descriptor>
180
typedef typename graph_traits<Graph>::vertex_descriptor V;
181
typedef std::vector<V> Vertices;
183
Bubbles bubbles = discoverBubbles(g);
184
for (Bubbles::const_iterator it = bubbles.begin();
185
it != bubbles.end(); ++it) {
186
scaffoldBubble(g, *it);
187
popped.insert(popped.end(), it->begin() + 1, it->end() - 1);
189
for (typename Vertices::const_iterator it = popped.begin();
190
it != popped.end(); ++it) {