alpar@906: /* -*- C++ -*-
alpar@921:  * src/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@906:  * (Egervary Combinatorial Optimization Research Group, 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 <cmath>
deba@983: 
klao@946: 
klao@946: #include <lemon/iterable_graph_extender.h>
deba@1039: #include <lemon/alteration_notifier.h>
klao@946: #include <lemon/default_map.h>
klao@946: 
klao@977: #include <lemon/invalid.h>
klao@977: #include <lemon/utility.h>
klao@977: 
klao@977: 
alpar@591: ///\ingroup graphs
alpar@591: ///\file
alpar@591: ///\brief FullGraph and SymFullGraph classes.
alpar@591: 
alpar@591: 
alpar@921: namespace lemon {
alpar@591: 
alpar@591: /// \addtogroup graphs
alpar@591: /// @{
alpar@591: 
klao@946:   class FullGraphBase {
alpar@591:     int NodeNum;
alpar@591:     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.
klao@946:     void construct(int n) { NodeNum = n; EdgeNum = n * n; }
alpar@591:     ///
klao@946:     //    FullGraphBase(const FullGraphBase &_g)
klao@946:     //      : 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.
alpar@813:     int nodeNum() const { return NodeNum; }
alpar@813:     ///Number of edges.
alpar@813:     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@980:     int maxId(Node = INVALID) const { return NodeNum-1; }
alpar@813:     /// Maximum edge ID.
alpar@813:     
alpar@813:     /// Maximum edge ID.
alpar@813:     ///\sa id(Edge)
deba@980:     int maxId(Edge = INVALID) const { return EdgeNum-1; }
alpar@591: 
alpar@986:     Node source(Edge e) const { return e.id % NodeNum; }
alpar@986:     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@1106:     static Node fromId(int id, Node) { return Node(id);}
deba@1106:     
deba@1106:     static Edge fromId(int id, Edge) { return Edge(id);}
deba@1106: 
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.
alpar@774:     Edge findEdge(Node u,Node v, Edge prev = INVALID) 
alpar@774:     {
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;
klao@946:       Node(int _id) { id = _id;}
alpar@591:     public:
alpar@591:       Node() {}
klao@946:       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:
alpar@986:       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) 
alpar@986: 	: 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 {
klao@946:       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 {
klao@946:       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 {
klao@946:       edge.id = EdgeNum + node.id - NodeNum;
klao@946:     }
klao@946: 
klao@946:     void nextOut(Edge& edge) const {
klao@946:       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 {
klao@946:       edge.id = node.id * NodeNum;
klao@946:     }
alpar@591:     
klao@946:     void nextIn(Edge& edge) const {
klao@946:       ++edge.id;
klao@946:       if (edge.id % NodeNum == 0) edge.id = -1;
klao@946:     }
alpar@591: 
alpar@591:   };
alpar@591: 
klao@946: 
klao@946:   typedef AlterableGraphExtender<FullGraphBase> AlterableFullGraphBase;
klao@946:   typedef IterableGraphExtender<AlterableFullGraphBase> IterableFullGraphBase;
deba@980:   typedef DefaultMappableGraphExtender<IterableFullGraphBase> MappableFullGraphBase;
klao@946: 
alpar@951:   ///A full graph class.
alpar@951: 
alpar@951:   ///This is a simple and fast directed full graph implementation.
alpar@951:   ///It is completely static, so you can neither add nor delete either
alpar@951:   ///edges or nodes.
alpar@951:   ///Thus it conforms to
klao@959:   ///the \ref concept::StaticGraph "StaticGraph" concept
klao@959:   ///\sa concept::StaticGraph.
alpar@951:   ///
alpar@951:   ///\author Alpar Juttner
klao@946:   class FullGraph : public MappableFullGraphBase {
klao@946:   public:
klao@946: 
klao@946:     FullGraph(int n) { construct(n); }
klao@946:   };
klao@946: 
deba@983: 
alpar@1161:   // Base graph class for UndirFullGraph.
deba@983:   class UndirFullGraphBase {
deba@983:     int NodeNum;
deba@983:     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@983:     void construct(int n) { NodeNum = n; EdgeNum = n * (n - 1) / 2; }
deba@983:     ///
deba@983:     //    FullGraphBase(const FullGraphBase &_g)
deba@983:     //      : 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@983:     int nodeNum() const { return NodeNum; }
deba@983:     ///Number of edges.
deba@983:     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@983:     int maxId(Node = INVALID) const { return NodeNum-1; }
deba@983:     /// Maximum edge ID.
deba@983:     
deba@983:     /// Maximum edge ID.
deba@983:     ///\sa id(Edge)
deba@983:     int maxId(Edge = INVALID) const { return EdgeNum-1; }
deba@983: 
alpar@986:     Node source(Edge e) const { 
deba@983:       /// \todo we may do it faster
deba@983:       return ((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@986:       return 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@983:     Edge findEdge(Node u,Node v, Edge prev = INVALID) 
deba@983:     {
deba@983:       return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID;
deba@983:     }
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:
alpar@986:       int id;  // NodeNum * target + source;
deba@983: 
deba@983:       Edge(int _id) : id(_id) {}
deba@983: 
alpar@986:       Edge(const UndirFullGraphBase& _graph, int source, int target) 
alpar@986: 	: id(_graph.NodeNum * target+source) {}
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@983:       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@983:       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@983:       edge.id = node.id != 0 ? node.id * (node.id - 1) / 2 : -1;
deba@983:     }
deba@983: 
deba@983:     /// \todo with specialized iterators we can make faster iterating
alpar@985:     void nextOut(Edge& e) const {
alpar@986:       int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;;
alpar@986:       int target = e.id - (source) * (source - 1) / 2; 
alpar@986:       ++target;
alpar@986:       e.id = target < source ? source * (source - 1) / 2 + target : -1;
deba@983:     }
deba@983: 
deba@983:     void firstIn(Edge& edge, const Node& node) const {
deba@983:       edge.id = node.id * (node.id + 1) / 2 - 1;
deba@983:     }
deba@983:     
alpar@985:     void nextIn(Edge& e) const {
alpar@986:       int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;;
alpar@986:       int target = e.id - (source) * (source - 1) / 2; ++target;
alpar@986:       ++source;
alpar@986:       e.id = source < NodeNum ? source * (source - 1) / 2 + target : -1;
deba@983:     }
deba@983: 
deba@983:   };
deba@983: 
deba@983:   /// \todo UndirFullGraph from the UndirFullGraphBase
deba@983: 
deba@983:   
deba@983: 
alpar@591:   /// @}  
alpar@591: 
alpar@921: } //namespace lemon
alpar@591: 
alpar@591: 
alpar@921: #endif //LEMON_FULL_GRAPH_H