1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2013
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/edmonds_karp.h>
25 #include <lemon/concepts/digraph.h>
26 #include <lemon/concepts/maps.h>
27 #include <lemon/lgf_reader.h>
28 #include <lemon/elevator.h>
29 #include <lemon/tolerance.h>
31 using namespace lemon;
69 char test_lgf_float[] =
101 // Checks the general interface of a max flow algorithm
102 template <typename GR, typename CAP>
103 struct MaxFlowClassConcept
106 template <typename MF>
109 typedef typename GR::Node Node;
110 typedef typename GR::Arc Arc;
111 typedef typename CAP::Value Value;
112 typedef concepts::ReadWriteMap<Arc, Value> FlowMap;
113 typedef concepts::WriteMap<Node, bool> CutMap;
125 checkConcept<concepts::Digraph, GR>();
127 const Constraints& me = *this;
130 ::template SetFlowMap<FlowMap>
131 ::Create MaxFlowType;
132 typedef typename MF::Create MaxFlowType2;
133 MaxFlowType max_flow(me.g, me.cap, me.n, me.n);
134 const MaxFlowType& const_max_flow = max_flow;
142 typename MaxFlowType::Tolerance tol = const_max_flow.tolerance();
143 max_flow.tolerance(tol);
149 v = const_max_flow.flowValue();
150 v = const_max_flow.flow(e);
151 const FlowMap& fm = const_max_flow.flowMap();
153 b = const_max_flow.minCut(n);
154 const_max_flow.minCutMap(cut);
156 ::lemon::ignore_unused_variable_warning(fm);
163 // Checks the specific parts of Preflow's interface
164 void checkPreflowCompile()
167 typedef concepts::Digraph Digraph;
168 typedef concepts::ReadMap<Digraph::Arc, Value> CapMap;
169 typedef Elevator<Digraph, Digraph::Node> Elev;
170 typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
176 typedef Preflow<Digraph, CapMap>
178 ::SetStandardElevator<LinkedElev>
179 ::Create PreflowType;
180 PreflowType preflow_test(g, cap, n, n);
181 const PreflowType& const_preflow_test = preflow_test;
183 const PreflowType::Elevator& elev = const_preflow_test.elevator();
184 preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
186 bool b = preflow_test.init(cap);
187 preflow_test.startFirstPhase();
188 preflow_test.startSecondPhase();
189 preflow_test.runMinCut();
191 ::lemon::ignore_unused_variable_warning(b);
194 // Checks the specific parts of EdmondsKarp's interface
195 void checkEdmondsKarpCompile()
198 typedef concepts::Digraph Digraph;
199 typedef concepts::ReadMap<Digraph::Arc, Value> CapMap;
205 EdmondsKarp<Digraph, CapMap> ek_test(g, cap, n, n);
208 bool b = ek_test.checkedInit(cap);
209 b = ek_test.augment();
212 ::lemon::ignore_unused_variable_warning(b);
216 template <typename T>
217 T cutValue(const SmartDigraph& g,
218 const SmartDigraph::NodeMap<bool>& cut,
219 const SmartDigraph::ArcMap<T>& cap) {
222 for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
223 if (cut[g.source(e)] && !cut[g.target(e)]) c += cap[e];
228 template <typename T>
229 bool checkFlow(const SmartDigraph& g,
230 const SmartDigraph::ArcMap<T>& flow,
231 const SmartDigraph::ArcMap<T>& cap,
232 SmartDigraph::Node s, SmartDigraph::Node t,
233 const Tolerance<T>& tol) {
235 for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
236 if (tol.negative(flow[e]) || tol.less(cap[e], flow[e])) return false;
239 for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
240 if (n == s || n == t) continue;
242 for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
245 for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
248 if (tol.nonZero(sum)) return false;
253 void checkInitPreflow()
255 DIGRAPH_TYPEDEFS(SmartDigraph);
258 SmartDigraph::ArcMap<int> cap(g), iflow(g);
259 Node s = g.addNode(); Node t = g.addNode();
260 Node n1 = g.addNode(); Node n2 = g.addNode();
262 a = g.addArc(s, n1); cap[a] = 20; iflow[a] = 20;
263 a = g.addArc(n1, n2); cap[a] = 10; iflow[a] = 0;
264 a = g.addArc(n2, t); cap[a] = 20; iflow[a] = 0;
266 Preflow<SmartDigraph> pre(g, cap, s, t);
268 pre.startFirstPhase();
270 check(pre.flowValue() == 10, "Incorrect max flow value.");
271 check(pre.minCut(s), "Wrong min cut (Node s).");
272 check(pre.minCut(n1), "Wrong min cut (Node n1).");
273 check(!pre.minCut(n2), "Wrong min cut (Node n2).");
274 check(!pre.minCut(t), "Wrong min cut (Node t).");
277 template <typename MF, typename SF>
278 void checkMaxFlowAlg(const char *input_lgf, typename MF::Value expected) {
279 typedef SmartDigraph Digraph;
280 DIGRAPH_TYPEDEFS(Digraph);
282 typedef typename MF::Value Value;
283 typedef Digraph::ArcMap<Value> CapMap;
284 typedef CapMap FlowMap;
285 typedef BoolNodeMap CutMap;
287 Tolerance<Value> tol;
292 std::istringstream input(input_lgf);
293 DigraphReader<Digraph>(g, input)
294 .arcMap("capacity", cap)
299 MF max_flow(g, cap, s, t);
302 check(!tol.different(expected, max_flow.flowValue()),
303 "Incorrect max flow value.");
304 check(checkFlow(g, max_flow.flowMap(), cap, s, t, tol),
305 "The flow is not feasible.");
308 max_flow.minCutMap(min_cut);
309 Value min_cut_value = cutValue(g, min_cut, cap);
311 check(!tol.different(expected, min_cut_value),
312 "Incorrect min cut value.");
315 for (ArcIt e(g); e != INVALID; ++e) flow[e] = 13 * max_flow.flowMap()[e];
316 for (ArcIt e(g); e != INVALID; ++e) cap[e] = 17 * cap[e];
319 SF::startFirstPhase(max_flow); // start first phase of the algorithm
322 max_flow.minCutMap(min_cut1);
323 min_cut_value = cutValue(g, min_cut1, cap);
325 check(!tol.different(17 * expected, max_flow.flowValue()),
326 "Incorrect max flow value.");
327 check(!tol.different(17 * expected, min_cut_value),
328 "Incorrect min cut value.");
330 SF::startSecondPhase(max_flow); // start second phase of the algorithm
332 check(checkFlow(g, max_flow.flowMap(), cap, s, t, tol),
333 "The flow is not feasible.");
336 max_flow.minCutMap(min_cut2);
337 min_cut_value = cutValue(g, min_cut2, cap);
339 check(!tol.different(17 * expected, max_flow.flowValue()),
340 "Incorrect max flow value.");
341 check(!tol.different(17 * expected, min_cut_value),
342 "Incorrect min cut value.");
344 max_flow.flowMap(flow);
348 if (tmp1 != INVALID) s = tmp1;
352 if (tmp2 != INVALID) t = tmp2;
360 max_flow.minCutMap(min_cut3);
361 min_cut_value = cutValue(g, min_cut3, cap);
363 check(!tol.different(max_flow.flowValue(), min_cut_value),
364 "The max flow value or the min cut value is wrong.");
367 // Struct for calling start functions of a general max flow algorithm
368 template <typename MF>
369 struct GeneralStartFunctions {
371 static void startFirstPhase(MF& mf) {
375 static void startSecondPhase(MF& mf) {
376 ::lemon::ignore_unused_variable_warning(mf);
381 // Struct for calling start functions of Preflow
382 template <typename MF>
383 struct PreflowStartFunctions {
385 static void startFirstPhase(MF& mf) {
386 mf.startFirstPhase();
389 static void startSecondPhase(MF& mf) {
390 mf.startSecondPhase();
397 typedef concepts::Digraph GR;
398 typedef concepts::ReadMap<GR::Arc, int> CM1;
399 typedef concepts::ReadMap<GR::Arc, double> CM2;
401 // Check the interface of Preflow
402 checkConcept< MaxFlowClassConcept<GR, CM1>,
403 Preflow<GR, CM1> >();
404 checkConcept< MaxFlowClassConcept<GR, CM2>,
405 Preflow<GR, CM2> >();
407 // Check the interface of EdmondsKarp
408 checkConcept< MaxFlowClassConcept<GR, CM1>,
409 EdmondsKarp<GR, CM1> >();
410 checkConcept< MaxFlowClassConcept<GR, CM2>,
411 EdmondsKarp<GR, CM2> >();
414 typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<int> > PType1;
415 typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<float> > PType2;
416 typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<double> > PType3;
418 checkMaxFlowAlg<PType1, PreflowStartFunctions<PType1> >(test_lgf, 13);
419 checkMaxFlowAlg<PType2, PreflowStartFunctions<PType2> >(test_lgf, 13);
420 checkMaxFlowAlg<PType3, PreflowStartFunctions<PType3> >(test_lgf, 13);
422 checkMaxFlowAlg<PType2, PreflowStartFunctions<PType2> >(test_lgf_float, 0.3f);
423 checkMaxFlowAlg<PType3, PreflowStartFunctions<PType3> >(test_lgf_float, 0.3);
428 typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<int> > EKType1;
429 typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<float> > EKType2;
430 typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<double> > EKType3;
432 checkMaxFlowAlg<EKType1, GeneralStartFunctions<EKType1> >(test_lgf, 13);
433 checkMaxFlowAlg<EKType2, GeneralStartFunctions<EKType2> >(test_lgf, 13);
434 checkMaxFlowAlg<EKType3, GeneralStartFunctions<EKType3> >(test_lgf, 13);
436 checkMaxFlowAlg<EKType2, GeneralStartFunctions<EKType2> >(test_lgf_float, 0.3f);
437 checkMaxFlowAlg<EKType3, GeneralStartFunctions<EKType3> >(test_lgf_float, 0.3);