# HG changeset patch
# User Peter Kovacs <kpeter@inf.elte.hu>
# Date 1220387524 -7200
# Node ID ada5f74d1c9e874b24256426f1c5c0e141fcbc2d
# Parent  c760d691fe3c47f3f57ee31f18f5aa5ae6fcf965
Port grid graph structure from SVN 3503 (ticket #57)

diff -r c760d691fe3c -r ada5f74d1c9e lemon/Makefile.am
--- a/lemon/Makefile.am	Tue Sep 02 22:27:19 2008 +0200
+++ b/lemon/Makefile.am	Tue Sep 02 22:32:04 2008 +0200
@@ -30,6 +30,7 @@
         lemon/dim2.h \
 	lemon/error.h \
         lemon/graph_to_eps.h \
+        lemon/grid_graph.h \
 	lemon/kruskal.h \
 	lemon/lgf_reader.h \
 	lemon/lgf_writer.h \
diff -r c760d691fe3c -r ada5f74d1c9e lemon/grid_graph.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lemon/grid_graph.h	Tue Sep 02 22:32:04 2008 +0200
@@ -0,0 +1,471 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2008
+ * 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 GRID_GRAPH_H
+#define GRID_GRAPH_H
+
+#include <iostream>
+#include <lemon/core.h>
+#include <lemon/assert.h>
+
+#include <lemon/bits/base_extender.h>
+#include <lemon/bits/graph_extender.h>
+
+#include <lemon/dim2.h>
+
+///\ingroup graphs
+///\file
+///\brief GridGraph class.
+
+namespace lemon {
+
+  class GridGraphBase {
+
+  public:
+
+    typedef GridGraphBase Graph;
+
+    class Node;
+    class Arc;
+
+  public:
+
+    GridGraphBase() {}
+
+  protected:
+
+    void construct(int w, int h) {
+      _height = h; _width = w;
+      _nodeNum = h * w; _arcNum = 2 * _nodeNum - w - h;
+      _arcLimit = _nodeNum - w;
+    }
+
+    Arc _down(Node n) const {
+      if (n.id < _nodeNum - _width) {
+        return Arc(n.id);
+      } else {
+        return INVALID;
+      }
+    }
+
+    Arc _up(Node n) const {
+      if (n.id >= _width) {
+        return Arc(n.id - _width);
+      } else {
+        return INVALID;
+      }
+    }
+
+    Arc _right(Node n) const {
+      if (n.id % _width < _width - 1) {
+        return _arcLimit + n.id % _width + (n.id / _width) * (_width - 1);
+      } else {
+        return INVALID;
+      }
+    }
+
+    Arc _left(Node n) const {
+      if (n.id % _width > 0) {
+        return _arcLimit + n.id % _width + (n.id / _width) * (_width - 1) - 1;
+      } else {
+        return INVALID;
+      }
+    }
+
+  public:
+
+    Node operator()(int i, int j) const {
+      LEMON_ASSERT(0 <= i && i < width() &&
+                   0 <= j && j < height(), "lemon::GridGraph::IndexError");
+      return Node(i + j * _width);
+    }
+
+    int row(Node n) const {
+      return n.id / _width;
+    }
+
+    int col(Node n) const {
+      return n.id % _width;
+    }
+
+    int width() const {
+      return _width;
+    }
+
+    int height() const {
+      return _height;
+    }
+
+    typedef True NodeNumTag;
+    typedef True ArcNumTag;
+
+    int nodeNum() const { return _nodeNum; }
+    int arcNum() const { return _arcNum; }
+
+    int maxNodeId() const { return nodeNum() - 1; }
+    int maxArcId() const { return arcNum() - 1; }
+
+    Node source(Arc e) const {
+      if (e.id < _arcLimit) {
+        return e.id;
+      } else {
+        return (e.id - _arcLimit) % (_width - 1) +
+          (e.id - _arcLimit) / (_width - 1) * _width;
+      }
+    }
+
+    Node target(Arc e) const {
+      if (e.id < _arcLimit) {
+        return e.id + _width;
+      } else {
+        return (e.id - _arcLimit) % (_width - 1) +
+          (e.id - _arcLimit) / (_width - 1) * _width + 1;
+      }
+    }
+
+    static int id(Node v) { return v.id; }
+    static int id(Arc e) { return e.id; }
+
+    static Node nodeFromId(int id) { return Node(id);}
+
+    static Arc arcFromId(int id) { return Arc(id);}
+
+    typedef True FindArcTag;
+
+    Arc findArc(Node u, Node v, Arc prev = INVALID) const {
+      if (prev != INVALID) return INVALID;
+      if (v.id - u.id == _width) return Arc(u.id);
+      if (v.id - u.id == 1 && u.id % _width < _width - 1) {
+        return Arc(u.id / _width * (_width - 1) +
+                   u.id % _width + _arcLimit);
+      }
+      return INVALID;
+    }
+
+    class Node {
+      friend class GridGraphBase;
+
+    protected:
+      int id;
+      Node(int _id) : id(_id) {}
+    public:
+      Node() {}
+      Node (Invalid) { id = -1; }
+      bool operator==(const Node node) const { return id == node.id; }
+      bool operator!=(const Node node) const { return id != node.id; }
+      bool operator<(const Node node) const { return id < node.id; }
+    };
+
+    class Arc {
+      friend class GridGraphBase;
+
+    protected:
+      int id;
+      Arc(int _id) : id(_id) {}
+    public:
+      Arc() {}
+      Arc (Invalid) { id = -1; }
+      bool operator==(const Arc arc) const { return id == arc.id; }
+      bool operator!=(const Arc arc) const { return id != arc.id; }
+      bool operator<(const Arc arc) const { return id < arc.id; }
+    };
+
+    void first(Node& node) const {
+      node.id = nodeNum() - 1;
+    }
+
+    static void next(Node& node) {
+      --node.id;
+    }
+
+    void first(Arc& arc) const {
+      arc.id = arcNum() - 1;
+    }
+
+    static void next(Arc& arc) {
+      --arc.id;
+    }
+
+    void firstOut(Arc& arc, const Node& node) const {
+      if (node.id < _nodeNum - _width) {
+        arc.id = node.id;
+      } else if (node.id % _width < _width - 1) {
+        arc.id = _arcLimit + node.id % _width +
+          (node.id / _width) * (_width - 1);
+      } else {
+        arc.id = -1;
+      }
+    }
+
+    void nextOut(Arc& arc) const {
+      if (arc.id >= _arcLimit) {
+        arc.id = -1;
+      } else if (arc.id % _width < _width - 1) {
+        arc.id = _arcLimit + arc.id % _width +
+          (arc.id / _width) * (_width - 1);
+      } else {
+        arc.id = -1;
+      }
+    }
+
+    void firstIn(Arc& arc, const Node& node) const {
+      if (node.id >= _width) {
+        arc.id = node.id - _width;
+      } else if (node.id % _width > 0) {
+        arc.id = _arcLimit + node.id % _width +
+          (node.id / _width) * (_width - 1) - 1;
+      } else {
+        arc.id = -1;
+      }
+    }
+
+    void nextIn(Arc& arc) const {
+      if (arc.id >= _arcLimit) {
+        arc.id = -1;
+      } else if (arc.id % _width > 0) {
+        arc.id = _arcLimit + arc.id % _width +
+          (arc.id / _width + 1) * (_width - 1) - 1;
+      } else {
+        arc.id = -1;
+      }
+    }
+
+  private:
+    int _width, _height;
+    int _nodeNum, _arcNum;
+    int _arcLimit;
+  };
+
+  typedef GraphExtender<UndirDigraphExtender<GridGraphBase> >
+    ExtendedGridGraphBase;
+
+  /// \ingroup graphs
+  ///
+  /// \brief Grid graph class
+  ///
+  /// This class implements a special graph type. The nodes of the
+  /// graph can be indiced by two integer \c (i,j) value where \c i
+  /// is in the \c [0,width) range and j is in the [0, height) range.
+  /// Two nodes are connected in the graph if the indices differ only
+  /// on one position and only one is the difference.
+  ///
+  /// \image html grid_graph.png
+  /// \image latex grid_graph.eps "Grid graph" width=\textwidth
+  ///
+  /// The graph can be indiced in the following way:
+  ///\code
+  /// GridGraph gr(w, h);
+  /// GridGraph::NodeMap<int> val(gr);
+  /// for (int i = 0; i < gr.width(); ++i) {
+  ///   for (int j = 0; j < gr.height(); ++j) {
+  ///     val[gr(i, j)] = i + j;
+  ///   }
+  /// }
+  ///\endcode
+  ///
+  /// This graph type is fully conform to the \ref concepts::Graph
+  /// "Undirected Graph" concept, and it also has an important extra
+  /// feature that its maps are real \ref concepts::ReferenceMap
+  /// "reference map"s.
+  class GridGraph : public ExtendedGridGraphBase {
+  public:
+
+    typedef ExtendedGridGraphBase Parent;
+
+    /// \brief Map to get the indices of the nodes as dim2::Point<int>.
+    ///
+    /// Map to get the indices of the nodes as dim2::Point<int>.
+    class IndexMap {
+    public:
+      /// The key type of the map
+      typedef GridGraph::Node Key;
+      /// The value type of the map
+      typedef dim2::Point<int> Value;
+
+      /// Constructor
+      IndexMap(const GridGraph& graph) : _graph(graph) {}
+
+      /// The subscript operator
+      Value operator[](const Key& key) const {
+        return dim2::Point<int>(_graph.row(key), _graph.col(key));
+      }
+
+    private:
+      const GridGraph& _graph;
+    };
+
+    /// \brief Map to get the row of the nodes.
+    ///
+    /// Map to get the row of the nodes.
+    class RowMap {
+    public:
+      /// The key type of the map
+      typedef GridGraph::Node Key;
+      /// The value type of the map
+      typedef int Value;
+
+      /// Constructor
+      RowMap(const GridGraph& graph) : _graph(graph) {}
+
+      /// The subscript operator
+      Value operator[](const Key& key) const {
+        return _graph.row(key);
+      }
+
+    private:
+      const GridGraph& _graph;
+    };
+
+    /// \brief Map to get the column of the nodes.
+    ///
+    /// Map to get the column of the nodes.
+    class ColMap {
+    public:
+      /// The key type of the map
+      typedef GridGraph::Node Key;
+      /// The value type of the map
+      typedef int Value;
+
+      /// Constructor
+      ColMap(const GridGraph& graph) : _graph(graph) {}
+
+      /// The subscript operator
+      Value operator[](const Key& key) const {
+        return _graph.col(key);
+      }
+
+    private:
+      const GridGraph& _graph;
+    };
+
+    /// \brief Constructor
+    ///
+    /// Constructor.
+    /// \param width The width of the grid.
+    /// \param height The height of the grid.
+    GridGraph(int width, int height) { construct(width, height); }
+
+    /// \brief Resize the graph
+    ///
+    /// Resize the grid.
+    void resize(int width, int height) {
+      Parent::notifier(Arc()).clear();
+      Parent::notifier(Edge()).clear();
+      Parent::notifier(Node()).clear();
+      construct(width, height);
+      Parent::notifier(Node()).build();
+      Parent::notifier(Edge()).build();
+      Parent::notifier(Arc()).build();
+    }
+
+    /// \brief The node on the given position.
+    ///
+    /// Gives back the node on the given position.
+    Node operator()(int i, int j) const {
+      return Parent::operator()(i, j);
+    }
+
+    /// \brief Gives back the row index of the node.
+    ///
+    /// Gives back the row index of the node.
+    int row(Node n) const {
+      return Parent::row(n);
+    }
+
+    /// \brief Gives back the column index of the node.
+    ///
+    /// Gives back the column index of the node.
+    int col(Node n) const {
+      return Parent::col(n);
+    }
+
+    /// \brief Gives back the width of the grid.
+    ///
+    /// Gives back the width of the grid.
+    int width() const {
+      return Parent::width();
+    }
+
+    /// \brief Gives back the height of the grid.
+    ///
+    /// Gives back the height of the grid.
+    int height() const {
+      return Parent::height();
+    }
+
+    /// \brief Gives back the arc goes down from the node.
+    ///
+    /// Gives back the arc goes down from the node. If there is not
+    /// outgoing arc then it gives back \c INVALID.
+    Arc down(Node n) const {
+      Edge e = _down(n);
+      return e != INVALID ? direct(e, true) : INVALID;
+    }
+
+    /// \brief Gives back the arc goes up from the node.
+    ///
+    /// Gives back the arc goes up from the node. If there is not
+    /// outgoing arc then it gives back \c INVALID.
+    Arc up(Node n) const {
+      Edge e = _up(n);
+      return e != INVALID ? direct(e, false) : INVALID;
+    }
+
+    /// \brief Gives back the arc goes right from the node.
+    ///
+    /// Gives back the arc goes right from the node. If there is not
+    /// outgoing arc then it gives back \c INVALID.
+    Arc right(Node n) const {
+      Edge e = _right(n);
+      return e != INVALID ? direct(e, true) : INVALID;
+    }
+
+    /// \brief Gives back the arc goes left from the node.
+    ///
+    /// Gives back the arc goes left from the node. If there is not
+    /// outgoing arc then it gives back \c INVALID.
+    Arc left(Node n) const {
+      Edge e = _left(n);
+      return e != INVALID ? direct(e, false) : INVALID;
+    }
+
+  }; // class GridGraph
+
+  /// \brief Index map of the grid graph
+  ///
+  /// Just returns an IndexMap for the grid graph.
+  inline GridGraph::IndexMap indexMap(const GridGraph& graph) {
+    return GridGraph::IndexMap(graph);
+  }
+
+  /// \brief Row map of the grid graph
+  ///
+  /// Just returns a RowMap for the grid graph.
+  inline GridGraph::RowMap rowMap(const GridGraph& graph) {
+    return GridGraph::RowMap(graph);
+  }
+
+  /// \brief Column map of the grid graph
+  ///
+  /// Just returns a ColMap for the grid graph.
+  inline GridGraph::ColMap colMap(const GridGraph& graph) {
+    return GridGraph::ColMap(graph);
+  }
+}
+
+#endif // GRID_GRAPH_H
diff -r c760d691fe3c -r ada5f74d1c9e test/graph_test.cc
--- a/test/graph_test.cc	Tue Sep 02 22:27:19 2008 +0200
+++ b/test/graph_test.cc	Tue Sep 02 22:32:04 2008 +0200
@@ -20,7 +20,7 @@
 #include <lemon/list_graph.h>
 #include <lemon/smart_graph.h>
 // #include <lemon/full_graph.h>
-// #include <lemon/grid_graph.h>
+#include <lemon/grid_graph.h>
 
 #include "test_tools.h"
 #include "graph_test.h"
@@ -126,12 +126,10 @@
   }
 //  { // Checking FullGraph
 //    checkConcept<Graph, FullGraph>();
