[med-svn] [abyss] 01/05: Imported Upstream version 2.0.2

Andreas Tille tille at debian.org
Tue Nov 1 12:31:53 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository abyss.

commit fe441e45d54dba1acfdaf67dbaa227f7e2d42e5b
Author: Andreas Tille <tille at debian.org>
Date:   Tue Nov 1 12:04:19 2016 +0100

    Imported Upstream version 2.0.2
---
 BloomDBG/bloom-dbg.cc                  |   5 +-
 ChangeLog                              |   5 +
 Common/Dictionary.h                    |   8 +
 Graph/DotIO.h                          |  59 +-
 Graph/GraphIO.h                        |   3 +-
 Graph/Makefile.am                      |   3 +-
 Graph/SAMIO.h                          |   1 +
 Graph/UndirectedGraph.h                | 948 +++++++++++++++++++++++++++++++++
 Konnector/DBGBloom.h                   |   9 +
 README.md                              |  26 +-
 Unittest/DBG/LoadAlgorithmTest.cpp     |   1 +
 Unittest/Graph/DotIOTest.cpp           | 115 ++++
 Unittest/Graph/UndirectedGraphTest.cpp |  54 ++
 Unittest/Makefile.am                   |  15 +
 configure.ac                           |  13 +-
 doc/ABYSS.1                            |   2 +-
 doc/abyss-pe.1                         |   2 +-
 doc/abyss-tofastq.1                    |   2 +-
 doc/flowchart.graffle                  |   2 +-
 19 files changed, 1250 insertions(+), 23 deletions(-)

diff --git a/BloomDBG/bloom-dbg.cc b/BloomDBG/bloom-dbg.cc
index 2c6a05b..9ace1d5 100644
--- a/BloomDBG/bloom-dbg.cc
+++ b/BloomDBG/bloom-dbg.cc
@@ -41,8 +41,9 @@ static const char USAGE_MESSAGE[] =
 "\n"
 "Basic Options:\n"
 "\n"
-"  -b  --bloom-size=N         Bloom filter memory size with unit suffix\n"
-"                             'k', 'M', or 'G' [required]\n"
+"  -b  --bloom-size=N         overall memory budget for the assembly in bytes.\n"
+"                             Unit suffixes 'k' (kilobytes), 'M' (megabytes),\n"
+"                             or 'G' (gigabytes) may be used. [required]\n"
 "      --chastity             discard unchaste reads [default]\n"
 "      --no-chastity          do not discard unchaste reads\n"
 "  -g  --graph=FILE           write de Bruijn graph to FILE (GraphViz)\n"
diff --git a/ChangeLog b/ChangeLog
index 368e132..f07eade 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2016-10-21  Ben Vandervalk <benv at bcgsc.ca>
+
+	* Release version 2.0.2
+	* Fix compile errors with gcc 6 and boost 1.62
+
 2016-09-14  Ben Vandervalk <benv at bcgsc.ca>
 
 	* Release version 2.0.1
diff --git a/Common/Dictionary.h b/Common/Dictionary.h
index 88f227a..f917fc4 100644
--- a/Common/Dictionary.h
+++ b/Common/Dictionary.h
@@ -100,6 +100,14 @@ class Dictionary
 			return m_vec.back();
 		}
 
+		/** Clear dictionary contents and reset to default state. */
+		void clear()
+		{
+			m_map.clear();
+			m_vec.clear();
+			m_locked = false;
+		}
+
 	private:
 		Map m_map;
 		Vector m_vec;
diff --git a/Graph/DotIO.h b/Graph/DotIO.h
index 1c8449e..af76ed4 100644
--- a/Graph/DotIO.h
+++ b/Graph/DotIO.h
@@ -133,15 +133,61 @@ DotWriter<Graph> dot_writer(const Graph& g)
 	return DotWriter<Graph>(g);
 }
 
+/** legal characters for an unquoted node ID */
+static const uint8_t GRAPHVIZ_ID_CHARS[256] = {
+	0, 0, 0, 0, 0, 0, 0, 0, // 000-007:
+	0, 0, 0, 0, 0, 0, 0, 0, // 008-015:
+	0, 0, 0, 0, 0, 0, 0, 0, // 016-023:
+	0, 0, 0, 0, 0, 0, 0, 0, // 024-031:
+	0, 0, 0, 0, 0, 0, 0, 0, // 032-039:    !, ", #, $, %, &, ',
+	0, 0, 0, 1, 0, 1, 1, 0, // 040-047: (, ), *, +, ,, -, ., /,
+	1, 1, 1, 1, 1, 1, 1, 1, // 048-055: 0, 1, 2, 3, 4, 5, 6, 7,
+	1, 1, 0, 0, 0, 0, 0, 0, // 056-063: 8, 9, :, ;, <, =, >, ?,
+	0, 1, 1, 1, 1, 1, 1, 1, // 064-071: @, A, B, C, D, E, F, G,
+	1, 1, 1, 1, 1, 1, 1, 1, // 072-079: H, I, J, K, L, M, N, O,
+	1, 1, 1, 1, 1, 1, 1, 1, // 080-087: P, Q, R, S, T, U, V, W,
+	1, 1, 1, 0, 0, 0, 0, 1, // 088-095: X, Y, Z, [, \, ], ^, _,
+	0, 1, 1, 1, 1, 1, 1, 1, // 096-103: `, a, b, c, d, e, f, g,
+	1, 1, 1, 1, 1, 1, 1, 1, // 104-111: h, i, j, k, l, m, n, o,
+	1, 1, 1, 1, 1, 1, 1, 1, // 112-119: p, q, r, s, t, u, v, w,
+	1, 1, 1, 0, 0, 0, 0, 0, // 120-127: x, y, z, {, |, }, ~,
+	0, 0, 0, 0, 0, 0, 0, 0, // 128-135:
+	0, 0, 0, 0, 0, 0, 0, 0, // 136-143:
+	0, 0, 0, 0, 0, 0, 0, 0, // 144-151:
+	0, 0, 0, 0, 0, 0, 0, 0, // 152-159:
+	0, 0, 0, 0, 0, 0, 0, 0, // 160-167:
+	0, 0, 0, 0, 0, 0, 0, 0, // 168-175:
+	0, 0, 0, 0, 0, 0, 0, 0, // 176-183:
+	0, 0, 0, 0, 0, 0, 0, 0, // 184-191:
+	0, 0, 0, 0, 0, 0, 0, 0, // 192-199:
+	0, 0, 0, 0, 0, 0, 0, 0, // 200-207:
+	0, 0, 0, 0, 0, 0, 0, 0, // 208-215:
+	0, 0, 0, 0, 0, 0, 0, 0, // 216-223:
+	0, 0, 0, 0, 0, 0, 0, 0, // 224-231:
+	0, 0, 0, 0, 0, 0, 0, 0, // 232-239:
+	0, 0, 0, 0, 0, 0, 0, 0, // 240-247:
+	0, 0, 0, 0, 0, 0, 0, 0  // 248-255:
+};
+
 /** Read a string delimited by double quotes. */
 static inline
 std::istream& read_dot_name(std::istream& in, std::string& s)
 {
-	if (in >> std::ws && in.peek() == '"') {
+	in >> std::ws;
+	if (in.peek() == '"') {
+		// quoted node ID
 		in.get();
 		getline(in, s, '"');
-	} else
+	} else if (GRAPHVIZ_ID_CHARS[in.peek()]) {
+		// unquoted node ID
+		std::ostringstream ss;
+		while (GRAPHVIZ_ID_CHARS[in.peek()])
+			ss << (char)in.get();
+		assert(ss.good());
+		s = ss.str();
+	} else {
 		in.clear(std::ios::failbit);
+	}
 	return in;
 }
 
