lemon/matrix_graph.h
author ladanyi
Fri, 29 Jul 2005 12:01:37 +0000
changeset 1606 dc4ea2010dee
parent 1590 ba2cb5006358
permissions -rw-r--r--
added support for saving files
deba@1567
     1
/* -*- C++ -*-
deba@1567
     2
 * lemon/matrix_graph.h - Part of LEMON, a generic C++ optimization library
deba@1567
     3
 *
deba@1567
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1567
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1567
     6
 *
deba@1567
     7
 * Permission to use, modify and distribute this software is granted
deba@1567
     8
 * provided that this copyright notice appears in all copies. For
deba@1567
     9
 * precise terms see the accompanying LICENSE file.
deba@1567
    10
 *
deba@1567
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1567
    12
 * express or implied, and with no claim as to its suitability for any
deba@1567
    13
 * purpose.
deba@1567
    14
 *
deba@1567
    15
 */
deba@1567
    16
deba@1567
    17
#ifndef MATRIX_GRAPH_H
deba@1567
    18
#define MATRIX_GRAPH_H
deba@1567
    19
deba@1567
    20
#include <iostream>
deba@1567
    21
#include <lemon/invalid.h>
deba@1567
    22
#include <lemon/utility.h>
deba@1567
    23
deba@1567
    24
#include <lemon/bits/iterable_graph_extender.h>
deba@1567
    25
#include <lemon/bits/alteration_notifier.h>
deba@1567
    26
#include <lemon/bits/default_map.h>
deba@1567
    27
deba@1567
    28
#include <lemon/bits/undir_graph_extender.h>
deba@1567
    29
deba@1567
    30
