Backport relevant parts of bugfixes [ad22262328b3], [61fdd06833a6] and [4add05447ca0] to branch 1.2 (#623)
1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2011
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
21 #include "test_tools.h"
22 #include <lemon/smart_graph.h>
23 #include <lemon/preflow.h>
24 #include <lemon/concepts/digraph.h>
25 #include <lemon/concepts/maps.h>
26 #include <lemon/lgf_reader.h>
27 #include <lemon/elevator.h>
29 using namespace lemon;
67 void checkPreflowCompile()
70 typedef concepts::Digraph Digraph;
72 typedef Digraph::Node Node;
73 typedef Digraph::Arc Arc;
74 typedef concepts::ReadMap<Arc,VType> CapMap;
75 typedef concepts::ReadWriteMap<Arc,VType> FlowMap;
76 typedef concepts::WriteMap<Node,bool> CutMap;
78 typedef Elevator<Digraph, Digraph::Node> Elev;
79 typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
89 ::lemon::ignore_unused_variable_warning(v,b);
91 typedef Preflow<Digraph, CapMap>
94 ::SetStandardElevator<LinkedElev>
96 PreflowType preflow_test(g, cap, n, n);
97 const PreflowType& const_preflow_test = preflow_test;
99 const PreflowType::Elevator& elev = const_preflow_test.elevator();
100 preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
101 PreflowType::Tolerance tol = const_preflow_test.tolerance();
102 preflow_test.tolerance(tol);
111 preflow_test.init(cap);
112 preflow_test.startFirstPhase();
113 preflow_test.startSecondPhase();
115 preflow_test.runMinCut();
117 v = const_preflow_test.flowValue();
118 v = const_preflow_test.flow(e);
119 const FlowMap& fm = const_preflow_test.flowMap();
120 b = const_preflow_test.minCut(n);
121 const_preflow_test.minCutMap(cut);
123 ::lemon::ignore_unused_variable_warning(fm);
126 int cutValue (const SmartDigraph& g,
127 const SmartDigraph::NodeMap<bool>& cut,
128 const SmartDigraph::ArcMap<int>& cap) {
131 for(SmartDigraph::ArcIt e(g); e!=INVALID; ++e) {
132 if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e];
137 bool checkFlow(const SmartDigraph& g,
138 const SmartDigraph::ArcMap<int>& flow,
139 const SmartDigraph::ArcMap<int>& cap,
140 SmartDigraph::Node s, SmartDigraph::Node t) {
142 for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
143 if (flow[e] < 0 || flow[e] > cap[e]) return false;
146 for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
147 if (n == s || n == t) continue;
149 for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
152 for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
155 if (sum != 0) return false;
162 DIGRAPH_TYPEDEFS(SmartDigraph);
165 SmartDigraph::ArcMap<int> cap(g),iflow(g);
166 Node s=g.addNode(); Node t=g.addNode();
167 Node n1=g.addNode(); Node n2=g.addNode();
169 a=g.addArc(s,n1); cap[a]=20; iflow[a]=20;
170 a=g.addArc(n1,n2); cap[a]=10; iflow[a]=0;
171 a=g.addArc(n2,t); cap[a]=20; iflow[a]=0;
173 Preflow<SmartDigraph> pre(g,cap,s,t);
175 pre.startFirstPhase();
176 check(pre.flowValue() == 10, "The incorrect max flow value.");
177 check(pre.minCut(s), "Wrong min cut (Node s).");
178 check(pre.minCut(n1), "Wrong min cut (Node n1).");
179 check(!pre.minCut(n2), "Wrong min cut (Node n2).");
180 check(!pre.minCut(t), "Wrong min cut (Node t).");
186 typedef SmartDigraph Digraph;
188 typedef Digraph::Node Node;
189 typedef Digraph::NodeIt NodeIt;
190 typedef Digraph::ArcIt ArcIt;
191 typedef Digraph::ArcMap<int> CapMap;
192 typedef Digraph::ArcMap<int> FlowMap;
193 typedef Digraph::NodeMap<bool> CutMap;
195 typedef Preflow<Digraph, CapMap> PType;
200 std::istringstream input(test_lgf);
201 DigraphReader<Digraph>(g,input).
202 arcMap("capacity", cap).
207 PType preflow_test(g, cap, s, t);
210 check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
211 "The flow is not feasible.");
214 preflow_test.minCutMap(min_cut);
215 int min_cut_value=cutValue(g,min_cut,cap);
217 check(preflow_test.flowValue() == min_cut_value,
218 "The max flow value is not equal to the three min cut values.");
221 for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
223 int flow_value=preflow_test.flowValue();
225 for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
226 preflow_test.init(flow);
227 preflow_test.startFirstPhase();
230 preflow_test.minCutMap(min_cut1);
231 min_cut_value=cutValue(g,min_cut1,cap);
233 check(preflow_test.flowValue() == min_cut_value &&
234 min_cut_value == 2*flow_value,
235 "The max flow value or the min cut value is wrong.");
237 preflow_test.startSecondPhase();
239 check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
240 "The flow is not feasible.");
243 preflow_test.minCutMap(min_cut2);
244 min_cut_value=cutValue(g,min_cut2,cap);
246 check(preflow_test.flowValue() == min_cut_value &&
247 min_cut_value == 2*flow_value,
248 "The max flow value or the three min cut values were not doubled");
251 preflow_test.flowMap(flow);
255 if ( tmp1 != INVALID ) s=tmp1;
259 if ( tmp2 != INVALID ) t=tmp2;
261 preflow_test.source(s);
262 preflow_test.target(t);
267 preflow_test.minCutMap(min_cut3);
268 min_cut_value=cutValue(g,min_cut3,cap);
271 check(preflow_test.flowValue() == min_cut_value,
272 "The max flow value or the three min cut values are incorrect.");