@@ -170,12 +216,17 @@ std::istream& read_dot(std::istream& in, Graph& g, BetterEP betterEP)
 	typedef typename graph_traits<Graph>::edge_descriptor
 		edge_descriptor;
 	typedef typename edge_property<Graph>::type edge_property_type;
+	typedef typename graph_traits<Graph>::directed_category
+		directed_category;
+
+	bool isDirectedGraph = boost::detail::is_directed(directed_category());
 
 	// Add vertices if this graph is empty.
 	bool addVertices = num_vertices(g) == 0;
 
 	// Graph properties
-	in >> expect("digraph") >> Ignore('{');
+	in >> expect(isDirectedGraph ? "digraph" : "graph");
+	in >> Ignore('{');
 	assert(in);
 
 	edge_property_type defaultEdgeProp;
@@ -243,7 +294,7 @@ std::istream& read_dot(std::istream& in, Graph& g, BetterEP betterEP)
 			}
 		} else if (c == '-') {
 			// Edge
-			in >> expect(">");
+			in >> expect(isDirectedGraph ? ">" : "-");
 			assert(in);
 			g_contigNames.lock();
 
diff --git a/Graph/GraphIO.h b/Graph/GraphIO.h
index 78370e3..c8da010 100644
--- a/Graph/GraphIO.h
+++ b/Graph/GraphIO.h
@@ -53,7 +53,8 @@ std::istream& read_graph(std::istream& in, ContigGraph<Graph>& g,
 	switch (in.peek()) {
 	  case '@': // @SQ: SAM format
 		return read_sam_header(in, g);
-	  case 'd': // digraph: GraphViz dot format
+	  case 'd': // digraph: GraphViz dot format (directed graph)
+	  case 'g': // graph:   GraphViz dot format (undirected graph)
 		return read_dot<Graph>(in, g, betterEP);
 	  case 'H': {
 		in.get();
diff --git a/Graph/Makefile.am b/Graph/Makefile.am
index cce5dd0..5a25efd 100644
--- a/Graph/Makefile.am
+++ b/Graph/Makefile.am
@@ -35,7 +35,8 @@ EXTRA_DIST = \
 	Path.h \
 	PopBubbles.h \
 	Properties.h \
-	SAMIO.h
+	SAMIO.h \
+	UndirectedGraph.h
 
 abyss_gc_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/Common
 abyss_gc_LDADD = $(top_builddir)/Common/libcommon.a
diff --git a/Graph/SAMIO.h b/Graph/SAMIO.h
index 5a20270..2d99b31 100644
--- a/Graph/SAMIO.h
+++ b/Graph/SAMIO.h
@@ -1,6 +1,7 @@
 #ifndef SAMIO_H
 #define SAMIO_H 1
 
+#include "Common/ContigNode.h"
 #include "Graph/Properties.h"
 #include <istream>
 #include <sstream>
diff --git a/Graph/UndirectedGraph.h b/Graph/UndirectedGraph.h
new file mode 100644
index 0000000..1be38eb
--- /dev/null
+++ b/Graph/UndirectedGraph.h
@@ -0,0 +1,948 @@
+#ifndef UNDIRECTEDGRAPH_H
+#define UNDIRECTEDGRAPH_H 1
+
+#include "Common/ContigNode.h"
+#include "Common/Hash.h"
+#include "Graph/Properties.h"
+#include <algorithm>
+#include <cassert>
+#include <utility>
+#include <vector>
+#include <iostream>
+
+/**
+ * An edge for an undirected graph, having the key property that
+ * (u, v) == (v, u). The unsigned values here are the vertex_descriptor's.
+ */
+class UndirectedEdge : public std::pair<unsigned, unsigned>
+{
+
+public:
+
+	UndirectedEdge() : std::pair<unsigned, unsigned>() {}
+
+	UndirectedEdge(unsigned u, unsigned v)
+		: std::pair<unsigned, unsigned>(u, v) {}
+
+	bool operator ==(const UndirectedEdge& e) const
+	{
+		return (first == e.first && second == e.second) ||
+			(first == e.second && second == e.first);
+	}
+
+	bool operator !=(const UndirectedEdge& e) const
+	{
+		return !(*this == e);
+	}
+
+	size_t hashCode() const
+	{
+		return first ^ second;
+	}
+};
+
+/**
+ * The hash function for an undirected edge, having the key property that
+ * hash(u, v) == hash(v, u).
+ */
+NAMESPACE_STD_HASH_BEGIN
+template <> struct hash<UndirectedEdge> {
+	/**
+	 * Hash function for graph vertex type (vertex_descriptor)
+	 */
+	size_t operator()(const UndirectedEdge& e) const
+	{
+		return e.hashCode();
+	}
+};
+NAMESPACE_STD_HASH_END
+
+/** A undirected graph. */
+template <typename VertexProp = no_property,
+		 typename EdgeProp = no_property>
+class UndirectedGraph
+{
+	class Vertex;
+	typedef typename std::vector<Vertex> Vertices;
+	class Edge;
+	typedef typename std::vector<Edge> Edges;
+
+  public:
+	// Graph
+	/* typedef ContigNode vertex_descriptor; */
+	typedef unsigned vertex_descriptor;
+
+	// IncidenceGraph
+	typedef UndirectedEdge edge_descriptor;
+
+	typedef unsigned degree_size_type;
+
+	// BidirectionalGraph
+	typedef void in_edge_iterator;
+
+	// VertexListGraph
+	typedef unsigned vertices_size_type;
+
+	// EdgeListGraph
+	typedef unsigned edges_size_type;
+
+	// PropertyGraph
+	typedef VertexProp vertex_bundled;
+	typedef VertexProp vertex_property_type;
+	typedef EdgeProp edge_bundled;
+	typedef EdgeProp edge_property_type;
+
+	typedef boost::undirected_tag directed_category;
+	typedef boost::allow_parallel_edge_tag edge_parallel_category;
+	struct traversal_category
+		: boost::incidence_graph_tag,
+		boost::adjacency_graph_tag,
+		boost::vertex_list_graph_tag,
+		boost::edge_list_graph_tag { };
+
+/** Iterate through the vertices of this graph. */
+class vertex_iterator
+	: public std::iterator<std::input_iterator_tag,
+		const vertex_descriptor>
+{
+  public:
+	vertex_iterator() { }
+	explicit vertex_iterator(vertices_size_type v) : m_v(v) { }
+	const vertex_descriptor& operator *() const { return m_v; }
+
+	bool operator ==(const vertex_iterator& it) const
+	{
+		return m_v == it.m_v;
+	}
+
+	bool operator !=(const vertex_iterator& it) const
+	{
+		return m_v != it.m_v;
+	}
+
+	vertex_iterator& operator ++() { ++m_v; return *this; }
+	vertex_iterator operator ++(int)
+	{
+		vertex_iterator it = *this;
+		++*this;
+		return it;
+	}
+
+  private:
+	vertex_descriptor m_v;
+};
+
+/** Iterate through the out-edges. */
+class out_edge_iterator
+	: public std::iterator<std::input_iterator_tag, edge_descriptor>
+{
+	typedef typename Edges::const_iterator const_iterator;
+
+  public:
+	out_edge_iterator() { }
+	out_edge_iterator(const const_iterator& it,
+			vertex_descriptor src) : m_it(it), m_src(src) { }
+
+	edge_descriptor operator *() const
+	{
+		return edge_descriptor(m_src, m_it->target());
+	}
+
+	bool operator ==(const out_edge_iterator& it) const
+	{
+		return m_it == it.m_it;
+	}
+
+	bool operator !=(const out_edge_iterator& it) const
+	{
+		return m_it != it.m_it;
+	}
+
+	out_edge_iterator& operator ++() { ++m_it; return *this; }
+	out_edge_iterator operator ++(int)
+	{
+		out_edge_iterator it = *this;
+		++*this;
+		return it;
+	}
+
+	const edge_property_type& get_property() const
+	{
+		return m_it->get_property();
+	}
+
+  private:
+	const_iterator m_it;
+	vertex_descriptor m_src;
+};
+
+/** Iterate through adjacent vertices. */
+class adjacency_iterator : public Edges::const_iterator
+{
+	typedef typename Edges::const_iterator It;
+  public:
+	adjacency_iterator() { }
+	adjacency_iterator(const It& it) : It(it) { }
+	vertex_descriptor operator*() const
+	{
+		return It::operator*().target();
+	}
+};
+
+/** Iterate through edges. */
+class edge_iterator
+	: public std::iterator<std::input_iterator_tag, edge_descriptor>
+{
+	void nextVertex()
+	{
+		vertex_iterator vlast = m_g->vertices().second;
+		for (; m_vit != vlast; ++m_vit) {
+			std::pair<adjacency_iterator, adjacency_iterator>
+				adj = m_g->adjacent_vertices(*m_vit);
+			/*
+			 * Since each edge exists as both (u, v) and
+			 * (v, u), require `adj.first >= *m_vit` to visit only
+			 * one of the two possible forms.
+			 */
+			if (adj.first != adj.second && *adj.first >= *m_vit) {
+				m_eit = adj.first;
+				return;
+			}
+		}
+		// Set m_eit to a known value.
+		static const adjacency_iterator s_eitNULL;
+		m_eit = s_eitNULL;
+	}
+
+  public:
+	edge_iterator() { }
+	edge_iterator(const UndirectedGraph* g, const vertex_iterator& vit)
+		: m_g(g), m_vit(vit)
+	{
+		nextVertex();
+	}
+
+	edge_descriptor operator*() const
+	{
+		return edge_descriptor(*m_vit, *m_eit);
+	}
+
+	bool operator==(const edge_iterator& it) const
+	{
+		return m_vit == it.m_vit && m_eit == it.m_eit;
+	}
+
+	bool operator!=(const edge_iterator& it) const
+	{
+		return !(*this == it);
+	}
+
+	edge_iterator& operator++()
+	{
+		if (++m_eit == m_g->adjacent_vertices(*m_vit).second) {
+			++m_vit;
+			nextVertex();
+		}
+		return *this;
+	}
+
+	edge_iterator operator++(int)
+	{
+		edge_iterator it = *this;
+		++*this;
+		return it;
+	}
+
+  private:
+	const UndirectedGraph* m_g;
+	vertex_iterator m_vit;
+	adjacency_iterator m_eit;
+};
+
+  private:
+/** A vertex and its properties. */
+class Vertex
+{
+  public:
+	Vertex() { }
+	Vertex(const vertex_property_type& p) : m_prop(p) { }
+
+	/** Return the properties of this vertex. */
+	const vertex_property_type& get_property() const
+	{
+		return m_prop;
+	}
+
+	/** Returns an iterator-range to the out edges of vertex u. */
+	std::pair<out_edge_iterator, out_edge_iterator>
+	out_edges(vertex_descriptor u) const
+	{
+		return make_pair(out_edge_iterator(m_edges.begin(), u),
+				out_edge_iterator(m_edges.end(), u));
+	}
+
+	/** Returns an iterator-range to the adjacent vertices. */
+	std::pair<adjacency_iterator, adjacency_iterator>
+	adjacent_vertices() const
+	{
+		return make_pair(m_edges.begin(), m_edges.end());
+	}
+
+	/** Return the number of outgoing edges. */
+	degree_size_type out_degree() const
+	{
+		return m_edges.size();
+	}
+
+	/** Add an edge to this vertex. */
+	bool add_edge(vertex_descriptor v, const edge_property_type& ep)
+	{
+		m_edges.push_back(Edge(v, ep));
+		return true;
+	}
+
+	/** Remove the edge to v from this vertex. */
+	void remove_edge(vertex_descriptor v)
+	{
+		m_edges.erase(remove(m_edges.begin(), m_edges.end(), v),
+				m_edges.end());
+	}
+
+	/** Remove all out edges from this vertex. */
+	void clear_out_edges()
+	{
+		m_edges.clear();
+	}
+
+	/** Return the properties of the edge with target v. */
+	edge_property_type& operator[](vertex_descriptor v)
+	{
+		typename Edges::iterator it
+			= find(m_edges.begin(), m_edges.end(), v);
+		assert(it != m_edges.end());
+		return it->get_property();
+	}
+
+	/** Return the properties of the edge with target v. */
+	const edge_property_type& operator[](vertex_descriptor v) const
+	{
+		typename Edges::const_iterator it
+			= find(m_edges.begin(), m_edges.end(), v);
+		assert(it != m_edges.end());
+		return it->get_property();
+	}
+
+	/** Return true if edge (u,v) exists. */
+	bool edge(vertex_descriptor v) const
+	{
+		return count(m_edges.begin(), m_edges.end(), v) > 0;
+	}
+
+	/** Remove edges that satisfy the predicate. */
+	template <typename Predicate>
+	void remove_edge_if(vertex_descriptor u, Predicate predicate)
+	{
+		typename Edges::iterator out = m_edges.begin();
+		for (typename Edges::iterator it = m_edges.begin();
+				it != m_edges.end(); ++it) {
+			if (!predicate(edge_descriptor(u, it->target()))) {
+				if (out != it)
+					*out = *it;
+				++out;
+			}
+		}
+		m_edges.erase(out, m_edges.end());
+	}
+
+  private:
+	Edges m_edges;
+	vertex_property_type m_prop;
+};
+
+/** A directed edge. */
+class Edge
+{
+  public:
+	explicit Edge(vertex_descriptor v, const edge_property_type& ep)
+		: m_target(v), m_ep(ep) { }
+
+	/** Returns the target vertex of this edge. */
+	vertex_descriptor target() const { return m_target; }
+
+	/** Return true if the target of this edge is v. */
+	bool operator ==(const vertex_descriptor& v) const
+	{
+		return m_target == v;
+	}
+
+	edge_property_type& get_property() { return m_ep; }
+	const edge_property_type& get_property() const { return m_ep; }
+
+  private:
+	/** The target vertex of this edge. */
+	vertex_descriptor m_target;
+	edge_property_type m_ep;
+};
+
+  public:
+	/** Create an empty graph. */
+	UndirectedGraph() { }
+
+	/** Create a graph with n vertices and zero edges. */
+	UndirectedGraph(vertices_size_type n) : m_vertices(n) { }
+
+	/** Swap this graph with graph x. */
+	void swap(UndirectedGraph& x)
+	{
+		m_vertices.swap(x.m_vertices);
+		m_removed.swap(x.m_removed);
+	}
+
+	/** Return properties of vertex u. */
+	const vertex_property_type& operator[](vertex_descriptor u) const
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		assert(ui < num_vertices());
+		return m_vertices[ui].get_property();
+	}
+
+	/** Returns an iterator-range to the vertices. */
+	std::pair<vertex_iterator, vertex_iterator> vertices() const
+	{
+		return make_pair(vertex_iterator(0),
+			vertex_iterator(num_vertices()));
+	}
+
+	/** Remove all the edges and vertices from this graph. */
+	void clear() { m_vertices.clear(); m_removed.clear(); }
+
+	/** Add a vertex to this graph. */
+	vertex_descriptor add_vertex(
+			const vertex_property_type& vp = vertex_property_type())
+	{
+		m_vertices.push_back(Vertex(vp));
+		return vertex_descriptor(num_vertices() - 1);
+	}
+
+	/** Returns an iterator-range to the out edges of vertex u. */
+	std::pair<out_edge_iterator, out_edge_iterator>
+	out_edges(vertex_descriptor u) const
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		assert(ui < num_vertices());
+		return m_vertices[ui].out_edges(u);
+	}
+
+	/** Returns an iterator-range to the adjacent vertices of
+	 * vertex u. */
+	std::pair<adjacency_iterator, adjacency_iterator>
+	adjacent_vertices(vertex_descriptor u) const
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		assert(ui < num_vertices());
+		return m_vertices[ui].adjacent_vertices();
+	}
+
+	/** Adds edge (u,v) to this graph. */
+	std::pair<edge_descriptor, bool>
+	add_edge(vertex_descriptor u, vertex_descriptor v,
+			const edge_property_type& ep = edge_property_type())
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		assert(ui < num_vertices());
+		vertices_size_type vi = get(vertex_index, *this, v);
+		assert(vi < num_vertices());
+		m_vertices[vi].add_edge(u, ep);
+		return make_pair(edge_descriptor(u, v),
+				m_vertices[ui].add_edge(v, ep));
+	}
+
+	/** Remove the edge (u,v) from this graph. */
+	void remove_edge(vertex_descriptor u, vertex_descriptor v)
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		assert(ui < num_vertices());
+		vertices_size_type vi = get(vertex_index, *this, v);
+		assert(vi < num_vertices());
+		m_vertices[ui].remove_edge(v);
+		m_vertices[ui].remove_edge(u);
+	}
+
+	/** Remove the edge e from this graph. */
+	void remove_edge(edge_descriptor e)
+	{
+		remove_edge(e.first, e.second);
+	}
+
+#if 0
+	/** Remove all out edges from vertex u. */
+	void clear_out_edges(vertex_descriptor u)
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		assert(ui < num_vertices());
+		m_vertices[ui].clear_out_edges();
+	}
+#endif
+
+	/** Remove all edges to and from vertex u from this graph.
+	 * O(V+E) */
+	void clear_vertex(vertex_descriptor u)
+	{
+		std::pair<adjacency_iterator, adjacency_iterator>
+			adj = adjacent_vertices(u);
+		for (adjacency_iterator v = adj.first; v != adj.second; ++v)
+			remove_edge(*v, u);
+	}
+
+	/** Set the vertex_removed property. */
+	void put(vertex_removed_t, vertex_descriptor u, bool flag)
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		if (ui >= m_removed.size())
+			m_removed.resize(ui + 1);
+		m_removed[ui] = flag;
+	}
+
+	/** Remove vertex u from this graph. It is assumed that there
+	 * are no edges to or from vertex u. It is best to call
+	 * clear_vertex before remove_vertex.
+	 */
+	void remove_vertex(vertex_descriptor u)
+	{
+		put(vertex_removed, u, true);
+	}
+
+	/** Return the number of vertices. */
+	vertices_size_type num_vertices() const
+	{
+		return m_vertices.size();
+	}
+
+	/** Return the number of edges. */
+	edges_size_type num_edges() const
+	{
+		edges_size_type n = 0;
+		std::pair<vertex_iterator, vertex_iterator> vit = vertices();
+		for (vertex_iterator v = vit.first; v != vit.second; ++v)
+			n += out_degree(*v);
+		/* should have (u, v) and (v, u) versions for each edge */
+		assert(n % 2 == 0);
+		return n / 2;
+	}
+
+	/** Return the out degree of vertex u. */
+	degree_size_type out_degree(vertex_descriptor u) const
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		assert(ui < num_vertices());
+		return m_vertices[ui].out_degree();
+	}
+
+	/** Return the nth vertex. */
+	static vertex_descriptor vertex(vertices_size_type n)
+	{
+		return vertex_descriptor(n);
+	}
+
+	/** Iterate through the edges of this graph. */
+	std::pair<edge_iterator, edge_iterator> edges() const
+	{
+		std::pair<vertex_iterator, vertex_iterator> vit = vertices();
+		return make_pair(edge_iterator(this, vit.first),
+				edge_iterator(this, vit.second));
+	}
+
+	/** Return the edge (u,v) if it exists and a flag indicating
+	 * whether the edge exists.
+	 */
+	std::pair<edge_descriptor, bool> edge(
+			vertex_descriptor u, vertex_descriptor v) const
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		assert(ui < num_vertices());
+		return make_pair(edge_descriptor(u, v),
+				m_vertices[ui].edge(v));
+	}
+
+	/** Return properties of edge e. */
+	edge_property_type& operator[](edge_descriptor e)
+	{
+		vertices_size_type ui = get(vertex_index, *this, e.first);
+		assert(ui < num_vertices());
+		return m_vertices[ui][e.second];
+	}
+
+	/** Return properties of edge e. */
+	const edge_property_type& operator[](edge_descriptor e) const
+	{
+		vertices_size_type ui = get(vertex_index, *this, e.first);
+		assert(ui < num_vertices());
+		return m_vertices[ui][e.second];
+	}
+
+	/** Remove edges that satisfy the predicate. */
+	template <typename Predicate>
+	void remove_edge_if(Predicate predicate)
+	{
+		unsigned i = 0;
+		for (typename Vertices::iterator it = m_vertices.begin();
+				it != m_vertices.end(); ++it)
+			it->remove_edge_if(vertex(i++), predicate);
+	}
+
+	/** Return true if this vertex has been removed. */
+	bool is_removed(vertex_descriptor u) const
+	{
+		vertices_size_type ui = get(vertex_index, *this, u);
+		return ui < m_removed.size() ? m_removed[ui] : false;
+	}
+
+	/** Set the name (usually contig ID) for a given vertex_descriptor */
+	void put(vertex_name_t, vertex_descriptor u, const Dictionary::name_type& name)
+	{
+		m_vertexNames.put(u, name);
+	}
+
+	/** Find a vertex_descriptor by name (usually contig ID) */
+	vertex_descriptor find_vertex(const Dictionary::name_type& name) const
+	{
+		return m_vertexNames.getIndex(name);
+	}
+
+  private:
+	UndirectedGraph& operator =(const UndirectedGraph& x);
+
+	/** The set of vertices. */
+	Vertices m_vertices;
+
+	/** Bidirectional map of names to vertex_descriptors */
+	Dictionary m_vertexNames;
+
+	/** Flags indicating vertices that have been removed. */
+	std::vector<bool> m_removed;
+};
+
+namespace std {
+	template <typename VertexProp, typename EdgeProp>
+	inline void swap(UndirectedGraph<VertexProp, EdgeProp>& a,
+			UndirectedGraph<VertexProp, EdgeProp>& b) { a.swap(b); }
+}
+
+// IncidenceGraph
+
+template <typename VP, typename EP>
+std::pair<
+	typename UndirectedGraph<VP, EP>::out_edge_iterator,
+	typename UndirectedGraph<VP, EP>::out_edge_iterator>
+out_edges(
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+		const UndirectedGraph<VP, EP>& g)
+{
+	return g.out_edges(u);
+}
+
+template <typename VP, typename EP>
+typename UndirectedGraph<VP, EP>::degree_size_type
+out_degree(
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+		const UndirectedGraph<VP, EP>& g)
+{
+	return g.out_degree(u);
+}
+
+// AdjacencyGraph
+
+template <typename VP, typename EP>
+std::pair<
+	typename UndirectedGraph<VP, EP>::adjacency_iterator,
+	typename UndirectedGraph<VP, EP>::adjacency_iterator>
+adjacent_vertices(
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+		const UndirectedGraph<VP, EP>& g)
+{
+	return g.adjacent_vertices(u);
+}
+
+// VertexListGraph
+
+template <typename VP, typename EP>
+typename UndirectedGraph<VP, EP>::vertices_size_type
+num_vertices(const UndirectedGraph<VP, EP>& g)
+{
+	return g.num_vertices();
+}
+
+template <typename VP, typename EP>
+typename UndirectedGraph<VP, EP>::vertex_descriptor
+vertex(typename UndirectedGraph<VP, EP>::vertices_size_type ui, const UndirectedGraph<VP, EP>& g)
+{
+	return g.vertex(ui);
+}
+
+template <typename VP, typename EP>
+std::pair<typename UndirectedGraph<VP, EP>::vertex_iterator,
+	typename UndirectedGraph<VP, EP>::vertex_iterator>
+vertices(const UndirectedGraph<VP, EP>& g)
+{
+	return g.vertices();
+}
+
+// EdgeListGraph
+
+template <typename VP, typename EP>
+typename UndirectedGraph<VP, EP>::edges_size_type
+num_edges(const UndirectedGraph<VP, EP>& g)
+{
+	return g.num_edges();
+}
+
+template <typename VP, typename EP>
+std::pair<typename UndirectedGraph<VP, EP>::edge_iterator,
+	typename UndirectedGraph<VP, EP>::edge_iterator>
+edges(const UndirectedGraph<VP, EP>& g)
+{
+	return g.edges();
+}
+
+// AdjacencyMatrix
+
+template <typename VP, typename EP>
+std::pair<typename UndirectedGraph<VP, EP>::edge_descriptor, bool>
+edge(
+	typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+	typename UndirectedGraph<VP, EP>::vertex_descriptor v,
+	const UndirectedGraph<VP, EP>& g)
+{
+	return g.edge(u, v);
+}
+
+// VertexMutableGraph
+
+template <typename VP, typename EP>
+typename UndirectedGraph<VP, EP>::vertex_descriptor
+add_vertex(UndirectedGraph<VP, EP>& g)
+{
+	return g.add_vertex();
+}
+
+template <typename VP, typename EP>
+void
+remove_vertex(
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+		UndirectedGraph<VP, EP>& g)
+{
+	g.remove_vertex(u);
+}
+
+// EdgeMutableGraph
+
+template <typename VP, typename EP>
+void
+clear_vertex(
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+		UndirectedGraph<VP, EP>& g)
+{
+	g.clear_vertex(u);
+}
+
+template <typename VP, typename EP>
+std::pair<typename UndirectedGraph<VP, EP>::edge_descriptor, bool>
+add_edge(
+	typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+	typename UndirectedGraph<VP, EP>::vertex_descriptor v,
+	UndirectedGraph<VP, EP>& g)
+{
+	return g.add_edge(u, v);
+}
+
+template <typename VP, typename EP>
+void
+remove_edge(
+	typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+	typename UndirectedGraph<VP, EP>::vertex_descriptor v,
+	UndirectedGraph<VP, EP>& g)
+{
+	g.remove_edge(u, v);
+}
+
+template <typename VP, typename EP>
+void
+remove_edge(
+		typename UndirectedGraph<VP, EP>::edge_descriptor e,
+		UndirectedGraph<VP, EP>& g)
+{
+	g.remove_edge(e);
+}
+
+// MutableIncidenceGraph
+
+template <typename VP, typename EP>
+void
+clear_out_edges(
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+		UndirectedGraph<VP, EP>& g)
+{
+	g.clear_out_edges(u);
+}
+
+// MutableEdgeListGraph
+
+template <typename VP, typename EP, class Predicate>
+void
+remove_edge_if(Predicate predicate, UndirectedGraph<VP, EP>& g)
+{
+	g.remove_edge_if(predicate);
+}
+
+// PropertyGraph
+
+/** Return true if this vertex has been removed. */
+template <typename VP, typename EP>
+bool get(vertex_removed_t, const UndirectedGraph<VP, EP>& g,
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u)
+{
+	return g.is_removed(u);
+}
+
+template <typename VP, typename EP>
+void put(vertex_removed_t tag, UndirectedGraph<VP, EP>& g,
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+		bool flag)
+{
+	g.put(tag, u, flag);
+}
+
+/** Return the properties of the edge of iterator eit. */
+template <typename VP, typename EP>
+const typename UndirectedGraph<VP, EP>::edge_property_type&
+get(edge_bundle_t, const UndirectedGraph<VP, EP>&,
+		typename UndirectedGraph<VP, EP>::out_edge_iterator eit)
+{
+	return eit.get_property();
+}
+
+// PropertyGraph
+
+template <typename VP, typename EP>
+const VP&
+get(vertex_bundle_t, const UndirectedGraph<VP, EP>& g,
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u)
+{
+	return g[u];
+}
+
+template <typename VP, typename EP>
+const EP&
+get(edge_bundle_t, const UndirectedGraph<VP, EP>& g,
+		typename UndirectedGraph<VP, EP>::edge_descriptor e)
+{
+	return g[e];
+}
+
+// PropertyGraph vertex_index
+
+#if 0
+namespace boost {
+template <typename VP, typename EP>
+struct property_map<UndirectedGraph<VP, EP>, vertex_index_t>
+{
+	typedef ContigNodeIndexMap type;
+	typedef type const_type;
+};
+}
+
+template <typename VP, typename EP>
+ContigNodeIndexMap
+get(vertex_index_t, const UndirectedGraph<VP, EP>&)
+{
+	return ContigNodeIndexMap();
+}
+
+template <typename VP, typename EP>
+ContigNodeIndexMap::reference
+get(vertex_index_t tag, const UndirectedGraph<VP, EP>& g,
+		typename UndirectedGraph<VP, EP>::vertex_descriptor u)
+{
+	return get(get(tag, g), u);
+}
+#endif
+
+// VertexMutablePropertyGraph
+
+template <typename VP, typename EP>
+typename UndirectedGraph<VP, EP>::vertex_descriptor
+add_vertex(const VP& vp, UndirectedGraph<VP, EP>& g)
+{
+	return g.add_vertex(vp);
+}
+
+// EdgeMutablePropertyGraph
+
+template <typename VP, typename EP>
+std::pair<typename UndirectedGraph<VP, EP>::edge_descriptor, bool>
+add_edge(
+	typename UndirectedGraph<VP, EP>::vertex_descriptor u,
+	typename UndirectedGraph<VP, EP>::vertex_descriptor v,
+	const typename UndirectedGraph<VP, EP>::edge_property_type& ep,
+	UndirectedGraph<VP, EP>& g)
+{
+	return g.add_edge(u, v, ep);
+}
+
+// NamedGraph
+
+template <typename VP, typename EP>
+typename UndirectedGraph<VP, EP>::vertex_descriptor
+find_vertex(const std::string& name, const UndirectedGraph<VP, EP>& g)
+{
+	/* return find_vertex(name, g_contigNames); */
+	return g.find_vertex(name);
+}
+
+#if 0
+template <typename VP, typename EP>
+typename UndirectedGraph<VP, EP>::vertex_descriptor
+find_vertex(const std::string& name, bool sense,
+		const UndirectedGraph<VP, EP>&)
+{
+	return find_vertex(name, sense, g_contigNames);
+}
+#endif
+
+/**
+ * Get the index of a vertex in UndirectedGraph's
+ * internal data structures (vertex list and
+ * vertex_descriptor => vertex_name map).
+ */
+template <typename VP, typename EP>
+typename UndirectedGraph<VP, EP>::vertices_size_type
+get(vertex_index_t, const UndirectedGraph<VP, EP>&,
+	typename UndirectedGraph<VP, EP>::vertex_descriptor u)
+{
+	/*
+	 * For UndirectedGraph, vertex_index and vertex_descriptor
+	 * are always the same, where `vertex_index` indicates the position of
+	 * the vertex in UndirectedGraph's vertex list (`m_vertices` above)
+	 * and also the position of the vertex in the
+	 * vertex_name <=> vertex_descriptor map (`m_vertexNames` above).
+	 *
+	 * For DirectedGraph, vertex_index and vertex_descriptor are
+	 * different types (unsigned and ContigNode, respectively), because
+	 * vertex names end with "+" or "-".
+	 */
+	return u;
+}
+
+/**
+ * Set the name for a vertex.  This is a std::string and usually
+ * stores the contig ID.
+ */
+template <typename VP, typename EP>
+void put(vertex_name_t tag, UndirectedGraph<VP, EP>& g,
+	typename UndirectedGraph<VP, EP>::vertex_descriptor& u,
+	const Dictionary::name_type& name)
+{
+	g.put(tag, u, name);
+}
+
+#endif
diff --git a/Konnector/DBGBloom.h b/Konnector/DBGBloom.h
index e3defdd..d72c033 100644
--- a/Konnector/DBGBloom.h
+++ b/Konnector/DBGBloom.h
@@ -346,6 +346,15 @@ in_degree(typename graph_traits<Graph>::vertex_descriptor u,
 
 template <typename Graph>
 static inline
+typename graph_traits<Graph>::degree_size_type
+degree(typename graph_traits<Graph>::vertex_descriptor u,
+	const Graph& g)
+{
+	return in_degree(u, g) + out_degree(u, g);
+}
+
+template <typename Graph>
+static inline
 std::pair<typename graph_traits<Graph>::in_edge_iterator,
 	typename graph_traits<Graph>::in_edge_iterator>
 in_edges(
diff --git a/README.md b/README.md
index 4765389..272a82e 100644
--- a/README.md
+++ b/README.md
@@ -248,21 +248,27 @@ Assembling using a Bloom filter de Bruijn graph
 =========================================
 
 Assemblies may be performed using a _Bloom filter de Bruijn graph_, which
-typically reduces memory requirements by an order of magnitude. In order to
-assemble in Bloom filter mode, the user must specify 3 additional parameters:
-`B` (Bloom filter size), `H` (number of Bloom filter hash functions), and `kc`
-(minimum k-mer count threshold). Valid size units for the `B` parameter are 'k',
-'M', 'G'. If no unit is specified, bytes are assumed. For example, the following
-will run a E. coli assembly with a Bloom filter size of 100 MB, 3 hash
-functions, a minimum k-mer count threshold of 3, and verbose logging:
+typically reduces memory requirements by an order of magnitude. To assemble in
+Bloom filter mode, the user must specify 3 additional parameters: `B` (Bloom
+filter size in bytes), `H` (number of Bloom filter hash functions), and `kc`
+(minimum k-mer count threshold). `B` is the overall memory budget for the Bloom
+filter assembler, and may be specified with unit suffixes 'k' (kilobytes), 'M'
+(megabytes), 'G' (gigabytes). If no units are specified bytes are assumed. For
+example, the following will run a E. coli assembly with an overall memory budget
+of 100 megabytes, 3 hash functions, a minimum k-mer count threshold of 3, with
+verbose logging enabled:
 
 	abyss-pe name=ecoli k=64 in='reads1.fa reads2.fa' B=100M H=3 kc=3 v=-v
 
 At the current time, the user must calculate suitable values for `B` and `H` on
 their own, and finding the best value for `kc` may require experimentation
-(optimal values are typically in the range of 2-4). Users are recommended to
-target a Bloom filter false positive rate (FPR) that is less than 5%, as
-reported by the assembly log when using the `v=-v` option (verbose level 1).
+(optimal values are typically in the range of 2-4). Internally, the Bloom filter
+assembler divides the memory budget (`B`) equally across (`kc` + 1) Bloom
+filters, where `kc` Bloom filters are used for the cascading Bloom filter and
+one additional Bloom filter is used to track k-mers that have previously been
+included in contigs. Users are recommended to target a Bloom filter false
+positive rate (FPR) that is less than 5%, as reported by the assembly log when
+using the `v=-v` option (verbose level 1).
 
 Assembling using a paired de Bruijn graph
 =========================================
diff --git a/Unittest/DBG/LoadAlgorithmTest.cpp b/Unittest/DBG/LoadAlgorithmTest.cpp
index 8de2f39..d31e825 100644
--- a/Unittest/DBG/LoadAlgorithmTest.cpp
+++ b/Unittest/DBG/LoadAlgorithmTest.cpp
@@ -1,3 +1,4 @@
+#include "config.h"
 #include "Assembly/SequenceCollection.h"
 #include "Assembly/DBG.h"
 #include "Assembly/AssemblyAlgorithms.h"
diff --git a/Unittest/Graph/DotIOTest.cpp b/Unittest/Graph/DotIOTest.cpp
new file mode 100644
index 0000000..9a2083d
--- /dev/null
+++ b/Unittest/Graph/DotIOTest.cpp
@@ -0,0 +1,115 @@
+#include "Common/ContigID.h"
+#include "Common/Dictionary.h"
+#include "Graph/GraphIO.h"
+#include "Graph/DotIO.h"
+#include "Graph/UndirectedGraph.h"
+#include "Graph/DirectedGraph.h"
+#include "Graph/Properties.h"
+#include <boost/tuple/tuple.hpp>
+#include <gtest/gtest.h>
+#include <string>
+#include <sstream>
+
+using namespace std;
+
+typedef UndirectedGraph<NoProperty, NoProperty> UGraph;
+typedef boost::graph_traits<UGraph>::vertex_descriptor UV;
+typedef boost::graph_traits<UGraph>::edge_descriptor UE;
+typedef boost::graph_traits<UGraph>::edge_iterator UEIt;
+
+typedef DirectedGraph<NoProperty, NoProperty> DGraph;
+typedef boost::graph_traits<DGraph>::vertex_descriptor DV;
+typedef boost::graph_traits<DGraph>::edge_descriptor DE;
+typedef boost::graph_traits<DGraph>::edge_iterator DEIt;
+
+TEST(DotIOTest, UndirectedGraph)
+{
+	/* reset state of global contig ID map */
+	g_contigNames.clear();
+
+	string graphviz;
+	stringstream ss;
+
+	/* undirected graph, unquoted IDs */
+
+	graphviz =
+		"graph {\n"
+		"     a;\n"
+		"     b;\n"
+		"     a -- b;\n"
+		"}\n";
+
+	ss << graphviz;
+	ASSERT_TRUE(ss.good());
+
+	UGraph g;
+	read_dot(ss, g, DisallowParallelEdges());
+	ASSERT_TRUE(!ss.fail());
+
+	/* check that correct graph structure was created */
+
+	ASSERT_EQ(2u, num_vertices(g));
+	UV a = find_vertex("a", g);
+	ASSERT_LT(a, num_vertices(g));
+	UV b = find_vertex("b", g);
+	ASSERT_LT(b, num_vertices(g));
+
+	ASSERT_EQ(1u, num_edges(g));
+	UEIt ueit, ueit_end;
+	boost::tie(ueit, ueit_end) = edges(g);
+	ASSERT_NE(ueit, ueit_end);
+	UE e = UE(a, b);
+	ASSERT_EQ(e, *ueit);
+	ASSERT_TRUE(source(*ueit, g) == a || target(*ueit, g) == a);
+	ASSERT_TRUE(source(*ueit, g) == b || target(*ueit, g) == b);
+	++ueit;
+	ASSERT_EQ(ueit, ueit_end);
+
+}
+
+TEST(DotIOTest, DirectedGraph)
+{
+	/* reset state of global contig ID map */
+	g_contigNames.clear();
+
+	string graphviz;
+	stringstream ss;
+
+	/* directed graph, quoted IDs */
+
+	graphviz =
+		"digraph {\n"
+		"     \"1+\";\n"
+		"     \"1-\";\n"
+		"     \"2+\";\n"
+		"     \"2-\";\n"
+		"     \"1+\" -> \"2-\";\n"
+		"}\n";
+
+	ss << graphviz;
+	ASSERT_TRUE(ss.good());
+
+	DGraph g;
+	read_dot(ss, g, DisallowParallelEdges());
+	ASSERT_TRUE(!ss.fail());
+
+	/* check that correct graph structure was created */
+
+	ASSERT_EQ(4u, num_vertices(g));
+	DV v1 = find_vertex("1+", g);
+	ASSERT_LT(v1.index(), num_vertices(g));
+	DV v2 = find_vertex("2-", g);
+	ASSERT_LT(v2.index(), num_vertices(g));
+
+	ASSERT_EQ(1u, num_edges(g));
+	DEIt ueit, ueit_end;
+	boost::tie(ueit, ueit_end) = edges(g);
+	ASSERT_NE(ueit, ueit_end);
+	DE e = DE(v1, v2);
+	ASSERT_EQ(e, *ueit);
+	ASSERT_TRUE(source(*ueit, g) == v1);
+	ASSERT_TRUE(target(*ueit, g) == v2);
+	++ueit;
+	ASSERT_EQ(ueit, ueit_end);
+
+}
diff --git a/Unittest/Graph/UndirectedGraphTest.cpp b/Unittest/Graph/UndirectedGraphTest.cpp
new file mode 100644
index 0000000..0f3f295
--- /dev/null
+++ b/Unittest/Graph/UndirectedGraphTest.cpp
@@ -0,0 +1,54 @@
+#include "Common/Hash.h"
+#include "Graph/UndirectedGraph.h"
+#include "Graph/Properties.h"
+#include <boost/tuple/tuple.hpp>
+#include <gtest/gtest.h>
+#include <string>
+#include <sstream>
+
+using namespace std;
+
+typedef UndirectedGraph<NoProperty, NoProperty> Graph;
+typedef boost::graph_traits<Graph>::vertex_descriptor V;
+typedef boost::graph_traits<Graph>::edge_descriptor E;
+typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator;
+
+TEST(UndirectedGraphTest, edgeComparison)
+{
+	Graph g;
+	V u = add_vertex(NoProperty(), g);
+	V v = add_vertex(NoProperty(), g);
+	E uv = E(u, v);
+	E vu = E(v, u);
+	ASSERT_EQ(uv, vu);
+	ASSERT_EQ(uv.hashCode(), vu.hashCode());
+}
+
+TEST(UndirectedGraphTest, edges)
+{
+	Graph g;
+
+	V u = add_vertex(NoProperty(), g);
+	V v = add_vertex(NoProperty(), g);
+
+	/*
+	 * Internally, both edge orientations (u, v) and (v, u) are
+	 * added to the graph data structures.  Make sure that
+	 * this isn't exposed externally and that we only see one edge.
+	 */
+
+	E e;
+	bool inserted;
+	boost::tie(e, inserted) = add_edge(u, v, NoProperty(), g);
+	ASSERT_TRUE(inserted);
+	ASSERT_EQ(1u, num_edges(g));
+
+	/* make sure iterator only visits one version of the edge */
+
+	EdgeIterator eit, eit_end;
+	boost::tie(eit, eit_end) = edges(g);
+	ASSERT_NE(eit, eit_end);
+	ASSERT_EQ(e, *eit);
+	++eit;
+	ASSERT_EQ(eit, eit_end);
+}
diff --git a/Unittest/Makefile.am b/Unittest/Makefile.am
index da0980f..b8770ca 100644
--- a/Unittest/Makefile.am
+++ b/Unittest/Makefile.am
@@ -5,6 +5,7 @@
 AM_CXXFLAGS += $(PTHREAD_CFLAGS) -Wno-error
 AM_LDFLAGS = $(PTHREAD_LIBS)
 AM_CPPFLAGS = \
+	-DGTEST_USE_OWN_TR1_TUPLE=0 \
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/lib/gtest-1.7.0/include
 LDADD = $(top_builddir)/lib/gtest-1.7.0/libgtest_main.a
@@ -83,6 +84,20 @@ graph_ExtendPath_SOURCES = Graph/ExtendPathTest.cpp
 graph_ExtendPath_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/Common
 graph_ExtendPath_LDADD = $(top_builddir)/Common/libcommon.a $(LDADD)
 
+check_PROGRAMS += graph_DotIO
+graph_DotIO_SOURCES = Graph/DotIOTest.cpp
+graph_DotIO_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/Common
+graph_DotIO_LDADD = \
+	$(top_builddir)/Assembly/libassembly.a \
+	$(top_builddir)/DataLayer/libdatalayer.a \
+	$(top_builddir)/Common/libcommon.a \
+	$(LDADD)
+
+check_PROGRAMS += graph_UndirectedGraph
+graph_UndirectedGraph_SOURCES = Graph/UndirectedGraphTest.cpp
+# graph_UndirectedGraph_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/Common
+# graph_UndirectedGraph_LDADD = $(top_builddir)/Common/libcommon.a $(LDADD)
+
 check_PROGRAMS += Konnector_konnector
 Konnector_konnector_SOURCES = \
 	Konnector/konnectorTest.cpp
diff --git a/configure.ac b/configure.ac
index 884852b..4b8df12 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
 AC_PREREQ(2.62)
-AC_INIT(ABySS, 2.0.1, abyss-users at bcgsc.ca, abyss,
+AC_INIT(ABySS, 2.0.2, abyss-users at bcgsc.ca, abyss,
 		http://www.bcgsc.ca/platform/bioinfo/software/abyss)
 m4_include(m4/m4_ax_pthread.m4)
 AM_INIT_AUTOMAKE(1.9.6 foreign subdir-objects)
@@ -55,6 +55,17 @@ AC_CHECK_TYPE([std::tr1::hash<int>],
 	AC_DEFINE(HAVE_STD_TR1_HASH, [1],
 		[Define if the system provides std::tr1::hash]),
 	[], [#include <tr1/functional>])
+AC_CHECK_TYPE([std::tr1::tuple<int>],
+	AC_DEFINE(HAVE_STD_TR1_TUPLE, [1],
+		[Define if the system provides std::tr1::tuple]),
+	[], [#include <tr1/tuple>])
+if test "x$ac_cv_type_std__tr1__tuple_int_" = "xyes"; then
+	# Avoid double-declaration of std::tr1::tuple by boost.
+	# See http://stackoverflow.com/questions/1156003/c-namespace-collision-with-gtest-and-boost
+	# for explanation.
+	AC_DEFINE(BOOST_HAS_TR1_TUPLE, [1],
+	[Define to disable declaration of std::tr1::tuple by boost])
+fi
 AC_LANG_POP([C++])
 
 # Checks for library functions.
diff --git a/doc/ABYSS.1 b/doc/ABYSS.1
index 14a9f69..8f3a30a 100644
--- a/doc/ABYSS.1
+++ b/doc/ABYSS.1
@@ -1,4 +1,4 @@
-.TH ABYSS "1" "2015-May" "ABYSS (ABySS) 2.0.1" "User Commands"
+.TH ABYSS "1" "2015-May" "ABYSS (ABySS) 2.0.2" "User Commands"
 .SH NAME
 ABYSS \- assemble short reads into contigs
 .SH SYNOPSIS
diff --git a/doc/abyss-pe.1 b/doc/abyss-pe.1
index fb94fe7..e6af3d7 100644
--- a/doc/abyss-pe.1
+++ b/doc/abyss-pe.1
@@ -1,4 +1,4 @@
-.TH abyss-pe "1" "2015-May" "abyss-pe (ABySS) 2.0.1" "User Commands"
+.TH abyss-pe "1" "2015-May" "abyss-pe (ABySS) 2.0.2" "User Commands"
 .SH NAME
 abyss-pe - assemble reads into contigs
 .SH SYNOPSIS
diff --git a/doc/abyss-tofastq.1 b/doc/abyss-tofastq.1
index 4250191..d8fd0ea 100644
--- a/doc/abyss-tofastq.1
+++ b/doc/abyss-tofastq.1
@@ -1,4 +1,4 @@
-.TH abyss-tofastq "1" "2015-May" "ABySS 2.0.1" "User Commands"
+.TH abyss-tofastq "1" "2015-May" "ABySS 2.0.2" "User Commands"
 .SH NAME
 abyss-tofastq \- convert various file formats to FASTQ format
 .br
diff --git a/doc/flowchart.graffle b/doc/flowchart.graffle
index a695117..73a03b0 100644
--- a/doc/flowchart.graffle
+++ b/doc/flowchart.graffle
@@ -5198,7 +5198,7 @@
 {\colortbl;\red255\green255\blue255;}
 \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
 
-\f0\b\fs28 \cf0 ABySS paired-end pipeline version 2.0.1}</string>
+\f0\b\fs28 \cf0 ABySS paired-end pipeline version 2.0.2}</string>
 				<key>VerticalPad</key>
 				<integer>0</integer>
 			</dict>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/abyss.git



More information about the debian-med-commit mailing list