deba@1623: /* -*- C++ -*- deba@1623: * lemon/grid_graph.h - Part of LEMON, a generic C++ optimization library deba@1623: * deba@1623: * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@1623: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@1623: * deba@1623: * Permission to use, modify and distribute this software is granted deba@1623: * provided that this copyright notice appears in all copies. For deba@1623: * precise terms see the accompanying LICENSE file. deba@1623: * deba@1623: * This software is provided "AS IS" with no warranty of any kind, deba@1623: * express or implied, and with no claim as to its suitability for any deba@1623: * purpose. deba@1623: * deba@1623: */ deba@1623: deba@1623: #ifndef GRID_GRAPH_H deba@1623: #define GRID_GRAPH_H deba@1623: deba@1623: #include deba@1623: #include deba@1623: #include deba@1623: deba@1623: #include deba@1623: #include deba@1623: #include deba@1623: deba@1623: #include deba@1623: deba@1623: namespace lemon { deba@1623: deba@1623: class GridGraphBase { deba@1623: deba@1623: public: deba@1623: deba@1623: typedef GridGraphBase Graph; deba@1623: deba@1623: class Node; deba@1623: class Edge; deba@1623: deba@1623: public: deba@1623: deba@1623: GridGraphBase() {} deba@1623: deba@1623: protected: deba@1623: deba@1623: /// \brief Creates a grid graph with the given size. deba@1623: /// deba@1623: /// Creates a grid graph with the given size. deba@1680: void construct(int width, int height) { deba@1623: _height = height; _width = width; deba@1623: _nodeNum = height * width; _edgeNum = 2 * _nodeNum - width - height; deba@1623: _edgeLimit = _nodeNum - width; deba@1623: } deba@1623: deba@1680: /// \brief Gives back the edge goes down from the node. deba@1680: /// deba@1680: /// Gives back the edge goes down from the node. If there is not deba@1680: /// outgoing edge then it gives back INVALID. deba@1680: Edge _down(Node n) const { deba@1680: if (n.id < _nodeNum - _width) { deba@1680: return Edge(n.id); deba@1680: } else { deba@1680: return INVALID; deba@1680: } deba@1680: } deba@1680: deba@1680: /// \brief Gives back the edge comes from up into the node. deba@1680: /// deba@1680: /// Gives back the edge comes from up into the node. If there is not deba@1680: /// incoming edge then it gives back INVALID. deba@1680: Edge _up(Node n) const { deba@1680: if (n.id >= _width) { deba@1680: return Edge(n.id - _width); deba@1680: } else { deba@1680: return INVALID; deba@1680: } deba@1680: } deba@1680: deba@1680: /// \brief Gives back the edge goes right from the node. deba@1680: /// deba@1680: /// Gives back the edge goes right from the node. If there is not deba@1680: /// outgoing edge then it gives back INVALID. deba@1680: Edge _right(Node n) const { deba@1680: if (n.id % _width < _width - 1) { deba@1680: return _edgeLimit + n.id % _width + (n.id / _width) * (_width - 1); deba@1680: } else { deba@1680: return INVALID; deba@1680: } deba@1680: } deba@1680: deba@1680: /// \brief Gives back the edge comes from left into the node. deba@1680: /// deba@1680: /// Gives back the edge comes left up into the node. If there is not deba@1680: /// incoming edge then it gives back INVALID. deba@1680: Edge _left(Node n) const { deba@1680: if (n.id % _width > 0) { deba@1680: return _edgeLimit + n.id % _width + (n.id / _width) * (_width - 1) - 1; deba@1680: } else { deba@1680: return INVALID; deba@1680: } deba@1680: } deba@1680: deba@1680: deba@1623: public: deba@1623: deba@1623: /// \brief The node on the given position. deba@1623: /// deba@1623: /// Gives back the node on the given position. deba@1623: Node operator()(int i, int j) const { deba@1680: return Node(i + j * _width); deba@1623: } deba@1623: deba@1623: /// \brief Gives back the row index of the node. deba@1623: /// deba@1623: /// Gives back the row index of the node. deba@1623: int row(Node n) const { deba@1623: return n.id / _width; deba@1623: } deba@1623: deba@1623: /// \brief Gives back the coloumn index of the node. deba@1623: /// deba@1623: /// Gives back the coloumn index of the node. deba@1680: int col(Node n) const { deba@1623: return n.id % _width; deba@1623: } deba@1623: deba@1623: /// \brief Gives back the width of the graph. deba@1623: /// deba@1623: /// Gives back the width of the graph. deba@1623: int width() const { deba@1623: return _width; deba@1623: } deba@1623: deba@1623: /// \brief Gives back the height of the graph. deba@1623: /// deba@1623: /// Gives back the height of the graph. deba@1623: int height() const { deba@1623: return _height; deba@1623: } deba@1623: deba@1623: typedef True NodeNumTag; deba@1623: typedef True EdgeNumTag; deba@1623: deba@1623: ///Number of nodes. deba@1623: int nodeNum() const { return _nodeNum; } deba@1623: ///Number of edges. deba@1623: int edgeNum() const { return _edgeNum; } deba@1623: deba@1623: /// Maximum node ID. deba@1623: deba@1623: /// Maximum node ID. deba@1623: ///\sa id(Node) deba@1623: int maxId(Node = INVALID) const { return nodeNum() - 1; } deba@1623: /// Maximum edge ID. deba@1623: deba@1623: /// Maximum edge ID. deba@1623: ///\sa id(Edge) deba@1623: int maxId(Edge = INVALID) const { return edgeNum() - 1; } deba@1623: deba@1623: /// \brief Gives back the source node of an edge. deba@1623: /// deba@1623: /// Gives back the source node of an edge. deba@1623: Node source(Edge e) const { deba@1623: if (e.id < _edgeLimit) { deba@1623: return e.id; deba@1623: } else { deba@1623: return (e.id - _edgeLimit) % (_width - 1) + deba@1623: (e.id - _edgeLimit) / (_width - 1) * _width; deba@1623: } deba@1623: } deba@1623: deba@1623: /// \brief Gives back the target node of an edge. deba@1623: /// deba@1623: /// Gives back the target node of an edge. deba@1623: Node target(Edge e) const { deba@1623: if (e.id < _edgeLimit) { deba@1623: return e.id + _width; deba@1623: } else { deba@1623: return (e.id - _edgeLimit) % (_width - 1) + deba@1623: (e.id - _edgeLimit) / (_width - 1) * _width + 1; deba@1623: } deba@1623: } deba@1623: deba@1623: /// Node ID. deba@1623: deba@1623: /// The ID of a valid Node is a nonnegative integer not greater than deba@1623: /// \ref maxNodeId(). The range of the ID's is not surely continuous deba@1623: /// and the greatest node ID can be actually less then \ref maxNodeId(). deba@1623: /// deba@1623: /// The ID of the \ref INVALID node is -1. deba@1623: ///\return The ID of the node \c v. deba@1623: deba@1623: static int id(Node v) { return v.id; } deba@1623: /// Edge ID. deba@1623: deba@1623: /// The ID of a valid Edge is a nonnegative integer not greater than deba@1623: /// \ref maxEdgeId(). The range of the ID's is not surely continuous deba@1623: /// and the greatest edge ID can be actually less then \ref maxEdgeId(). deba@1623: /// deba@1623: /// The ID of the \ref INVALID edge is -1. deba@1623: ///\return The ID of the edge \c e. deba@1623: static int id(Edge e) { return e.id; } deba@1623: deba@1623: static Node fromId(int id, Node) { return Node(id);} deba@1623: deba@1623: static Edge fromId(int id, Edge) { return Edge(id);} deba@1623: deba@1623: typedef True FindEdgeTag; deba@1623: deba@1623: /// Finds an edge between two nodes. deba@1623: deba@1623: /// Finds an edge from node \c u to node \c v. deba@1623: /// deba@1623: /// If \c prev is \ref INVALID (this is the default value), then deba@1623: /// It finds the first edge from \c u to \c v. Otherwise it looks for deba@1623: /// the next edge from \c u to \c v after \c prev. deba@1623: /// \return The found edge or INVALID if there is no such an edge. deba@1623: Edge findEdge(Node u, Node v, Edge prev = INVALID) { deba@1623: if (prev != INVALID) return INVALID; deba@1623: if (v.id - u.id == _width) return Edge(u.id); deba@1623: if (v.id - u.id == 1 && u.id % _width < _width - 1) { deba@1623: return Edge(u.id / _width * (_width - 1) + deba@1623: u.id % _width + _edgeLimit); deba@1623: } deba@1623: return INVALID; deba@1623: } deba@1623: deba@1623: deba@1623: class Node { deba@1623: friend class GridGraphBase; deba@1623: deba@1623: protected: deba@1623: int id; deba@1623: Node(int _id) { id = _id;} deba@1623: public: deba@1623: Node() {} deba@1623: Node (Invalid) { id = -1; } deba@1623: bool operator==(const Node node) const {return id == node.id;} deba@1623: bool operator!=(const Node node) const {return id != node.id;} deba@1623: bool operator<(const Node node) const {return id < node.id;} deba@1623: }; deba@1623: deba@1623: deba@1623: deba@1623: class Edge { deba@1623: friend class GridGraphBase; deba@1623: deba@1623: protected: deba@1623: int id; deba@1623: deba@1623: Edge(int _id) : id(_id) {} deba@1623: deba@1623: public: deba@1623: Edge() { } deba@1623: Edge (Invalid) { id = -1; } deba@1623: bool operator==(const Edge edge) const {return id == edge.id;} deba@1623: bool operator!=(const Edge edge) const {return id != edge.id;} deba@1623: bool operator<(const Edge edge) const {return id < edge.id;} deba@1623: }; deba@1623: deba@1623: void first(Node& node) const { deba@1623: node.id = nodeNum() - 1; deba@1623: } deba@1623: deba@1623: static void next(Node& node) { deba@1623: --node.id; deba@1623: } deba@1623: deba@1623: void first(Edge& edge) const { deba@1623: edge.id = edgeNum() - 1; deba@1623: } deba@1623: deba@1623: static void next(Edge& edge) { deba@1623: --edge.id; deba@1623: } deba@1623: deba@1623: void firstOut(Edge& edge, const Node& node) const { deba@1623: if (node.id < _nodeNum - _width) { deba@1623: edge.id = node.id; deba@1623: } else if (node.id % _width < _width - 1) { deba@1623: edge.id = _edgeLimit + node.id % _width + deba@1623: (node.id / _width) * (_width - 1); deba@1623: } else { deba@1623: edge.id = -1; deba@1623: } deba@1623: } deba@1623: deba@1623: void nextOut(Edge& edge) const { deba@1623: if (edge.id >= _edgeLimit) { deba@1623: edge.id = -1; deba@1623: } else if (edge.id % _width < _width - 1) { deba@1623: edge.id = _edgeLimit + edge.id % _width + deba@1623: (edge.id / _width) * (_width - 1); deba@1623: } else { deba@1623: edge.id = -1; deba@1623: } deba@1623: } deba@1623: deba@1623: void firstIn(Edge& edge, const Node& node) const { deba@1623: if (node.id >= _width) { deba@1623: edge.id = node.id - _width; deba@1623: } else if (node.id % _width > 0) { deba@1623: edge.id = _edgeLimit + node.id % _width + deba@1623: (node.id / _width) * (_width - 1) - 1; deba@1623: } else { deba@1623: edge.id = -1; deba@1623: } deba@1623: } deba@1623: deba@1623: void nextIn(Edge& edge) const { deba@1623: if (edge.id >= _edgeLimit) { deba@1623: edge.id = -1; deba@1623: } else if (edge.id % _width > 0) { deba@1623: edge.id = _edgeLimit + edge.id % _width + deba@1623: (edge.id / _width + 1) * (_width - 1) - 1; deba@1623: } else { deba@1623: edge.id = -1; deba@1623: } deba@1623: } deba@1623: deba@1623: private: deba@1623: int _width, _height; deba@1623: int _nodeNum, _edgeNum; deba@1623: int _edgeLimit; deba@1623: }; deba@1623: deba@1623: deba@1680: typedef MappableUndirGraphExtender< deba@1680: IterableUndirGraphExtender< deba@1680: AlterableUndirGraphExtender< deba@1680: UndirGraphExtender > > > ExtendedGridGraphBase; deba@1623: deba@1623: /// \ingroup graphs deba@1623: /// deba@1623: /// \brief Grid graph class deba@1623: /// deba@1623: /// This class implements a special graph type. The nodes of the deba@1623: /// graph can be indiced by two integer \c (i,j) value where \c i deba@1623: /// is in the \c [0,height) range and j is in the [0, width) range. deba@1623: /// Two nodes are connected in the graph if the indices differ only deba@1623: /// on one position and only one is the difference. deba@1623: /// deba@1623: /// The graph can be indiced in the following way: deba@1623: /// \code deba@1623: /// GridGraph graph(h, w); deba@1623: /// GridGraph::NodeMap val(graph); deba@1623: /// for (int i = 0; i < graph.height(); ++i) { deba@1623: /// for (int j = 0; j < graph.width(); ++j) { deba@1623: /// val[graph(i, j)] = i + j; deba@1623: /// } deba@1623: /// } deba@1623: /// \endcode deba@1623: /// deba@1623: /// The graph type is fully conform to the \ref concept::UndirGraph deba@1623: /// "Undirected Graph" concept. deba@1623: /// deba@1623: /// \author Balazs Dezso deba@1680: class GridGraph : public ExtendedGridGraphBase { deba@1623: public: deba@1623: deba@1680: GridGraph(int n, int m) { construct(n, m); } deba@1680: deba@1680: /// \brief Gives back the edge goes down from the node. deba@1680: /// deba@1680: /// Gives back the edge goes down from the node. If there is not deba@1680: /// outgoing edge then it gives back INVALID. deba@1680: Edge down(Node n) const { deba@1680: UndirEdge ue = _down(n); deba@1680: return ue != INVALID ? direct(ue, true) : INVALID; deba@1680: } deba@1680: deba@1680: /// \brief Gives back the edge goes up from the node. deba@1680: /// deba@1680: /// Gives back the edge goes up from the node. If there is not deba@1680: /// outgoing edge then it gives back INVALID. deba@1680: Edge up(Node n) const { deba@1680: UndirEdge ue = _up(n); deba@1680: return ue != INVALID ? direct(ue, false) : INVALID; deba@1680: } deba@1680: deba@1680: /// \brief Gives back the edge goes right from the node. deba@1680: /// deba@1680: /// Gives back the edge goes right from the node. If there is not deba@1680: /// outgoing edge then it gives back INVALID. deba@1680: Edge right(Node n) const { deba@1680: UndirEdge ue = _right(n); deba@1680: return ue != INVALID ? direct(ue, true) : INVALID; deba@1680: } deba@1680: deba@1680: /// \brief Gives back the edge goes left from the node. deba@1680: /// deba@1680: /// Gives back the edge goes left from the node. If there is not deba@1680: /// outgoing edge then it gives back INVALID. deba@1680: Edge left(Node n) const { deba@1680: UndirEdge ue = _left(n); deba@1680: return ue != INVALID ? direct(ue, false) : INVALID; deba@1680: } deba@1680: deba@1623: }; deba@1623: } deba@1623: #endif