lemon/topology.h
author deba
Mon, 24 Oct 2005 17:03:02 +0000
changeset 1740 4cade8579363
parent 1739 b1385f5da81b
child 1750 5c76ebbb4818
permissions -rw-r--r--
Bug fix in connectedComponents
Strongly connected components
deba@1698
     1
/* -*- C++ -*-
deba@1698
     2
 * lemon/topology.h - Part of LEMON, a generic C++ optimization library
deba@1698
     3
 *
deba@1698
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1698
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1698
     6
 *
deba@1698
     7
 * Permission to use, modify and distribute this software is granted
deba@1698
     8
 * provided that this copyright notice appears in all copies. For
deba@1698
     9
 * precise terms see the accompanying LICENSE file.
deba@1698
    10
 *
deba@1698
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1698
    12
 * express or implied, and with no claim as to its suitability for any
deba@1698
    13
 * purpose.
deba@1698
    14
 *
deba@1698
    15
 */
deba@1698
    16
deba@1698
    17
#ifndef LEMON_TOPOLOGY_H
deba@1698
    18
#define LEMON_TOPOLOGY_H
deba@1698
    19
deba@1698
    20
#include <lemon/dfs.h>
deba@1740
    21
#include <lemon/bfs.h>
deba@1698
    22
#include <lemon/graph_utils.h>
deba@1698
    23
deba@1698
    24
#include <lemon/concept/graph.h>
deba@1698
    25
#include <lemon/concept/undir_graph.h>
deba@1698
    26
#include <lemon/concept_check.h>
deba@1698
    27
deba@1698
    28
/// \ingroup flowalgs
deba@1698
    29
/// \file
deba@1698
    30
/// \brief Topology related algorithms
deba@1698
    31
///
deba@1698
    32
/// Topology related algorithms
alpar@1739
    33
///\todo Place the file contents is the module tree.
deba@1698
    34
deba@1698
    35
namespace lemon {
deba@1698
    36
deba@1698
    37
  namespace _topology_bits {
deba@1698
    38
    
deba@1698
    39
    template <typename NodeMap>
deba@1698
    40
    class BackCounterMap {
deba@1698
    41
    public:
deba@1698
    42
      BackCounterMap(NodeMap& _nodeMap, int _counter)
deba@1698
    43
	: nodeMap(_nodeMap), counter(_counter) {}
deba@1698
    44
deba@1698
    45
      void set(typename NodeMap::Key key, bool val) {
deba@1698
    46
	if (val) {
deba@1698
    47
	  nodeMap.set(key, --counter);
deba@1698
    48
	} else {
deba@1698
    49
	  nodeMap.set(key, -1);
deba@1698
    50
	}
deba@1698
    51
      }
deba@1698
    52
deba@1698
    53
      bool operator[](typename NodeMap::Key key) const {
deba@1698
    54
	return nodeMap[key] != -1;
deba@1698
    55
      }
deba@1698
    56
deba@1698
    57
    private:
deba@1698
    58
      NodeMap& nodeMap;
deba@1698
    59
      int counter;
deba@1698
    60
    };
deba@1698
    61
  }
deba@1698
    62
deba@1698
    63
  // \todo Its to special output // ReadWriteMap
deba@1698
    64
  template <typename Graph, typename NodeMap>
deba@1698
    65
  bool topological_sort(const Graph& graph, NodeMap& nodeMap) {
deba@1698
    66
    using namespace _topology_bits;
deba@1698
    67
deba@1698
    68
    checkConcept<concept::StaticGraph, Graph>();
deba@1698
    69
    checkConcept<concept::ReadWriteMap<typename Graph::Node, int>, NodeMap>();
deba@1698
    70
deba@1698
    71
    typedef typename Graph::Node Node;
deba@1698
    72
    typedef typename Graph::NodeIt NodeIt;
deba@1698
    73
    typedef typename Graph::Edge Edge;
deba@1698
    74
deba@1698
    75
    typedef BackCounterMap<NodeMap> ProcessedMap;
deba@1698
    76
deba@1698
    77
    typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
deba@1709
    78
      Create dfs(graph);
deba@1698
    79
deba@1698
    80
    ProcessedMap processed(nodeMap, countNodes(graph));
deba@1698
    81
deba@1698
    82
    dfs.processedMap(processed);
deba@1698
    83
    dfs.init();
deba@1698
    84
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
    85
      if (!dfs.reached(it)) {
deba@1698
    86
	dfs.addSource(it);
deba@1698
    87
	while (!dfs.emptyQueue()) {
deba@1698
    88
	  Edge edge = dfs.nextEdge();
deba@1698
    89
	  Node target = graph.target(edge);
deba@1698
    90
	  if (dfs.reached(target) && !processed[target]) {
deba@1698
    91
	    return false;
deba@1698
    92
	  }
deba@1698
    93
	  dfs.processNextEdge();
deba@1698
    94
	}
deba@1698
    95
      }
deba@1698
    96
    }    
deba@1698
    97
    return true;
deba@1698
    98
  }
