Commit fa8ca4ff authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Implement topology.is_bipartite()

parent e43e4e8b
...@@ -16,6 +16,7 @@ libgraph_tool_topology_la_LDFLAGS = $(MOD_LDFLAGS) ...@@ -16,6 +16,7 @@ libgraph_tool_topology_la_LDFLAGS = $(MOD_LDFLAGS)
libgraph_tool_topology_la_SOURCES = \ libgraph_tool_topology_la_SOURCES = \ \ \ \ \ \ \ \ \ \
// graph-tool -- a general graph modification and manipulation thingy
// Copyright (C) 2007-2012 Tiago de Paula Peixoto <>
// This program 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.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <>.
#include "graph_filtering.hh"
#include "graph.hh"
#include "graph_properties.hh"
#include <boost/graph/bipartite.hpp>
using namespace std;
using namespace boost;
using namespace graph_tool;
struct get_bipartite
template <class Graph, class VertexIndex, class PartMap>
void operator()(Graph& g, VertexIndex vertex_index, PartMap part_map,
bool& is_bip) const
unchecked_vector_property_map<default_color_type, VertexIndex>
part(vertex_index, num_vertices(g));
is_bip = is_bipartite(g, vertex_index, part);
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
for (i = 0; i < N; ++i)
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
part_map[v] = (part[v] == color_traits<default_color_type>::white());
template <class Graph, class VertexIndex>
void operator()(Graph& g, VertexIndex vertex_index,
dummy_property_map, bool& is_bip) const
is_bip = is_bipartite(g, vertex_index);
bool is_bipartite(GraphInterface& gi, boost::any part_map)
bool is_bip;
if (part_map.empty())
part_map = dummy_property_map();
typedef mpl::push_back<writable_vertex_scalar_properties,
dummy_property_map>::type vertex_map_types;
(gi, bind<void>(get_bipartite(), _1, gi.GetVertexIndex(),
_2, ref(is_bip)),
return is_bip;
...@@ -38,6 +38,7 @@ void subgraph_isomorphism(GraphInterface& gi1, GraphInterface& gi2, ...@@ -38,6 +38,7 @@ void subgraph_isomorphism(GraphInterface& gi1, GraphInterface& gi2,
python::list vmapping, python::list emapping, python::list vmapping, python::list emapping,
size_t n_max, size_t seed); size_t n_max, size_t seed);
double reciprocity(GraphInterface& gi); double reciprocity(GraphInterface& gi);
bool is_bipartite(GraphInterface& gi, boost::any part_map);
void export_components(); void export_components();
void export_similarity(); void export_similarity();
...@@ -59,6 +60,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_topology) ...@@ -59,6 +60,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_topology)
def("transitive_closure", &transitive_closure); def("transitive_closure", &transitive_closure);
def("is_planar", &is_planar); def("is_planar", &is_planar);
def("reciprocity", &reciprocity); def("reciprocity", &reciprocity);
def("is_bipartite", &is_bipartite);
export_components(); export_components();
export_similarity(); export_similarity();
export_dists(); export_dists();
...@@ -44,6 +44,7 @@ Summary ...@@ -44,6 +44,7 @@ Summary
label_components label_components
label_biconnected_components label_biconnected_components
label_largest_component label_largest_component
is_planar is_planar
edge_reciprocity edge_reciprocity
...@@ -66,7 +67,7 @@ __all__ = ["isomorphism", "subgraph_isomorphism", "mark_subgraph", ...@@ -66,7 +67,7 @@ __all__ = ["isomorphism", "subgraph_isomorphism", "mark_subgraph",
"min_spanning_tree", "dominator_tree", "topological_sort", "min_spanning_tree", "dominator_tree", "topological_sort",
"transitive_closure", "label_components", "label_largest_component", "transitive_closure", "label_components", "label_largest_component",
"label_biconnected_components", "shortest_distance", "shortest_path", "label_biconnected_components", "shortest_distance", "shortest_path",
"pseudo_diameter", "is_planar", "similarity", "edge_reciprocity"] "pseudo_diameter", "is_bipartite", "is_planar", "similarity", "edge_reciprocity"]
def similarity(g1, g2, label1=None, label2=None, norm=True): def similarity(g1, g2, label1=None, label2=None, norm=True):
...@@ -1006,6 +1007,65 @@ def pseudo_diameter(g, source=None, weights=None): ...@@ -1006,6 +1007,65 @@ def pseudo_diameter(g, source=None, weights=None):
return dist, (g.vertex(source), g.vertex(target)) return dist, (g.vertex(source), g.vertex(target))
def is_bipartite(g, partition=False):
Test if the graph is bipartite.
g : :class:`~graph_tool.Graph`
Graph to be used.
partition : bool (optional, default: ``False``)
If ``True``, return the two partitions in case the graph is bipartite.
is_bipartite : bool
Whether or not the graph is bipartite.
partition : :class:`~graph_tool.PropertyMap` (only if `partition=True`)
A vertex property map with the graph partitioning (or `None`) if the
graph is not bipartite.
An undirected graph is bipartite if one can partition its set of vertices
into two sets, such that all edges go from one set to the other.
This algorithm runs in :math:`O(V + E)` time.
>>> g = gt.lattice([10, 10])
>>> is_bi, part = gt.is_bipartite(g, partition=True)
>>> print(is_bi)
>>> gt.graph_draw(g, vertex_color=part, output_size=(300, 300), output="bipartite.pdf")
.. figure:: bipartite.*
:align: center
Bipartition of a 2D lattice.
.. [boost-bipartite]
if partition:
part = g.new_vertex_property("bool")
part = None
g = GraphView(g, directed=False)
is_bi = libgraph_tool_topology.is_bipartite(g._Graph__graph,
_prop("v", g, part))
if partition:
return is_bi, part
return is_bi
def is_planar(g, embedding=False, kuratowski=False): def is_planar(g, embedding=False, kuratowski=False):
""" """
Test if the graph is planar. Test if the graph is planar.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment