lemon/full_graph.h
author deba
Wed, 23 Nov 2005 11:20:14 +0000
changeset 1828 fd3771591a5c
parent 1820 22099ef840d7
child 1875 98698b69a902
permissions -rw-r--r--
Static maps for bipartite graphs.
     1 /* -*- C++ -*-
     2  * lemon/full_graph.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, 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/bits/iterable_graph_extender.h>
    24 #include <lemon/bits/alteration_notifier.h>
    25 #include <lemon/bits/static_map.h>
    26 #include <lemon/bits/graph_extender.h>
    27 
    28 #include <lemon/invalid.h>
    29 #include <lemon/utility.h>
    30 
    31 
    32 ///\ingroup graphs
    33 ///\file
    34 ///\brief FullGraph and UndirFullGraph classes.
    35 
    36 
    37 namespace lemon {
    38 
    39   class FullGraphBase {
    40     int _nodeNum;
    41     int _edgeNum;
    42   public:
    43 
    44     typedef FullGraphBase Graph;
    45 
    46     class Node;
    47     class Edge;
    48 
    49   public:
    50 
    51     FullGraphBase() {}
    52 
    53 
    54     ///Creates a full graph with \c n nodes.
    55     void construct(int n) { _nodeNum = n; _edgeNum = n * n; }
    56     ///
    57     //    FullGraphBase(const FullGraphBase &_g)
    58     //      : _nodeNum(_g.nodeNum()), _edgeNum(_nodeNum*_nodeNum) { }
    59     
    60     typedef True NodeNumTag;
    61     typedef True EdgeNumTag;
    62 
    63     ///Number of nodes.
    64     int nodeNum() const { return _nodeNum; }
    65     ///Number of edges.
    66     int edgeNum() const { return _edgeNum; }
    67 
    68     /// Maximum node ID.
    69     
    70     /// Maximum node ID.
    71     ///\sa id(Node)
    72     int maxNodeId() const { return _nodeNum-1; }
    73     /// Maximum edge ID.
    74     
    75     /// Maximum edge ID.
    76     ///\sa id(Edge)
    77     int maxEdgeId() const { return _edgeNum-1; }
    78 
    79     Node source(Edge e) const { return e.id % _nodeNum; }
    80     Node target(Edge e) const { return e.id / _nodeNum; }
    81 
    82 
    83     /// Node ID.
    84     
    85     /// The ID of a valid Node is a nonnegative integer not greater than
    86     /// \ref maxNodeId(). The range of the ID's is not surely continuous
    87     /// and the greatest node ID can be actually less then \ref maxNodeId().
    88     ///
    89     /// The ID of the \ref INVALID node is -1.
    90     ///\return The ID of the node \c v. 
    91 
    92     static int id(Node v) { return v.id; }
    93     /// Edge ID.
    94     
    95     /// The ID of a valid Edge is a nonnegative integer not greater than
    96     /// \ref maxEdgeId(). The range of the ID's is not surely continuous
    97     /// and the greatest edge ID can be actually less then \ref maxEdgeId().
    98     ///
    99     /// The ID of the \ref INVALID edge is -1.
   100     ///\return The ID of the edge \c e. 
   101     static int id(Edge e) { return e.id; }
   102 
   103     static Node nodeFromId(int id) { return Node(id);}
   104     
   105     static Edge edgeFromId(int id) { return Edge(id);}
   106 
   107     typedef True FindEdgeTag;
   108 
   109     /// Finds an edge between two nodes.
   110     
   111     /// Finds an edge from node \c u to node \c v.
   112     ///
   113     /// If \c prev is \ref INVALID (this is the default value), then
   114     /// It finds the first edge from \c u to \c v. Otherwise it looks for
   115     /// the next edge from \c u to \c v after \c prev.
   116     /// \return The found edge or INVALID if there is no such an edge.
   117     Edge findEdge(Node u,Node v, Edge prev = INVALID) const {
   118       return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID;
   119     }
   120     
   121       
   122     class Node {
   123       friend class FullGraphBase;
   124 
   125     protected:
   126       int id;
   127       Node(int _id) : id(_id) {}
   128     public:
   129       Node() {}
   130       Node (Invalid) : id(-1) {}
   131       bool operator==(const Node node) const {return id == node.id;}
   132       bool operator!=(const Node node) const {return id != node.id;}
   133       bool operator<(const Node node) const {return id < node.id;}
   134     };
   135     
   136 
   137 
   138     class Edge {
   139       friend class FullGraphBase;
   140       
   141     protected:
   142       int id;  // _nodeNum * target + source;
   143 
   144       Edge(int _id) : id(_id) {}
   145 
   146       Edge(const FullGraphBase& _graph, int source, int target) 
   147 	: id(_graph._nodeNum * target+source) {}
   148     public:
   149       Edge() { }
   150       Edge (Invalid) { id = -1; }
   151       bool operator==(const Edge edge) const {return id == edge.id;}
   152       bool operator!=(const Edge edge) const {return id != edge.id;}
   153       bool operator<(const Edge edge) const {return id < edge.id;}
   154     };
   155 
   156     void first(Node& node) const {
   157       node.id = _nodeNum-1;
   158     }
   159 
   160     static void next(Node& node) {
   161       --node.id;
   162     }
   163 
   164     void first(Edge& edge) const {
   165       edge.id = _edgeNum-1;
   166     }
   167 
   168     static void next(Edge& edge) {
   169       --edge.id;
   170     }
   171 
   172     void firstOut(Edge& edge, const Node& node) const {
   173       edge.id = _edgeNum + node.id - _nodeNum;
   174     }
   175 
   176     void nextOut(Edge& edge) const {
   177       edge.id -= _nodeNum;
   178       if (edge.id < 0) edge.id = -1;
   179     }
   180 
   181     void firstIn(Edge& edge, const Node& node) const {
   182       edge.id = node.id * _nodeNum;
   183     }
   184     
   185     void nextIn(Edge& edge) const {
   186       ++edge.id;
   187       if (edge.id % _nodeNum == 0) edge.id = -1;
   188     }
   189 
   190   };
   191 
   192   typedef StaticMappableGraphExtender<
   193     IterableGraphExtender<
   194     AlterableGraphExtender<
   195     GraphExtender<FullGraphBase> > > > ExtendedFullGraphBase;
   196 
   197   /// \ingroup graphs
   198   ///
   199   /// \brief A full graph class.
   200   ///
   201   /// This is a simple and fast directed full graph implementation.
   202   /// It is completely static, so you can neither add nor delete either
   203   /// edges or nodes.
   204   /// Thus it conforms to
   205   /// the \ref concept::StaticGraph "StaticGraph" concept
   206   /// \sa concept::StaticGraph.
   207   ///
   208   /// \author Alpar Juttner
   209   class FullGraph : public ExtendedFullGraphBase {
   210   public:
   211 
   212     FullGraph(int n) { construct(n); }
   213   };
   214 
   215 
   216   class UndirFullGraphBase {
   217     int _nodeNum;
   218     int _edgeNum;
   219   public:
   220 
   221     typedef UndirFullGraphBase Graph;
   222 
   223     class Node;
   224     class Edge;
   225 
   226   public:
   227 
   228     UndirFullGraphBase() {}
   229 
   230 
   231     ///Creates a full graph with \c n nodes.
   232     void construct(int n) { _nodeNum = n; _edgeNum = n * (n - 1) / 2; }
   233     ///
   234     //    FullGraphBase(const FullGraphBase &_g)
   235     //      : _nodeNum(_g.nodeNum()), _edgeNum(_nodeNum*_nodeNum) { }
   236     
   237     typedef True NodeNumTag;
   238     typedef True EdgeNumTag;
   239 
   240     ///Number of nodes.
   241     int nodeNum() const { return _nodeNum; }
   242     ///Number of edges.
   243     int edgeNum() const { return _edgeNum; }
   244 
   245     /// Maximum node ID.
   246     
   247     /// Maximum node ID.
   248     ///\sa id(Node)
   249     int maxNodeId() const { return _nodeNum-1; }
   250     /// Maximum edge ID.
   251     
   252     /// Maximum edge ID.
   253     ///\sa id(Edge)
   254     int maxEdgeId() const { return _edgeNum-1; }
   255 
   256     Node source(Edge e) const { 
   257       /// \todo we may do it faster
   258       return Node(((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2);
   259     }
   260 
   261     Node target(Edge e) const { 
   262       int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;;
   263       return Node(e.id - (source) * (source - 1) / 2);
   264     }
   265 
   266 
   267     /// Node ID.
   268     
   269     /// The ID of a valid Node is a nonnegative integer not greater than
   270     /// \ref maxNodeId(). The range of the ID's is not surely continuous
   271     /// and the greatest node ID can be actually less then \ref maxNodeId().
   272     ///
   273     /// The ID of the \ref INVALID node is -1.
   274     ///\return The ID of the node \c v. 
   275 
   276     static int id(Node v) { return v.id; }
   277     /// Edge ID.
   278     
   279     /// The ID of a valid Edge is a nonnegative integer not greater than
   280     /// \ref maxEdgeId(). The range of the ID's is not surely continuous
   281     /// and the greatest edge ID can be actually less then \ref maxEdgeId().
   282     ///
   283     /// The ID of the \ref INVALID edge is -1.
   284     ///\return The ID of the edge \c e. 
   285     static int id(Edge e) { return e.id; }
   286 
   287     /// Finds an edge between two nodes.
   288     
   289     /// Finds an edge from node \c u to node \c v.
   290     ///
   291     /// If \c prev is \ref INVALID (this is the default value), then
   292     /// It finds the first edge from \c u to \c v. Otherwise it looks for
   293     /// the next edge from \c u to \c v after \c prev.
   294     /// \return The found edge or INVALID if there is no such an edge.
   295     Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
   296       if (prev.id != -1 || u.id <= v.id) return -1;
   297       return Edge(u.id * (u.id - 1) / 2 + v.id);
   298     }
   299 
   300     typedef True FindEdgeTag;
   301     
   302       
   303     class Node {
   304       friend class UndirFullGraphBase;
   305 
   306     protected:
   307       int id;
   308       Node(int _id) { id = _id;}
   309     public:
   310       Node() {}
   311       Node (Invalid) { id = -1; }
   312       bool operator==(const Node node) const {return id == node.id;}
   313       bool operator!=(const Node node) const {return id != node.id;}
   314       bool operator<(const Node node) const {return id < node.id;}
   315     };
   316     
   317 
   318 
   319     class Edge {
   320       friend class UndirFullGraphBase;
   321       
   322     protected:
   323       int id;  // _nodeNum * target + source;
   324 
   325       Edge(int _id) : id(_id) {}
   326 
   327     public:
   328       Edge() { }
   329       Edge (Invalid) { id = -1; }
   330       bool operator==(const Edge edge) const {return id == edge.id;}
   331       bool operator!=(const Edge edge) const {return id != edge.id;}
   332       bool operator<(const Edge edge) const {return id < edge.id;}
   333     };
   334 
   335     void first(Node& node) const {
   336       node.id = _nodeNum - 1;
   337     }
   338 
   339     static void next(Node& node) {
   340       --node.id;
   341     }
   342 
   343     void first(Edge& edge) const {
   344       edge.id = _edgeNum - 1;
   345     }
   346 
   347     static void next(Edge& edge) {
   348       --edge.id;
   349     }
   350 
   351     void firstOut(Edge& edge, const Node& node) const {      
   352       int src = node.id;
   353       int trg = 0;
   354       edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1);
   355     }
   356 
   357     /// \todo with specialized iterators we can make faster iterating
   358     void nextOut(Edge& edge) const {
   359       int src = source(edge).id;
   360       int trg = target(edge).id;
   361       ++trg;
   362       edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1);
   363     }
   364 
   365     void firstIn(Edge& edge, const Node& node) const {
   366       int src = node.id + 1;
   367       int trg = node.id;
   368       edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1);
   369     }
   370     
   371     void nextIn(Edge& edge) const {
   372       int src = source(edge).id;
   373       int trg = target(edge).id;
   374       ++src;
   375       edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1);
   376     }
   377 
   378   };
   379 
   380   typedef StaticMappableUndirGraphExtender<
   381     IterableUndirGraphExtender<
   382     AlterableUndirGraphExtender<
   383     UndirGraphExtender<UndirFullGraphBase> > > > ExtendedUndirFullGraphBase;
   384 
   385   /// \ingroup graphs
   386   ///
   387   /// \brief An undirected full graph class.
   388   ///
   389   /// This is a simple and fast undirected full graph implementation.
   390   /// It is completely static, so you can neither add nor delete either
   391   /// edges or nodes.
   392   ///
   393   /// The main difference beetween the \e FullGraph and \e UndirFullGraph class
   394   /// is that this class conforms to the undirected graph concept and
   395   /// it does not contain the loop edges.
   396   ///
   397   /// \sa FullGraph
   398   ///
   399   /// \author Balazs Dezso
   400   class UndirFullGraph : public ExtendedUndirFullGraphBase {
   401   public:
   402     UndirFullGraph(int n) { construct(n); }
   403   };
   404 
   405 
   406   class FullUndirBipartiteGraphBase {
   407   protected:
   408 
   409     int _upperNodeNum;
   410     int _lowerNodeNum;
   411 
   412     int _edgeNum;
   413 
   414   public:
   415 
   416     class NodeSetError : public LogicError {
   417       virtual const char* exceptionName() const { 
   418 	return "lemon::FullUndirBipartiteGraph::NodeSetError";
   419       }
   420     };
   421   
   422     class Node {
   423       friend class FullUndirBipartiteGraphBase;
   424     protected:
   425       int id;
   426 
   427       Node(int _id) : id(_id) {}
   428     public:
   429       Node() {}
   430       Node(Invalid) { id = -1; }
   431       bool operator==(const Node i) const {return id==i.id;}
   432       bool operator!=(const Node i) const {return id!=i.id;}
   433       bool operator<(const Node i) const {return id<i.id;}
   434     };
   435 
   436     class Edge {
   437       friend class FullUndirBipartiteGraphBase;
   438     protected:
   439       int id;
   440 
   441       Edge(int _id) { id = _id;}
   442     public:
   443       Edge() {}
   444       Edge (Invalid) { id = -1; }
   445       bool operator==(const Edge i) const {return id==i.id;}
   446       bool operator!=(const Edge i) const {return id!=i.id;}
   447       bool operator<(const Edge i) const {return id<i.id;}
   448     };
   449 
   450     void construct(int upperNodeNum, int lowerNodeNum) {
   451       _upperNodeNum = upperNodeNum;
   452       _lowerNodeNum = lowerNodeNum;
   453       _edgeNum = upperNodeNum * lowerNodeNum;
   454     }
   455 
   456     void firstUpper(Node& node) const {
   457       node.id = 2 * _upperNodeNum - 2;
   458       if (node.id < 0) node.id = -1; 
   459     }
   460     void nextUpper(Node& node) const {
   461       node.id -= 2;
   462       if (node.id < 0) node.id = -1; 
   463     }
   464 
   465     void firstLower(Node& node) const {
   466       node.id = 2 * _lowerNodeNum - 1;
   467     }
   468     void nextLower(Node& node) const {
   469       node.id -= 2;
   470     }
   471 
   472     void first(Node& node) const {
   473       if (_upperNodeNum > 0) {
   474 	node.id = 2 * _upperNodeNum - 2;
   475       } else {
   476 	node.id = 2 * _lowerNodeNum - 1;
   477       }
   478     }
   479     void next(Node& node) const {
   480       node.id -= 2;
   481       if (node.id == -2) {
   482 	node.id = 2 * _lowerNodeNum - 1;
   483       }
   484     }
   485   
   486     void first(Edge& edge) const {
   487       edge.id = _edgeNum - 1;
   488     }
   489     void next(Edge& edge) const {
   490       --edge.id;
   491     }
   492 
   493     void firstDown(Edge& edge, const Node& node) const {
   494       LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
   495       edge.id = (node.id >> 1) * _lowerNodeNum;
   496     }
   497     void nextDown(Edge& edge) const {
   498       ++(edge.id);
   499       if (edge.id % _lowerNodeNum == 0) edge.id = -1;
   500     }
   501 
   502     void firstUp(Edge& edge, const Node& node) const {
   503       LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
   504       edge.id = (node.id >> 1);
   505     }
   506     void nextUp(Edge& edge) const {
   507       edge.id += _lowerNodeNum;
   508       if (edge.id >= _edgeNum) edge.id = -1;
   509     }
   510 
   511     static int id(const Node& node) {
   512       return node.id;
   513     }
   514     static Node nodeFromId(int id) {
   515       return Node(id);
   516     }
   517     int maxNodeId() const {
   518       return _upperNodeNum > _lowerNodeNum ? 
   519 	_upperNodeNum * 2 - 2 : _lowerNodeNum * 2 - 1;
   520     }
   521   
   522     static int id(const Edge& edge) {
   523       return edge.id;
   524     }
   525     static Edge edgeFromId(int id) {
   526       return Edge(id);
   527     }
   528     int maxEdgeId() const {
   529       return _edgeNum - 1;
   530     }
   531   
   532     static int upperId(const Node& node) {
   533       return node.id >> 1;
   534     }
   535     static Node fromUpperId(int id, Node) {
   536       return Node(id << 1);
   537     }
   538     int maxUpperId() const {
   539       return _upperNodeNum;
   540     }
   541 
   542     static int lowerId(const Node& node) {
   543       return node.id >> 1;
   544     }
   545     static Node fromLowerId(int id) {
   546       return Node((id << 1) + 1);
   547     }
   548     int maxLowerId() const {
   549       return _lowerNodeNum;
   550     }
   551 
   552     Node upperNode(const Edge& edge) const {
   553       return Node((edge.id / _lowerNodeNum) << 1);
   554     }
   555     Node lowerNode(const Edge& edge) const {
   556       return Node(((edge.id % _lowerNodeNum) << 1) + 1);
   557     }
   558 
   559     static bool upper(const Node& node) {
   560       return (node.id & 1) == 0;
   561     }
   562 
   563     static bool lower(const Node& node) {
   564       return (node.id & 1) == 1;
   565     }
   566 
   567     static Node upperNode(int index) {
   568       return Node(index << 1);
   569     }
   570 
   571     static Node lowerNode(int index) {
   572       return Node((index << 1) + 1);
   573     }
   574 
   575   };
   576 
   577 
   578   typedef StaticMappableUndirBipartiteGraphExtender<
   579     IterableUndirBipartiteGraphExtender<
   580     AlterableUndirBipartiteGraphExtender<
   581     UndirBipartiteGraphExtender <
   582     FullUndirBipartiteGraphBase> > > >
   583   ExtendedFullUndirBipartiteGraphBase;
   584 
   585 
   586   class FullUndirBipartiteGraph : 
   587     public ExtendedFullUndirBipartiteGraphBase {
   588   public:
   589     typedef ExtendedFullUndirBipartiteGraphBase Parent;
   590     FullUndirBipartiteGraph(int upperNodeNum, int lowerNodeNum) {
   591       Parent::construct(upperNodeNum, lowerNodeNum);
   592     }
   593   };
   594 
   595 } //namespace lemon
   596 
   597 
   598 #endif //LEMON_FULL_GRAPH_H