src/lemon/full_graph.h
author alpar
Sat, 20 Nov 2004 10:19:06 +0000
changeset 1011 5bd6c7671c9e
parent 985 741f3108a90f
child 1039 bd01c5a3f989
permissions -rw-r--r--
- snapshot-rollback functionarity added to ListGraph
- The iterface of the snapshot-rollback functionarity in SmartGraph has
changed to be compatible with ListGraph::SnapShot.
     1 /* -*- C++ -*-
     2  * src/lemon/full_graph.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Combinatorial Optimization Research Group, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 
    17 #ifndef LEMON_FULL_GRAPH_H
    18 #define LEMON_FULL_GRAPH_H
    19 
    20 #include <cmath>
    21 
    22 
    23 #include <lemon/iterable_graph_extender.h>
    24 #include <lemon/alteration_observer_registry.h>
    25 #include <lemon/default_map.h>
    26 
    27 #include <lemon/invalid.h>
    28 #include <lemon/utility.h>
    29 
    30 
    31 ///\ingroup graphs
    32 ///\file
    33 ///\brief FullGraph and SymFullGraph classes.
    34 
    35 
    36 namespace lemon {
    37 
    38 /// \addtogroup graphs
    39 /// @{
    40 
    41   class FullGraphBase {
    42     int NodeNum;
    43     int EdgeNum;
    44   public:
    45 
    46     typedef FullGraphBase Graph;
    47 
    48     class Node;
    49     class Edge;
    50 
    51   public:
    52 
    53     FullGraphBase() {}
    54 
    55 
    56     ///Creates a full graph with \c n nodes.
    57     void construct(int n) { NodeNum = n; EdgeNum = n * n; }
    58     ///
    59     //    FullGraphBase(const FullGraphBase &_g)
    60     //      : NodeNum(_g.nodeNum()), EdgeNum(NodeNum*NodeNum) { }
    61     
    62     typedef True NodeNumTag;
    63     typedef True EdgeNumTag;
    64 
    65     ///Number of nodes.
    66     int nodeNum() const { return NodeNum; }
    67     ///Number of edges.
    68     int edgeNum() const { return EdgeNum; }
    69 
    70     /// Maximum node ID.
    71     
    72     /// Maximum node ID.
    73     ///\sa id(Node)
    74     int maxId(Node = INVALID) const { return NodeNum-1; }
    75     /// Maximum edge ID.
    76     
    77     /// Maximum edge ID.
    78     ///\sa id(Edge)
    79     int maxId(Edge = INVALID) const { return EdgeNum-1; }
    80 
    81     Node source(Edge e) const { return e.id % NodeNum; }
    82     Node target(Edge e) const { return e.id / NodeNum; }
    83 
    84 
    85     /// Node ID.
    86     
    87     /// The ID of a valid Node is a nonnegative integer not greater than
    88     /// \ref maxNodeId(). The range of the ID's is not surely continuous
    89     /// and the greatest node ID can be actually less then \ref maxNodeId().
    90     ///
    91     /// The ID of the \ref INVALID node is -1.
    92     ///\return The ID of the node \c v. 
    93 
    94     static int id(Node v) { return v.id; }
    95     /// Edge ID.
    96     
    97     /// The ID of a valid Edge is a nonnegative integer not greater than
    98     /// \ref maxEdgeId(). The range of the ID's is not surely continuous
    99     /// and the greatest edge ID can be actually less then \ref maxEdgeId().
   100     ///
   101     /// The ID of the \ref INVALID edge is -1.
   102     ///\return The ID of the edge \c e. 
   103     static int id(Edge e) { return e.id; }
   104 
   105     /// Finds an edge between two nodes.
   106     
   107     /// Finds an edge from node \c u to node \c v.
   108     ///
   109     /// If \c prev is \ref INVALID (this is the default value), then
   110     /// It finds the first edge from \c u to \c v. Otherwise it looks for
   111     /// the next edge from \c u to \c v after \c prev.
   112     /// \return The found edge or INVALID if there is no such an edge.
   113     Edge findEdge(Node u,Node v, Edge prev = INVALID) 
   114     {
   115       return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID;
   116     }
   117     
   118       
   119     class Node {
   120       friend class FullGraphBase;
   121 
   122     protected:
   123       int id;
   124       Node(int _id) { id = _id;}
   125     public:
   126       Node() {}
   127       Node (Invalid) { id = -1; }
   128       bool operator==(const Node node) const {return id == node.id;}
   129       bool operator!=(const Node node) const {return id != node.id;}
   130       bool operator<(const Node node) const {return id < node.id;}
   131     };
   132     
   133 
   134 
   135     class Edge {
   136       friend class FullGraphBase;
   137       
   138     protected:
   139       int id;  // NodeNum * target + source;
   140 
   141       Edge(int _id) : id(_id) {}
   142 
   143       Edge(const FullGraphBase& _graph, int source, int target) 
   144 	: id(_graph.NodeNum * target+source) {}
   145     public:
   146       Edge() { }
   147       Edge (Invalid) { id = -1; }
   148       bool operator==(const Edge edge) const {return id == edge.id;}
   149       bool operator!=(const Edge edge) const {return id != edge.id;}
   150       bool operator<(const Edge edge) const {return id < edge.id;}
   151     };
   152 
   153     void first(Node& node) const {
   154       node.id = NodeNum-1;
   155     }
   156 
   157     static void next(Node& node) {
   158       --node.id;
   159     }
   160 
   161     void first(Edge& edge) const {
   162       edge.id = EdgeNum-1;
   163     }
   164 
   165     static void next(Edge& edge) {
   166       --edge.id;
   167     }
   168 
   169     void firstOut(Edge& edge, const Node& node) const {
   170       edge.id = EdgeNum + node.id - NodeNum;
   171     }
   172 
   173     void nextOut(Edge& edge) const {
   174       edge.id -= NodeNum;
   175       if (edge.id < 0) edge.id = -1;
   176     }
   177 
   178     void firstIn(Edge& edge, const Node& node) const {
   179       edge.id = node.id * NodeNum;
   180     }
   181     
   182     void nextIn(Edge& edge) const {
   183       ++edge.id;
   184       if (edge.id % NodeNum == 0) edge.id = -1;
   185     }
   186 
   187   };
   188 
   189 
   190   typedef AlterableGraphExtender<FullGraphBase> AlterableFullGraphBase;
   191   typedef IterableGraphExtender<AlterableFullGraphBase> IterableFullGraphBase;
   192   typedef DefaultMappableGraphExtender<IterableFullGraphBase> MappableFullGraphBase;
   193 
   194   ///A full graph class.
   195 
   196   ///This is a simple and fast directed full graph implementation.
   197   ///It is completely static, so you can neither add nor delete either
   198   ///edges or nodes.
   199   ///Thus it conforms to
   200   ///the \ref concept::StaticGraph "StaticGraph" concept
   201   ///\sa concept::StaticGraph.
   202   ///
   203   ///\author Alpar Juttner
   204   class FullGraph : public MappableFullGraphBase {
   205   public:
   206 
   207     FullGraph(int n) { construct(n); }
   208   };
   209 
   210 
   211   /// Base graph class for UndirFullGraph.
   212 
   213   class UndirFullGraphBase {
   214     int NodeNum;
   215     int EdgeNum;
   216   public:
   217 
   218     typedef UndirFullGraphBase Graph;
   219 
   220     class Node;
   221     class Edge;
   222 
   223   public:
   224 
   225     UndirFullGraphBase() {}
   226 
   227 
   228     ///Creates a full graph with \c n nodes.
   229     void construct(int n) { NodeNum = n; EdgeNum = n * (n - 1) / 2; }
   230     ///
   231     //    FullGraphBase(const FullGraphBase &_g)
   232     //      : NodeNum(_g.nodeNum()), EdgeNum(NodeNum*NodeNum) { }
   233     
   234     typedef True NodeNumTag;
   235     typedef True EdgeNumTag;
   236 
   237     ///Number of nodes.
   238     int nodeNum() const { return NodeNum; }
   239     ///Number of edges.
   240     int edgeNum() const { return EdgeNum; }
   241 
   242     /// Maximum node ID.
   243     
   244     /// Maximum node ID.
   245     ///\sa id(Node)
   246     int maxId(Node = INVALID) const { return NodeNum-1; }
   247     /// Maximum edge ID.
   248     
   249     /// Maximum edge ID.
   250     ///\sa id(Edge)
   251     int maxId(Edge = INVALID) const { return EdgeNum-1; }
   252 
   253     Node source(Edge e) const { 
   254       /// \todo we may do it faster
   255       return ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2; 
   256     }
   257 
   258     Node target(Edge e) const { 
   259       int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;;
   260       return e.id - (source) * (source - 1) / 2; 
   261     }
   262 
   263 
   264     /// Node ID.
   265     
   266     /// The ID of a valid Node is a nonnegative integer not greater than
   267     /// \ref maxNodeId(). The range of the ID's is not surely continuous
   268     /// and the greatest node ID can be actually less then \ref maxNodeId().
   269     ///
   270     /// The ID of the \ref INVALID node is -1.
   271     ///\return The ID of the node \c v. 
   272 
   273     static int id(Node v) { return v.id; }
   274     /// Edge ID.
   275     
   276     /// The ID of a valid Edge is a nonnegative integer not greater than
   277     /// \ref maxEdgeId(). The range of the ID's is not surely continuous
   278     /// and the greatest edge ID can be actually less then \ref maxEdgeId().
   279     ///
   280     /// The ID of the \ref INVALID edge is -1.
   281     ///\return The ID of the edge \c e. 
   282     static int id(Edge e) { return e.id; }
   283 
   284     /// Finds an edge between two nodes.
   285     
   286     /// Finds an edge from node \c u to node \c v.
   287     ///
   288     /// If \c prev is \ref INVALID (this is the default value), then
   289     /// It finds the first edge from \c u to \c v. Otherwise it looks for
   290     /// the next edge from \c u to \c v after \c prev.
   291     /// \return The found edge or INVALID if there is no such an edge.
   292     Edge findEdge(Node u,Node v, Edge prev = INVALID) 
   293     {
   294       return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID;
   295     }
   296     
   297       
   298     class Node {
   299       friend class UndirFullGraphBase;
   300 
   301     protected:
   302       int id;
   303       Node(int _id) { id = _id;}
   304     public:
   305       Node() {}
   306       Node (Invalid) { id = -1; }
   307       bool operator==(const Node node) const {return id == node.id;}
   308       bool operator!=(const Node node) const {return id != node.id;}
   309       bool operator<(const Node node) const {return id < node.id;}
   310     };
   311     
   312 
   313 
   314     class Edge {
   315       friend class UndirFullGraphBase;
   316       
   317     protected:
   318       int id;  // NodeNum * target + source;
   319 
   320       Edge(int _id) : id(_id) {}
   321 
   322       Edge(const UndirFullGraphBase& _graph, int source, int target) 
   323 	: id(_graph.NodeNum * target+source) {}
   324     public:
   325       Edge() { }
   326       Edge (Invalid) { id = -1; }
   327       bool operator==(const Edge edge) const {return id == edge.id;}
   328       bool operator!=(const Edge edge) const {return id != edge.id;}
   329       bool operator<(const Edge edge) const {return id < edge.id;}
   330     };
   331 
   332     void first(Node& node) const {
   333       node.id = NodeNum-1;
   334     }
   335 
   336     static void next(Node& node) {
   337       --node.id;
   338     }
   339 
   340     void first(Edge& edge) const {
   341       edge.id = EdgeNum-1;
   342     }
   343 
   344     static void next(Edge& edge) {
   345       --edge.id;
   346     }
   347 
   348     void firstOut(Edge& edge, const Node& node) const {      
   349       edge.id = node.id != 0 ? node.id * (node.id - 1) / 2 : -1;
   350     }
   351 
   352     /// \todo with specialized iterators we can make faster iterating
   353     void nextOut(Edge& e) const {
   354       int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;;
   355       int target = e.id - (source) * (source - 1) / 2; 
   356       ++target;
   357       e.id = target < source ? source * (source - 1) / 2 + target : -1;
   358     }
   359 
   360     void firstIn(Edge& edge, const Node& node) const {
   361       edge.id = node.id * (node.id + 1) / 2 - 1;
   362     }
   363     
   364     void nextIn(Edge& e) const {
   365       int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;;
   366       int target = e.id - (source) * (source - 1) / 2; ++target;
   367       ++source;
   368       e.id = source < NodeNum ? source * (source - 1) / 2 + target : -1;
   369     }
   370 
   371   };
   372 
   373   /// \todo UndirFullGraph from the UndirFullGraphBase
   374 
   375   
   376 
   377   /// @}  
   378 
   379 } //namespace lemon
   380 
   381 
   382 #endif //LEMON_FULL_GRAPH_H