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

is_bipartite(): add option 'find_odd_cycle'

parent eb8e7f10
......@@ -29,35 +29,51 @@ struct get_bipartite
{
template <class Graph, class VertexIndex, class PartMap>
void operator()(Graph& g, VertexIndex vertex_index, PartMap part_map,
bool& is_bip) const
bool& is_bip, bool find_cycle, vector<size_t>& odd_cycle)
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(runtime) if (N > 100)
for (i = 0; i < N; ++i)
if (!find_cycle)
{
is_bip = is_bipartite(g, vertex_index, part);
}
else
{
auto v = vertex(i, g);
if (!is_valid_vertex(v, g))
continue;
part_map[v] = (part[v] == color_traits<default_color_type>::white());
find_odd_cycle(g, vertex_index, part, std::back_inserter(odd_cycle));
is_bip = odd_cycle.empty();
}
parallel_vertex_loop
(g,
[&](auto v)
{
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
void operator()(Graph& g, VertexIndex vertex_index, dummy_property_map,
bool& is_bip, bool find_cycle, vector<size_t>& odd_cycle) const
{
is_bip = is_bipartite(g, vertex_index);
if (!find_cycle)
{
is_bip = is_bipartite(g, vertex_index);
}
else
{
find_odd_cycle(g, vertex_index, std::back_inserter(odd_cycle));
is_bip = odd_cycle.empty();
}
}
};
bool is_bipartite(GraphInterface& gi, boost::any part_map)
bool is_bipartite(GraphInterface& gi, boost::any part_map, bool find_cycle,
boost::python::list cycle)
{
bool is_bip;
vector<size_t> vcycle;
if (part_map.empty())
part_map = dummy_property_map();
......@@ -66,8 +82,13 @@ bool is_bipartite(GraphInterface& gi, boost::any part_map)
dummy_property_map>::type vertex_map_types;
run_action<graph_tool::detail::never_directed>()
(gi, std::bind(get_bipartite(), std::placeholders::_1, gi.get_vertex_index(),
std::placeholders::_2, std::ref(is_bip)),
(gi, std::bind(get_bipartite(), std::placeholders::_1,
gi.get_vertex_index(), std::placeholders::_2,
std::ref(is_bip), find_cycle, std::ref(vcycle)),
vertex_map_types())(part_map);
for (auto v : vcycle)
cycle.append(v);
return is_bip;
}
......@@ -44,7 +44,8 @@ python::object subgraph_isomorphism(GraphInterface& gi1, GraphInterface& gi2,
double reciprocity(GraphInterface& gi);
size_t sequential_coloring(GraphInterface& gi, boost::any order,
boost::any color);
bool is_bipartite(GraphInterface& gi, boost::any part_map);
bool is_bipartite(GraphInterface& gi, boost::any part_map, bool find_cycle,
boost::python::list cycle);
void get_random_spanning_tree(GraphInterface& gi, size_t root,
boost::any weight_map, boost::any tree_map,
rng_t& rng);
......
......@@ -1810,9 +1810,8 @@ 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.
def is_bipartite(g, partition=False, find_odd_cycle=False):
"""Test if the graph is bipartite.
Parameters
----------
......@@ -1820,14 +1819,19 @@ def is_bipartite(g, partition=False):
Graph to be used.
partition : bool (optional, default: ``False``)
If ``True``, return the two partitions in case the graph is bipartite.
find_odd_cycle : bool (optional, default: ``False``)
If ``True``, return an odd cycle if the graph is not bipartite.
Returns
-------
is_bipartite : bool
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
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.
odd_cycle : list of vertices (only if ``find_odd_cycle=True``)
A list of vertices corresponding to an odd cycle, or ``None`` if none is
found.
Notes
-----
......@@ -1859,22 +1863,37 @@ def is_bipartite(g, partition=False):
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)
g = GraphView(g, directed=False, skip_properties=True)
cycle = []
is_bi = libgraph_tool_topology.is_bipartite(g._Graph__graph,
_prop("v", g, part))
_prop("v", g, part),
find_odd_cycle, cycle)
if not is_bi and part is not None:
part.a = 0
if partition:
return is_bi, part
if len(cycle) == 0:
cycle = None
else:
return is_bi
cycle.append(cycle[0])
if find_odd_cycle:
if partition:
return is_bi, part, cycle
else:
return is_bi, cycle
else:
if partition:
return is_bi, part
else:
return is_bi
def is_planar(g, embedding=False, kuratowski=False):
......
Supports Markdown
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