marci@1104
|
1 |
// -*- c++ -*-
|
marci@1104
|
2 |
#include <iostream>
|
marci@1104
|
3 |
#include <fstream>
|
marci@1104
|
4 |
|
marci@1143
|
5 |
#include <lemon/graph_utils.h>
|
marci@1104
|
6 |
#include <lemon/smart_graph.h>
|
marci@1104
|
7 |
#include <lemon/list_graph.h>
|
marci@1104
|
8 |
#include <lemon/dimacs.h>
|
marci@1104
|
9 |
#include <lemon/time_measure.h>
|
marci@1111
|
10 |
#include <lp_solver_base.h>
|
marci@1104
|
11 |
|
marci@1104
|
12 |
using std::cout;
|
marci@1104
|
13 |
using std::endl;
|
marci@1104
|
14 |
using namespace lemon;
|
marci@1104
|
15 |
|
marci@1104
|
16 |
template<typename Edge, typename EdgeIndexMap>
|
marci@1104
|
17 |
class PrimalMap {
|
marci@1104
|
18 |
protected:
|
marci@1104
|
19 |
LPGLPK* lp;
|
marci@1104
|
20 |
EdgeIndexMap* edge_index_map;
|
marci@1104
|
21 |
public:
|
marci@1104
|
22 |
PrimalMap(LPGLPK& _lp, EdgeIndexMap& _edge_index_map) :
|
marci@1104
|
23 |
lp(&_lp), edge_index_map(&_edge_index_map) { }
|
marci@1104
|
24 |
double operator[](Edge e) const {
|
marci@1104
|
25 |
return lp->getPrimal((*edge_index_map)[e]);
|
marci@1104
|
26 |
}
|
marci@1104
|
27 |
};
|
marci@1104
|
28 |
|
marci@1104
|
29 |
// Use a DIMACS max flow file as stdin.
|
marci@1104
|
30 |
// max_flow_expresion < dimacs_max_flow_file
|
marci@1104
|
31 |
|
marci@1104
|
32 |
int main(int, char **) {
|
marci@1104
|
33 |
|
marci@1104
|
34 |
typedef ListGraph Graph;
|
marci@1104
|
35 |
typedef Graph::Node Node;
|
marci@1104
|
36 |
typedef Graph::Edge Edge;
|
marci@1104
|
37 |
typedef Graph::EdgeIt EdgeIt;
|
marci@1104
|
38 |
|
marci@1104
|
39 |
Graph g;
|
marci@1104
|
40 |
|
marci@1104
|
41 |
Node s, t;
|
marci@1104
|
42 |
Graph::EdgeMap<int> cap(g);
|
marci@1104
|
43 |
readDimacs(std::cin, g, cap, s, t);
|
marci@1104
|
44 |
Timer ts;
|
marci@1104
|
45 |
|
marci@1104
|
46 |
typedef LPGLPK LPSolver;
|
marci@1104
|
47 |
LPSolver lp;
|
marci@1104
|
48 |
lp.setMaximize();
|
marci@1144
|
49 |
typedef LPSolver::Col Col;
|
marci@1144
|
50 |
typedef LPSolver::Row Row;
|
marci@1144
|
51 |
typedef Graph::EdgeMap<Col> EdgeIndexMap;
|
marci@1144
|
52 |
typedef Graph::NodeMap<Row> NodeIndexMap;
|
marci@1104
|
53 |
EdgeIndexMap edge_index_map(g);
|
marci@1143
|
54 |
NodeIndexMap node_index_map(g);
|
marci@1110
|
55 |
PrimalMap<Edge, EdgeIndexMap> flow(lp, edge_index_map);
|
marci@1104
|
56 |
|
marci@1111
|
57 |
// nonnegativity of flow and capacity function
|
marci@1104
|
58 |
for (Graph::EdgeIt e(g); e!=INVALID; ++e) {
|
marci@1144
|
59 |
Col col=lp.addCol();
|
marci@1144
|
60 |
edge_index_map.set(e, col);
|
marci@1110
|
61 |
// interesting property in GLPK:
|
marci@1110
|
62 |
// if you change the order of the following two lines, the
|
marci@1110
|
63 |
// two runs of GLPK are extremely different
|
marci@1144
|
64 |
lp.setColLowerBound(col, 0);
|
marci@1144
|
65 |
lp.setColUpperBound(col, cap[e]);
|
marci@1104
|
66 |
}
|
marci@1104
|
67 |
|
marci@1104
|
68 |
for (Graph::NodeIt n(g); n!=INVALID; ++n) {
|
marci@1104
|
69 |
LPSolver::Expression expr;
|
marci@1104
|
70 |
for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e)
|
marci@1104
|
71 |
expr+=edge_index_map[e];
|
marci@1104
|
72 |
for (Graph::InEdgeIt e(g, n); e!=INVALID; ++e)
|
marci@1104
|
73 |
expr-=edge_index_map[e];
|
marci@1104
|
74 |
// cost function
|
marci@1104
|
75 |
if (n==s) {
|
marci@1104
|
76 |
lp.setObjCoeffs(expr);
|
marci@1104
|
77 |
}
|
marci@1111
|
78 |
// flow conservation constraints
|
marci@1104
|
79 |
if ((n!=s) && (n!=t)) {
|
marci@1144
|
80 |
node_index_map.set(n, lp.addRow(expr == 0.0));
|
marci@1104
|
81 |
}
|
marci@1104
|
82 |
}
|
marci@1104
|
83 |
lp.solveSimplex();
|
marci@1110
|
84 |
cout << "elapsed time: " << ts << endl;
|
marci@1104
|
85 |
}
|