alpar@906: /* -*- C++ -*- ladanyi@1435: * lemon/full_graph.h - Part of LEMON, a generic C++ optimization library alpar@906: * alpar@1164: * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@1359: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@906: * alpar@906: * Permission to use, modify and distribute this software is granted alpar@906: * provided that this copyright notice appears in all copies. For alpar@906: * precise terms see the accompanying LICENSE file. alpar@906: * alpar@906: * This software is provided "AS IS" with no warranty of any kind, alpar@906: * express or implied, and with no claim as to its suitability for any alpar@906: * purpose. alpar@906: * alpar@906: */ alpar@591: alpar@921: #ifndef LEMON_FULL_GRAPH_H alpar@921: #define LEMON_FULL_GRAPH_H alpar@591: deba@983: #include deba@983: klao@946: deba@1307: #include deba@1307: #include deba@1703: #include deba@1791: #include deba@1566: klao@977: #include klao@977: #include klao@977: klao@977: alpar@591: ///\ingroup graphs alpar@591: ///\file deba@1692: ///\brief FullGraph and UndirFullGraph classes. alpar@591: alpar@591: alpar@921: namespace lemon { alpar@591: klao@946: class FullGraphBase { deba@1566: int _nodeNum; deba@1566: int _edgeNum; alpar@591: public: deba@782: klao@946: typedef FullGraphBase Graph; alpar@591: alpar@591: class Node; alpar@591: class Edge; deba@782: alpar@591: public: alpar@591: klao@946: FullGraphBase() {} klao@946: klao@946: alpar@591: ///Creates a full graph with \c n nodes. deba@1566: void construct(int n) { _nodeNum = n; _edgeNum = n * n; } alpar@591: /// klao@946: // FullGraphBase(const FullGraphBase &_g) deba@1566: // : _nodeNum(_g.nodeNum()), _edgeNum(_nodeNum*_nodeNum) { } alpar@591: klao@977: typedef True NodeNumTag; klao@977: typedef True EdgeNumTag; klao@977: alpar@813: ///Number of nodes. deba@1566: int nodeNum() const { return _nodeNum; } alpar@813: ///Number of edges. deba@1566: int edgeNum() const { return _edgeNum; } alpar@591: alpar@813: /// Maximum node ID. alpar@813: alpar@813: /// Maximum node ID. alpar@813: ///\sa id(Node) deba@1791: int maxNodeId() const { return _nodeNum-1; } alpar@813: /// Maximum edge ID. alpar@813: alpar@813: /// Maximum edge ID. alpar@813: ///\sa id(Edge) deba@1791: int maxEdgeId() const { return _edgeNum-1; } alpar@591: deba@1566: Node source(Edge e) const { return e.id % _nodeNum; } deba@1566: Node target(Edge e) const { return e.id / _nodeNum; } alpar@591: alpar@591: alpar@813: /// Node ID. alpar@813: alpar@813: /// The ID of a valid Node is a nonnegative integer not greater than alpar@813: /// \ref maxNodeId(). The range of the ID's is not surely continuous alpar@813: /// and the greatest node ID can be actually less then \ref maxNodeId(). alpar@813: /// alpar@813: /// The ID of the \ref INVALID node is -1. alpar@813: ///\return The ID of the node \c v. klao@946: klao@946: static int id(Node v) { return v.id; } alpar@813: /// Edge ID. alpar@813: alpar@813: /// The ID of a valid Edge is a nonnegative integer not greater than alpar@813: /// \ref maxEdgeId(). The range of the ID's is not surely continuous alpar@813: /// and the greatest edge ID can be actually less then \ref maxEdgeId(). alpar@813: /// alpar@813: /// The ID of the \ref INVALID edge is -1. alpar@813: ///\return The ID of the edge \c e. klao@946: static int id(Edge e) { return e.id; } alpar@591: deba@1791: static Node nodeFromId(int id) { return Node(id);} deba@1106: deba@1791: static Edge edgeFromId(int id) { return Edge(id);} deba@1106: deba@1566: typedef True FindEdgeTag; deba@1566: alpar@774: /// Finds an edge between two nodes. alpar@774: alpar@774: /// Finds an edge from node \c u to node \c v. alpar@774: /// alpar@774: /// If \c prev is \ref INVALID (this is the default value), then alpar@774: /// It finds the first edge from \c u to \c v. Otherwise it looks for alpar@774: /// the next edge from \c u to \c v after \c prev. alpar@774: /// \return The found edge or INVALID if there is no such an edge. deba@1566: Edge findEdge(Node u,Node v, Edge prev = INVALID) const { klao@946: return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID; alpar@774: } alpar@774: alpar@774: alpar@591: class Node { klao@946: friend class FullGraphBase; alpar@591: alpar@591: protected: klao@946: int id; alpar@1643: Node(int _id) : id(_id) {} alpar@591: public: alpar@591: Node() {} alpar@1643: Node (Invalid) : id(-1) {} klao@946: bool operator==(const Node node) const {return id == node.id;} klao@946: bool operator!=(const Node node) const {return id != node.id;} klao@946: bool operator<(const Node node) const {return id < node.id;} alpar@591: }; alpar@591: klao@946: klao@946: klao@946: class Edge { klao@946: friend class FullGraphBase; klao@946: klao@946: protected: deba@1566: int id; // _nodeNum * target + source; klao@946: klao@946: Edge(int _id) : id(_id) {} klao@946: alpar@986: Edge(const FullGraphBase& _graph, int source, int target) deba@1566: : id(_graph._nodeNum * target+source) {} alpar@591: public: klao@946: Edge() { } klao@946: Edge (Invalid) { id = -1; } klao@946: bool operator==(const Edge edge) const {return id == edge.id;} klao@946: bool operator!=(const Edge edge) const {return id != edge.id;} klao@946: bool operator<(const Edge edge) const {return id < edge.id;} alpar@591: }; alpar@591: klao@946: void first(Node& node) const { deba@1566: node.id = _nodeNum-1; klao@946: } alpar@591: klao@946: static void next(Node& node) { klao@946: --node.id; klao@946: } klao@946: klao@946: void first(Edge& edge) const { deba@1566: edge.id = _edgeNum-1; klao@946: } klao@946: klao@946: static void next(Edge& edge) { klao@946: --edge.id; klao@946: } klao@946: klao@946: void firstOut(Edge& edge, const Node& node) const { deba@1566: edge.id = _edgeNum + node.id - _nodeNum; klao@946: } klao@946: klao@946: void nextOut(Edge& edge) const { deba@1566: edge.id -= _nodeNum; klao@946: if (edge.id < 0) edge.id = -1; klao@946: } klao@946: klao@946: void firstIn(Edge& edge, const Node& node) const { deba@1566: edge.id = node.id * _nodeNum; klao@946: } alpar@591: klao@946: void nextIn(Edge& edge) const { klao@946: ++edge.id; deba@1566: if (edge.id % _nodeNum == 0) edge.id = -1; klao@946: } alpar@591: alpar@591: }; alpar@591: deba@1703: typedef StaticMappableGraphExtender< deba@1669: IterableGraphExtender< deba@1791: AlterableGraphExtender< deba@1791: GraphExtender > > > ExtendedFullGraphBase; klao@946: deba@1566: /// \ingroup graphs alpar@951: /// deba@1566: /// \brief A full graph class. deba@1566: /// deba@1566: /// This is a simple and fast directed full graph implementation. deba@1566: /// It is completely static, so you can neither add nor delete either deba@1566: /// edges or nodes. deba@1566: /// Thus it conforms to deba@1566: /// the \ref concept::StaticGraph "StaticGraph" concept deba@1566: /// \sa concept::StaticGraph. deba@1566: /// deba@1566: /// \author Alpar Juttner deba@1669: class FullGraph : public ExtendedFullGraphBase { klao@946: public: klao@946: klao@946: FullGraph(int n) { construct(n); } klao@946: }; klao@946: deba@983: deba@983: class UndirFullGraphBase { deba@1566: int _nodeNum; deba@1566: int _edgeNum; deba@983: public: deba@983: deba@984: typedef UndirFullGraphBase Graph; deba@983: deba@983: class Node; deba@983: class Edge; deba@983: deba@983: public: deba@983: deba@984: UndirFullGraphBase() {} deba@983: deba@983: deba@983: ///Creates a full graph with \c n nodes. deba@1566: void construct(int n) { _nodeNum = n; _edgeNum = n * (n - 1) / 2; } deba@983: /// deba@983: // FullGraphBase(const FullGraphBase &_g) deba@1566: // : _nodeNum(_g.nodeNum()), _edgeNum(_nodeNum*_nodeNum) { } deba@983: deba@983: typedef True NodeNumTag; deba@983: typedef True EdgeNumTag; deba@983: deba@983: ///Number of nodes. deba@1566: int nodeNum() const { return _nodeNum; } deba@983: ///Number of edges. deba@1566: int edgeNum() const { return _edgeNum; } deba@983: deba@983: /// Maximum node ID. deba@983: deba@983: /// Maximum node ID. deba@983: ///\sa id(Node) deba@1791: int maxNodeId() const { return _nodeNum-1; } deba@983: /// Maximum edge ID. deba@983: deba@983: /// Maximum edge ID. deba@983: ///\sa id(Edge) deba@1791: int maxEdgeId() const { return _edgeNum-1; } deba@983: alpar@986: Node source(Edge e) const { deba@983: /// \todo we may do it faster alpar@1643: return Node(((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2); deba@983: } deba@983: alpar@986: Node target(Edge e) const { alpar@986: int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;; alpar@1643: return Node(e.id - (source) * (source - 1) / 2); deba@983: } deba@983: deba@983: deba@983: /// Node ID. deba@983: deba@983: /// The ID of a valid Node is a nonnegative integer not greater than deba@983: /// \ref maxNodeId(). The range of the ID's is not surely continuous deba@983: /// and the greatest node ID can be actually less then \ref maxNodeId(). deba@983: /// deba@983: /// The ID of the \ref INVALID node is -1. deba@983: ///\return The ID of the node \c v. deba@983: deba@983: static int id(Node v) { return v.id; } deba@983: /// Edge ID. deba@983: deba@983: /// The ID of a valid Edge is a nonnegative integer not greater than deba@983: /// \ref maxEdgeId(). The range of the ID's is not surely continuous deba@983: /// and the greatest edge ID can be actually less then \ref maxEdgeId(). deba@983: /// deba@983: /// The ID of the \ref INVALID edge is -1. deba@983: ///\return The ID of the edge \c e. deba@983: static int id(Edge e) { return e.id; } deba@983: deba@983: /// Finds an edge between two nodes. deba@983: deba@983: /// Finds an edge from node \c u to node \c v. deba@983: /// deba@983: /// If \c prev is \ref INVALID (this is the default value), then deba@983: /// It finds the first edge from \c u to \c v. Otherwise it looks for deba@983: /// the next edge from \c u to \c v after \c prev. deba@983: /// \return The found edge or INVALID if there is no such an edge. deba@1703: Edge findEdge(Node u, Node v, Edge prev = INVALID) const { deba@1703: if (prev.id != -1 || u.id <= v.id) return -1; deba@1703: return Edge(u.id * (u.id - 1) / 2 + v.id); deba@983: } deba@1703: deba@1703: typedef True FindEdgeTag; deba@983: deba@983: deba@983: class Node { alpar@985: friend class UndirFullGraphBase; deba@983: deba@983: protected: deba@983: int id; deba@983: Node(int _id) { id = _id;} deba@983: public: deba@983: Node() {} deba@983: Node (Invalid) { id = -1; } deba@983: bool operator==(const Node node) const {return id == node.id;} deba@983: bool operator!=(const Node node) const {return id != node.id;} deba@983: bool operator<(const Node node) const {return id < node.id;} deba@983: }; deba@983: deba@983: deba@983: deba@983: class Edge { alpar@985: friend class UndirFullGraphBase; deba@983: deba@983: protected: deba@1566: int id; // _nodeNum * target + source; deba@983: deba@983: Edge(int _id) : id(_id) {} deba@983: deba@983: public: deba@983: Edge() { } deba@983: Edge (Invalid) { id = -1; } deba@983: bool operator==(const Edge edge) const {return id == edge.id;} deba@983: bool operator!=(const Edge edge) const {return id != edge.id;} deba@983: bool operator<(const Edge edge) const {return id < edge.id;} deba@983: }; deba@983: deba@983: void first(Node& node) const { deba@1703: node.id = _nodeNum - 1; deba@983: } deba@983: deba@983: static void next(Node& node) { deba@983: --node.id; deba@983: } deba@983: deba@983: void first(Edge& edge) const { deba@1703: edge.id = _edgeNum - 1; deba@983: } deba@983: deba@983: static void next(Edge& edge) { deba@983: --edge.id; deba@983: } deba@983: deba@983: void firstOut(Edge& edge, const Node& node) const { deba@1703: int src = node.id; deba@1703: int trg = 0; deba@1703: edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1); deba@983: } deba@983: deba@983: /// \todo with specialized iterators we can make faster iterating deba@1703: void nextOut(Edge& edge) const { deba@1703: int src = source(edge).id; deba@1703: int trg = target(edge).id; deba@1703: ++trg; deba@1703: edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1); deba@983: } deba@983: deba@983: void firstIn(Edge& edge, const Node& node) const { deba@1703: int src = node.id + 1; deba@1703: int trg = node.id; deba@1703: edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1); deba@983: } deba@983: deba@1703: void nextIn(Edge& edge) const { deba@1703: int src = source(edge).id; deba@1703: int trg = target(edge).id; deba@1703: ++src; deba@1703: edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1); deba@983: } deba@983: deba@983: }; deba@983: deba@1703: typedef StaticMappableUndirGraphExtender< deba@1669: IterableUndirGraphExtender< deba@1669: AlterableUndirGraphExtender< deba@1669: UndirGraphExtender > > > ExtendedUndirFullGraphBase; alpar@1555: deba@1566: /// \ingroup graphs deba@1566: /// deba@1566: /// \brief An undirected full graph class. deba@1566: /// deba@1726: /// This is a simple and fast undirected full graph implementation. deba@1566: /// It is completely static, so you can neither add nor delete either deba@1566: /// edges or nodes. deba@1566: /// deba@1566: /// The main difference beetween the \e FullGraph and \e UndirFullGraph class deba@1566: /// is that this class conforms to the undirected graph concept and deba@1726: /// it does not contain the loop edges. deba@1566: /// deba@1566: /// \sa FullGraph deba@1566: /// deba@1566: /// \author Balazs Dezso deba@1669: class UndirFullGraph : public ExtendedUndirFullGraphBase { deba@1566: public: deba@1566: UndirFullGraph(int n) { construct(n); } deba@1566: }; alpar@591: deba@1820: deba@1820: class FullUndirBipartiteGraphBase { deba@1820: protected: deba@1820: deba@1820: int _upperNodeNum; deba@1820: int _lowerNodeNum; deba@1820: deba@1820: int _edgeNum; deba@1820: deba@1820: public: deba@1820: deba@1820: class NodeSetError : public LogicError { deba@1820: virtual const char* exceptionName() const { deba@1820: return "lemon::FullUndirBipartiteGraph::NodeSetError"; deba@1820: } deba@1820: }; deba@1820: deba@1820: class Node { deba@1820: friend class FullUndirBipartiteGraphBase; deba@1820: protected: deba@1820: int id; deba@1820: deba@1820: Node(int _id) : id(_id) {} deba@1820: public: deba@1820: Node() {} deba@1820: Node(Invalid) { id = -1; } deba@1820: bool operator==(const Node i) const {return id==i.id;} deba@1820: bool operator!=(const Node i) const {return id!=i.id;} deba@1820: bool operator<(const Node i) const {return id 0) { deba@1820: node.id = 2 * _upperNodeNum - 2; deba@1820: } else { deba@1820: node.id = 2 * _lowerNodeNum - 1; deba@1820: } deba@1820: } deba@1820: void next(Node& node) const { deba@1820: node.id -= 2; deba@1820: if (node.id == -2) { deba@1820: node.id = 2 * _lowerNodeNum - 1; deba@1820: } deba@1820: } deba@1820: deba@1820: void first(Edge& edge) const { deba@1820: edge.id = _edgeNum - 1; deba@1820: } deba@1820: void next(Edge& edge) const { deba@1820: --edge.id; deba@1820: } deba@1820: deba@1820: void firstDown(Edge& edge, const Node& node) const { deba@1820: LEMON_ASSERT((node.id & 1) == 0, NodeSetError()); deba@1820: edge.id = (node.id >> 1) * _lowerNodeNum; deba@1820: } deba@1820: void nextDown(Edge& edge) const { deba@1820: ++(edge.id); deba@1820: if (edge.id % _lowerNodeNum == 0) edge.id = -1; deba@1820: } deba@1820: deba@1820: void firstUp(Edge& edge, const Node& node) const { deba@1820: LEMON_ASSERT((node.id & 1) == 1, NodeSetError()); deba@1820: edge.id = (node.id >> 1); deba@1820: } deba@1820: void nextUp(Edge& edge) const { deba@1820: edge.id += _lowerNodeNum; deba@1820: if (edge.id >= _edgeNum) edge.id = -1; deba@1820: } deba@1820: deba@1820: static int id(const Node& node) { deba@1820: return node.id; deba@1820: } deba@1820: static Node nodeFromId(int id) { deba@1820: return Node(id); deba@1820: } deba@1820: int maxNodeId() const { deba@1820: return _upperNodeNum > _lowerNodeNum ? deba@1820: _upperNodeNum * 2 - 2 : _lowerNodeNum * 2 - 1; deba@1820: } deba@1820: deba@1820: static int id(const Edge& edge) { deba@1820: return edge.id; deba@1820: } deba@1820: static Edge edgeFromId(int id) { deba@1820: return Edge(id); deba@1820: } deba@1820: int maxEdgeId() const { deba@1820: return _edgeNum - 1; deba@1820: } deba@1820: deba@1820: static int upperId(const Node& node) { deba@1820: return node.id >> 1; deba@1820: } deba@1820: static Node fromUpperId(int id, Node) { deba@1820: return Node(id << 1); deba@1820: } deba@1820: int maxUpperId() const { deba@1820: return _upperNodeNum; deba@1820: } deba@1820: deba@1820: static int lowerId(const Node& node) { deba@1820: return node.id >> 1; deba@1820: } deba@1820: static Node fromLowerId(int id) { deba@1820: return Node((id << 1) + 1); deba@1820: } deba@1820: int maxLowerId() const { deba@1820: return _lowerNodeNum; deba@1820: } deba@1820: deba@1820: Node upperNode(const Edge& edge) const { deba@1820: return Node((edge.id / _lowerNodeNum) << 1); deba@1820: } deba@1820: Node lowerNode(const Edge& edge) const { deba@1820: return Node(((edge.id % _lowerNodeNum) << 1) + 1); deba@1820: } deba@1820: deba@1820: static bool upper(const Node& node) { deba@1820: return (node.id & 1) == 0; deba@1820: } deba@1820: deba@1820: static bool lower(const Node& node) { deba@1820: return (node.id & 1) == 1; deba@1820: } deba@1820: deba@1820: static Node upperNode(int index) { deba@1820: return Node(index << 1); deba@1820: } deba@1820: deba@1820: static Node lowerNode(int index) { deba@1820: return Node((index << 1) + 1); deba@1820: } deba@1820: deba@1820: }; deba@1820: deba@1820: deba@1828: typedef StaticMappableUndirBipartiteGraphExtender< deba@1820: IterableUndirBipartiteGraphExtender< deba@1820: AlterableUndirBipartiteGraphExtender< deba@1820: UndirBipartiteGraphExtender < deba@1820: FullUndirBipartiteGraphBase> > > > deba@1820: ExtendedFullUndirBipartiteGraphBase; deba@1820: deba@1820: deba@1820: class FullUndirBipartiteGraph : deba@1820: public ExtendedFullUndirBipartiteGraphBase { deba@1820: public: deba@1820: typedef ExtendedFullUndirBipartiteGraphBase Parent; deba@1820: FullUndirBipartiteGraph(int upperNodeNum, int lowerNodeNum) { deba@1820: Parent::construct(upperNodeNum, lowerNodeNum); deba@1820: } deba@1820: }; deba@1820: alpar@921: } //namespace lemon alpar@591: alpar@591: alpar@921: #endif //LEMON_FULL_GRAPH_H