deba@1698
    99
deba@1698
   100
  /// \brief Check that the given graph is a DAG.
deba@1698
   101
  ///
deba@1698
   102
  /// Check that the given graph is a DAG. The DAG is
deba@1698
   103
  /// an Directed Acyclic Graph.
deba@1698
   104
  template <typename Graph>
deba@1698
   105
  bool dag(const Graph& graph) {
deba@1698
   106
deba@1698
   107
    checkConcept<concept::StaticGraph, Graph>();
deba@1698
   108
deba@1698
   109
    typedef typename Graph::Node Node;
deba@1698
   110
    typedef typename Graph::NodeIt NodeIt;
deba@1698
   111
    typedef typename Graph::Edge Edge;
deba@1698
   112
deba@1698
   113
    typedef typename Graph::template NodeMap<bool> ProcessedMap;
deba@1698
   114
deba@1698
   115
    typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
deba@1709
   116
      Create dfs(graph);
deba@1698
   117
deba@1698
   118
    ProcessedMap processed(graph);
deba@1698
   119
    dfs.processedMap(processed);
deba@1698
   120
deba@1698
   121
    dfs.init();
deba@1698
   122
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   123
      if (!dfs.reached(it)) {
deba@1698
   124
	dfs.addSource(it);
deba@1698
   125
	while (!dfs.emptyQueue()) {
deba@1698
   126
	  Edge edge = dfs.nextEdge();
deba@1698
   127
	  Node target = graph.target(edge);
deba@1698
   128
	  if (dfs.reached(target) && !processed[target]) {
deba@1698
   129
	    return false;
deba@1698
   130
	  }
deba@1698
   131
	  dfs.processNextEdge();
deba@1698
   132
	}
deba@1698
   133
      }
deba@1698
   134
    }    
deba@1698
   135
    return true;
deba@1698
   136
  }
deba@1698
   137
deba@1698
   138
  // UndirGraph algorithms
deba@1698
   139
deba@1698
   140
  /// \brief Check that the given undirected graph is connected.
deba@1698
   141
  ///
deba@1698
   142
  /// Check that the given undirected graph connected.
deba@1698
   143
  template <typename UndirGraph>
deba@1698
   144
  bool connected(const UndirGraph& graph) {
deba@1698
   145
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
   146
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
   147
    if (NodeIt(graph) == INVALID) return false;
deba@1698
   148
    Dfs<UndirGraph> dfs(graph);
deba@1698
   149
    dfs.run(NodeIt(graph));
deba@1698
   150
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   151
      if (!dfs.reached(it)) {
deba@1698
   152
	return false;
deba@1698
   153
      }
deba@1698
   154
    }
deba@1698
   155
    return true;
deba@1698
   156
  }
deba@1698
   157
deba@1698
   158
  /// \brief Check that the given undirected graph is acyclic.
deba@1698
   159
  ///
deba@1698
   160
  /// Check that the given undirected graph acyclic.
deba@1698
   161
  template <typename UndirGraph>
