kpeter@334: /* -*- mode: C++; indent-tabs-mode: nil; -*- kpeter@334: * kpeter@334: * This file is a part of LEMON, a generic C++ optimization library. kpeter@334: * kpeter@334: * Copyright (C) 2003-2008 kpeter@334: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport kpeter@334: * (Egervary Research Group on Combinatorial Optimization, EGRES). kpeter@334: * kpeter@334: * Permission to use, modify and distribute this software is granted kpeter@334: * provided that this copyright notice appears in all copies. For kpeter@334: * precise terms see the accompanying LICENSE file. kpeter@334: * kpeter@334: * This software is provided "AS IS" with no warranty of any kind, kpeter@334: * express or implied, and with no claim as to its suitability for any kpeter@334: * purpose. kpeter@334: * kpeter@334: */ kpeter@334: kpeter@334: #ifndef GRID_GRAPH_H kpeter@334: #define GRID_GRAPH_H kpeter@334: kpeter@334: #include deba@335: #include deba@335: #include kpeter@334: #include kpeter@334: kpeter@334: ///\ingroup graphs kpeter@334: ///\file kpeter@334: ///\brief GridGraph class. kpeter@334: kpeter@334: namespace lemon { kpeter@334: kpeter@334: class GridGraphBase { kpeter@334: kpeter@334: public: kpeter@334: kpeter@334: typedef GridGraphBase Graph; kpeter@334: kpeter@334: class Node; deba@335: class Edge; kpeter@334: class Arc; kpeter@334: kpeter@334: public: kpeter@334: kpeter@334: GridGraphBase() {} kpeter@334: kpeter@334: protected: kpeter@334: deba@335: void construct(int width, int height) { deba@335: _width = width; _height = height; deba@335: _node_num = width * height; deba@335: _edge_num = 2 * _node_num - width - height; deba@335: _edge_limit = _node_num - _width; kpeter@334: } kpeter@334: kpeter@334: public: kpeter@334: kpeter@334: Node operator()(int i, int j) const { deba@335: LEMON_DEBUG(0 <= i && i < _width && deba@335: 0 <= j && j < _height, "Index out of range"); kpeter@334: return Node(i + j * _width); kpeter@334: } kpeter@334: deba@335: int col(Node n) const { deba@335: return n._id % _width; kpeter@334: } kpeter@334: deba@335: int row(Node n) const { deba@335: return n._id / _width; deba@335: } deba@335: deba@335: dim2::Point pos(Node n) const { deba@335: return dim2::Point(col(n), row(n)); kpeter@334: } kpeter@334: kpeter@334: int width() const { kpeter@334: return _width; kpeter@334: } kpeter@334: kpeter@334: int height() const { kpeter@334: return _height; kpeter@334: } kpeter@334: kpeter@334: typedef True NodeNumTag; kpeter@360: typedef True EdgeNumTag; kpeter@334: typedef True ArcNumTag; kpeter@334: deba@335: int nodeNum() const { return _node_num; } deba@335: int edgeNum() const { return _edge_num; } deba@335: int arcNum() const { return 2 * _edge_num; } kpeter@334: deba@335: Node u(Edge edge) const { deba@335: if (edge._id < _edge_limit) { deba@335: return edge._id; kpeter@334: } else { deba@335: return (edge._id - _edge_limit) % (_width - 1) + deba@335: (edge._id - _edge_limit) / (_width - 1) * _width; kpeter@334: } kpeter@334: } kpeter@334: deba@335: Node v(Edge edge) const { deba@335: if (edge._id < _edge_limit) { deba@335: return edge._id + _width; kpeter@334: } else { deba@335: return (edge._id - _edge_limit) % (_width - 1) + deba@335: (edge._id - _edge_limit) / (_width - 1) * _width + 1; kpeter@334: } kpeter@334: } kpeter@334: deba@335: Node source(Arc arc) const { deba@335: return (arc._id & 1) == 1 ? u(arc) : v(arc); deba@335: } deba@335: deba@335: Node target(Arc arc) const { deba@335: return (arc._id & 1) == 1 ? v(arc) : u(arc); deba@335: } deba@335: deba@335: static int id(Node node) { return node._id; } deba@335: static int id(Edge edge) { return edge._id; } deba@335: static int id(Arc arc) { return arc._id; } deba@335: deba@335: int maxNodeId() const { return _node_num - 1; } deba@335: int maxEdgeId() const { return _edge_num - 1; } deba@335: int maxArcId() const { return 2 * _edge_num - 1; } kpeter@334: kpeter@334: static Node nodeFromId(int id) { return Node(id);} deba@335: static Edge edgeFromId(int id) { return Edge(id);} kpeter@334: static Arc arcFromId(int id) { return Arc(id);} kpeter@334: deba@335: typedef True FindEdgeTag; kpeter@360: typedef True FindArcTag; deba@335: deba@335: Edge findEdge(Node u, Node v, Edge prev = INVALID) const { deba@335: if (prev != INVALID) return INVALID; deba@335: if (v._id > u._id) { deba@335: if (v._id - u._id == _width) deba@335: return Edge(u._id); deba@335: if (v._id - u._id == 1 && u._id % _width < _width - 1) { deba@335: return Edge(u._id / _width * (_width - 1) + deba@335: u._id % _width + _edge_limit); deba@335: } deba@335: } else { deba@335: if (u._id - v._id == _width) deba@335: return Edge(v._id); deba@335: if (u._id - v._id == 1 && v._id % _width < _width - 1) { deba@335: return Edge(v._id / _width * (_width - 1) + deba@335: v._id % _width + _edge_limit); deba@335: } deba@335: } deba@335: return INVALID; deba@335: } kpeter@334: kpeter@334: Arc findArc(Node u, Node v, Arc prev = INVALID) const { kpeter@334: if (prev != INVALID) return INVALID; deba@335: if (v._id > u._id) { deba@335: if (v._id - u._id == _width) deba@335: return Arc((u._id << 1) | 1); deba@335: if (v._id - u._id == 1 && u._id % _width < _width - 1) { deba@335: return Arc(((u._id / _width * (_width - 1) + deba@335: u._id % _width + _edge_limit) << 1) | 1); deba@335: } deba@335: } else { deba@335: if (u._id - v._id == _width) deba@335: return Arc(v._id << 1); deba@335: if (u._id - v._id == 1 && v._id % _width < _width - 1) { deba@335: return Arc((v._id / _width * (_width - 1) + deba@335: v._id % _width + _edge_limit) << 1); deba@335: } kpeter@334: } kpeter@334: return INVALID; kpeter@334: } kpeter@334: kpeter@334: class Node { kpeter@334: friend class GridGraphBase; kpeter@334: kpeter@334: protected: deba@335: int _id; deba@335: Node(int id) : _id(id) {} kpeter@334: public: kpeter@334: Node() {} deba@335: Node (Invalid) : _id(-1) {} deba@335: bool operator==(const Node node) const {return _id == node._id;} deba@335: bool operator!=(const Node node) const {return _id != node._id;} deba@335: bool operator<(const Node node) const {return _id < node._id;} deba@335: }; deba@335: deba@335: class Edge { deba@335: friend class GridGraphBase; kpeter@336: friend class Arc; deba@335: deba@335: protected: deba@335: int _id; deba@335: deba@335: Edge(int id) : _id(id) {} deba@335: deba@335: public: deba@335: Edge() {} deba@335: Edge (Invalid) : _id(-1) {} deba@335: bool operator==(const Edge edge) const {return _id == edge._id;} deba@335: bool operator!=(const Edge edge) const {return _id != edge._id;} deba@335: bool operator<(const Edge edge) const {return _id < edge._id;} kpeter@334: }; kpeter@334: kpeter@334: class Arc { kpeter@334: friend class GridGraphBase; kpeter@334: kpeter@334: protected: deba@335: int _id; deba@335: deba@335: Arc(int id) : _id(id) {} deba@335: kpeter@334: public: kpeter@334: Arc() {} deba@335: Arc (Invalid) : _id(-1) {} deba@335: operator Edge() const { return _id != -1 ? Edge(_id >> 1) : INVALID; } deba@335: bool operator==(const Arc arc) const {return _id == arc._id;} deba@335: bool operator!=(const Arc arc) const {return _id != arc._id;} deba@335: bool operator<(const Arc arc) const {return _id < arc._id;} kpeter@334: }; kpeter@334: deba@335: static bool direction(Arc arc) { deba@335: return (arc._id & 1) == 1; deba@335: } deba@335: deba@335: static Arc direct(Edge edge, bool dir) { deba@335: return Arc((edge._id << 1) | (dir ? 1 : 0)); deba@335: } deba@335: kpeter@334: void first(Node& node) const { deba@335: node._id = _node_num - 1; kpeter@334: } kpeter@334: kpeter@334: static void next(Node& node) { deba@335: --node._id; deba@335: } deba@335: deba@335: void first(Edge& edge) const { deba@335: edge._id = _edge_num - 1; deba@335: } deba@335: deba@335: static void next(Edge& edge) { deba@335: --edge._id; kpeter@334: } kpeter@334: kpeter@334: void first(Arc& arc) const { deba@335: arc._id = 2 * _edge_num - 1; kpeter@334: } kpeter@334: kpeter@334: static void next(Arc& arc) { deba@335: --arc._id; kpeter@334: } kpeter@334: kpeter@334: void firstOut(Arc& arc, const Node& node) const { deba@335: if (node._id % _width < _width - 1) { deba@335: arc._id = (_edge_limit + node._id % _width + deba@335: (node._id / _width) * (_width - 1)) << 1 | 1; deba@335: return; deba@335: } deba@335: if (node._id < _node_num - _width) { deba@335: arc._id = node._id << 1 | 1; deba@335: return; deba@335: } deba@335: if (node._id % _width > 0) { deba@335: arc._id = (_edge_limit + node._id % _width + deba@335: (node._id / _width) * (_width - 1) - 1) << 1; deba@335: return; deba@335: } deba@335: if (node._id >= _width) { deba@335: arc._id = (node._id - _width) << 1; deba@335: return; deba@335: } deba@335: arc._id = -1; deba@335: } deba@335: deba@335: void nextOut(Arc& arc) const { deba@335: int nid = arc._id >> 1; deba@335: if ((arc._id & 1) == 1) { deba@335: if (nid >= _edge_limit) { deba@335: nid = (nid - _edge_limit) % (_width - 1) + deba@335: (nid - _edge_limit) / (_width - 1) * _width; deba@335: if (nid < _node_num - _width) { deba@335: arc._id = nid << 1 | 1; deba@335: return; deba@335: } deba@335: } deba@335: if (nid % _width > 0) { deba@335: arc._id = (_edge_limit + nid % _width + deba@335: (nid / _width) * (_width - 1) - 1) << 1; deba@335: return; deba@335: } deba@335: if (nid >= _width) { deba@335: arc._id = (nid - _width) << 1; deba@335: return; deba@335: } kpeter@334: } else { deba@335: if (nid >= _edge_limit) { deba@335: nid = (nid - _edge_limit) % (_width - 1) + deba@335: (nid - _edge_limit) / (_width - 1) * _width + 1; deba@335: if (nid >= _width) { deba@335: arc._id = (nid - _width) << 1; deba@335: return; deba@335: } deba@335: } deba@335: } deba@335: arc._id = -1; deba@335: } deba@335: deba@335: void firstIn(Arc& arc, const Node& node) const { deba@335: if (node._id % _width < _width - 1) { deba@335: arc._id = (_edge_limit + node._id % _width + deba@335: (node._id / _width) * (_width - 1)) << 1; deba@335: return; deba@335: } deba@335: if (node._id < _node_num - _width) { deba@335: arc._id = node._id << 1; deba@335: return; deba@335: } deba@335: if (node._id % _width > 0) { deba@335: arc._id = (_edge_limit + node._id % _width + deba@335: (node._id / _width) * (_width - 1) - 1) << 1 | 1; deba@335: return; deba@335: } deba@335: if (node._id >= _width) { deba@335: arc._id = (node._id - _width) << 1 | 1; deba@335: return; deba@335: } deba@335: arc._id = -1; deba@335: } deba@335: deba@335: void nextIn(Arc& arc) const { deba@335: int nid = arc._id >> 1; deba@335: if ((arc._id & 1) == 0) { deba@335: if (nid >= _edge_limit) { deba@335: nid = (nid - _edge_limit) % (_width - 1) + deba@335: (nid - _edge_limit) / (_width - 1) * _width; deba@335: if (nid < _node_num - _width) { deba@335: arc._id = nid << 1; deba@335: return; deba@335: } deba@335: } deba@335: if (nid % _width > 0) { deba@335: arc._id = (_edge_limit + nid % _width + deba@335: (nid / _width) * (_width - 1) - 1) << 1 | 1; deba@335: return; deba@335: } deba@335: if (nid >= _width) { deba@335: arc._id = (nid - _width) << 1 | 1; deba@335: return; deba@335: } deba@335: } else { deba@335: if (nid >= _edge_limit) { deba@335: nid = (nid - _edge_limit) % (_width - 1) + deba@335: (nid - _edge_limit) / (_width - 1) * _width + 1; deba@335: if (nid >= _width) { deba@335: arc._id = (nid - _width) << 1 | 1; deba@335: return; deba@335: } deba@335: } deba@335: } deba@335: arc._id = -1; deba@335: } deba@335: deba@335: void firstInc(Edge& edge, bool& dir, const Node& node) const { deba@335: if (node._id % _width < _width - 1) { deba@335: edge._id = _edge_limit + node._id % _width + deba@335: (node._id / _width) * (_width - 1); deba@335: dir = true; deba@335: return; deba@335: } deba@335: if (node._id < _node_num - _width) { deba@335: edge._id = node._id; deba@335: dir = true; deba@335: return; deba@335: } deba@335: if (node._id % _width > 0) { deba@335: edge._id = _edge_limit + node._id % _width + deba@335: (node._id / _width) * (_width - 1) - 1; deba@335: dir = false; deba@335: return; deba@335: } deba@335: if (node._id >= _width) { deba@335: edge._id = node._id - _width; deba@335: dir = false; deba@335: return; deba@335: } deba@335: edge._id = -1; deba@335: dir = true; deba@335: } deba@335: deba@335: void nextInc(Edge& edge, bool& dir) const { deba@335: int nid = edge._id; deba@335: if (dir) { deba@335: if (nid >= _edge_limit) { deba@335: nid = (nid - _edge_limit) % (_width - 1) + deba@335: (nid - _edge_limit) / (_width - 1) * _width; deba@335: if (nid < _node_num - _width) { deba@335: edge._id = nid; deba@335: return; deba@335: } deba@335: } deba@335: if (nid % _width > 0) { deba@335: edge._id = _edge_limit + nid % _width + deba@335: (nid / _width) * (_width - 1) - 1; deba@335: dir = false; deba@335: return; deba@335: } deba@335: if (nid >= _width) { deba@335: edge._id = nid - _width; deba@335: dir = false; deba@335: return; deba@335: } deba@335: } else { deba@335: if (nid >= _edge_limit) { deba@335: nid = (nid - _edge_limit) % (_width - 1) + deba@335: (nid - _edge_limit) / (_width - 1) * _width + 1; deba@335: if (nid >= _width) { deba@335: edge._id = nid - _width; deba@335: return; deba@335: } deba@335: } deba@335: } deba@335: edge._id = -1; deba@335: dir = true; deba@335: } deba@335: deba@335: Arc right(Node n) const { deba@335: if (n._id % _width < _width - 1) { deba@335: return Arc(((_edge_limit + n._id % _width + deba@335: (n._id / _width) * (_width - 1)) << 1) | 1); deba@335: } else { deba@335: return INVALID; kpeter@334: } kpeter@334: } kpeter@334: deba@335: Arc left(Node n) const { deba@335: if (n._id % _width > 0) { deba@335: return Arc((_edge_limit + n._id % _width + deba@335: (n._id / _width) * (_width - 1) - 1) << 1); kpeter@334: } else { deba@335: return INVALID; kpeter@334: } kpeter@334: } kpeter@334: deba@335: Arc up(Node n) const { deba@335: if (n._id < _edge_limit) { deba@335: return Arc((n._id << 1) | 1); kpeter@334: } else { deba@335: return INVALID; kpeter@334: } kpeter@334: } kpeter@334: deba@335: Arc down(Node n) const { deba@335: if (n._id >= _width) { deba@335: return Arc((n._id - _width) << 1); kpeter@334: } else { deba@335: return INVALID; kpeter@334: } kpeter@334: } kpeter@334: kpeter@334: private: kpeter@334: int _width, _height; deba@335: int _node_num, _edge_num; deba@335: int _edge_limit; kpeter@334: }; kpeter@334: deba@335: deba@335: typedef GraphExtender ExtendedGridGraphBase; kpeter@334: kpeter@334: /// \ingroup graphs kpeter@334: /// kpeter@334: /// \brief Grid graph class kpeter@334: /// kpeter@334: /// This class implements a special graph type. The nodes of the deba@335: /// graph can be indexed by two integer \c (i,j) value where \c i is deba@335: /// in the \c [0..width()-1] range and j is in the \c deba@335: /// [0..height()-1] range. Two nodes are connected in the graph if deba@335: /// the indexes differ exactly on one position and exactly one is kpeter@336: /// the difference. The nodes of the graph can be indexed by position kpeter@336: /// with the \c operator()() function. The positions of the nodes can be deba@335: /// get with \c pos(), \c col() and \c row() members. The outgoing deba@335: /// arcs can be retrieved with the \c right(), \c up(), \c left() deba@335: /// and \c down() functions, where the bottom-left corner is the deba@335: /// origin. kpeter@334: /// kpeter@334: /// \image html grid_graph.png deba@338: /// \image latex grid_graph.eps "Grid graph" width=\textwidth kpeter@334: /// deba@335: /// A short example about the basic usage: kpeter@334: ///\code deba@335: /// GridGraph graph(rows, cols); deba@335: /// GridGraph::NodeMap val(graph); deba@335: /// for (int i = 0; i < graph.width(); ++i) { deba@335: /// for (int j = 0; j < graph.height(); ++j) { deba@335: /// val[graph(i, j)] = i + j; kpeter@334: /// } kpeter@334: /// } kpeter@334: ///\endcode kpeter@334: /// kpeter@336: /// This graph type is fully conform to the \ref concepts::Graph deba@335: /// "Graph" concept, and it also has an important extra feature kpeter@336: /// that its maps are real \ref concepts::ReferenceMap kpeter@336: /// "reference map"s. kpeter@334: class GridGraph : public ExtendedGridGraphBase { kpeter@334: public: kpeter@334: kpeter@334: typedef ExtendedGridGraphBase Parent; kpeter@334: kpeter@334: /// \brief Map to get the indices of the nodes as dim2::Point. kpeter@334: /// kpeter@334: /// Map to get the indices of the nodes as dim2::Point. kpeter@334: class IndexMap { kpeter@334: public: deba@335: /// \brief The key type of the map kpeter@334: typedef GridGraph::Node Key; deba@335: /// \brief The value type of the map kpeter@334: typedef dim2::Point Value; kpeter@334: deba@335: /// \brief Constructor deba@335: /// kpeter@334: /// Constructor kpeter@334: IndexMap(const GridGraph& graph) : _graph(graph) {} kpeter@334: deba@335: /// \brief The subscript operator deba@335: /// deba@335: /// The subscript operator. deba@335: Value operator[](Key key) const { deba@335: return _graph.pos(key); deba@335: } deba@335: deba@335: private: deba@335: const GridGraph& _graph; deba@335: }; deba@335: deba@335: /// \brief Map to get the column of the nodes. deba@335: /// deba@335: /// Map to get the column of the nodes. deba@335: class ColMap { deba@335: public: deba@335: /// \brief The key type of the map deba@335: typedef GridGraph::Node Key; deba@335: /// \brief The value type of the map deba@335: typedef int Value; deba@335: deba@335: /// \brief Constructor deba@335: /// deba@335: /// Constructor deba@335: ColMap(const GridGraph& graph) : _graph(graph) {} deba@335: deba@335: /// \brief The subscript operator deba@335: /// deba@335: /// The subscript operator. deba@335: Value operator[](Key key) const { deba@335: return _graph.col(key); kpeter@334: } kpeter@334: kpeter@334: private: kpeter@334: const GridGraph& _graph; kpeter@334: }; kpeter@334: kpeter@334: /// \brief Map to get the row of the nodes. kpeter@334: /// kpeter@334: /// Map to get the row of the nodes. kpeter@334: class RowMap { kpeter@334: public: deba@335: /// \brief The key type of the map kpeter@334: typedef GridGraph::Node Key; deba@335: /// \brief The value type of the map kpeter@334: typedef int Value; kpeter@334: deba@335: /// \brief Constructor deba@335: /// kpeter@334: /// Constructor kpeter@334: RowMap(const GridGraph& graph) : _graph(graph) {} kpeter@334: deba@335: /// \brief The subscript operator deba@335: /// deba@335: /// The subscript operator. deba@335: Value operator[](Key key) const { kpeter@334: return _graph.row(key); kpeter@334: } kpeter@334: kpeter@334: private: kpeter@334: const GridGraph& _graph; kpeter@334: }; kpeter@334: kpeter@334: /// \brief Constructor kpeter@334: /// deba@335: /// Construct a grid graph with given size. kpeter@334: GridGraph(int width, int height) { construct(width, height); } kpeter@334: kpeter@334: /// \brief Resize the graph kpeter@334: /// deba@335: /// Resize the graph. The function will fully destroy and rebuild deba@335: /// the graph. This cause that the maps of the graph will deba@335: /// reallocated automatically and the previous values will be deba@335: /// lost. kpeter@334: void resize(int width, int height) { kpeter@334: Parent::notifier(Arc()).clear(); kpeter@334: Parent::notifier(Edge()).clear(); kpeter@334: Parent::notifier(Node()).clear(); kpeter@334: construct(width, height); kpeter@334: Parent::notifier(Node()).build(); kpeter@334: Parent::notifier(Edge()).build(); kpeter@334: Parent::notifier(Arc()).build(); kpeter@334: } kpeter@334: kpeter@334: /// \brief The node on the given position. kpeter@334: /// kpeter@334: /// Gives back the node on the given position. kpeter@334: Node operator()(int i, int j) const { kpeter@334: return Parent::operator()(i, j); kpeter@334: } kpeter@334: deba@335: /// \brief Gives back the column index of the node. deba@335: /// deba@335: /// Gives back the column index of the node. deba@335: int col(Node n) const { deba@335: return Parent::col(n); deba@335: } deba@335: kpeter@334: /// \brief Gives back the row index of the node. kpeter@334: /// kpeter@334: /// Gives back the row index of the node. kpeter@334: int row(Node n) const { kpeter@334: return Parent::row(n); kpeter@334: } kpeter@334: deba@335: /// \brief Gives back the position of the node. kpeter@334: /// deba@335: /// Gives back the position of the node, ie. the (col,row) pair. deba@335: dim2::Point pos(Node n) const { deba@335: return Parent::pos(n); kpeter@334: } kpeter@334: deba@335: /// \brief Gives back the number of the columns. kpeter@334: /// deba@335: /// Gives back the number of the columns. kpeter@334: int width() const { kpeter@334: return Parent::width(); kpeter@334: } kpeter@334: deba@335: /// \brief Gives back the number of the rows. kpeter@334: /// deba@335: /// Gives back the number of the rows. kpeter@334: int height() const { kpeter@334: return Parent::height(); kpeter@334: } kpeter@334: deba@335: /// \brief Gives back the arc goes right from the node. deba@335: /// deba@335: /// Gives back the arc goes right from the node. If there is not deba@335: /// outgoing arc then it gives back INVALID. deba@335: Arc right(Node n) const { deba@335: return Parent::right(n); deba@335: } deba@335: deba@335: /// \brief Gives back the arc goes left from the node. deba@335: /// deba@335: /// Gives back the arc goes left from the node. If there is not deba@335: /// outgoing arc then it gives back INVALID. deba@335: Arc left(Node n) const { deba@335: return Parent::left(n); deba@335: } deba@335: deba@335: /// \brief Gives back the arc goes up from the node. deba@335: /// deba@335: /// Gives back the arc goes up from the node. If there is not deba@335: /// outgoing arc then it gives back INVALID. deba@335: Arc up(Node n) const { deba@335: return Parent::up(n); deba@335: } deba@335: kpeter@334: /// \brief Gives back the arc goes down from the node. kpeter@334: /// kpeter@334: /// Gives back the arc goes down from the node. If there is not deba@335: /// outgoing arc then it gives back INVALID. kpeter@334: Arc down(Node n) const { deba@335: return Parent::down(n); kpeter@334: } kpeter@334: deba@335: /// \brief Index map of the grid graph kpeter@334: /// deba@335: /// Just returns an IndexMap for the grid graph. deba@335: IndexMap indexMap() const { deba@335: return IndexMap(*this); kpeter@334: } kpeter@334: deba@335: /// \brief Row map of the grid graph kpeter@334: /// deba@335: /// Just returns a RowMap for the grid graph. deba@335: RowMap rowMap() const { deba@335: return RowMap(*this); kpeter@334: } kpeter@334: deba@335: /// \brief Column map of the grid graph kpeter@334: /// deba@335: /// Just returns a ColMap for the grid graph. deba@335: ColMap colMap() const { deba@335: return ColMap(*this); kpeter@334: } kpeter@334: deba@335: }; kpeter@334: kpeter@334: } deba@335: #endif