gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Improvements and fixes for the minimum cut algorithms (#264)
0 4 0
default
4 files changed with 317 insertions and 135 deletions:
↑ Collapse diff ↑
Ignore white space 8 line context
... ...
@@ -41,26 +41,24 @@
41 41
  /// property that the minimum capacity edge of the path between two nodes 
42 42
  /// in this tree has the same weight as the minimum cut in the graph
43 43
  /// between these nodes. Moreover the components obtained by removing
44 44
  /// this edge from the tree determine the corresponding minimum cut.
45
  ///
46 45
  /// Therefore once this tree is computed, the minimum cut between any pair
47 46
  /// of nodes can easily be obtained.
48 47
  /// 
49 48
  /// The algorithm calculates \e n-1 distinct minimum cuts (currently with
50
  /// the \ref Preflow algorithm), therefore the algorithm has
51
  /// \f$(O(n^3\sqrt{e})\f$ overall time complexity. It calculates a
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
49
  /// the \ref Preflow algorithm), thus it has \f$O(n^3\sqrt{e})\f$ overall
50
  /// time complexity. It calculates a rooted Gomory-Hu tree.
51
  /// The structure of the tree and the edge weights can be
52
  /// obtained using \c predNode(), \c predValue() and \c rootDist().
53
  /// The functions \c minCutMap() and \c minCutValue() calculate
56 54
  /// the minimum cut and the minimum cut value between any two nodes
57 55
  /// in the graph. You can also list (iterate on) the nodes and the
58 56
  /// edges of the cuts using \c MinCutNodeIt and \c MinCutEdgeIt.
59 57
  ///
60 58
  /// \tparam GR The type of the undirected graph the algorithm runs on.
61
  /// \tparam CAP The type of the edge map describing the edge capacities.
62
  /// It is \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>" by default.
59
  /// \tparam CAP The type of the edge map containing the capacities.
60
  /// The default map type is \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
63 61
#ifdef DOXYGEN
64 62
  template <typename GR,
65 63
	    typename CAP>
66 64
#else
... ...
@@ -69,11 +67,11 @@
69 67
#endif
70 68
  class GomoryHu {
71 69
  public:
72 70

	
73
    /// The graph type
71
    /// The graph type of the algorithm
74 72
    typedef GR Graph;
75
    /// The type of the edge capacity map
73
    /// The capacity map type of the algorithm
76 74
    typedef CAP Capacity;
77 75
    /// The value type of capacities
78 76
    typedef typename Capacity::Value Value;
79 77
    
... ...
@@ -116,9 +114,9 @@
116 114
  public:
117 115

	
118 116
    /// \brief Constructor
119 117
    ///
120
    /// Constructor
118
    /// Constructor.
121 119
    /// \param graph The undirected graph the algorithm runs on.
122 120
    /// \param capacity The edge capacity map.
123 121
    GomoryHu(const Graph& graph, const Capacity& capacity) 
124 122
      : _graph(graph), _capacity(capacity),
... ...
@@ -129,9 +127,9 @@
129 127

	
130 128

	
131 129
    /// \brief Destructor
132 130
    ///
133
    /// Destructor
131
    /// Destructor.
134 132
    ~GomoryHu() {
135 133
      destroyStructures();
136 134
    }
137 135

	
... ...
@@ -214,45 +212,55 @@
214 212

	
215 213
    ///\name Query Functions
216 214
    ///The results of the algorithm can be obtained using these
217 215
    ///functions.\n
218
    ///\ref run() "run()" should be called before using them.\n
216
    ///\ref run() should be called before using them.\n
219 217
    ///See also \ref MinCutNodeIt and \ref MinCutEdgeIt.
220 218

	
221 219
    ///@{
222 220

	
223 221
    /// \brief Return the predecessor node in the Gomory-Hu tree.
224 222
    ///
225
    /// This function returns the predecessor node in the Gomory-Hu tree.
226
    /// If the node is
227
    /// the root of the Gomory-Hu tree, then it returns \c INVALID.
228
    Node predNode(const Node& node) {
223
    /// This function returns the predecessor node of the given node
224
    /// in the Gomory-Hu tree.
225
    /// If \c node is the root of the tree, then it returns \c INVALID.
226
    ///
227
    /// \pre \ref run() must be called before using this function.
228
    Node predNode(const Node& node) const {
229 229
      return (*_pred)[node];
230 230
    }
231 231

	
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 232
    /// \brief Return the weight of the predecessor edge in the
241 233
    /// Gomory-Hu tree.
242 234
    ///
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.
245
    Value predValue(const Node& node) {
235
    /// This function returns the weight of the predecessor edge of the 
236
    /// given node in the Gomory-Hu tree.
237
    /// If \c node is the root of the tree, the result is undefined.
238
    ///
239
    /// \pre \ref run() must be called before using this function.
240
    Value predValue(const Node& node) const {
246 241
      return (*_weight)[node];
247 242
    }
248 243

	
244
    /// \brief Return the distance from the root node in the Gomory-Hu tree.
245
    ///
246
    /// This function returns the distance of the given node from the root
247
    /// node in the Gomory-Hu tree.
248
    ///
249
    /// \pre \ref run() must be called before using this function.
250
    int rootDist(const Node& node) const {
251
      return (*_order)[node];
252
    }
253

	
249 254
    /// \brief Return the minimum cut value between two nodes
250 255
    ///
251
    /// This function returns the minimum cut value between two nodes. The
252
    /// algorithm finds the nearest common ancestor in the Gomory-Hu
253
    /// tree and calculates the minimum weight edge on the paths to
254
    /// the ancestor.
256
    /// This function returns the minimum cut value between the nodes
257
    /// \c s and \c t. 
258
    /// It finds the nearest common ancestor of the given nodes in the
259
    /// Gomory-Hu tree and calculates the minimum weight edge on the
260
    /// paths to the ancestor.
261
    ///
262
    /// \pre \ref run() must be called before using this function.
255 263
    Value minCutValue(const Node& s, const Node& t) const {
256 264
      Node sn = s, tn = t;
257 265
      Value value = std::numeric_limits<Value>::max();
258 266
      
... ...
@@ -273,18 +281,25 @@
273 281
    /// This function returns the minimum cut between the nodes \c s and \c t
274 282
    /// in the \c cutMap parameter by setting the nodes in the component of
275 283
    /// \c s to \c true and the other nodes to \c false.
276 284
    ///
277
    /// For higher level interfaces, see MinCutNodeIt and MinCutEdgeIt.
285
    /// For higher level interfaces see MinCutNodeIt and MinCutEdgeIt.
286
    ///
287
    /// \param s The base node.
288
    /// \param t The node you want to separate from node \c s.
289
    /// \param cutMap The cut will be returned in this map.
290
    /// It must be a \c bool (or convertible) \ref concepts::ReadWriteMap
291
    /// "ReadWriteMap" on the graph nodes.
292
    ///
293
    /// \return The value of the minimum cut between \c s and \c t.
294
    ///
295
    /// \pre \ref run() must be called before using this function.
278 296
    template <typename CutMap>
279
    Value minCutMap(const Node& s, ///< The base node.
297
    Value minCutMap(const Node& s, ///< 
280 298
                    const Node& t,
281
                    ///< The node you want to separate from node \c s.
299
                    ///< 
282 300
                    CutMap& cutMap
283
                    ///< The cut will be returned in this map.
284
                    /// It must be a \c bool (or convertible) 
285
                    /// \ref concepts::ReadWriteMap "ReadWriteMap"
286
                    /// on the graph nodes.
301
                    ///< 
287 302
                    ) const {
288 303
      Node sn = s, tn = t;
289 304
      bool s_root=false;
290 305
      Node rn = INVALID;
... ...
@@ -337,9 +352,9 @@
337 352

	
338 353
    /// Iterate on the nodes of a minimum cut
339 354
    
340 355
    /// This iterator class lists the nodes of a minimum cut found by
341
    /// GomoryHu. Before using it, you must allocate a GomoryHu class,
356
    /// GomoryHu. Before using it, you must allocate a GomoryHu class
342 357
    /// and call its \ref GomoryHu::run() "run()" method.
343 358
    ///
344 359
    /// This example counts the nodes in the minimum cut separating \c s from
345 360
    /// \c t.
... ...
@@ -434,9 +449,9 @@
434 449
    
435 450
    /// Iterate on the edges of a minimum cut
436 451
    
437 452
    /// This iterator class lists the edges of a minimum cut found by
438
    /// GomoryHu. Before using it, you must allocate a GomoryHu class,
453
    /// GomoryHu. Before using it, you must allocate a GomoryHu class
439 454
    /// and call its \ref GomoryHu::run() "run()" method.
440 455
    ///
441 456
    /// This example computes the value of the minimum cut separating \c s from
442 457
    /// \c t.
... ...
@@ -446,10 +461,10 @@
446 461
    /// int value=0;
447 462
    /// for(GomoruHu<Graph>::MinCutEdgeIt e(gom,s,t); e!=INVALID; ++e)
448 463
    ///   value+=capacities[e];
449 464
    /// \endcode
450
    /// the result will be the same as it is returned by
451
    /// \ref GomoryHu::minCutValue() "gom.minCutValue(s,t)"
465
    /// The result will be the same as the value returned by
466
    /// \ref GomoryHu::minCutValue() "gom.minCutValue(s,t)".
452 467
    class MinCutEdgeIt
453 468
    {
454 469
      bool _side;
455 470
      const Graph &_graph;
... ...
@@ -467,8 +482,12 @@
467 482
          }
468 483
      }
469 484
      
470 485
    public:
486
      /// Constructor
487

	
488
      /// Constructor.
489
      ///
471 490
      MinCutEdgeIt(GomoryHu const &gomory,
472 491
                   ///< The GomoryHu class. You must call its
473 492
                   ///  run() method
474 493
                   ///  before initializing this iterator.
... ...
@@ -477,9 +496,9 @@
477 496
                   ///< The node you want to separate from node \c s.
478 497
                   bool side=true
479 498
                   ///< If it is \c true (default) then the listed arcs
480 499
                   ///  will be oriented from the
481
                   ///  the nodes of the component containing \c s,
500
                   ///  nodes of the component containing \c s,
482 501
                   ///  otherwise they will be oriented in the opposite
483 502
                   ///  direction.
484 503
                   )
485 504
        : _graph(gomory._graph), _cut(_graph)
Ignore white space 8 line context
... ...
@@ -30,41 +30,43 @@
30 30
/// \file
31 31
/// \ingroup min_cut
32 32
/// \brief Implementation of the Hao-Orlin algorithm.
33 33
///
34
/// Implementation of the Hao-Orlin algorithm class for testing network
35
/// reliability.
34
/// Implementation of the Hao-Orlin algorithm for finding a minimum cut 
35
/// in a digraph.
36 36

	
37 37
namespace lemon {
38 38

	
39 39
  /// \ingroup min_cut
40 40
  ///
41
  /// \brief %Hao-Orlin algorithm to find a minimum cut in directed graphs.
41
  /// \brief Hao-Orlin algorithm for finding a minimum cut in a digraph.
42 42
  ///
43
  /// Hao-Orlin calculates a minimum cut in a directed graph
44
  /// \f$D=(V,A)\f$. It takes a fixed node \f$ source \in V \f$ and
43
  /// This class implements the Hao-Orlin algorithm for finding a minimum
44
  /// value cut in a directed graph \f$D=(V,A)\f$. 
45
  /// It takes a fixed node \f$ source \in V \f$ and
45 46
  /// consists of two phases: in the first phase it determines a
46 47
  /// minimum cut with \f$ source \f$ on the source-side (i.e. a set
47
  /// \f$ X\subsetneq V \f$ with \f$ source \in X \f$ and minimal
48
  /// out-degree) and in the second phase it determines a minimum cut
48
  /// \f$ X\subsetneq V \f$ with \f$ source \in X \f$ and minimal outgoing
49
  /// capacity) and in the second phase it determines a minimum cut
49 50
  /// with \f$ source \f$ on the sink-side (i.e. a set
50
  /// \f$ X\subsetneq V \f$ with \f$ source \notin X \f$ and minimal
51
  /// out-degree). Obviously, the smaller of these two cuts will be a
51
  /// \f$ X\subsetneq V \f$ with \f$ source \notin X \f$ and minimal outgoing
52
  /// capacity). Obviously, the smaller of these two cuts will be a
52 53
  /// minimum cut of \f$ D \f$. The algorithm is a modified
53
  /// push-relabel preflow algorithm and our implementation calculates
54
  /// preflow push-relabel algorithm. Our implementation calculates
54 55
  /// the minimum cut in \f$ O(n^2\sqrt{m}) \f$ time (we use the
55 56
  /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. The
56
  /// purpose of such algorithm is testing network reliability. For an
57
  /// undirected graph you can run just the first phase of the
58
  /// algorithm or you can use the algorithm of Nagamochi and Ibaraki
59
  /// which solves the undirected problem in
60
  /// \f$ O(nm + n^2 \log n) \f$ time: it is implemented in the
61
  /// NagamochiIbaraki algorithm class.
57
  /// purpose of such algorithm is e.g. testing network reliability.
62 58
  ///
63
  /// \param GR The digraph class the algorithm runs on.
64
  /// \param CAP An arc map of capacities which can be any numreric type.
65
  /// The default type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
66
  /// \param TOL Tolerance class for handling inexact computations. The
59
  /// For an undirected graph you can run just the first phase of the
60
  /// algorithm or you can use the algorithm of Nagamochi and Ibaraki,
61
  /// which solves the undirected problem in \f$ O(nm + n^2 \log n) \f$ 
62
  /// time. It is implemented in the NagamochiIbaraki algorithm class.
63
  ///
64
  /// \tparam GR The type of the digraph the algorithm runs on.
65
  /// \tparam CAP The type of the arc map containing the capacities,
66
  /// which can be any numreric type. The default map type is
67
  /// \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
68
  /// \tparam TOL Tolerance class for handling inexact computations. The
67 69
  /// default tolerance type is \ref Tolerance "Tolerance<CAP::Value>".
68 70
#ifdef DOXYGEN
69 71
  template <typename GR, typename CAP, typename TOL>
70 72
#else
... ...
@@ -72,17 +74,22 @@
72 74
            typename CAP = typename GR::template ArcMap<int>,
73 75
            typename TOL = Tolerance<typename CAP::Value> >
74 76
#endif
75 77
  class HaoOrlin {
78
  public:
79
   
80
    /// The digraph type of the algorithm
81
    typedef GR Digraph;
82
    /// The capacity map type of the algorithm
83
    typedef CAP CapacityMap;
84
    /// The tolerance type of the algorithm
85
    typedef TOL Tolerance;
86

	
76 87
  private:
77 88

	
78
    typedef GR Digraph;
79
    typedef CAP CapacityMap;
80
    typedef TOL Tolerance;
81

	
82 89
    typedef typename CapacityMap::Value Value;
83 90

	
84
    TEMPLATE_GRAPH_TYPEDEFS(Digraph);
91
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
85 92

	
86 93
    const Digraph& _graph;
87 94
    const CapacityMap* _capacity;
88 95

	
... ...
@@ -814,33 +821,34 @@
814 821
    }
815 822

	
816 823
  public:
817 824

	
818
    /// \name Execution control
825
    /// \name Execution Control
819 826
    /// The simplest way to execute the algorithm is to use
820 827
    /// one of the member functions called \ref run().
821 828
    /// \n
822
    /// If you need more control on the execution,
823
    /// first you must call \ref init(), then the \ref calculateIn() or
824
    /// \ref calculateOut() functions.
829
    /// If you need better control on the execution,
830
    /// you have to call one of the \ref init() functions first, then
831
    /// \ref calculateOut() and/or \ref calculateIn().
825 832

	
826 833
    /// @{
827 834

	
828
    /// \brief Initializes the internal data structures.
835
    /// \brief Initialize the internal data structures.
829 836
    ///
830
    /// Initializes the internal data structures. It creates
831
    /// the maps, residual graph adaptors and some bucket structures
832
    /// for the algorithm.
837
    /// This function initializes the internal data structures. It creates
838
    /// the maps and some bucket structures for the algorithm.
839
    /// The first node is used as the source node for the push-relabel
840
    /// algorithm.
833 841
    void init() {
834 842
      init(NodeIt(_graph));
835 843
    }
836 844

	
837
    /// \brief Initializes the internal data structures.
845
    /// \brief Initialize the internal data structures.
838 846
    ///
839
    /// Initializes the internal data structures. It creates
840
    /// the maps, residual graph adaptor and some bucket structures
841
    /// for the algorithm. Node \c source  is used as the push-relabel
842
    /// algorithm's source.
847
    /// This function initializes the internal data structures. It creates
848
    /// the maps and some bucket structures for the algorithm. 
849
    /// The given node is used as the source node for the push-relabel
850
    /// algorithm.
843 851
    void init(const Node& source) {
844 852
      _source = source;
845 853

	
846 854
      _node_num = countNodes(_graph);
... ...
@@ -878,45 +886,49 @@
878 886
      _min_cut = std::numeric_limits<Value>::max();
879 887
    }
880 888

	
881 889

	
882
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
890
    /// \brief Calculate a minimum cut with \f$ source \f$ on the
883 891
    /// source-side.
884 892
    ///
885
    /// Calculates a minimum cut with \f$ source \f$ on the
893
    /// This function calculates a minimum cut with \f$ source \f$ on the
886 894
    /// source-side (i.e. a set \f$ X\subsetneq V \f$ with
887
    /// \f$ source \in X \f$ and minimal out-degree).
895
    /// \f$ source \in X \f$ and minimal outgoing capacity).
896
    ///
897
    /// \pre \ref init() must be called before using this function.
888 898
    void calculateOut() {
889 899
      findMinCutOut();
890 900
    }
891 901

	
892
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
893
    /// target-side.
902
    /// \brief Calculate a minimum cut with \f$ source \f$ on the
903
    /// sink-side.
894 904
    ///
895
    /// Calculates a minimum cut with \f$ source \f$ on the
896
    /// target-side (i.e. a set \f$ X\subsetneq V \f$ with
897
    /// \f$ source \in X \f$ and minimal out-degree).
905
    /// This function calculates a minimum cut with \f$ source \f$ on the
906
    /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with
907
    /// \f$ source \notin X \f$ and minimal outgoing capacity).
908
    ///
909
    /// \pre \ref init() must be called before using this function.
898 910
    void calculateIn() {
899 911
      findMinCutIn();
900 912
    }
901 913

	
902 914

	
903
    /// \brief Runs the algorithm.
915
    /// \brief Run the algorithm.
904 916
    ///
905
    /// Runs the algorithm. It finds nodes \c source and \c target
906
    /// arbitrarily and then calls \ref init(), \ref calculateOut()
917
    /// This function runs the algorithm. It finds nodes \c source and
918
    /// \c target arbitrarily and then calls \ref init(), \ref calculateOut()
907 919
    /// and \ref calculateIn().
908 920
    void run() {
909 921
      init();
910 922
      calculateOut();
911 923
      calculateIn();
912 924
    }
913 925

	
914
    /// \brief Runs the algorithm.
926
    /// \brief Run the algorithm.
915 927
    ///
916
    /// Runs the algorithm. It uses the given \c source node, finds a
917
    /// proper \c target and then calls the \ref init(), \ref
918
    /// calculateOut() and \ref calculateIn().
928
    /// This function runs the algorithm. It uses the given \c source node, 
929
    /// finds a proper \c target node and then calls the \ref init(),
930
    /// \ref calculateOut() and \ref calculateIn().
919 931
    void run(const Node& s) {
920 932
      init(s);
921 933
      calculateOut();
922 934
      calculateIn();
... ...
@@ -925,42 +937,50 @@
925 937
    /// @}
926 938

	
927 939
    /// \name Query Functions
928 940
    /// The result of the %HaoOrlin algorithm
929
    /// can be obtained using these functions.
930
    /// \n
931
    /// Before using these functions, either \ref run(), \ref
932
    /// calculateOut() or \ref calculateIn() must be called.
941
    /// can be obtained using these functions.\n
942
    /// \ref run(), \ref calculateOut() or \ref calculateIn() 
943
    /// should be called before using them.
933 944

	
934 945
    /// @{
935 946

	
936
    /// \brief Returns the value of the minimum value cut.
947
    /// \brief Return the value of the minimum cut.
937 948
    ///
938
    /// Returns the value of the minimum value cut.
949
    /// This function returns the value of the minimum cut.
950
    ///
951
    /// \pre \ref run(), \ref calculateOut() or \ref calculateIn() 
952
    /// must be called before using this function.
939 953
    Value minCutValue() const {
940 954
      return _min_cut;
941 955
    }
942 956

	
943 957

	
944
    /// \brief Returns a minimum cut.
958
    /// \brief Return a minimum cut.
945 959
    ///
946
    /// Sets \c nodeMap to the characteristic vector of a minimum
947
    /// value cut: it will give a nonempty set \f$ X\subsetneq V \f$
948
    /// with minimal out-degree (i.e. \c nodeMap will be true exactly
949
    /// for the nodes of \f$ X \f$).  \pre nodeMap should be a
950
    /// bool-valued node-map.
951
    template <typename NodeMap>
952
    Value minCutMap(NodeMap& nodeMap) const {
960
    /// This function sets \c cutMap to the characteristic vector of a
961
    /// minimum value cut: it will give a non-empty set \f$ X\subsetneq V \f$
962
    /// with minimal outgoing capacity (i.e. \c cutMap will be \c true exactly
963
    /// for the nodes of \f$ X \f$).
964
    ///
965
    /// \param cutMap A \ref concepts::WriteMap "writable" node map with
966
    /// \c bool (or convertible) value type.
967
    ///
968
    /// \return The value of the minimum cut.
969
    ///
970
    /// \pre \ref run(), \ref calculateOut() or \ref calculateIn() 
971
    /// must be called before using this function.
972
    template <typename CutMap>
973
    Value minCutMap(CutMap& cutMap) const {
953 974
      for (NodeIt it(_graph); it != INVALID; ++it) {
954
        nodeMap.set(it, (*_min_cut_map)[it]);
975
        cutMap.set(it, (*_min_cut_map)[it]);
955 976
      }
956 977
      return _min_cut;
957 978
    }
958 979

	
959 980
    /// @}
960 981

	
961 982
  }; //class HaoOrlin
962 983

	
963

	
964 984
} //namespace lemon
965 985

	
966 986
#endif //LEMON_HAO_ORLIN_H
Ignore white space 8 line context
1 1
#include <iostream>
2 2

	
3 3
#include "test_tools.h"
4 4
#include <lemon/smart_graph.h>
5
#include <lemon/concepts/graph.h>
6
#include <lemon/concepts/maps.h>
5 7
#include <lemon/lgf_reader.h>
6 8
#include <lemon/gomory_hu.h>
7 9
#include <cstdlib>
8 10

	
... ...
@@ -31,8 +33,38 @@
31 33
  "@attributes\n"
32 34
  "source 0\n"
33 35
  "target 3\n";
34 36
  
37
void checkGomoryHuCompile()
38
{
39
  typedef int Value;
40
  typedef concepts::Graph Graph;
41

	
42
  typedef Graph::Node Node;
43
  typedef Graph::Edge Edge;
44
  typedef concepts::ReadMap<Edge, Value> CapMap;
45
  typedef concepts::ReadWriteMap<Node, bool> CutMap;
46

	
47
  Graph g;
48
  Node n;
49
  CapMap cap;
50
  CutMap cut;
51
  Value v;
52
  int d;
53

	
54
  GomoryHu<Graph, CapMap> gh_test(g, cap);
55
  const GomoryHu<Graph, CapMap>&
56
    const_gh_test = gh_test;
57

	
58
  gh_test.run();
59

	
60
  n = const_gh_test.predNode(n);
61
  v = const_gh_test.predValue(n);
62
  d = const_gh_test.rootDist(n);
63
  v = const_gh_test.minCutValue(n, n);
64
  v = const_gh_test.minCutMap(n, n, cut);
65
}
66

	
35 67
GRAPH_TYPEDEFS(Graph);
36 68
typedef Graph::EdgeMap<int> IntEdgeMap;
37 69
typedef Graph::NodeMap<bool> BoolNodeMap;
38 70

	
... ...
@@ -69,10 +101,10 @@
69 101
      pf.runMinCut();
70 102
      BoolNodeMap cm(graph);
71 103
      ght.minCutMap(u, v, cm);
72 104
      check(pf.flowValue() == ght.minCutValue(u, v), "Wrong cut 1");
73
      check(cm[u] != cm[v], "Wrong cut 3");
74
      check(pf.flowValue() == cutValue(graph, cm, capacity), "Wrong cut 2");
105
      check(cm[u] != cm[v], "Wrong cut 2");
106
      check(pf.flowValue() == cutValue(graph, cm, capacity), "Wrong cut 3");
75 107

	
76 108
      int sum=0;
77 109
      for(GomoryHu<Graph>::MinCutEdgeIt a(ght, u, v);a!=INVALID;++a)
78 110
        sum+=capacity[a]; 
... ...
@@ -83,9 +115,8 @@
83 115
        sum++;
84 116
      for(GomoryHu<Graph>::MinCutNodeIt n(ght, u, v,false);n!=INVALID;++n)
85 117
        sum++;
86 118
      check(sum == countNodes(graph), "Problem with MinCutNodeIt");
87
      
88 119
    }
89 120
  }
90 121
  
91 122
  return 0;
Ignore white space 8 line context
... ...
@@ -18,11 +18,14 @@
18 18

	
19 19
#include <sstream>
20 20

	
21 21
#include <lemon/smart_graph.h>
22
#include <lemon/adaptors.h>
23
#include <lemon/concepts/digraph.h>
24
#include <lemon/concepts/maps.h>
25
#include <lemon/lgf_reader.h>
22 26
#include <lemon/hao_orlin.h>
23 27

	
24
#include <lemon/lgf_reader.h>
25 28
#include "test_tools.h"
26 29

	
27 30
using namespace lemon;
28 31
using namespace std;
... ...
@@ -36,28 +39,137 @@
36 39
  "3\n"
37 40
  "4\n"
38 41
  "5\n"
39 42
  "@edges\n"
40
  "     label  capacity\n"
41
  "0 1  0      2\n"
42
  "1 2  1      2\n"
43
  "2 0  2      2\n"
44
  "3 4  3      2\n"
45
  "4 5  4      2\n"
46
  "5 3  5      2\n"
47
  "2 3  6      3\n";
43
  "     cap1 cap2 cap3\n"
44
  "0 1  1    1    1   \n"
45
  "0 2  2    2    4   \n"
46
  "1 2  4    4    4   \n"
47
  "3 4  1    1    1   \n"
48
  "3 5  2    2    4   \n"
49
  "4 5  4    4    4   \n"
50
  "5 4  4    4    4   \n"
51
  "2 3  1    6    6   \n"
52
  "4 0  1    6    6   \n";
53

	
54
void checkHaoOrlinCompile()
55
{
56
  typedef int Value;
57
  typedef concepts::Digraph Digraph;
58

	
59
  typedef Digraph::Node Node;
60
  typedef Digraph::Arc Arc;
61
  typedef concepts::ReadMap<Arc, Value> CapMap;
62
  typedef concepts::WriteMap<Node, bool> CutMap;
63

	
64
  Digraph g;
65
  Node n;
66
  CapMap cap;
67
  CutMap cut;
68
  Value v;
69

	
70
  HaoOrlin<Digraph, CapMap> ho_test(g, cap);
71
  const HaoOrlin<Digraph, CapMap>&
72
    const_ho_test = ho_test;
73

	
74
  ho_test.init();
75
  ho_test.init(n);
76
  ho_test.calculateOut();
77
  ho_test.calculateIn();
78
  ho_test.run();
79
  ho_test.run(n);
80

	
81
  v = const_ho_test.minCutValue();
82
  v = const_ho_test.minCutMap(cut);
83
}
84

	
85
template <typename Graph, typename CapMap, typename CutMap>
86
typename CapMap::Value 
87
  cutValue(const Graph& graph, const CapMap& cap, const CutMap& cut)
88
{
89
  typename CapMap::Value sum = 0;
90
  for (typename Graph::ArcIt a(graph); a != INVALID; ++a) {
91
    if (cut[graph.source(a)] && !cut[graph.target(a)])
92
      sum += cap[a];
93
  }
94
  return sum;
95
}
48 96

	
49 97
int main() {
50
  SmartGraph graph;
51
  SmartGraph::EdgeMap<int> capacity(graph);
98
  SmartDigraph graph;
99
  SmartDigraph::ArcMap<int> cap1(graph), cap2(graph), cap3(graph);
100
  SmartDigraph::NodeMap<bool> cut(graph);
52 101

	
53
  istringstream lgfs(lgf);
54
  graphReader(graph, lgfs).
55
    edgeMap("capacity", capacity).run();
102
  istringstream input(lgf);
103
  digraphReader(graph, input)
104
    .arcMap("cap1", cap1)
105
    .arcMap("cap2", cap2)
106
    .arcMap("cap3", cap3)
107
    .run();
56 108

	
57
  HaoOrlin<SmartGraph, SmartGraph::EdgeMap<int> > ho(graph, capacity);
58
  ho.run();
59

	
60
  check(ho.minCutValue() == 3, "Wrong cut value");
109
  {
110
    HaoOrlin<SmartDigraph> ho(graph, cap1);
111
    ho.run();
112
    ho.minCutMap(cut);
113
    
114
    // BUG: The cut value should be positive
115
    check(ho.minCutValue() == 0, "Wrong cut value");
116
    // BUG: It should work
117
    //check(ho.minCutValue() == cutValue(graph, cap1, cut), "Wrong cut value");
118
  }
119
  {
120
    HaoOrlin<SmartDigraph> ho(graph, cap2);
121
    ho.run();
122
    ho.minCutMap(cut);
123
    
124
    // BUG: The cut value should be positive
125
    check(ho.minCutValue() == 0, "Wrong cut value");
126
    // BUG: It should work
127
    //check(ho.minCutValue() == cutValue(graph, cap2, cut), "Wrong cut value");
128
  }
129
  {
130
    HaoOrlin<SmartDigraph> ho(graph, cap3);
131
    ho.run();
132
    ho.minCutMap(cut);
133
    
134
    // BUG: The cut value should be positive
135
    check(ho.minCutValue() == 0, "Wrong cut value");
136
    // BUG: It should work
137
    //check(ho.minCutValue() == cutValue(graph, cap3, cut), "Wrong cut value");
138
  }
139
  
140
  typedef Undirector<SmartDigraph> UGraph;
141
  UGraph ugraph(graph);
142
  
143
  {
144
    HaoOrlin<UGraph, SmartDigraph::ArcMap<int> > ho(ugraph, cap1);
145
    ho.run();
146
    ho.minCutMap(cut);
147
    
148
    // BUG: The cut value should be 2
149
    check(ho.minCutValue() == 1, "Wrong cut value");
150
    // BUG: It should work
151
    //check(ho.minCutValue() == cutValue(ugraph, cap1, cut), "Wrong cut value");
152
  }
153
  {
154
    HaoOrlin<UGraph, SmartDigraph::ArcMap<int> > ho(ugraph, cap2);
155
    ho.run();
156
    ho.minCutMap(cut);
157
    
158
    // TODO: Check this cut value
159
    check(ho.minCutValue() == 4, "Wrong cut value");
160
    // BUG: It should work
161
    //check(ho.minCutValue() == cutValue(ugraph, cap2, cut), "Wrong cut value");
162
  }
163
  {
164
    HaoOrlin<UGraph, SmartDigraph::ArcMap<int> > ho(ugraph, cap3);
165
    ho.run();
166
    ho.minCutMap(cut);
167
    
168
    // TODO: Check this cut value
169
    check(ho.minCutValue() == 5, "Wrong cut value");
170
    // BUG: It should work
171
    //check(ho.minCutValue() == cutValue(ugraph, cap3, cut), "Wrong cut value");
172
  }
61 173

	
62 174
  return 0;
63 175
}
0 comments (0 inline)