deba@1698
   162
  bool acyclic(const UndirGraph& graph) {
deba@1698
   163
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
   164
    typedef typename UndirGraph::Node Node;
deba@1698
   165
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
   166
    typedef typename UndirGraph::Edge Edge;
deba@1698
   167
    Dfs<UndirGraph> dfs(graph);
deba@1698
   168
    dfs.init();
deba@1698
   169
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   170
      if (!dfs.reached(it)) {
deba@1698
   171
	dfs.addSource(it);
deba@1698
   172
	while (!dfs.emptyQueue()) {
deba@1698
   173
	  Edge edge = dfs.nextEdge();
deba@1698
   174
	  Node source = graph.source(edge);
deba@1698
   175
	  Node target = graph.target(edge);
deba@1698
   176
	  if (dfs.reached(target) && 
deba@1698
   177
	      dfs.pred(source) != graph.oppositeEdge(edge)) {
deba@1698
   178
	    return false;
deba@1698
   179
	  }
deba@1698
   180
	  dfs.processNextEdge();
deba@1698
   181
	}
deba@1698
   182
      }
deba@1698
   183
    }
deba@1698
   184
    return true;
deba@1698
   185
  }
deba@1698
   186
deba@1698
   187
  /// \brief Check that the given undirected graph is tree.
deba@1698
   188
  ///
deba@1698
   189
  /// Check that the given undirected graph is tree.
deba@1698
   190
  template <typename UndirGraph>
deba@1698
   191
  bool tree(const UndirGraph& graph) {
deba@1698
   192
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
   193
    typedef typename UndirGraph::Node Node;
deba@1698
   194
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
   195
    typedef typename UndirGraph::Edge Edge;
deba@1698
   196
    if (NodeIt(graph) == INVALID) return false;
deba@1698
   197
    Dfs<UndirGraph> dfs(graph);
deba@1698
   198
    dfs.init();
deba@1698
   199
    dfs.addSource(NodeIt(graph));
deba@1698
   200
    while (!dfs.emptyQueue()) {
deba@1698
   201
      Edge edge = dfs.nextEdge();
deba@1698
   202
      Node source = graph.source(edge);
deba@1698
   203
      Node target = graph.target(edge);
deba@1698
   204
      if (dfs.reached(target) && 
deba@1698
   205
	  dfs.pred(source) != graph.oppositeEdge(edge)) {
deba@1698
   206
	return false;
deba@1698
   207
      }
deba@1698
   208
      dfs.processNextEdge();
deba@1698
   209
    }
deba@1698
   210
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   211
      if (!dfs.reached(it)) {
deba@1698
   212
	return false;
deba@1698
   213
      }
deba@1698
   214
    }    
deba@1698
   215
    return true;
deba@1698
   216
  }
deba@1698
   217
 
alpar@1739
   218
  ///Count the number of connected components of an undirected graph
alpar@1739
   219
alpar@1739
   220
  ///Count the number of connected components of an undirected graph
alpar@1739
   221
  ///
alpar@1739
   222
  ///\param g The graph. In must be undirected.
alpar@1739
   223
  ///\return The number of components
deba@1740
   224
  template <class UndirGraph>
deba@1740
   225
  int countConnectedComponents(const UndirGraph &g) {
deba@1740
   226
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1740
   227
    int c = 0;
deba@1740
   228
    Bfs<UndirGraph> bfs(g);
alpar@1739
   229
    bfs.init();
deba@1740
   230
    for(typename UndirGraph::NodeIt n(g); n != INVALID; ++n) {
alpar@1739
   231
      if(!bfs.reached(n)) {
alpar@1739
   232
	bfs.addSource(n);
alpar@1739
   233
	bfs.start();
deba@1740
   234
	++c;
alpar@1739
   235
      }
deba@1740
   236
    }
alpar@1739
   237
    return c;
alpar@1739
   238
  }
alpar@1739
   239
alpar@1739
   240
alpar@1739
   241
  ///Find the connected components of an undirected graph
alpar@1739
   242
alpar@1739
   243
  ///Find the connected components of an undirected graph
alpar@1739
   244
  ///
alpar@1739
   245
  ///\param g The graph. In must be undirected.
alpar@1739
   246
  ///\retval comp A writable node map. The values will be set from 0 to
alpar@1739
   247
  ///the number of the connected components minus one. Each values of the map
alpar@1739
   248
  ///will be set exactly once, the values of a certain component will be
alpar@1739
   249
  ///set continuously.
alpar@1739
   250
  ///\return The number of components
alpar@1739
   251
  ///\todo Test required
deba@1740
   252
  template <class UndirGraph, class IntNodeMap>
