[Lemon-commits] Balazs Dezso: Port planarity related algorithms ...

Lemon HG hg at lemon.cs.elte.hu
Wed Dec 9 11:30:50 CET 2009


details:   http://lemon.cs.elte.hu/hg/lemon/rev/30cb42e3e43a
changeset: 861:30cb42e3e43a
user:      Balazs Dezso <deba [at] inf.elte.hu>
date:      Wed Sep 09 15:32:03 2009 +0200
description:
	Port planarity related algorithms from SVN 3509 (#62)

diffstat:

 lemon/Makefile.am      |     1 +
 lemon/planarity.h      |  2737 +++++++++++++++++++++++++++++++++++++++++++++++++++
 test/CMakeLists.txt    |     1 +
 test/Makefile.am       |     2 +
 test/planarity_test.cc |   259 ++++
 5 files changed, 3000 insertions(+), 0 deletions(-)

diffs (truncated from 3047 to 300 lines):

diff --git a/lemon/Makefile.am b/lemon/Makefile.am
--- a/lemon/Makefile.am
+++ b/lemon/Makefile.am
@@ -104,6 +104,7 @@
 	lemon/network_simplex.h \
 	lemon/pairing_heap.h \
 	lemon/path.h \
+	lemon/planarity.h \
 	lemon/preflow.h \
 	lemon/radix_heap.h \
 	lemon/radix_sort.h \
diff --git a/lemon/planarity.h b/lemon/planarity.h
new file mode 100644
--- /dev/null
+++ b/lemon/planarity.h
@@ -0,0 +1,2737 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_PLANARITY_H
+#define LEMON_PLANARITY_H
+
+/// \ingroup planar
+/// \file
+/// \brief Planarity checking, embedding, drawing and coloring
+
+#include <vector>
+#include <list>
+
+#include <lemon/dfs.h>
+#include <lemon/bfs.h>
+#include <lemon/radix_sort.h>
+#include <lemon/maps.h>
+#include <lemon/path.h>
+#include <lemon/bucket_heap.h>
+#include <lemon/adaptors.h>
+#include <lemon/edge_set.h>
+#include <lemon/color.h>
+#include <lemon/dim2.h>
+
+namespace lemon {
+
+  namespace _planarity_bits {
+
+    template <typename Graph>
+    struct PlanarityVisitor : DfsVisitor<Graph> {
+
+      TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+      typedef typename Graph::template NodeMap<Arc> PredMap;
+
+      typedef typename Graph::template EdgeMap<bool> TreeMap;
+
+      typedef typename Graph::template NodeMap<int> OrderMap;
+      typedef std::vector<Node> OrderList;
+
+      typedef typename Graph::template NodeMap<int> LowMap;
+      typedef typename Graph::template NodeMap<int> AncestorMap;
+
+      PlanarityVisitor(const Graph& graph,
+                       PredMap& pred_map, TreeMap& tree_map,
+                       OrderMap& order_map, OrderList& order_list,
+                       AncestorMap& ancestor_map, LowMap& low_map)
+        : _graph(graph), _pred_map(pred_map), _tree_map(tree_map),
+          _order_map(order_map), _order_list(order_list),
+          _ancestor_map(ancestor_map), _low_map(low_map) {}
+
+      void reach(const Node& node) {
+        _order_map[node] = _order_list.size();
+        _low_map[node] = _order_list.size();
+        _ancestor_map[node] = _order_list.size();
+        _order_list.push_back(node);
+      }
+
+      void discover(const Arc& arc) {
+        Node source = _graph.source(arc);
+        Node target = _graph.target(arc);
+
+        _tree_map[arc] = true;
+        _pred_map[target] = arc;
+      }
+
+      void examine(const Arc& arc) {
+        Node source = _graph.source(arc);
+        Node target = _graph.target(arc);
+
+        if (_order_map[target] < _order_map[source] && !_tree_map[arc]) {
+          if (_low_map[source] > _order_map[target]) {
+            _low_map[source] = _order_map[target];
+          }
+          if (_ancestor_map[source] > _order_map[target]) {
+            _ancestor_map[source] = _order_map[target];
+          }
+        }
+      }
+
+      void backtrack(const Arc& arc) {
+        Node source = _graph.source(arc);
+        Node target = _graph.target(arc);
+
+        if (_low_map[source] > _low_map[target]) {
+          _low_map[source] = _low_map[target];
+        }
+      }
+
+      const Graph& _graph;
+      PredMap& _pred_map;
+      TreeMap& _tree_map;
+      OrderMap& _order_map;
+      OrderList& _order_list;
+      AncestorMap& _ancestor_map;
+      LowMap& _low_map;
+    };
+
+    template <typename Graph, bool embedding = true>
+    struct NodeDataNode {
+      int prev, next;
+      int visited;
+      typename Graph::Arc first;
+      bool inverted;
+    };
+
+    template <typename Graph>
+    struct NodeDataNode<Graph, false> {
+      int prev, next;
+      int visited;
+    };
+
+    template <typename Graph>
+    struct ChildListNode {
+      typedef typename Graph::Node Node;
+      Node first;
+      Node prev, next;
+    };
+
+    template <typename Graph>
+    struct ArcListNode {
+      typename Graph::Arc prev, next;
+    };
+
+  }
+
+  /// \ingroup planar
+  ///
+  /// \brief Planarity checking of an undirected simple graph
+  ///
+  /// This class implements the Boyer-Myrvold algorithm for planarity
+  /// checking of an undirected graph. This class is a simplified
+  /// version of the PlanarEmbedding algorithm class because neither
+  /// the embedding nor the kuratowski subdivisons are not computed.
+  template <typename Graph>
+  class PlanarityChecking {
+  private:
+
+    TEMPLATE_GRAPH_TYPEDEFS(Graph);
+
+    const Graph& _graph;
+
+  private:
+
+    typedef typename Graph::template NodeMap<Arc> PredMap;
+
+    typedef typename Graph::template EdgeMap<bool> TreeMap;
+
+    typedef typename Graph::template NodeMap<int> OrderMap;
+    typedef std::vector<Node> OrderList;
+
+    typedef typename Graph::template NodeMap<int> LowMap;
+    typedef typename Graph::template NodeMap<int> AncestorMap;
+
+    typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode;
+    typedef std::vector<NodeDataNode> NodeData;
+
+    typedef _planarity_bits::ChildListNode<Graph> ChildListNode;
+    typedef typename Graph::template NodeMap<ChildListNode> ChildLists;
+
+    typedef typename Graph::template NodeMap<std::list<int> > MergeRoots;
+
+    typedef typename Graph::template NodeMap<bool> EmbedArc;
+
+  public:
+
+    /// \brief Constructor
+    ///
+    /// \note The graph should be simple, i.e. parallel and loop arc
+    /// free.
+    PlanarityChecking(const Graph& graph) : _graph(graph) {}
+
+    /// \brief Runs the algorithm.
+    ///
+    /// Runs the algorithm.
+    /// \return %True when the graph is planar.
+    bool run() {
+      typedef _planarity_bits::PlanarityVisitor<Graph> Visitor;
+
+      PredMap pred_map(_graph, INVALID);
+      TreeMap tree_map(_graph, false);
+
+      OrderMap order_map(_graph, -1);
+      OrderList order_list;
+
+      AncestorMap ancestor_map(_graph, -1);
+      LowMap low_map(_graph, -1);
+
+      Visitor visitor(_graph, pred_map, tree_map,
+                      order_map, order_list, ancestor_map, low_map);
+      DfsVisit<Graph, Visitor> visit(_graph, visitor);
+      visit.run();
+
+      ChildLists child_lists(_graph);
+      createChildLists(tree_map, order_map, low_map, child_lists);
+
+      NodeData node_data(2 * order_list.size());
+
+      EmbedArc embed_arc(_graph, false);
+
+      MergeRoots merge_roots(_graph);
+
+      for (int i = order_list.size() - 1; i >= 0; --i) {
+
+        Node node = order_list[i];
+
+        Node source = node;
+        for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+          Node target = _graph.target(e);
+
+          if (order_map[source] < order_map[target] && tree_map[e]) {
+            initFace(target, node_data, order_map, order_list);
+          }
+        }
+
+        for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+          Node target = _graph.target(e);
+
+          if (order_map[source] < order_map[target] && !tree_map[e]) {
+            embed_arc[target] = true;
+            walkUp(target, source, i, pred_map, low_map,
+                   order_map, order_list, node_data, merge_roots);
+          }
+        }
+
+        for (typename MergeRoots::Value::iterator it =
+               merge_roots[node].begin(); it != merge_roots[node].end(); ++it) {
+          int rn = *it;
+          walkDown(rn, i, node_data, order_list, child_lists,
+                   ancestor_map, low_map, embed_arc, merge_roots);
+        }
+        merge_roots[node].clear();
+
+        for (OutArcIt e(_graph, node); e != INVALID; ++e) {
+          Node target = _graph.target(e);
+
+          if (order_map[source] < order_map[target] && !tree_map[e]) {
+            if (embed_arc[target]) {
+              return false;
+            }
+          }
+        }
+      }
+
+      return true;
+    }
+
+  private:
+
+    void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
+                          const LowMap& low_map, ChildLists& child_lists) {
+
+      for (NodeIt n(_graph); n != INVALID; ++n) {
+        Node source = n;
+
+        std::vector<Node> targets;
+        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
+          Node target = _graph.target(e);
+
+          if (order_map[source] < order_map[target] && tree_map[e]) {
+            targets.push_back(target);
+          }
+        }
+
+        if (targets.size() == 0) {
+          child_lists[source].first = INVALID;
+        } else if (targets.size() == 1) {
+          child_lists[source].first = targets[0];
+          child_lists[targets[0]].prev = INVALID;



More information about the Lemon-commits mailing list