gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Cut iterators for GomoryHuTree + doc cleanup + bug fixes (#66)
0 2 0
default
2 files changed with 325 insertions and 61 deletions:
↑ Collapse diff ↑
Show white space 6 line context
... ...
@@ -23,2 +23,3 @@
23 23

	
24
#include <lemon/core.h>
24 25
#include <lemon/preflow.h>
... ...
@@ -37,20 +38,29 @@
37 38
  ///
38
  /// The Gomory-Hu tree is a tree on the nodeset of the digraph, but it
39
  /// may contain arcs which are not in the original digraph. It helps
40
  /// to calculate the minimum cut between all pairs of nodes, because
41
  /// the minimum capacity arc on the tree path between two nodes has
42
  /// the same weight as the minimum cut in the digraph between these
43
  /// nodes. Moreover this arc separates the nodes to two parts which
44
  /// determine this minimum cut.
39
  /// The Gomory-Hu tree is a tree on the node set of the graph, but it
40
  /// may contain edges which are not in the original digraph. It has the
41
  /// property that the minimum capacity edge of the path between two nodes 
42
  /// in this tree has the same weight as the minimum cut in the digraph
43
  /// between these nodes. Moreover the components obtained by removing
44
  /// this edge from the tree determine the corresponding minimum cut.
45
  ///
46
  /// Therefore once this tree is computed, the minimum cut between any pair
47
  /// of nodes can easily be obtained.
45 48
  /// 
46
  /// The algorithm calculates \e n-1 distinict minimum cuts with
47
  /// preflow algorithm, therefore the algorithm has
49
  /// The algorithm calculates \e n-1 distinct minimum cuts (currently with
50
  /// the \ref Preflow algorithm), therefore the algorithm has
48 51
  /// \f$(O(n^3\sqrt{e})\f$ overall time complexity. It calculates a
49
  /// rooted Gomory-Hu tree, the structure of the tree and the weights
50
  /// can be obtained with \c predNode() and \c predValue()
51
  /// functions. The \c minCutValue() and \c minCutMap() calculates
52
  /// rooted Gomory-Hu tree, its structure and the weights can be obtained
53
  /// by \c predNode(), \c predValue() and \c rootDist().
54
  /// 
55
  /// The members \c minCutMap() and \c minCutValue() calculate
52 56
  /// the minimum cut and the minimum cut value between any two node
53
  /// in the digraph.
54
  template <typename _Graph, 
55
	    typename _Capacity = typename _Graph::template EdgeMap<int> >
57
  /// in the digraph. You can also list (iterate on) the nodes and the
58
  /// edges of the cuts using MinCutNodeIt and MinCutEdgeIt.
59
  ///
60
  /// \tparam GR The undirected graph data structure the algorithm will run on
61
  /// \tparam CAP type of the EdgeMap describing the Edge capacities.
62
  /// it is typename GR::template EdgeMap<int> by default.
63
  template <typename GR,
64
	    typename CAP = typename GR::template EdgeMap<int>
65
            >
56 66
  class GomoryHuTree {
... ...
@@ -59,5 +69,5 @@
59 69
    /// The graph type
60
    typedef _Graph Graph;
61
    /// The capacity on edges
62
    typedef _Capacity Capacity;
70
    typedef GR Graph;
71
    /// The type if the edge capacity map
72
    typedef CAP Capacity;
63 73
    /// The value type of capacities
... ...
@@ -106,3 +116,3 @@
106 116
    /// Constructor
107
    /// \param graph The graph type.
117
    /// \param graph The graph the algorithm will run on.
108 118
    /// \param capacity The capacity map.
... ...
@@ -123,6 +133,6 @@
123 133

	
124
    /// \brief Initializes the internal data structures.
125
    ///
126
    /// Initializes the internal data structures.
127
    ///
134
    // \brief Initialize the internal data structures.
135
    //
136
    // This function initializes the internal data structures.
137
    //
128 138
    void init() {
... ...
@@ -140,5 +150,8 @@
140 150

	
141
    /// \brief Starts the algorithm
142
    ///
143
    /// Starts the algorithm.
151
    // \brief Start the algorithm
152
    //
153
    // This function starts the algorithm.
154
    //
155
    // \pre \ref init() must be called before using this function.
156
    //
144 157
    void start() {
... ...
@@ -187,10 +200,9 @@
187 200

	
188
    /// \brief Runs the Gomory-Hu algorithm.  
201
    ///\name Execution Control
202
 
203
    ///@{
204

	
205
    /// \brief Run the Gomory-Hu algorithm.
189 206
    ///
190
    /// Runs the Gomory-Hu algorithm.
191
    /// \note gh.run() is just a shortcut of the following code.
192
    /// \code
193
    ///   ght.init();
194
    ///   ght.start();
195
    /// \endcode
207
    /// This function runs the Gomory-Hu algorithm.
196 208
    void run() {
... ...
@@ -199,6 +211,17 @@
199 211
    }
212
    
213
    /// @}
200 214

	
201
    /// \brief Returns the predecessor node in the Gomory-Hu tree.
215
    ///\name Query Functions
216
    ///The results of the algorithm can be obtained using these
217
    ///functions.\n
218
    ///The \ref run() "run()" should be called before using them.\n
219
    ///See also MinCutNodeIt and MinCutEdgeIt
220

	
221
    ///@{
222

	
223
    /// \brief Return the predecessor node in the Gomory-Hu tree.
202 224
    ///
203
    /// Returns the predecessor node in the Gomory-Hu tree. If the node is
225
    /// This function returns the predecessor node in the Gomory-Hu tree.
226
    /// If the node is
204 227
    /// the root of the Gomory-Hu tree, then it returns \c INVALID.
... ...
@@ -208,8 +231,15 @@
208 231

	
209
    /// \brief Returns the weight of the predecessor arc in the
232
    /// \brief Return the distance from the root node in the Gomory-Hu tree.
233
    ///
234
    /// This function returns the distance of \c node from the root node
235
    /// in the Gomory-Hu tree.
236
    int rootDist(const Node& node) {
237
      return (*_order)[node];
238
    }
239

	
240
    /// \brief Return the weight of the predecessor edge in the
210 241
    /// Gomory-Hu tree.
211 242
    ///
212
    /// Returns the weight of the predecessor arc in the Gomory-Hu
213
    /// tree.  If the node is the root of the Gomory-Hu tree, the
214
    /// result is undefined.
243
    /// This function returns the weight of the predecessor edge in the
244
    /// Gomory-Hu tree.  If the node is the root, the result is undefined.
215 245
    Value predValue(const Node& node) {
... ...
@@ -218,5 +248,5 @@
218 248

	
219
    /// \brief Returns the minimum cut value between two nodes
249
    /// \brief Return the minimum cut value between two nodes
220 250
    ///
221
    /// Returns the minimum cut value between two nodes. The
251
    /// This function returns the minimum cut value between two nodes. The
222 252
    /// algorithm finds the nearest common ancestor in the Gomory-Hu
... ...
@@ -230,6 +260,6 @@
230 260
	if ((*_order)[sn] < (*_order)[tn]) {
231
	  if ((*_weight)[tn] < value) value = (*_weight)[tn];
261
	  if ((*_weight)[tn] <= value) value = (*_weight)[tn];
232 262
	  tn = (*_pred)[tn];
233 263
	} else {
234
	  if ((*_weight)[sn] < value) value = (*_weight)[sn];
264
	  if ((*_weight)[sn] <= value) value = (*_weight)[sn];
235 265
	  sn = (*_pred)[sn];
... ...
@@ -240,14 +270,23 @@
240 270

	
241
    /// \brief Returns the minimum cut between two nodes
271
    /// \brief Return the minimum cut between two nodes
242 272
    ///
243
    /// Returns the minimum cut value between two nodes. The
244
    /// algorithm finds the nearest common ancestor in the Gomory-Hu
245
    /// tree and calculates the minimum weight arc on the paths to
246
    /// the ancestor. Then it sets all nodes to the cut determined by
247
    /// this arc. The \c cutMap should be \ref concepts::ReadWriteMap
273
    /// This function returns the minimum cut between the nodes \c s and \c t
274
    /// the \r cutMap parameter by setting the nodes in the component of
275
    /// \c \s to true and the other nodes to false.
276
    ///
277
    /// The \c cutMap should be \ref concepts::ReadWriteMap
248 278
    /// "ReadWriteMap".
279
    ///
280
    /// For higher level interfaces, see MinCutNodeIt and MinCutEdgeIt
249 281
    template <typename CutMap>
250
    Value minCutMap(const Node& s, const Node& t, CutMap& cutMap) const {
282
    Value minCutMap(const Node& s, ///< Base node
283
                    const Node& t,
284
                    ///< The node you want to separate from Node s.
285
                    CutMap& cutMap
286
                    ///< The cut will be return in this map.
287
                    /// It must be a \c bool \ref concepts::ReadWriteMap
288
                    /// "ReadWriteMap" on the graph nodes.
289
                    ) const {
251 290
      Node sn = s, tn = t;
252

	
291
      bool s_root=false;
253 292
      Node rn = INVALID;
... ...
@@ -257,4 +296,5 @@
257 296
	if ((*_order)[sn] < (*_order)[tn]) {
258
	  if ((*_weight)[tn] < value) {
297
	  if ((*_weight)[tn] <= value) {
259 298
	    rn = tn;
299
            s_root = false;
260 300
	    value = (*_weight)[tn];
... ...
@@ -263,4 +303,5 @@
263 303
	} else {
264
	  if ((*_weight)[sn] < value) {
304
	  if ((*_weight)[sn] <= value) {
265 305
	    rn = sn;
306
            s_root = true;
266 307
	    value = (*_weight)[sn];
... ...
@@ -273,9 +314,10 @@
273 314
      reached.set(_root, true);
274
      cutMap.set(_root, false);
315
      cutMap.set(_root, !s_root);
275 316
      reached.set(rn, true);
276
      cutMap.set(rn, true);
317
      cutMap.set(rn, s_root);
277 318

	
319
      std::vector<Node> st;
278 320
      for (NodeIt n(_graph); n != INVALID; ++n) {
279
	std::vector<Node> st;
280
	Node nn = n;
321
	st.clear();
322
        Node nn = n;
281 323
	while (!reached[nn]) {
... ...
@@ -293,2 +335,216 @@
293 335

	
336
    ///@}
337

	
338
    friend class MinCutNodeIt;
339

	
340
    /// Iterate on the nodes of a minimum cut
341
    
342
    /// This iterator class lists the nodes of a minimum cut found by
343
    /// GomoryHuTree. Before using it, you must allocate a GomoryHuTree class,
344
    /// and call its \ref GomoryHuTree::run() "run()" method.
345
    ///
346
    /// This example counts the nodes in the minimum cut separating \c s from
347
    /// \c t.
348
    /// \code
349
    /// GomoruHuTree<Graph> gom(g, capacities);
350
    /// gom.run();
351
    /// int sum=0;
352
    /// for(GomoruHuTree<Graph>::MinCutNodeIt n(gom,s,t);n!=INVALID;++n) ++sum;
353
    /// \endcode
354
    class MinCutNodeIt
355
    {
356
      bool _side;
357
      typename Graph::NodeIt _node_it;
358
      typename Graph::template NodeMap<bool> _cut;
359
    public:
360
      /// Constructor
361

	
362
      /// Constructor
363
      ///
364
      MinCutNodeIt(GomoryHuTree const &gomory,
365
                   ///< The GomoryHuTree class. You must call its
366
                   ///  run() method
367
                   ///  before initializing this iterator
368
                   const Node& s, ///< Base node
369
                   const Node& t,
370
                   ///< The node you want to separate from Node s.
371
                   bool side=true
372
                   ///< If it is \c true (default) then the iterator lists
373
                   ///  the nodes of the component containing \c s,
374
                   ///  otherwise it lists the other component.
375
                   /// \note As the minimum cut is not always unique,
376
                   /// \code
377
                   /// MinCutNodeIt(gomory, s, t, true);
378
                   /// \endcode
379
                   /// and
380
                   /// \code
381
                   /// MinCutNodeIt(gomory, t, s, false);
382
                   /// \endcode
383
                   /// does not necessarily give the same set of nodes.
384
                   /// However it is ensured that
385
                   /// \code
386
                   /// MinCutNodeIt(gomory, s, t, true);
387
                   /// \endcode
388
                   /// and
389
                   /// \code
390
                   /// MinCutNodeIt(gomory, s, t, false);
391
                   /// \endcode
392
                   /// together list each node exactly once.
393
                   )
394
        : _side(side), _cut(gomory._graph)
395
      {
396
        gomory.minCutMap(s,t,_cut);
397
        for(_node_it=typename Graph::NodeIt(gomory._graph);
398
            _node_it!=INVALID && _cut[_node_it]!=_side;
399
            ++_node_it) {}
400
      }
401
      /// Conversion to Node
402

	
403
      /// Conversion to Node
404
      ///
405
      operator typename Graph::Node() const
406
      {
407
        return _node_it;
408
      }
409
      bool operator==(Invalid) { return _node_it==INVALID; }
410
      bool operator!=(Invalid) { return _node_it!=INVALID; }
411
      /// Next node
412

	
413
      /// Next node
414
      ///
415
      MinCutNodeIt &operator++()
416
      {
417
        for(++_node_it;_node_it!=INVALID&&_cut[_node_it]!=_side;++_node_it) {}
418
        return *this;
419
      }
420
      /// Postfix incrementation
421

	
422
      /// Postfix incrementation
423
      ///
424
      /// \warning This incrementation
425
      /// returns a \c Node, not a \ref MinCutNodeIt, as one may
426
      /// expect.
427
      typename Graph::Node operator++(int)
428
      {
429
        typename Graph::Node n=*this;
430
        ++(*this);
431
        return n;
432
      }
433
    };
434
    
435
    friend class MinCutEdgeIt;
436
    
437
    /// Iterate on the edges of a minimum cut
438
    
439
    /// This iterator class lists the edges of a minimum cut found by
440
    /// GomoryHuTree. Before using it, you must allocate a GomoryHuTree class,
441
    /// and call its \ref GomoryHuTree::run() "run()" method.
442
    ///
443
    /// This example computes the value of the minimum cut separating \c s from
444
    /// \c t.
445
    /// \code
446
    /// GomoruHuTree<Graph> gom(g, capacities);
447
    /// gom.run();
448
    /// int value=0;
449
    /// for(GomoruHuTree<Graph>::MinCutEdgeIt e(gom,s,t);e!=INVALID;++e)
450
    ///   value+=capacities[e];
451
    /// \endcode
452
    /// the result will be the same as it is returned by
453
    /// \ref GomoryHuTree::minCostValue() "gom.minCostValue(s,t)"
454
    class MinCutEdgeIt
455
    {
456
      bool _side;
457
      const Graph &_graph;
458
      typename Graph::NodeIt _node_it;
459
      typename Graph::OutArcIt _arc_it;
460
      typename Graph::template NodeMap<bool> _cut;
461
      void step()
462
      {
463
        ++_arc_it;
464
        while(_node_it!=INVALID && _arc_it==INVALID)
465
          {
466
            for(++_node_it;_node_it!=INVALID&&!_cut[_node_it];++_node_it) {}
467
            if(_node_it!=INVALID)
468
              _arc_it=typename Graph::OutArcIt(_graph,_node_it);
469
          }
470
      }
471
      
472
    public:
473
      MinCutEdgeIt(GomoryHuTree const &gomory,
474
                   ///< The GomoryHuTree class. You must call its
475
                   ///  run() method
476
                   ///  before initializing this iterator
477
                   const Node& s,  ///< Base node
478
                   const Node& t,
479
                   ///< The node you want to separate from Node s.
480
                   bool side=true
481
                   ///< If it is \c true (default) then the listed arcs
482
                   ///  will be oriented from the
483
                   ///  the nodes of the component containing \c s,
484
                   ///  otherwise they will be oriented in the opposite
485
                   ///  direction.
486
                   )
487
        : _graph(gomory._graph), _cut(_graph)
488
      {
489
        gomory.minCutMap(s,t,_cut);
490
        if(!side)
491
          for(typename Graph::NodeIt n(_graph);n!=INVALID;++n)
492
            _cut[n]=!_cut[n];
493

	
494
        for(_node_it=typename Graph::NodeIt(_graph);
495
            _node_it!=INVALID && !_cut[_node_it];
496
            ++_node_it) {}
497
        _arc_it = _node_it!=INVALID ?
498
          typename Graph::OutArcIt(_graph,_node_it) : INVALID;
499
        while(_node_it!=INVALID && _arc_it == INVALID)
500
          {
501
            for(++_node_it; _node_it!=INVALID&&!_cut[_node_it]; ++_node_it) {}
502
            if(_node_it!=INVALID)
503
              _arc_it= typename Graph::OutArcIt(_graph,_node_it);
504
          }
505
        while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
506
      }
507
      /// Conversion to Arc
508

	
509
      /// Conversion to Arc
510
      ///
511
      operator typename Graph::Arc() const
512
      {
513
        return _arc_it;
514
      }
515
      /// Conversion to Edge
516

	
517
      /// Conversion to Edge
518
      ///
519
      operator typename Graph::Edge() const
520
      {
521
        return _arc_it;
522
      }
523
      bool operator==(Invalid) { return _node_it==INVALID; }
524
      bool operator!=(Invalid) { return _node_it!=INVALID; }
525
      /// Next edge
526

	
527
      /// Next edge
528
      ///
529
      MinCutEdgeIt &operator++()
530
      {
531
        step();
532
        while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
533
        return *this;
534
      }
535
      /// Postfix incrementation
536
      
537
      /// Postfix incrementation
538
      ///
539
      /// \warning This incrementation
540
      /// returns a \c Arc, not a \ref MinCutEdgeIt, as one may
541
      /// expect.
542
      typename Graph::Arc operator++(int)
543
      {
544
        typename Graph::Arc e=*this;
545
        ++(*this);
546
        return e;
547
      }
548
    };
549

	
294 550
  };
Ignore white space 6 line context
... ...
@@ -4,7 +4,3 @@
4 4
#include <lemon/smart_graph.h>
5
#include <lemon/adaptors.h>
6 5
#include <lemon/lgf_reader.h>
7
#include <lemon/lgf_writer.h>
8
#include <lemon/dimacs.h>
9
#include <lemon/time_measure.h>
10 6
#include <lemon/gomory_hu_tree.h>
... ...
@@ -79,2 +75,14 @@
79 75
      check(pf.flowValue() == cutValue(graph, cm, capacity), "Wrong cut 2");
76

	
77
      int sum=0;
78
      for(GomoryHuTree<Graph>::MinCutEdgeIt a(ght, u, v);a!=INVALID;++a)
79
        sum+=capacity[a]; 
80
      check(sum == ght.minCutValue(u, v), "Problem with MinCutEdgeIt");
81

	
82
      sum=0;
83
      for(GomoryHuTree<Graph>::MinCutNodeIt n(ght, u, v,true);n!=INVALID;++n)
84
        sum++;
85
      for(GomoryHuTree<Graph>::MinCutNodeIt n(ght, u, v,false);n!=INVALID;++n)
86
        sum++;
87
      check(sum == countNodes(graph), "Problem with MinCutNodeIt");
80 88
      
0 comments (0 inline)