-//    checkGraphIterators<FullGraph>();
 //  }
-//  { // Checking GridGraph
-//    checkConcept<Graph, GridGraph>();
-//    checkGraphIterators<GridGraph>();
-//  }
+  { // Checking GridGraph
+    checkConcept<Graph, GridGraph>();
+  }
 }
 
 template <typename Graph>
@@ -188,49 +186,77 @@
   check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
 }
 
-// void checkGridGraph(const GridGraph& g, int w, int h) {
-//   check(g.width() == w, "Wrong width");
-//   check(g.height() == h, "Wrong height");
+void checkGridGraph(const GridGraph& g, int w, int h) {
+  check(g.width() == w, "Wrong width");
+  check(g.height() == h, "Wrong height");
 
-//   for (int i = 0; i < w; ++i) {
-//     for (int j = 0; j < h; ++j) {
-//       check(g.col(g(i, j)) == i, "Wrong col");
-//       check(g.row(g(i, j)) == j, "Wrong row");
-//     }
-//   }
+  for (int i = 0; i < w; ++i) {
+    for (int j = 0; j < h; ++j) {
+      check(g.col(g(i, j)) == i, "Wrong col");
+      check(g.row(g(i, j)) == j, "Wrong row");
+    }
+  }
 
-//   for (int i = 0; i < w; ++i) {
-//     for (int j = 0; j < h - 1; ++j) {
-//       check(g.source(g.down(g(i, j))) == g(i, j), "Wrong down");
-//       check(g.target(g.down(g(i, j))) == g(i, j + 1), "Wrong down");
-//     }
-//     check(g.down(g(i, h - 1)) == INVALID, "Wrong down");
-//   }
+  for (int i = 0; i < w; ++i) {
+    for (int j = 0; j < h - 1; ++j) {
+      check(g.source(g.down(g(i, j))) == g(i, j), "Wrong down");
+      check(g.target(g.down(g(i, j))) == g(i, j + 1), "Wrong down");
+    }
+    check(g.down(g(i, h - 1)) == INVALID, "Wrong down");
+  }
 
-//   for (int i = 0; i < w; ++i) {
-//     for (int j = 1; j < h; ++j) {
-//       check(g.source(g.up(g(i, j))) == g(i, j), "Wrong up");
-//       check(g.target(g.up(g(i, j))) == g(i, j - 1), "Wrong up");
-//     }
-//     check(g.up(g(i, 0)) == INVALID, "Wrong up");
-//   }
+  for (int i = 0; i < w; ++i) {
+    for (int j = 1; j < h; ++j) {
+      check(g.source(g.up(g(i, j))) == g(i, j), "Wrong up");
+      check(g.target(g.up(g(i, j))) == g(i, j - 1), "Wrong up");
+    }
+    check(g.up(g(i, 0)) == INVALID, "Wrong up");
+  }
 
-//   for (int j = 0; j < h; ++j) {
-//     for (int i = 0; i < w - 1; ++i) {
-//       check(g.source(g.right(g(i, j))) == g(i, j), "Wrong right");
-//       check(g.target(g.right(g(i, j))) == g(i + 1, j), "Wrong right");
-//     }
-//     check(g.right(g(w - 1, j)) == INVALID, "Wrong right");
-//   }
+  for (int j = 0; j < h; ++j) {
+    for (int i = 0; i < w - 1; ++i) {
+      check(g.source(g.right(g(i, j))) == g(i, j), "Wrong right");
+      check(g.target(g.right(g(i, j))) == g(i + 1, j), "Wrong right");
+    }
+    check(g.right(g(w - 1, j)) == INVALID, "Wrong right");
+  }
 
-//   for (int j = 0; j < h; ++j) {
-//     for (int i = 1; i < w; ++i) {
-//       check(g.source(g.left(g(i, j))) == g(i, j), "Wrong left");
-//       check(g.target(g.left(g(i, j))) == g(i - 1, j), "Wrong left");
-//     }
-//     check(g.left(g(0, j)) == INVALID, "Wrong left");
-//   }
-// }
+  for (int j = 0; j < h; ++j) {
+    for (int i = 1; i < w; ++i) {
+      check(g.source(g.left(g(i, j))) == g(i, j), "Wrong left");
+      check(g.target(g.left(g(i, j))) == g(i - 1, j), "Wrong left");
+    }
+    check(g.left(g(0, j)) == INVALID, "Wrong left");
+  }
+
+  checkGraphNodeList(g, w*h);
+  checkGraphArcList(g, 2*(2*w*h-w-h));
+  checkGraphEdgeList(g, 2*w*h-w-h);
+
+  checkGraphOutArcList(g, g(0,0), 2);
+  checkGraphOutArcList(g, g(0,1), 3);
+  checkGraphOutArcList(g, g(w-2,h-2), 4);
+
+  checkGraphInArcList(g, g(0,0), 2);
+  checkGraphInArcList(g, g(0,1), 3);
+  checkGraphInArcList(g, g(w-2,h-2), 4);
+
+  checkGraphIncEdgeList(g, g(0,0), 2);
+  checkGraphIncEdgeList(g, g(0,1), 3);
+  checkGraphIncEdgeList(g, g(w-2,h-2), 4);
+
+  checkGraphConArcList(g, 2*(2*w*h-w-h));
+  checkGraphConEdgeList(g, 2*w*h-w-h);
+
+  checkArcDirections(g);
+
+  checkNodeIds(g);
+  checkArcIds(g);
+  checkEdgeIds(g);
+  checkGraphNodeMap(g);
+  checkGraphArcMap(g);
+  checkGraphEdgeMap(g);
+}
 
 void checkGraphs() {
   { // Checking ListGraph
@@ -246,12 +272,10 @@
 //     checkGraphNodeList(g, 5);
 //     checkGraphEdgeList(g, 10);
 //   }
-//   { // Checking GridGraph
-//     GridGraph g(5, 6);
-//     checkGraphNodeList(g, 30);
-//     checkGraphEdgeList(g, 49);
-//     checkGridGraph(g, 5, 6);
-//   }
+  { // Checking GridGraph
+    GridGraph g(5, 6);
+    checkGridGraph(g, 5, 6);
+  }
 }
 
 int main() {