deba@1740
   253
  int connectedComponents(const UndirGraph &g, IntNodeMap &comp) {
deba@1740
   254
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1740
   255
    checkConcept<concept::WriteMap<typename UndirGraph::Node, int>, 
deba@1740
   256
      IntNodeMap>();
deba@1740
   257
    int c = 0;
deba@1740
   258
    Bfs<UndirGraph> bfs(g);
alpar@1739
   259
    bfs.init();
deba@1740
   260
    for(typename UndirGraph::NodeIt n(g); n != INVALID; ++n) {
alpar@1739
   261
      if(!bfs.reached(n)) {
alpar@1739
   262
	bfs.addSource(n);
deba@1740
   263
	while (!bfs.emptyQueue()) {
deba@1740
   264
	  comp[bfs.nextNode()] = c;
deba@1740
   265
	  bfs.processNextNode();
deba@1740
   266
	}
deba@1740
   267
	++c;
alpar@1739
   268
      }
deba@1740
   269
    }
alpar@1739
   270
    return c;
alpar@1739
   271
  }
deba@1698
   272
deba@1740
   273
  namespace _components_bits {
deba@1740
   274
deba@1740
   275
    template <typename Key, typename IntMap>
deba@1740
   276
    struct FillWriteMap : public MapBase<Key, bool> {
deba@1740
   277
    public:
deba@1740
   278
      FillWriteMap(IntMap& _map, int& _comp) 
deba@1740
   279
	: map(_map), comp(_comp) {}
deba@1740
   280
      void set(Key key, bool value) {
deba@1740
   281
	if (value) { map.set(key, comp); }
deba@1740
   282
      }
deba@1740
   283
    private:
deba@1740
   284
      IntMap& map;
deba@1740
   285
      int& comp;
deba@1740
   286
    };
deba@1740
   287
deba@1740
   288
    template <typename Key, typename Container = std::vector<Key> >
deba@1740
   289
    struct BackInserterWriteMap : public MapBase<Key, bool> {
deba@1740
   290
    public:
deba@1740
   291
      BackInserterWriteMap(Container& _container) 
deba@1740
   292
	: container(_container) {}
deba@1740
   293
      void set(Key key, bool value) {
deba@1740
   294
	if (value) { container.push_back(key); }
deba@1740
   295
      }
deba@1740
   296
    private:
deba@1740
   297
      Container& container;
deba@1740
   298
    };
deba@1740
   299
deba@1740
   300
  }
deba@1740
   301
deba@1740
   302
  /// \brief Count the strongly connected components of a directed graph
deba@1740
   303
  ///
deba@1740
   304
  /// Count the strongly connected components of a directed graph
deba@1740
   305
  ///
deba@1740
   306
  /// \param g The graph.
deba@1740
   307
  /// \return The number of components
deba@1740
   308
  template <typename Graph>
deba@1740
   309
  int countStronglyConnectedComponents(const Graph& graph) {
deba@1740
   310
    checkConcept<concept::StaticGraph, Graph>();
deba@1740
   311
deba@1740
   312
    using namespace _components_bits;
deba@1740
   313
deba@1740
   314
    typedef typename Graph::Node Node;
deba@1740
   315
    typedef typename Graph::Edge Edge;
deba@1740
   316
    typedef typename Graph::NodeIt NodeIt;
deba@1740
   317
    typedef typename Graph::EdgeIt EdgeIt;
deba@1740
   318
    
deba@1740
   319
deba@1740
   320
    typename Dfs<Graph>::
deba@1740
   321
      template DefProcessedMap<BackInserterWriteMap<Node> >::
deba@1740
   322
      Create dfs(graph);
deba@1740
   323
deba@1740
   324
    std::vector<Node> nodes;
deba@1740
   325
    BackInserterWriteMap<Node> processed(nodes);
deba@1740
   326
    dfs.processedMap(processed);
deba@1740
   327
deba@1740
   328
    dfs.init();
deba@1740
   329
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1740
   330
      if (!dfs.reached(it)) {
deba@1740
   331
	dfs.addSource(it);
deba@1740
   332
	dfs.start();
deba@1740
   333
      }
deba@1740
   334
    }
deba@1740
   335
deba@1740
   336
    typedef RevGraphAdaptor<const Graph> RGraph;
deba@1740
   337
deba@1740
   338
    RGraph rgraph(graph);
deba@1740
   339
deba@1740
   340
    Dfs<RGraph> rdfs(rgraph);
