lemon/topology.h
author alpar
Mon, 24 Oct 2005 15:59:38 +0000
changeset 1739 b1385f5da81b
parent 1709 a323456bf7c8
child 1740 4cade8579363
permissions -rw-r--r--
Computing the number of the connected components and the components themselves.
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@1698
    21
#include <lemon/graph_utils.h>
deba@1698
    22
deba@1698
    23
#include <lemon/concept/graph.h>
deba@1698
    24
#include <lemon/concept/undir_graph.h>
deba@1698
    25
#include <lemon/concept_check.h>
deba@1698
    26
deba@1698
    27
/// \ingroup flowalgs
deba@1698
    28
/// \file
deba@1698
    29
/// \brief Topology related algorithms
deba@1698
    30
///
deba@1698
    31
/// Topology related algorithms
alpar@1739
    32
///\todo Place the file contents is the module tree.
deba@1698
    33
deba@1698
    34
namespace lemon {
deba@1698
    35
deba@1698
    36
  namespace _topology_bits {
deba@1698
    37
    
deba@1698
    38
    template <typename NodeMap>
deba@1698
    39
    class BackCounterMap {
deba@1698
    40
    public:
deba@1698
    41
      BackCounterMap(NodeMap& _nodeMap, int _counter)
deba@1698
    42
	: nodeMap(_nodeMap), counter(_counter) {}
deba@1698
    43
deba@1698
    44
      void set(typename NodeMap::Key key, bool val) {
deba@1698
    45
	if (val) {
deba@1698
    46
	  nodeMap.set(key, --counter);
deba@1698
    47
	} else {
deba@1698
    48
	  nodeMap.set(key, -1);
deba@1698
    49
	}
deba@1698
    50
      }
deba@1698
    51
deba@1698
    52
      bool operator[](typename NodeMap::Key key) const {
deba@1698
    53
	return nodeMap[key] != -1;
deba@1698
    54
      }
deba@1698
    55
deba@1698
    56
    private:
deba@1698
    57
      NodeMap& nodeMap;
deba@1698
    58
      int counter;
deba@1698
    59
    };
deba@1698
    60
  }
deba@1698
    61
deba@1698
    62
  // \todo Its to special output // ReadWriteMap
deba@1698
    63
  template <typename Graph, typename NodeMap>
deba@1698
    64
  bool topological_sort(const Graph& graph, NodeMap& nodeMap) {
deba@1698
    65
    using namespace _topology_bits;
deba@1698
    66
deba@1698
    67
    checkConcept<concept::StaticGraph, Graph>();
deba@1698
    68
    checkConcept<concept::ReadWriteMap<typename Graph::Node, int>, NodeMap>();
deba@1698
    69
deba@1698
    70
    typedef typename Graph::Node Node;
deba@1698
    71
    typedef typename Graph::NodeIt NodeIt;
deba@1698
    72
    typedef typename Graph::Edge Edge;
deba@1698
    73
deba@1698
    74
    typedef BackCounterMap<NodeMap> ProcessedMap;
deba@1698
    75
deba@1698
    76
    typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
deba@1709
    77
      Create dfs(graph);
deba@1698
    78
deba@1698
    79
    ProcessedMap processed(nodeMap, countNodes(graph));
deba@1698
    80
deba@1698
    81
    dfs.processedMap(processed);
deba@1698
    82
    dfs.init();
deba@1698
    83
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
    84
      if (!dfs.reached(it)) {
deba@1698
    85
	dfs.addSource(it);
deba@1698
    86
	while (!dfs.emptyQueue()) {
deba@1698
    87
	  Edge edge = dfs.nextEdge();
deba@1698
    88
	  Node target = graph.target(edge);
deba@1698
    89
	  if (dfs.reached(target) && !processed[target]) {
deba@1698
    90
	    return false;
deba@1698
    91
	  }
deba@1698
    92
	  dfs.processNextEdge();
deba@1698
    93
	}
deba@1698
    94
      }
deba@1698
    95
    }    
deba@1698
    96
    return true;
deba@1698
    97
  }
deba@1698
    98
deba@1698
    99
  /// \brief Check that the given graph is a DAG.
deba@1698
   100
  ///
deba@1698
   101
  /// Check that the given graph is a DAG. The DAG is
