kpeter@54
|
1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*-
|
kpeter@54
|
2 |
*
|
kpeter@54
|
3 |
* This file is a part of LEMON, a generic C++ optimization library.
|
kpeter@54
|
4 |
*
|
kpeter@54
|
5 |
* Copyright (C) 2003-2010
|
kpeter@54
|
6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
kpeter@54
|
7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
kpeter@54
|
8 |
*
|
kpeter@54
|
9 |
* Permission to use, modify and distribute this software is granted
|
kpeter@54
|
10 |
* provided that this copyright notice appears in all copies. For
|
kpeter@54
|
11 |
* precise terms see the accompanying LICENSE file.
|
kpeter@54
|
12 |
*
|
kpeter@54
|
13 |
* This software is provided "AS IS" with no warranty of any kind,
|
kpeter@54
|
14 |
* express or implied, and with no claim as to its suitability for any
|
kpeter@54
|
15 |
* purpose.
|
kpeter@54
|
16 |
*
|
kpeter@54
|
17 |
*/
|
kpeter@54
|
18 |
|
kpeter@54
|
19 |
///\file
|
kpeter@54
|
20 |
///\brief Demo program that solves maximum flow problems using the LP interface
|
kpeter@54
|
21 |
///
|
kpeter@54
|
22 |
/// This demo program shows how to solve the maximum flow problem using
|
kpeter@54
|
23 |
/// the LEMON LP solver interface. We would like to lay the emphasis on the
|
kpeter@54
|
24 |
/// simplicity of the way one can formulate LP constraints that arise in graph
|
kpeter@54
|
25 |
/// theory using LEMON.
|
kpeter@54
|
26 |
///
|
kpeter@54
|
27 |
/// \include lp_maxflow_demo.cc
|
kpeter@54
|
28 |
|
kpeter@54
|
29 |
#include <iostream>
|
kpeter@54
|
30 |
#include <lemon/smart_graph.h>
|
kpeter@54
|
31 |
#include <lemon/lgf_reader.h>
|
kpeter@54
|
32 |
#include <lemon/lp.h>
|
kpeter@54
|
33 |
|
kpeter@54
|
34 |
using namespace lemon;
|
kpeter@54
|
35 |
|
kpeter@54
|
36 |
template <typename GR, typename CAP>
|
kpeter@54
|
37 |
double maxFlow(const GR &g, const CAP &capacity,
|
kpeter@54
|
38 |
typename GR::Node source, typename GR::Node target)
|
kpeter@54
|
39 |
{
|
kpeter@54
|
40 |
TEMPLATE_DIGRAPH_TYPEDEFS(GR);
|
kpeter@54
|
41 |
|
kpeter@54
|
42 |
// Create an instance of the default LP solver
|
kpeter@54
|
43 |
Lp lp;
|
kpeter@54
|
44 |
|
kpeter@54
|
45 |
// Add a column to the problem for each arc
|
kpeter@54
|
46 |
typename GR::template ArcMap<Lp::Col> f(g);
|
kpeter@54
|
47 |
lp.addColSet(f);
|
kpeter@54
|
48 |
|
kpeter@54
|
49 |
// Capacity constraints
|
kpeter@54
|
50 |
for (ArcIt a(g); a != INVALID; ++a) {
|
kpeter@54
|
51 |
lp.colLowerBound(f[a], 0);
|
kpeter@54
|
52 |
lp.colUpperBound(f[a], capacity[a]);
|
kpeter@54
|
53 |
}
|
kpeter@54
|
54 |
|
kpeter@54
|
55 |
// Flow conservation constraints
|
kpeter@54
|
56 |
for (NodeIt n(g); n != INVALID; ++n) {
|
kpeter@54
|
57 |
if (n == source || n == target) continue;
|
kpeter@54
|
58 |
Lp::Expr e;
|
kpeter@54
|
59 |
for (OutArcIt a(g, n); a != INVALID; ++a) e += f[a];
|
kpeter@54
|
60 |
for (InArcIt a(g, n); a != INVALID; ++a) e -= f[a];
|
kpeter@54
|
61 |
lp.addRow(e == 0);
|
kpeter@54
|
62 |
}
|
kpeter@54
|
63 |
|
kpeter@54
|
64 |
// Objective function
|
kpeter@54
|
65 |
Lp::Expr o;
|
kpeter@54
|
66 |
for (OutArcIt a(g, source); a != INVALID; ++a) o += f[a];
|
kpeter@54
|
67 |
for (InArcIt a(g, source); a != INVALID; ++a) o -= f[a];
|
kpeter@54
|
68 |
lp.max();
|
kpeter@54
|
69 |
lp.obj(o);
|
kpeter@54
|
70 |
|
kpeter@54
|
71 |
// Solve the LP problem
|
kpeter@54
|
72 |
lp.solve();
|
kpeter@54
|
73 |
|
kpeter@54
|
74 |
return lp.primal();
|
kpeter@54
|
75 |
}
|
kpeter@54
|
76 |
|
kpeter@54
|
77 |
|
kpeter@54
|
78 |
int main(int argc, char *argv[])
|
kpeter@54
|
79 |
{
|
kpeter@54
|
80 |
// Check the arguments
|
kpeter@54
|
81 |
if (argc < 2) {
|
kpeter@54
|
82 |
std::cerr << "Usage:" << std::endl;
|
kpeter@54
|
83 |
std::cerr << " lp_maxflow_demo <input_file>" << std::endl;
|
kpeter@54
|
84 |
std::cerr << "The given input file has to contain a maximum flow\n"
|
kpeter@54
|
85 |
<< "problem in LGF format (like 'maxflow.lgf')."
|
kpeter@54
|
86 |
<< std::endl;
|
kpeter@54
|
87 |
return 0;
|
kpeter@54
|
88 |
}
|
kpeter@54
|
89 |
|
kpeter@54
|
90 |
// Read the input file
|
kpeter@54
|
91 |
SmartDigraph g;
|
kpeter@54
|
92 |
SmartDigraph::ArcMap<double> cap(g);
|
kpeter@54
|
93 |
SmartDigraph::Node s, t;
|
kpeter@54
|
94 |
|
kpeter@54
|
95 |
digraphReader(g, argv[1])
|
kpeter@54
|
96 |
.arcMap("capacity", cap)
|
kpeter@54
|
97 |
.node("source", s)
|
kpeter@54
|
98 |
.node("target", t)
|
kpeter@54
|
99 |
.run();
|
kpeter@54
|
100 |
|
kpeter@54
|
101 |
// Solve the problem and print the result
|
kpeter@54
|
102 |
std::cout << "Max flow value: " << maxFlow(g, cap, s, t) << std::endl;
|
kpeter@54
|
103 |
|
kpeter@54
|
104 |
return 0;
|
kpeter@54
|
105 |
}
|