$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r60485 - in trunk: boost/graph libs/graph/doc libs/graph/example libs/graph/test
From: jewillco_at_[hidden]
Date: 2010-03-11 11:56:03
Author: jewillco
Date: 2010-03-11 11:56:01 EST (Thu, 11 Mar 2010)
New Revision: 60485
URL: http://svn.boost.org/trac/boost/changeset/60485
Log:
Added bipartite graph algorithms from Matthias Walter
Added:
   trunk/boost/graph/bipartite.hpp   (contents, props changed)
   trunk/libs/graph/doc/find_odd_cycle.html   (contents, props changed)
   trunk/libs/graph/doc/is_bipartite.html   (contents, props changed)
   trunk/libs/graph/example/bipartite_example.cpp   (contents, props changed)
   trunk/libs/graph/test/bipartite_test.cpp   (contents, props changed)
Text files modified: 
   trunk/libs/graph/doc/table_of_contents.html |     2 ++                                      
   trunk/libs/graph/example/Jamfile.v2         |     1 +                                       
   trunk/libs/graph/test/Jamfile.v2            |     1 +                                       
   3 files changed, 4 insertions(+), 0 deletions(-)
Added: trunk/boost/graph/bipartite.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/graph/bipartite.hpp	2010-03-11 11:56:01 EST (Thu, 11 Mar 2010)
@@ -0,0 +1,386 @@
+/**
+ *
+ * Copyright (c) 2010 Matthias Walter (xammy_at_[hidden])
+ *
+ * Authors: Matthias Walter
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef BOOST_GRAPH_BIPARTITE_HPP
+#define BOOST_GRAPH_BIPARTITE_HPP
+
+#include <utility>
+#include <vector>
+#include <exception>
+#include <boost/graph/properties.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/depth_first_search.hpp>
+#include <boost/graph/one_bit_color_map.hpp>
+#include <boost/bind.hpp>
+
+namespace boost {
+
+  namespace detail {
+
+    /**
+     * The bipartite_visitor_error is thrown if an edge cannot be colored.
+     * The witnesses are the edges incident vertices.
+     */
+
+    template <typename Vertex>
+    struct bipartite_visitor_error: std::exception
+    {
+      std::pair <Vertex, Vertex> witnesses;
+
+      bipartite_visitor_error (Vertex a, Vertex b) :
+        witnesses (a, b)
+      {
+
+      }
+
+      const char* what () const throw ()
+      {
+        return "Graph is not bipartite.";
+      }
+    };
+
+    /**
+     * Functor which colors edges to be non-monochromatic.
+     */
+
+    template <typename PartitionMap>
+    struct bipartition_colorize
+    {
+      typedef on_tree_edge event_filter;
+
+      bipartition_colorize (PartitionMap partition_map) :
+        partition_map_ (partition_map)
+      {
+
+      }
+
+      template <typename Edge, typename Graph>
+      void operator() (Edge e, const Graph& g)
+      {
+        typedef typename graph_traits <Graph>::vertex_descriptor vertex_descriptor_t;
+        typedef color_traits <typename property_traits <PartitionMap>::value_type> color_traits;
+
+        vertex_descriptor_t source_vertex = source (e, g);
+        vertex_descriptor_t target_vertex = target (e, g);
+        if (get (partition_map_, source_vertex) == color_traits::white ())
+          put (partition_map_, target_vertex, color_traits::black ());
+        else
+          put (partition_map_, target_vertex, color_traits::white ());
+      }
+
+    private:
+      PartitionMap partition_map_;
+    };
+
+    /**
+     * Creates a bipartition_colorize functor which colors edges
+     * to be non-monochromatic.
+     *
+     * @param partition_map Color map for the bipartition
+     * @return The functor.
+     */
+
+    template <typename PartitionMap>
+    inline bipartition_colorize <PartitionMap> colorize_bipartition (PartitionMap partition_map)
+    {
+      return bipartition_colorize <PartitionMap> (partition_map);
+    }
+
+    /**
+     * Functor which tests an edge to be monochromatic.
+     */
+
+    template <typename PartitionMap>
+    struct bipartition_check
+    {
+      typedef on_back_edge event_filter;
+
+      bipartition_check (PartitionMap partition_map) :
+        partition_map_ (partition_map)
+      {
+
+      }
+
+      template <typename Edge, typename Graph>
+      void operator() (Edge e, const Graph& g)
+      {
+        typedef typename graph_traits <Graph>::vertex_descriptor vertex_descriptor_t;
+
+        vertex_descriptor_t source_vertex = source (e, g);
+        vertex_descriptor_t target_vertex = target (e, g);
+        if (get (partition_map_, source_vertex) == get (partition_map_, target_vertex))
+          throw bipartite_visitor_error <vertex_descriptor_t> (source_vertex, target_vertex);
+      }
+
+    private:
+      PartitionMap partition_map_;
+    };
+
+    /**
+     * Creates a bipartition_check functor which raises an error if a
+     * monochromatic edge is found.
+     *
+     * @param partition_map The map for a bipartition.
+     * @return The functor.
+     */
+
+    template <typename PartitionMap>
+    inline bipartition_check <PartitionMap> check_bipartition (PartitionMap partition_map)
+    {
+      return bipartition_check <PartitionMap> (partition_map);
+    }
+
+    /**
+     * Find the beginning of a common suffix of two sequences
+     * 
+     * @param sequence1 Pair of bidirectional iterators defining the first sequence.
+     * @param sequence2 Pair of bidirectional iterators defining the second sequence.
+     * @return Pair of iterators pointing to the beginning of the common suffix.
+     */
+
+    template <typename BiDirectionalIterator1, typename BiDirectionalIterator2>
+    inline std::pair <BiDirectionalIterator1, BiDirectionalIterator2> reverse_mismatch (std::pair <
+        BiDirectionalIterator1, BiDirectionalIterator1> sequence1, std::pair <BiDirectionalIterator2,
+        BiDirectionalIterator2> sequence2)
+    {
+      if (sequence1.first == sequence1.second || sequence2.first == sequence2.second)
+        return std::make_pair (sequence1.first, sequence2.first);
+
+      BiDirectionalIterator1 iter1 = sequence1.second;
+      BiDirectionalIterator2 iter2 = sequence2.second;
+
+      while (true)
+      {
+        --iter1;
+        --iter2;
+        if (*iter1 != *iter2)
+        {
+          ++iter1;
+          ++iter2;
+          break;
+        }
+        if (iter1 == sequence1.first)
+          break;
+        if (iter2 == sequence2.first)
+          break;
+      }
+
+      return std::make_pair (iter1, iter2);
+    }
+
+  }
+
+  /**
+   * Checks a given graph for bipartiteness and fills the given color map with
+   * white and black according to the bipartition. If the graph is not
+   * bipartite, the contents of the color map are undefined. Runs in linear
+   * time in the size of the graph, if access to the property maps is in
+   * constant time.
+   *
+   * @param graph The given graph.
+   * @param index_map An index map associating vertices with an index.
+   * @param partition_map A color map to fill with the bipartition.
+   * @return true if and only if the given graph is bipartite.
+   */
+
+  template <typename Graph, typename IndexMap, typename PartitionMap>
+  bool is_bipartite (const Graph& graph, const IndexMap index_map, PartitionMap partition_map)
+  {
+    /// General types and variables
+    typedef typename property_traits <PartitionMap>::value_type partition_color_t;
+    typedef typename graph_traits <Graph>::vertex_descriptor vertex_descriptor_t;
+    typedef typename graph_traits <Graph>::vertex_iterator vertex_iterator_t;
+
+    /// Declare dfs visitor
+    //    detail::empty_recorder recorder;
+    //    typedef detail::bipartite_visitor <PartitionMap, detail::empty_recorder> dfs_visitor_t;
+    //    dfs_visitor_t dfs_visitor (partition_map, recorder);
+
+
+    /// Call dfs
+    try
+    {
+      depth_first_search (graph, vertex_index_map (index_map).visitor (make_dfs_visitor (std::make_pair (
+          detail::colorize_bipartition (partition_map), std::make_pair (detail::check_bipartition (partition_map),
+              put_property (partition_map, color_traits <partition_color_t>::white (), on_start_vertex ()))))));
+
+      //      depth_first_search (graph, vertex_index_map (index_map).visitor (dfs_visitor));
+    }
+    catch (detail::bipartite_visitor_error <vertex_descriptor_t> error)
+    {
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Checks a given graph for bipartiteness.
+   *
+   * @param graph The given graph.
+   * @param index_map An index map associating vertices with an index.
+   * @return true if and only if the given graph is bipartite.
+   */
+
+  template <typename Graph, typename IndexMap>
+  bool is_bipartite (const Graph& graph, const IndexMap index_map)
+  {
+    typedef one_bit_color_map <IndexMap> partition_map_t;
+    partition_map_t partition_map (num_vertices (graph), index_map);
+
+    return is_bipartite (graph, index_map, partition_map);
+  }
+
+  /**
+   * Checks a given graph for bipartiteness. The graph must
+   * have an internal vertex_index property. Runs in linear time in the
+   * size of the graph, if access to the property maps is in constant time.
+   *
+   * @param graph The given graph.
+   * @return true if and only if the given graph is bipartite.
+   */
+
+  template <typename Graph>
+  bool is_bipartite (const Graph& graph)
+  {
+    return is_bipartite (graph, get (vertex_index, graph));
+  }
+
+  /**
+   * Checks a given graph for bipartiteness and fills a given color map with
+   * white and black according to the bipartition. If the graph is not
+   * bipartite, a sequence of vertices, producing an odd-cycle, is written to
+   * the output iterator. The final iterator value is returned. Runs in linear
+   * time in the size of the graph, if access to the property maps is in
+   * constant time.
+   *
+   * @param graph The given graph.
+   * @param index_map An index map associating vertices with an index.
+   * @param partition_map A color map to fill with the bipartition.
+   * @param result An iterator to write the odd-cycle vertices to.
+   * @return The final iterator value after writing.
+   */
+
+  template <typename Graph, typename IndexMap, typename PartitionMap, typename OutputIterator>
+  OutputIterator find_odd_cycle (const Graph& graph, const IndexMap index_map, PartitionMap partition_map,
+      OutputIterator result)
+  {
+    /// General types and variables
+    typedef typename property_traits <PartitionMap>::value_type partition_color_t;
+    typedef typename graph_traits <Graph>::vertex_descriptor vertex_descriptor_t;
+    typedef typename graph_traits <Graph>::vertex_iterator vertex_iterator_t;
+    vertex_iterator_t vertex_iter, vertex_end;
+
+    /// Declare predecessor map
+    typedef std::vector <vertex_descriptor_t> predecessors_t;
+    typedef iterator_property_map <typename predecessors_t::iterator, IndexMap, vertex_descriptor_t,
+        vertex_descriptor_t&> predecessor_map_t;
+    typedef predecessor_recorder <predecessor_map_t, IndexMap> predecessor_recorder_t;
+
+    predecessors_t predecessors (num_vertices (graph), graph_traits <Graph>::null_vertex ());
+    predecessor_map_t predecessor_map (predecessors.begin (), index_map);
+    predecessor_recorder_t predecessor_recorder (predecessor_map);
+
+    /// Initialize predecessor map
+    for (tie (vertex_iter, vertex_end) = vertices (graph); vertex_iter != vertex_end; ++vertex_iter)
+    {
+      put (predecessor_map, *vertex_iter, *vertex_iter);
+    }
+
+    /// Call dfs
+    try
+    {
+      depth_first_search (graph, vertex_index_map (index_map).visitor (make_dfs_visitor (std::make_pair (
+          detail::colorize_bipartition (partition_map), std::make_pair (detail::check_bipartition (partition_map),
+              std::make_pair (put_property (partition_map, color_traits <partition_color_t>::white (),
+                  on_start_vertex ()), record_predecessors (predecessor_map, on_tree_edge ())))))));
+    }
+    catch (detail::bipartite_visitor_error <vertex_descriptor_t> error)
+    {
+      typedef std::vector <vertex_descriptor_t> path_t;
+
+      path_t path1, path2;
+      vertex_descriptor_t next, current;
+
+      /// First path
+      next = error.witnesses.first;
+      do
+      {
+        current = next;
+        path1.push_back (current);
+        next = predecessor_map[current];
+      }
+      while (current != next);
+
+      /// Second path
+      next = error.witnesses.second;
+      do
+      {
+        current = next;
+        path2.push_back (current);
+        next = predecessor_map[current];
+      }
+      while (current != next);
+
+      /// Find beginning of common suffix
+      std::pair <typename path_t::iterator, typename path_t::iterator> mismatch = detail::reverse_mismatch (
+          std::make_pair (path1.begin (), path1.end ()), std::make_pair (path2.begin (), path2.end ()));
+
+      /// Copy the odd-length cycle
+      result = std::copy (path1.begin (), mismatch.first + 1, result);
+      return std::reverse_copy (path2.begin (), mismatch.second, result);
+    }
+
+    return result;
+  }
+
+  /**
+   * Checks a given graph for bipartiteness. If the graph is not bipartite, a
+   * sequence of vertices, producing an odd-cycle, is written to the output
+   * iterator. The final iterator value is returned. Runs in linear time in the
+   * size of the graph, if access to the property maps is in constant time.
+   *
+   * @param graph The given graph.
+   * @param index_map An index map associating vertices with an index.
+   * @param result An iterator to write the odd-cycle vertices to.
+   * @return The final iterator value after writing.
+   */
+
+  template <typename Graph, typename IndexMap, typename OutputIterator>
+  OutputIterator find_odd_cycle (const Graph& graph, const IndexMap index_map, OutputIterator result)
+  {
+    typedef one_bit_color_map <IndexMap> partition_map_t;
+    partition_map_t partition_map (num_vertices (graph), index_map);
+
+    return find_odd_cycle (graph, index_map, partition_map, result);
+  }
+
+  /**
+   * Checks a given graph for bipartiteness. If the graph is not bipartite, a
+   * sequence of vertices, producing an odd-cycle, is written to the output
+   * iterator. The final iterator value is returned. The graph must have an
+   * internal vertex_index property. Runs in linear time in the size of the
+   * graph, if access to the property maps is in constant time.
+   *
+   * @param graph The given graph.
+   * @param result An iterator to write the odd-cycle vertices to.
+   * @return The final iterator value after writing.
+   */
+
+  template <typename Graph, typename OutputIterator>
+  OutputIterator find_odd_cycle (const Graph& graph, OutputIterator result)
+  {
+    return find_odd_cycle (graph, get (vertex_index, graph), result);
+  }
+}
+
+#endif /// BOOST_GRAPH_BIPARTITE_HPP
Added: trunk/libs/graph/doc/find_odd_cycle.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph/doc/find_odd_cycle.html	2010-03-11 11:56:01 EST (Thu, 11 Mar 2010)
@@ -0,0 +1,152 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<!--
+     Authors: Matthias Walter
+    
+     Distributed under the Boost Software License, Version 1.0.
+     (See accompanying file LICENSE_1_0.txt or copy at
+     http://www.boost.org/LICENSE_1_0.txt)
+  -->
+<head>
+<title>Boost Graph Library: find_odd_cycle</title>
+</head>
+<body>
+
+<IMG SRC="../../../boost.png" 
+ALT="C++ Boost" width="277" height="86"> 
+<h1>
+<tt>find_odd_cycle</tt>
+</h1>
+
+<pre>
+<i>// Version with a colormap to retrieve the bipartition</i>
+template <typename Graph, typename IndexMap, typename PartitionMap, typename OutputIterator>
+OutputIterator find_odd_cycle (const Graph& graph, const IndexMap index_map, PartitionMap partition_map, OutputIterator result)
+
+template <typename Graph, typename IndexMap, typename OutputIterator>
+OutputIterator find_odd_cycle (const Graph& graph, const IndexMap index_map, OutputIterator result)
+
+<i>// Version which uses the internal index map</i>
+template <typename Graph, typename OutputIterator>
+OutputIterator find_odd_cycle (const Graph& graph, OutputIterator result)
+</pre>
+
+<p>
+The <tt>find_odd_cycle</tt> function tests a given graph for bipartiteness
+using a DFS-based coloring approach.
+</p>
+
+<p>
+An undirected graph is bipartite if one can partition its set of vertices
+into two sets "left" and "right", such that each edge goes from either side
+to the other. Obviously, a two-coloring of the graph is exactly the same as
+a two-partition. <tt>is_bipartite()</tt> tests whether such a two-coloring
+is possible and can return it in a given property map.
+</p>
+
+<p>
+Another equivalent characterization is the non-existance of odd-length cycles,
+meaning that a graph is bipartite if and only if it does not contain a
+cycle with an odd number of vertices as a subgraph.
+<tt>find_odd_cycle()</tt> does nearly the same as
+is_bipartite(),
+but additionally constructs an odd-length cycle if the graph is found to be
+not bipartite.
+</p>
+
+<p>
+The bipartition is recorded in the color map <tt>partition_map</tt>,
+which will contain a two-coloring of the graph, i.e. an assignment of
+<i>black</i> and <i>white</i> to the vertices such that no edge is monochromatic.
+The odd-length cycle is written into the Output Iterator <tt>result</tt> if
+one exists. The final final iterator is returned by the function.
+</p>
+
+<h3>Where Defined</h3>
+
+<p>
+boost/graph/bipartite.hpp
+</p>
+
+<h3>Parameters</h3>
+
+<p>
+IN: <tt>const Graph& graph</tt>
+</p>
+<blockquote><p>
+An undirected graph. The graph type must be a model of <a
+href="VertexListGraph.html">Vertex List Graph</a> and <a
+href="IncidenceGraph.html">Incidence Graph</a>.<br/>
+</p></blockquote>
+
+<p>
+IN: <tt>const IndexMap index_map</tt>
+</p>
+<blockquote><p>
+This maps each vertex to an integer in the range <tt>[0,
+num_vertices(graph))</tt>. The type <tt>VertexIndexMap</tt>
+must be a model of <a
+href="../../property_map/doc/ReadablePropertyMap.html">Readable Property
+Map</a>. The value type of the map must be an integer type. The
+vertex descriptor type of the graph needs to be usable as the key
+type of the map.<br/>
+</p></blockquote>
+
+
+<p>
+OUT: <tt>PartitionMap partition_map</tt>
+</p>
+<blockquote><p>
+The algorithm tests whether the graph is bipartite and assigns each
+vertex either a white or a black color, according to the partition.
+The <tt>PartitionMap</tt> type must be a model of
+<a href="../../property_map/doc/ReadablePropertyMap.html">Readable Property
+Map</a> and
+<a href="../../property_map/doc/WritablePropertyMap.html">Writable Property
+Map</a>. The value type must model ColorValue.
+</p></blockquote>
+
+<p>
+OUT: <tt>OutputIterator result</tt>
+</p>
+<blockquote><p>
+The <tt>find_odd_cycle</tt> function finds an odd-length cycle if the graph is
+not bipartite. The sequence of vertices producing such a cycle is written
+into this iterator. The <tt>OutputIterator</tt> type must be a model of
+<a class="external" href="http://www.sgi.com/tech/stl/OutputIterator.html">
+OutputIterator</a>. The graph's vertex descriptor type must be in the set
+of value types of the iterator. The final value is returned by the
+function. If the graph is bipartite (i.e. no odd-length cycle exists), nothing
+is written, thus the given iterator matches the return value.
+</p></blockquote>
+
+
+<h3>Complexity</h3>
+
+<p>
+The time complexity for the algorithm is <i>O(V + E)</i>.
+</p>
+
+<h3>See Also</h3>
+
+<p>
+is_bipartite()
+</p>
+
+<h3>Example</h3>
+
+<p>
+The file example/bipartite_example.cpp
+contains an example of testing an undirected graph for bipartiteness.
+<br/>
+</p>
+
+<hr/>
+
+<p>
+Copyright © 2010 Matthias Walter
+(<a class="external" href="mailto:xammy_at_[hidden]">xammy_at_[hidden]</a>)
+</p>
+
+</body>
+</html> 
Added: trunk/libs/graph/doc/is_bipartite.html
==============================================================================
--- (empty file)
+++ trunk/libs/graph/doc/is_bipartite.html	2010-03-11 11:56:01 EST (Thu, 11 Mar 2010)
@@ -0,0 +1,127 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<!--
+     Authors: Matthias Walter
+    
+     Distributed under the Boost Software License, Version 1.0.
+     (See accompanying file LICENSE_1_0.txt or copy at
+     http://www.boost.org/LICENSE_1_0.txt)
+  -->
+<head>
+<title>Boost Graph Library: is_bipartite</title>
+</head>
+<body>
+
+<IMG SRC="../../../boost.png" 
+ALT="C++ Boost" width="277" height="86"> 
+<h1>
+<tt>is_bipartite</tt>
+</h1>
+
+<pre>
+<i>// Version with a colormap to retrieve the bipartition</i>
+template <typename Graph, typename IndexMap, typename PartitionMap>
+bool is_bipartite (const Graph& graph, const IndexMap index_map, PartitionMap partition_map)
+
+template <typename Graph, typename IndexMap>
+bool is_bipartite (const Graph& graph, const IndexMap index_map)
+
+<i>// Version which uses the internal index map</i>
+template <typename Graph>
+bool is_bipartite (const Graph& graph);
+</pre>
+
+<p>
+The <tt>is_bipartite()</tt> functions tests a given graph for
+bipartiteness using a DFS-based coloring approach.
+</p>
+
+<p>
+An undirected graph is bipartite if one can partition its set of vertices
+into two sets "left" and "right", such that each edge goes from either side
+to the other. Obviously, a two-coloring of the graph is exactly the same as
+a two-partition. <tt>is_bipartite()</tt> tests whether such a two-coloring
+is possible and can return it in a given property map.
+</p>
+
+<p>
+The bipartition is recorded in the color map <tt>partition_map</tt>,
+which will contain a two-coloring of the graph, i.e. an assignment of
+<i>black</i> and <i>white</i> to the vertices such that no edge is monochromatic.
+The predicate whether the graph is bipartite is the return value of the function.
+</p>
+
+<h3>Where Defined</h3>
+
+<p>
+boost/graph/bipartite.hpp
+</p>
+
+<h3>Parameters</h3>
+
+<p>
+IN: <tt>const Graph& graph</tt>
+</p>
+<blockquote><p>
+An undirected graph. The graph type must be a model of <a
+href="VertexListGraph.html">Vertex List Graph</a> and <a
+href="IncidenceGraph.html">Incidence Graph</a>.<br/>
+</p></blockquote>
+
+<p>
+IN: <tt>const IndexMap index_map</tt>
+</p>
+<blockquote><p>
+This maps each vertex to an integer in the range <tt>[0,
+num_vertices(graph))</tt>. The type <tt>VertexIndexMap</tt>
+must be a model of <a
+href="../../property_map/doc/ReadablePropertyMap.html">Readable Property
+Map</a>. The value type of the map must be an integer type. The
+vertex descriptor type of the graph needs to be usable as the key
+type of the map.<br/>
+</p></blockquote>
+
+
+<p>
+OUT: <tt>PartitionMap partition_map</tt>
+</p>
+<blockquote><p>
+The algorithm tests whether the graph is bipartite and assigns each
+vertex either a white or a black color, according to the partition.
+The <tt>PartitionMap</tt> type must be a model of
+<a href="../../property_map/doc/ReadablePropertyMap.html">Readable Property
+Map</a> and
+<a href="../../property_map/doc/WritablePropertyMap.html">Writable Property
+Map</a> The value type must model ColorValue.
+</p></blockquote>
+
+
+<h3>Complexity</h3>
+
+<p>
+The time complexity for the algorithm is <i>O(V + E)</i>.
+</p>
+
+<h3>See Also</h3>
+
+<p>
+find_odd_cycle()
+</p>
+
+<h3>Example</h3>
+
+<p>
+The file examples/bipartite.cpp
+contains an example of testing an undirected graph for bipartiteness.
+<br/>
+</p>
+
+<hr/>
+
+<p>
+Copyright © 2010 Matthias Walter
+(<a class="external" href="mailto:xammy_at_[hidden]">xammy_at_[hidden]</a>)
+</p>
+
+</body>
+</html> 
Modified: trunk/libs/graph/doc/table_of_contents.html
==============================================================================
--- trunk/libs/graph/doc/table_of_contents.html	(original)
+++ trunk/libs/graph/doc/table_of_contents.html	2010-03-11 11:56:01 EST (Thu, 11 Mar 2010)
@@ -265,6 +265,8 @@
                   <ol>
                       <li>metric_tsp_approx</li>
                       <LI>sequential_vertex_coloring
+                      <LI>is_bipartite (including two-coloring of bipartite graphs)
+                      <LI>find_odd_cycle
                   </ol>
               </li>
 
Modified: trunk/libs/graph/example/Jamfile.v2
==============================================================================
--- trunk/libs/graph/example/Jamfile.v2	(original)
+++ trunk/libs/graph/example/Jamfile.v2	2010-03-11 11:56:01 EST (Thu, 11 Mar 2010)
@@ -20,3 +20,4 @@
 exe bron_kerbosch_clique_number : bron_kerbosch_clique_number.cpp ;
 exe mcgregor_subgraphs_example : mcgregor_subgraphs_example.cpp ;
 exe grid_graph_example : grid_graph_example.cpp ;
+exe bipartite_example : bipartite_example.cpp ;
Added: trunk/libs/graph/example/bipartite_example.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph/example/bipartite_example.cpp	2010-03-11 11:56:01 EST (Thu, 11 Mar 2010)
@@ -0,0 +1,115 @@
+/**
+ *
+ * Copyright (c) 2010 Matthias Walter (xammy_at_[hidden])
+ *
+ * Authors: Matthias Walter
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include <iostream>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/bipartite.hpp>
+
+using namespace boost;
+
+/// Example to test for bipartiteness and print the certificates.
+
+template <typename Graph>
+void print_bipartite (const Graph& g)
+{
+  typedef graph_traits <Graph> traits;
+  typename traits::vertex_iterator vertex_iter, vertex_end;
+
+  /// Most simple interface just tests for bipartiteness. 
+
+  bool bipartite = is_bipartite (g);
+
+  if (bipartite)
+  {
+    typedef std::vector <default_color_type> partition_t;
+    typedef vec_adj_list_vertex_id_map <no_property, unsigned int> index_map_t;
+    typedef iterator_property_map <partition_t::iterator, index_map_t> partition_map_t;
+
+    partition_t partition (num_vertices (g));
+    partition_map_t partition_map (partition.begin (), get (vertex_index, g));
+
+    /// A second interface yields a bipartition in a color map, if the graph is bipartite.
+
+    is_bipartite (g, get (vertex_index, g), partition_map);
+
+    for (tie (vertex_iter, vertex_end) = vertices (g); vertex_iter != vertex_end; ++vertex_iter)
+    {
+      std::cout << "Vertex " << *vertex_iter << " has color " << (get (partition_map, *vertex_iter) == color_traits <
+          default_color_type>::white () ? "white" : "black") << std::endl;
+    }
+  }
+  else
+  {
+    typedef std::vector <typename traits::vertex_descriptor> vertex_vector_t;
+    vertex_vector_t odd_cycle;
+
+    /// A third interface yields an odd-cycle if the graph is not bipartite.
+
+    find_odd_cycle (g, get (vertex_index, g), std::back_inserter (odd_cycle));
+
+    std::cout << "Odd cycle consists of the vertices:";
+    for (size_t i = 0; i < odd_cycle.size (); ++i)
+    {
+      std::cout << " " << odd_cycle[i];
+    }
+    std::cout << std::endl;
+  }
+}
+
+int main (int argc, char **argv)
+{
+  typedef adjacency_list <vecS, vecS, undirectedS> vector_graph_t;
+  typedef std::pair <int, int> E;
+
+  /**
+   * Create the graph drawn below.
+   *
+   *       0 - 1 - 2
+   *       |       |
+   *   3 - 4 - 5 - 6
+   *  /      \   /
+   *  |        7
+   *  |        |
+   *  8 - 9 - 10
+   **/
+
+  E bipartite_edges[] = { E (0, 1), E (0, 4), E (1, 2), E (2, 6), E (3, 4), E (3, 8), E (4, 5), E (4, 7), E (5, 6), E (
+      6, 7), E (7, 10), E (8, 9), E (9, 10) };
+  vector_graph_t bipartite_vector_graph (&bipartite_edges[0],
+      &bipartite_edges[0] + sizeof(bipartite_edges) / sizeof(E), 11);
+
+  /**
+   * Create the graph drawn below.
+   * 
+   *       2 - 1 - 0
+   *       |       |
+   *   3 - 6 - 5 - 4
+   *  /      \   /
+   *  |        7
+   *  |       /
+   *  8 ---- 9
+   *  
+   **/
+
+  E non_bipartite_edges[] = { E (0, 1), E (0, 4), E (1, 2), E (2, 6), E (3, 6), E (3, 8), E (4, 5), E (4, 7), E (5, 6),
+      E (6, 7), E (7, 9), E (8, 9) };
+  vector_graph_t non_bipartite_vector_graph (&non_bipartite_edges[0], &non_bipartite_edges[0]
+      + sizeof(non_bipartite_edges) / sizeof(E), 10);
+
+  /// Call test routine for a bipartite and a non-bipartite graph.
+
+  print_bipartite (bipartite_vector_graph);
+
+  print_bipartite (non_bipartite_vector_graph);
+
+  return 0;
+}
Modified: trunk/libs/graph/test/Jamfile.v2
==============================================================================
--- trunk/libs/graph/test/Jamfile.v2	(original)
+++ trunk/libs/graph/test/Jamfile.v2	2010-03-11 11:56:01 EST (Thu, 11 Mar 2010)
@@ -36,6 +36,7 @@
     [ run bellman-test.cpp ]
     [ run betweenness_centrality_test.cpp : 100 ]
     [ run bidir_remove_edge.cpp ]
+    [ run bipartite_test.cpp ]
     [ run csr_graph_test.cpp : : : : : <variant>release ]
     [ run dag_longest_paths.cpp ]
     [ run dfs.cpp ../../test/build//boost_test_exec_monitor ]
Added: trunk/libs/graph/test/bipartite_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/graph/test/bipartite_test.cpp	2010-03-11 11:56:01 EST (Thu, 11 Mar 2010)
@@ -0,0 +1,189 @@
+/**
+ *
+ * Copyright (c) 2010 Matthias Walter (xammy_at_[hidden])
+ *
+ * Authors: Matthias Walter
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/lookup_edge.hpp>
+#include <boost/test/minimal.hpp>
+#include <boost/graph/bipartite.hpp>
+
+/// Verifies a 2-coloring
+
+template <typename Graph, typename ColorMap>
+void check_two_coloring (const Graph& g, const ColorMap color_map)
+{
+  typedef boost::graph_traits <Graph> traits;
+  typename traits::edge_iterator edge_iter, edge_end;
+
+  for (boost::tie (edge_iter, edge_end) = boost::edges (g); edge_iter != edge_end; ++edge_iter)
+  {
+    typename traits::vertex_descriptor source, target;
+    source = boost::source (*edge_iter, g);
+    target = boost::target (*edge_iter, g);
+    BOOST_REQUIRE (boost::get(color_map, source) != boost::get(color_map, target));
+  }
+}
+
+/// Tests for a vertex sequence to define an odd cycle
+
+template <typename Graph, typename RandomAccessIterator>
+void check_odd_cycle (const Graph& g, RandomAccessIterator first, RandomAccessIterator beyond)
+{
+  typedef boost::graph_traits <Graph> traits;
+
+  typename traits::vertex_descriptor first_vertex, current_vertex, last_vertex;
+
+  BOOST_CHECK ((beyond - first) % 2 == 1);
+
+  //  std::cout << "odd_cycle: " << int(*first) << std::endl;
+
+  for (first_vertex = current_vertex = *first++; first != beyond; ++first)
+  {
+    //    std::cout << "odd_cycle: " << int(*first) << std::endl;
+
+    last_vertex = current_vertex;
+    current_vertex = *first;
+
+    BOOST_REQUIRE (boost::lookup_edge (current_vertex, last_vertex, g).second);
+  }
+
+  BOOST_REQUIRE (boost::lookup_edge (first_vertex, current_vertex, g).second);
+}
+
+/// Call the is_bipartite and find_odd_cycle functions and verify their results.
+
+template <typename Graph, typename IndexMap>
+void check_bipartite (const Graph& g, IndexMap index_map, bool is_bipartite)
+{
+  typedef boost::graph_traits <Graph> traits;
+  typedef std::vector <boost::default_color_type> partition_t;
+  typedef std::vector <typename traits::vertex_descriptor> vertex_vector_t;
+  typedef boost::iterator_property_map <partition_t::iterator, IndexMap> partition_map_t;
+
+  partition_t partition (boost::num_vertices (g));
+  partition_map_t partition_map (partition.begin (), index_map);
+
+  vertex_vector_t odd_cycle (boost::num_vertices (g));
+
+  bool first_result = boost::is_bipartite (g, index_map, partition_map);
+
+  BOOST_REQUIRE (first_result == boost::is_bipartite(g, index_map));
+
+  if (first_result)
+    check_two_coloring (g, partition_map);
+
+  BOOST_CHECK (first_result == is_bipartite);
+
+  typename vertex_vector_t::iterator second_first = odd_cycle.begin ();
+  typename vertex_vector_t::iterator second_beyond = boost::find_odd_cycle (g, index_map, partition_map, second_first);
+
+  if (is_bipartite)
+  {
+    BOOST_CHECK (second_beyond == second_first);
+    check_two_coloring (g, partition_map);
+  }
+  else
+  {
+    check_odd_cycle (g, second_first, second_beyond);
+  }
+
+  second_beyond = boost::find_odd_cycle (g, index_map, second_first);
+  if (is_bipartite)
+  {
+    BOOST_CHECK (second_beyond == second_first);
+  }
+  else
+  {
+    check_odd_cycle (g, second_first, second_beyond);
+  }
+}
+
+int test_main (int argc, char **argv)
+{
+  typedef boost::adjacency_list <boost::vecS, boost::vecS, boost::undirectedS> vector_graph_t;
+  typedef boost::adjacency_list <boost::listS, boost::listS, boost::undirectedS> list_graph_t;
+  typedef std::pair <int, int> E;
+
+  typedef std::map <boost::graph_traits <list_graph_t>::vertex_descriptor, size_t> index_map_t;
+  typedef boost::associative_property_map <index_map_t> index_property_map_t;
+
+  /**
+   * Create the graph drawn below.
+   *
+   *       0 - 1 - 2
+   *       |       |
+   *   3 - 4 - 5 - 6
+   *  /      \   /
+   *  |        7
+   *  |        |
+   *  8 - 9 - 10
+   **/
+
+  E bipartite_edges[] = { E (0, 1), E (0, 4), E (1, 2), E (2, 6), E (3, 4), E (3, 8), E (4, 5), E (4, 7), E (5, 6), E (
+      6, 7), E (7, 10), E (8, 9), E (9, 10) };
+  vector_graph_t bipartite_vector_graph (&bipartite_edges[0],
+      &bipartite_edges[0] + sizeof(bipartite_edges) / sizeof(E), 11);
+  list_graph_t
+      bipartite_list_graph (&bipartite_edges[0], &bipartite_edges[0] + sizeof(bipartite_edges) / sizeof(E), 11);
+
+  /**
+   * Create the graph drawn below.
+   * 
+   *       2 - 1 - 0
+   *       |       |
+   *   3 - 6 - 5 - 4
+   *  /      \   /
+   *  |        7
+   *  |       /
+   *  8 ---- 9
+   *  
+   **/
+
+  E non_bipartite_edges[] = { E (0, 1), E (0, 4), E (1, 2), E (2, 6), E (3, 4), E (3, 8), E (4, 5), E (4, 7), E (5, 6),
+      E (6, 7), E (7, 9), E (8, 9) };
+  vector_graph_t non_bipartite_vector_graph (&non_bipartite_edges[0], &non_bipartite_edges[0]
+      + sizeof(non_bipartite_edges) / sizeof(E), 10);
+  list_graph_t non_bipartite_list_graph (&non_bipartite_edges[0], &non_bipartite_edges[0] + sizeof(non_bipartite_edges)
+      / sizeof(E), 10);
+
+  /// Create index maps
+
+  index_map_t bipartite_index_map, non_bipartite_index_map;
+  boost::graph_traits <list_graph_t>::vertex_iterator vertex_iter, vertex_end;
+  size_t i = 0;
+  for (boost::tie (vertex_iter, vertex_end) = boost::vertices (bipartite_list_graph); vertex_iter != vertex_end; ++vertex_iter)
+  {
+    bipartite_index_map[*vertex_iter] = i++;
+  }
+  index_property_map_t bipartite_index_property_map = index_property_map_t (bipartite_index_map);
+
+  i = 0;
+  for (boost::tie (vertex_iter, vertex_end) = boost::vertices (non_bipartite_list_graph); vertex_iter != vertex_end; ++vertex_iter)
+  {
+    non_bipartite_index_map[*vertex_iter] = i++;
+  }
+  index_property_map_t non_bipartite_index_property_map = index_property_map_t (non_bipartite_index_map);
+
+  /// Call real checks
+
+  check_bipartite (bipartite_vector_graph, boost::get (boost::vertex_index, bipartite_vector_graph), true);
+  check_bipartite (bipartite_list_graph, bipartite_index_property_map, true);
+
+  check_bipartite (non_bipartite_vector_graph, boost::get (boost::vertex_index, non_bipartite_vector_graph), false);
+  check_bipartite (non_bipartite_list_graph, non_bipartite_index_property_map, false);
+
+  /// Test some more interfaces
+
+  BOOST_REQUIRE (is_bipartite (bipartite_vector_graph));
+  BOOST_REQUIRE (!is_bipartite (non_bipartite_vector_graph));
+
+  return 0;
+}