deba@1740
   341
deba@1740
   342
    int num = 0;
deba@1740
   343
deba@1740
   344
    rdfs.init();
deba@1740
   345
    for (typename std::vector<Node>::reverse_iterator 
deba@1740
   346
	   it = nodes.rbegin(); it != nodes.rend(); ++it) {
deba@1740
   347
      if (!rdfs.reached(*it)) {
deba@1740
   348
	rdfs.addSource(*it);
deba@1740
   349
	rdfs.start();
deba@1740
   350
	++num;
deba@1740
   351
      }
deba@1740
   352
    }
deba@1740
   353
    return num;
deba@1740
   354
  }
deba@1740
   355
deba@1740
   356
  /// \brief Find the strongly connected components of a directed graph
deba@1740
   357
  ///
deba@1740
   358
  /// Find the strongly connected components of a directed graph
deba@1740
   359
  ///
deba@1740
   360
  /// \param g The graph.
deba@1740
   361
  /// \retval comp A writable node map. The values will be set from 0 to
deba@1740
   362
  /// the number of the strongly connected components minus one. Each values 
deba@1740
   363
  /// of the map will be set exactly once, the values of a certain component 
deba@1740
   364
  /// will be set continuously.
deba@1740
   365
  /// \return The number of components
deba@1740
   366
  template <typename Graph, typename IntNodeMap>
deba@1740
   367
  int stronglyConnectedComponents(const Graph& graph, IntNodeMap& comp) {
deba@1740
   368
    checkConcept<concept::StaticGraph, Graph>();
deba@1740
   369
    checkConcept<concept::WriteMap<typename Graph::Node, int>, IntNodeMap>();
deba@1740
   370
deba@1740
   371
    using namespace _components_bits;
deba@1740
   372
deba@1740
   373
    typedef typename Graph::Node Node;
deba@1740
   374
    typedef typename Graph::Edge Edge;
deba@1740
   375
    typedef typename Graph::NodeIt NodeIt;
deba@1740
   376
    typedef typename Graph::EdgeIt EdgeIt;
deba@1740
   377
    
deba@1740
   378
deba@1740
   379
    typename Dfs<Graph>::
deba@1740
   380
      template DefProcessedMap<BackInserterWriteMap<Node> >::
deba@1740
   381
      Create dfs(graph);
deba@1740
   382
deba@1740
   383
    std::vector<Node> nodes;
deba@1740
   384
    BackInserterWriteMap<Node> processed(nodes);
deba@1740
   385
    dfs.processedMap(processed);
deba@1740
   386
deba@1740
   387
    dfs.init();
deba@1740
   388
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1740
   389
      if (!dfs.reached(it)) {
deba@1740
   390
	dfs.addSource(it);
deba@1740
   391
	dfs.start();
deba@1740
   392
      }
deba@1740
   393
    }
deba@1740
   394
deba@1740
   395
    typedef RevGraphAdaptor<const Graph> RGraph;
deba@1740
   396
deba@1740
   397
    RGraph rgraph(graph);
deba@1740
   398
deba@1740
   399
    typename Dfs<RGraph>::
deba@1740
   400
      template DefProcessedMap<FillWriteMap<Node, IntNodeMap> >::
deba@1740
   401
      Create rdfs(rgraph);
deba@1740
   402
deba@1740
   403
    int num = 0;
deba@1740
   404
    FillWriteMap<Node, IntNodeMap> rprocessed(comp, num);
deba@1740
   405
    rdfs.processedMap(rprocessed);
deba@1740
   406
deba@1740
   407
    rdfs.init();
deba@1740
   408
    for (typename std::vector<Node>::reverse_iterator 
deba@1740
   409
	   it = nodes.rbegin(); it != nodes.rend(); ++it) {
deba@1740
   410
      if (!rdfs.reached(*it)) {
deba@1740
   411
	rdfs.addSource(*it);
deba@1740
   412
	rdfs.start();
deba@1740
   413
	++num;
deba@1740
   414
      }
deba@1740
   415
    }
deba@1740
   416
    return num;
deba@1740
   417
  }
deba@1740
   418
deba@1698
   419
} //namespace lemon
deba@1698
   420
deba@1698
   421
#endif //LEMON_TOPOLOGY_H