namespace lemon {
deba@1567
    31
deba@1567
    32
  class MatrixGraphBase {
deba@1567
    33
deba@1567
    34
  public:
deba@1567
    35
deba@1567
    36
    typedef MatrixGraphBase Graph;
deba@1567
    37
deba@1567
    38
    class Node;
deba@1567
    39
    class Edge;
deba@1567
    40
deba@1567
    41
  public:
deba@1567
    42
deba@1567
    43
    MatrixGraphBase() {}
deba@1567
    44
deba@1567
    45
    ///Creates a full graph with \c n nodes.
deba@1567
    46
    void construct(int height, int width) {
deba@1567
    47
      _height = height; _width = width;
deba@1567
    48
      _nodeNum = height * width; _edgeNum = 2 * _nodeNum - width - height;
deba@1567
    49
      _edgeLimit = _nodeNum - width;
deba@1567
    50
    }
deba@1567
    51
    
deba@1567
    52
    Node operator()(int i, int j) const {
deba@1567
    53
      return Node(i * _width + j);
deba@1567
    54
    }
deba@1567
    55
deba@1567
    56
    int width() const {
deba@1567
    57
      return _width;
deba@1567
    58
    }
deba@1567
    59
deba@1567
    60
    int height() const {
deba@1567
    61
      return _height;
deba@1567
    62
    }
deba@1567
    63
deba@1567
    64
    typedef True NodeNumTag;
deba@1567
    65
    typedef True EdgeNumTag;
deba@1567
    66
deba@1567
    67
    ///Number of nodes.
deba@1567
    68
    int nodeNum() const { return _nodeNum; }
deba@1567
    69
    ///Number of edges.
deba@1567
    70
    int edgeNum() const { return _edgeNum; }
deba@1567
    71
deba@1567
    72
    /// Maximum node ID.
deba@1567
    73
    
deba@1567
    74
    /// Maximum node ID.
deba@1567
    75
    ///\sa id(Node)
deba@1567
    76
    int maxId(Node = INVALID) const { return nodeNum() - 1; }
deba@1567
    77
    /// Maximum edge ID.
deba@1567
    78
    
deba@1567
    79
    /// Maximum edge ID.
deba@1567
    80
    ///\sa id(Edge)
deba@1567
    81
    int maxId(Edge = INVALID) const { return edgeNum() - 1; }
deba@1567
    82
deba@1567
    83
    Node source(Edge e) const {
deba@1567
    84
      if (e.id < _edgeLimit) {
deba@1567
    85
	return e.id;
deba@1567
    86
      } else {
deba@1567
    87
	return (e.id - _edgeLimit) % (_width - 1) +
deba@1567
    88
	  (e.id - _edgeLimit) / (_width - 1) * _width;
deba@1567
    89
      }
deba@1567
    90
    }
deba@1567
    91
deba@1567
    92
    Node target(Edge e) const {
deba@1567
    93
      if (e.id < _edgeLimit) {
deba@1567
    94
	return e.id + _width;
deba@1567
    95
      } else {
deba@1567
    96
	return (e.id - _edgeLimit) % (_width - 1) +
deba@1567
    97
	  (e.id - _edgeLimit) / (_width - 1) * _width + 1;
deba@1567
    98
      }
deba@1567
    99
    }
deba@1567
   100
deba@1567
   101
    /// Node ID.
deba@1567
   102
    
deba@1567
   103
    /// The ID of a valid Node is a nonnegative integer not greater than
deba@1567
   104
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
deba@1567
   105
    /// and the greatest node ID can be actually less then \ref maxNodeId().
deba@1567
   106
    ///
deba@1567
   107
    /// The ID of the \ref INVALID node is -1.
deba@1567
   108
    ///\return The ID of the node \c v. 
deba@1567
   109
deba@1567
   110
    static int id(Node v) { return v.id; }
deba@1567
   111
    /// Edge ID.
deba@1567
   112
    
deba@1567
   113
    /// The ID of a valid Edge is a nonnegative integer not greater than
deba@1567
   114
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
deba@1567
   115
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
deba@1567
   116
    ///
deba@1567
   117
    /// The ID of the \ref INVALID edge is -1.
deba@1567
   118
    ///\return The ID of the edge \c e. 
deba@1567
   119
    static int id(Edge e) { return e.id; }
deba@1567
   120
deba@1567
   121
    static Node fromId(int id, Node) { return Node(id);}
deba@1567
   122
    
deba@1567
   123
    static Edge fromId(int id, Edge) { return Edge(id);}
deba@1567
   124
deba@1567
   125
    typedef True FindEdgeTag;
deba@1567
   126
deba@1567
   127
    /// Finds an edge between two nodes.
deba@1567
   128
    
deba@1567
   129
    /// Finds an edge from node \c u to node \c v.
deba@1567
   130
    ///
deba@1567
   131
    /// If \c prev is \ref INVALID (this is the default value), then
deba@1567
   132
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
deba@1567
   133
    /// the next edge from \c u to \c v after \c prev.
deba@1567
   134
    /// \return The found edge or INVALID if there is no such an edge.
deba@1567
   135
    Edge findEdge(Node u, Node v, Edge prev = INVALID) {
deba@1567
   136
      if (prev != INVALID) return INVALID;
deba@1567
   137
      if (v.id - u.id == _width) return Edge(u.id);
deba@1567
   138
      if (v.id - u.id == 1 && u.id % _width < _width - 1) {
deba@1567
   139
	return Edge(u.id / _width * (_width - 1) +
deba@1567
   140
		    u.id % _width + _edgeLimit);
deba@1567
   141
      }
deba@1567
   142
      return INVALID;
deba@1567
   143
    }
deba@1567
   144
    
deba@1567
   145
      
deba@1567
   146
    class Node {
deba@1567
   147
      friend class MatrixGraphBase;
deba@1567
   148
deba@1567
   149
    protected:
deba@1567
   150
      int id;
deba@1567
   151
      Node(int _id) { id = _id;}
deba@1567
   152
    public:
deba@1567
   153
      Node() {}
deba@1567
   154
      Node (Invalid) { id = -1; }
deba@1567
   155
      bool operator==(const Node node) const {return id == node.id;}
deba@1567
   156
      bool operator!=(const Node node) const {return id != node.id;}
deba@1567
   157
      bool operator<(const Node node) const {return id < node.id;}
deba@1567
   158
    };
deba@1567
   159
    
deba@1567
   160
deba@1567
   161
deba@1567
   162
    class Edge {
deba@1567
   163
      friend class MatrixGraphBase;
deba@1567
   164
      
deba@1567
   165
    protected:
deba@1567
   166
      int id; 
deba@1567
   167
deba@1567
   168
      Edge(int _id) : id(_id) {}
deba@1567
   169
deba@1567
   170
    public:
deba@1567
   171
      Edge() { }
deba@1567
   172
      Edge (Invalid) { id = -1; }
deba@1567
   173
      bool operator==(const Edge edge) const {return id == edge.id;}
deba@1567
   174
      bool operator!=(const Edge edge) const {return id != edge.id;}
deba@1567
   175
      bool operator<(const Edge edge) const {return id < edge.id;}
deba@1567
   176
    };
deba@1567
   177
deba@1567
   178
    void first(Node& node) const {
deba@1567
   179
      node.id = nodeNum() - 1;
deba@1567
   180
    }
deba@1567
   181
deba@1567
   182
    static void next(Node& node) {
deba@1567
   183
      --node.id;
deba@1567
   184
    }
deba@1567
   185
deba@1567
   186
    void first(Edge& edge) const {
deba@1567
   187
      edge.id = edgeNum() - 1;
deba@1567
   188
    }
deba@1567
   189
deba@1567
   190
    static void next(Edge& edge) {
deba@1567
   191
      --edge.id;
deba@1567
   192
    }
deba@1567
   193
deba@1567
   194
    void firstOut(Edge& edge, const Node& node) const {
deba@1567
   195
      if (node.id < _nodeNum - _width) {
deba@1567
   196
	edge.id = node.id;
deba@1567
   197
      } else if (node.id % _width < _width - 1) {
deba@1567
   198
	edge.id = _edgeLimit + node.id % _width +
deba@1567
   199
	  (node.id / _width) * (_width - 1);
deba@1567
   200
      } else {
deba@1567
   201
	edge.id = -1;
deba@1567
   202
      }
deba@1567
   203
    }
deba@1567
   204
deba@1567
   205
    void nextOut(Edge& edge) const {
deba@1567
   206
      if (edge.id >= _edgeLimit) {
deba@1567
   207
	edge.id = -1;
deba@1567
   208
      } else if (edge.id % _width < _width - 1) {
deba@1567
   209
	edge.id = _edgeLimit + edge.id % _width +
deba@1567
   210
	  (edge.id / _width) * (_width - 1);
deba@1567
   211
      } else {
deba@1567
   212
	edge.id = -1;
deba@1567
   213
      }
deba@1567
   214
    }
deba@1567
   215
deba@1567
   216
    void firstIn(Edge& edge, const Node& node) const {
deba@1567
   217
      if (node.id >= _width) {
deba@1567
   218
	edge.id = node.id - _width;
deba@1567
   219
      } else if (node.id % _width > 0) {
deba@1567
   220
	edge.id = _edgeLimit + node.id % _width +
deba@1567
   221
	  (node.id / _width) * (_width - 1) - 1;
deba@1567
   222
      } else {
deba@1567
   223
	edge.id = -1;
deba@1567
   224
      }
deba@1567
   225
    }
deba@1567
   226
    
deba@1567
   227
    void nextIn(Edge& edge) const {
deba@1567
   228
      if (edge.id >= _edgeLimit) {
deba@1567
   229
	edge.id = -1;
deba@1567
   230
      } else if (edge.id % _width > 0) {
deba@1567
   231
	edge.id = _edgeLimit + edge.id % _width +
deba@1567
   232
	  (edge.id / _width + 1) * (_width - 1) - 1;
deba@1567
   233
      } else {
deba@1567
   234
	edge.id = -1;
deba@1567
   235
      }
deba@1567
   236
    }
deba@1567
   237
deba@1567
   238
  private:
deba@1567
   239
    int _width, _height;
deba@1567
   240
    int _nodeNum, _edgeNum;
deba@1567
   241
    int _edgeLimit;
deba@1567
   242
  };
deba@1567
   243
deba@1567
   244
deba@1567
   245
  typedef UndirGraphExtender<MatrixGraphBase>
deba@1567
   246
  UndirMatrixGraphBase;
deba@1567
   247
  typedef AlterableUndirGraphExtender<UndirMatrixGraphBase> 
deba@1567
   248
  AlterableMatrixGraphBase;
deba@1567
   249
  typedef IterableUndirGraphExtender<AlterableMatrixGraphBase> 
deba@1567
   250
  IterableMatrixGraphBase;
deba@1567
   251
  typedef MappableUndirGraphExtender<IterableMatrixGraphBase> 
deba@1567
   252
  MappableMatrixGraphBase;
deba@1567
   253
deba@1567
   254
  /// \ingroup graphs
deba@1567
   255
  ///
deba@1567
   256
  /// \brief Matrix graph class
deba@1567
   257
  ///
deba@1567
   258
  /// This class implements a special graph type. The nodes of the
deba@1567
   259
  /// graph can be indiced by two integer \c (i,j) value where \c i
deba@1567
   260
  /// is in the \c [0,height) range and j is in the [0, width) range.
deba@1567
   261
  /// Two nodes are connected in the graph if the indices differ only
deba@1567
   262
  /// on one position and only one is the difference. 
deba@1567
   263
  ///
alpar@1591
   264
  /// The graph can be indiced in the following way:
deba@1567
   265
  /// \code
deba@1567
   266
  /// MatrixGraph graph(h, w);
deba@1567
   267
  /// MatrixGraph::NodeMap<int> val(graph); 
deba@1567
   268
  /// for (int i = 0; i < graph.height(); ++i) {
deba@1567
   269
  ///   for (int j = 0; j < graph.width(); ++j) {
deba@1567
   270
  ///     val[graph(i, j)] = i + j;
deba@1567
   271
  ///   }
deba@1567
   272
  /// }
deba@1567
   273
  /// \endcode
deba@1567
   274
  ///
deba@1567
   275
  /// The graph type is fully conform to the \ref concept::UndirGraph
deba@1567
   276
  /// "Undirected Graph" concept.
deba@1567
   277
  ///
deba@1567
   278
  /// \author Balazs Dezso
deba@1567
   279
  class MatrixGraph : public MappableMatrixGraphBase {
deba@1567
   280
  public:
deba@1567
   281
    
deba@1567
   282
    MatrixGraph(int m, int n) { construct(m, n); }
deba@1567
   283
  };
deba@1567
   284
}
deba@1567
   285
#endif