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)
libgraph_tool_topology_la_SOURCES = \
graph_all_distances.cc \
graph_bipartite.cc \
graph_components.cc \
graph_distance.cc \
graph_diameter.cc \
......
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007-2012 Tiago de Paula Peixoto <tiago@skewed.de>
//
// 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
// 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 this program. If not, see <http://www.gnu.org/licenses/>.
#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())
continue;
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;
run_action<graph_tool::detail::never_directed>()
(gi, bind<void>(get_bipartite(), _1, gi.GetVertexIndex(),
_2, ref(is_bip)),
vertex_map_types())(part_map);
return is_bip;
}
......@@ -38,6 +38,7 @@ void subgraph_isomorphism(GraphInterface& gi1, GraphInterface& gi2,
python::list vmapping, python::list emapping,
size_t n_max, size_t seed);
double reciprocity(GraphInterface& gi);
bool is_bipartite(GraphInterface& gi, boost::any part_map);
void export_components();
void export_similarity();
......@@ -59,6 +60,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_topology)
def("transitive_closure", &transitive_closure);
def("is_planar", &is_planar);
def("reciprocity", &reciprocity);
def("is_bipartite", &is_bipartite);
export_components();
export_similarity();
export_dists();
......
......@@ -44,6 +44,7 @@ Summary
label_components
label_biconnected_components
label_largest_component
is_bipartite
is_planar
edge_reciprocity
......@@ -66,7 +67,7 @@ __all__ = ["isomorphism", "subgraph_isomorphism", "mark_subgraph",
"min_spanning_tree", "dominator_tree", "topological_sort",
"transitive_closure", "label_components", "label_largest_component",
"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):
......@@ -1006,6 +1007,65 @@ def pseudo_diameter(g, source=None, weights=None):
return dist, (g.vertex(source), g.vertex(target))
def is_bipartite(g, partition=False):
"""
Test if the graph is bipartite.
Parameters
----------
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.
Returns
-------
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.
Notes
-----
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.
Examples
--------
>>> g = gt.lattice([10, 10])
>>> is_bi, part = gt.is_bipartite(g, partition=True)
>>> print(is_bi)
True
>>> gt.graph_draw(g, vertex_color=part, output_size=(300, 300), output="bipartite.pdf")
<...>
.. figure:: bipartite.*
:align: center
Bipartition of a 2D lattice.
References
----------
.. [boost-bipartite] http://www.boost.org/libs/graph/doc/is_bipartite.html
"""
if partition:
part = g.new_vertex_property("bool")
else:
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
else:
return is_bi
def is_planar(g, embedding=False, kuratowski=False):
"""
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