# 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; |