[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