deba@1698
   102
  /// an Directed Acyclic Graph.
deba@1698
   103
  template <typename Graph>
deba@1698
   104
  bool dag(const Graph& graph) {
deba@1698
   105
deba@1698
   106
    checkConcept<concept::StaticGraph, Graph>();
deba@1698
   107
deba@1698
   108
    typedef typename Graph::Node Node;
deba@1698
   109
    typedef typename Graph::NodeIt NodeIt;
deba@1698
   110
    typedef typename Graph::Edge Edge;
deba@1698
   111
deba@1698
   112
    typedef typename Graph::template NodeMap<bool> ProcessedMap;
deba@1698
   113
deba@1698
   114
    typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
deba@1709
   115
      Create dfs(graph);
deba@1698
   116
deba@1698
   117
    ProcessedMap processed(graph);
deba@1698
   118
    dfs.processedMap(processed);
deba@1698
   119
deba@1698
   120
    dfs.init();
deba@1698
   121
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   122
      if (!dfs.reached(it)) {
deba@1698
   123
	dfs.addSource(it);
deba@1698
   124
	while (!dfs.emptyQueue()) {
deba@1698
   125
	  Edge edge = dfs.nextEdge();
deba@1698
   126
	  Node target = graph.target(edge);
deba@1698
   127
	  if (dfs.reached(target) && !processed[target]) {
deba@1698
   128
	    return false;
deba@1698
   129
	  }
deba@1698
   130
	  dfs.processNextEdge();
deba@1698
   131
	}
deba@1698
   132
      }
deba@1698
   133
    }    
deba@1698
   134
    return true;
deba@1698
   135
  }
deba@1698
   136
deba@1698
   137
  // UndirGraph algorithms
deba@1698
   138
deba@1698
   139
  /// \brief Check that the given undirected graph is connected.
deba@1698
   140
  ///
deba@1698
   141
  /// Check that the given undirected graph connected.
deba@1698
   142
  template <typename UndirGraph>
deba@1698
   143
  bool connected(const UndirGraph& graph) {
deba@1698
   144
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
   145
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
   146
    if (NodeIt(graph) == INVALID) return false;
deba@1698
   147
    Dfs<UndirGraph> dfs(graph);
deba@1698
   148
    dfs.run(NodeIt(graph));
deba@1698
   149
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   150
      if (!dfs.reached(it)) {
deba@1698
   151
	return false;
deba@1698
   152
      }
deba@1698
   153
    }
deba@1698
   154
    return true;
deba@1698
   155
  }
deba@1698
   156
deba@1698
   157
  /// \brief Check that the given undirected graph is acyclic.
deba@1698
   158
  ///
deba@1698
   159
  /// Check that the given undirected graph acyclic.
deba@1698
   160
  template <typename UndirGraph>
deba@1698
   161
  bool acyclic(const UndirGraph& graph) {
deba@1698
   162
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
   163
    typedef typename UndirGraph::Node Node;
deba@1698
   164
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
   165
    typedef typename UndirGraph::Edge Edge;
deba@1698
   166
    Dfs<UndirGraph> dfs(graph);
deba@1698
   167
    dfs.init();
deba@1698
   168
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   169
      if (!dfs.reached(it)) {
deba@1698
   170
	dfs.addSource(it);
deba@1698
   171
	while (!dfs.emptyQueue()) {
deba@1698
   172
	  Edge edge = dfs.nextEdge();
deba@1698
   173
	  Node source = graph.source(edge);
deba@1698
   174
	  Node target = graph.target(edge);
deba@1698
   175
	  if (dfs.reached(target) && 
deba@1698
   176
	      dfs.pred(source) != graph.oppositeEdge(edge)) {
deba@1698
   177
	    return false;
deba@1698
   178
	  }
deba@1698
   179
	  dfs.processNextEdge();
deba@1698
   180
	}
deba@1698
   181
      }
deba@1698
   182
    }
deba@1698
   183
    return true;
deba@1698
   184
  }
deba@1698
   185
deba@1698
   186
  /// \brief Check that the given undirected graph is tree.
deba@1698
   187
  ///
deba@1698
   188
  /// Check that the given undirected graph is tree.
deba@1698
   189
  template <typename UndirGraph>
