# HG changeset patch
# User Malte SchÃŒrks <s6jnschu@uni-bonn.de>
# Date 1549222758 -3600
# Sun Feb 03 20:39:18 2019 +0100
# Node ID 89dd204d3d126f89c40f1a2a9e050dd9a6db68bb
# Parent 8c567e298d7f3fad82cc66754f2fb6c4a420366b
Fix infinite loops when using Nagamochi-Ibaraki on graphs with floating-point capacities
diff --git a/lemon/nagamochi_ibaraki.h b/lemon/nagamochi_ibaraki.h
a
|
b
|
|
30 | 30 | #include <lemon/maps.h> |
31 | 31 | #include <lemon/radix_sort.h> |
32 | 32 | #include <lemon/unionfind.h> |
| 33 | #include <lemon/tolerance.h> |
33 | 34 | |
34 | 35 | #include <cassert> |
35 | 36 | |
… |
… |
|
98 | 99 | static Heap *createHeap(HeapCrossRef& r) { |
99 | 100 | return new Heap(r); |
100 | 101 | } |
| 102 | |
| 103 | /// \brief The tolerance used by the algorithm |
| 104 | /// |
| 105 | /// The tolerance used by the algorithm to handle inexact computation. |
| 106 | typedef lemon::Tolerance<Value> Tolerance; |
101 | 107 | }; |
102 | 108 | |
103 | 109 | /// \ingroup min_cut |
… |
… |
|
275 | 281 | |
276 | 282 | typedef typename Graph::template NodeMap<bool> MinCutMap; |
277 | 283 | MinCutMap *_cut_map; |
| 284 | |
| 285 | typedef typename Traits::Tolerance Tolerance; |
| 286 | Tolerance _tolerance; |
278 | 287 | |
279 | 288 | void createStructures() { |
280 | 289 | if (!_nodes) { |
… |
… |
|
560 | 569 | n != INVALID; n = (*_nodes)[n].next) { |
561 | 570 | bool merged = false; |
562 | 571 | for (int a = (*_nodes)[n].first_arc; a != -1; a = _arcs[a].next) { |
563 | | if (!(_edges[a >> 1].cut < pmc)) { |
| 572 | if (!_tolerance.less(_edges[a >> 1].cut, pmc)) { |
564 | 573 | if (!merged) { |
565 | 574 | for (int b = (*_nodes)[n].first_arc; b != -1; b = _arcs[b].next) { |
566 | 575 | (*_nodes)[_arcs[b].target].curr_arc = b; |
diff --git a/test/nagamochi_ibaraki_test.cc b/test/nagamochi_ibaraki_test.cc
a
|
b
|
|
40 | 40 | "4\n" |
41 | 41 | "5\n" |
42 | 42 | "@edges\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 | | "2 3 1 6 6 \n"; |
| 43 | " cap1 cap2 cap3 cap4\n" |
| 44 | "0 1 1 1 1 1 \n" |
| 45 | "0 2 2 2 4 1 \n" |
| 46 | "1 2 4 4 4 1 \n" |
| 47 | "3 4 1 1 1 1e-4\n" |
| 48 | "3 5 2 2 4 1e-5\n" |
| 49 | "4 5 4 4 4 1 \n" |
| 50 | "2 3 1 6 6 1 \n"; |
51 | 51 | |
52 | 52 | void checkNagamochiIbarakiCompile() |
53 | 53 | { |
… |
… |
|
95 | 95 | int main() { |
96 | 96 | SmartGraph graph; |
97 | 97 | SmartGraph::EdgeMap<int> cap1(graph), cap2(graph), cap3(graph); |
| 98 | SmartGraph::EdgeMap<double> cap4(graph); |
98 | 99 | SmartGraph::NodeMap<bool> cut(graph); |
99 | 100 | |
100 | 101 | istringstream input(lgf); |
… |
… |
|
102 | 103 | .edgeMap("cap1", cap1) |
103 | 104 | .edgeMap("cap2", cap2) |
104 | 105 | .edgeMap("cap3", cap3) |
| 106 | .edgeMap("cap4", cap4) |
105 | 107 | .run(); |
106 | 108 | |
107 | 109 | { |
… |
… |
|
133 | 135 | ni.run(); |
134 | 136 | ni.minCutMap(cut); |
135 | 137 | |
136 | | ConstMap<SmartGraph::Edge, int> cap4(1); |
| 138 | ConstMap<SmartGraph::Edge, int> cap5(1); |
137 | 139 | check(ni.minCutValue() == 1, "Wrong cut value"); |
138 | | check(ni.minCutValue() == cutValue(graph, cap4, cut), "Wrong cut value"); |
| 140 | check(ni.minCutValue() == cutValue(graph, cap5, cut), "Wrong cut value"); |
| 141 | } |
| 142 | { |
| 143 | NagamochiIbaraki<SmartGraph, SmartGraph::EdgeMap<double>> ni(graph, cap4); |
| 144 | ni.run(); |
| 145 | ni.minCutMap(cut); |
| 146 | |
| 147 | Tolerance<double> tolerance; |
| 148 | check(!tolerance.different(ni.minCutValue(), 1.1e-4), "Wrong cut value"); |
| 149 | check(!tolerance.different(ni.minCutValue(), cutValue(graph, cap4, cut)), "Wrong cut value"); |
139 | 150 | } |
140 | 151 | |
141 | 152 | return 0; |