deba@1698
   190
  bool tree(const UndirGraph& graph) {
deba@1698
   191
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
   192
    typedef typename UndirGraph::Node Node;
deba@1698
   193
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
   194
    typedef typename UndirGraph::Edge Edge;
deba@1698
   195
    if (NodeIt(graph) == INVALID) return false;
deba@1698
   196
    Dfs<UndirGraph> dfs(graph);
deba@1698
   197
    dfs.init();
deba@1698
   198
    dfs.addSource(NodeIt(graph));
deba@1698
   199
    while (!dfs.emptyQueue()) {
deba@1698
   200
      Edge edge = dfs.nextEdge();
deba@1698
   201
      Node source = graph.source(edge);
deba@1698
   202
      Node target = graph.target(edge);
deba@1698
   203
      if (dfs.reached(target) && 
deba@1698
   204
	  dfs.pred(source) != graph.oppositeEdge(edge)) {
deba@1698
   205
	return false;
deba@1698
   206
      }
deba@1698
   207
      dfs.processNextEdge();
deba@1698
   208
    }
deba@1698
   209
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   210
      if (!dfs.reached(it)) {
deba@1698
   211
	return false;
deba@1698
   212
      }
deba@1698
   213
    }    
deba@1698
   214
    return true;
deba@1698
   215
  }
deba@1698
   216
 
alpar@1739
   217
  ///Count the number of connected components of an undirected graph
alpar@1739
   218
alpar@1739
   219
  ///Count the number of connected components of an undirected graph
alpar@1739
   220
  ///
alpar@1739
   221
  ///\param g The graph. In must be undirected.
alpar@1739
   222
  ///\return The number of components
alpar@1739
   223
  ///\todo Test required
alpar@1739
   224
  template<class UGraph>
alpar@1739
   225
  int numberOfComponents(const UGraph &g)
alpar@1739
   226
  {
alpar@1739
   227
    int c=0;
alpar@1739
   228
    Bfs<Graph> bfs(g);
alpar@1739
   229
    bfs.init();
alpar@1739
   230
    for(typename Graph::NodeIt n(g);n!=INVALID;++n)
alpar@1739
   231
      if(!bfs.reached(n)) {
alpar@1739
   232
	c++;
alpar@1739
   233
	bfs.addSource(n);
alpar@1739
   234
	bfs.start();
alpar@1739
   235
      }
alpar@1739
   236
    return c;
alpar@1739
   237
  }
alpar@1739
   238
alpar@1739
   239
alpar@1739
   240
  ///Find the connected components of an undirected graph
alpar@1739
   241
alpar@1739
   242
  ///Find the connected components of an undirected graph
alpar@1739
   243
  ///
alpar@1739
   244
  ///\param g The graph. In must be undirected.
alpar@1739
   245
  ///\retval comp A writable node map. The values will be set from 0 to
alpar@1739
   246
  ///the number of the connected components minus one. Each values of the map
alpar@1739
   247
  ///will be set exactly once, the values of a certain component will be
alpar@1739
   248
  ///set continuously.
alpar@1739
   249
  ///\return The number of components
alpar@1739
   250
  ///\todo Test required
alpar@1739
   251
  template<class UGraph, class WMap>
alpar@1739
   252
  int connectedComponents(const UGraph &g, WMap &comp)
alpar@1739
   253
  {
alpar@1739
   254
    int c=0;
alpar@1739
   255
    Bfs<Graph> bfs(g);
alpar@1739
   256
    bfs.init();
alpar@1739
   257
    for(typename Graph::NodeIt n(g);n!=INVALID;++n)
alpar@1739
   258
      if(!bfs.reached(n)) {
alpar@1739
   259
	bfs.addSource(n);
alpar@1739
   260
	while ( bfs.nextNode()!=INVALID ) {
alpar@1739
   261
	  comp[bfs.nextNode()]=c;
alpar@1739
   262
	  processNextNode();
alpar@1739
   263
	  c++;
alpar@1739
   264
      }
alpar@1739
   265
    return c;
alpar@1739
   266
  }
deba@1698
   267
deba@1698
   268
} //namespace lemon
deba@1698
   269
deba@1698
   270
#endif //LEMON_TOPOLOGY_H