Darwin  1.10(beta)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
drwnMaxFlow.h
1 /******************************************************************************
2 ** DARWIN: A FRAMEWORK FOR MACHINE LEARNING RESEARCH AND DEVELOPMENT
3 ** Distributed under the terms of the BSD license (see the LICENSE file)
4 ** Copyright (c) 2007-2015, Stephen Gould
5 ** All rights reserved.
6 **
7 ******************************************************************************
8 ** FILENAME: drwnMaxFlow.h
9 ** AUTHOR(S): Stephen Gould <stephen.gould@anu.edu.au>
10 **
11 *****************************************************************************/
12 
13 #pragma once
14 
15 #include <cassert>
16 #include <vector>
17 #include <map>
18 #include <deque>
19 
20 using namespace std;
21 
22 class drwnMaxFlow;
23 
24 // drwnMaxFlow --------------------------------------------------------------
31 
32 class drwnMaxFlow {
33  protected:
35  static const unsigned char FREE = 0x00;
36  static const unsigned char SOURCE = 0x01;
37  static const unsigned char TARGET = 0x02;
38 
40  typedef map<int, pair<unsigned, unsigned> > _drwnCapacitatedEdge;
41 
42  vector<double> _sourceEdges;
43  vector<double> _targetEdges;
44  vector<double> _edgeWeights;
45  vector<_drwnCapacitatedEdge> _nodes;
46  double _flowValue;
47 
48  vector<unsigned char> _cut;
49 
50  public:
52  drwnMaxFlow(unsigned maxNodes = 0) : _flowValue(0.0) {
53  _sourceEdges.reserve(maxNodes);
54  _targetEdges.reserve(maxNodes);
55  _edgeWeights.reserve(2 * maxNodes);
56  _nodes.reserve(maxNodes);
57  }
58 
60  virtual ~drwnMaxFlow() {
61  // do nothing
62  }
63 
65  size_t numNodes() const { return _nodes.size(); }
66 
68  virtual void reset();
70  virtual void clear();
71 
73  inline int addNodes(unsigned n = 1) {
74  int nodeId = (int)_nodes.size();
75  _nodes.resize(_nodes.size() + n);
76  _sourceEdges.resize(_nodes.size(), 0.0);
77  _targetEdges.resize(_nodes.size(), 0.0);
78  return nodeId;
79  }
80 
82  void addConstant(double c) {
83  _flowValue += c;
84  }
85 
87  inline void addSourceEdge(int u, double cap) {
88  DRWN_ASSERT((u >= 0) && (u < (int)_nodes.size()));
89  if (cap < 0.0) { _flowValue += cap; _targetEdges[u] -= cap; }
90  else _sourceEdges[u] += cap;
91  }
92 
94  inline void addTargetEdge(int u, double cap) {
95  DRWN_ASSERT((u >= 0) && (u < (int)_nodes.size()));
96  if (cap < 0.0) { _flowValue += cap; _sourceEdges[u] -= cap; }
97  else _targetEdges[u] += cap;
98  }
99 
102  inline void addEdge(int u, int v, double cap_uv, double cap_vu = 0.0) {
103  DRWN_ASSERT((u >= 0) && (u < (int)_nodes.size()));
104  DRWN_ASSERT((v >= 0) && (v < (int)_nodes.size()));
105  DRWN_ASSERT(u != v);
106 
107  _drwnCapacitatedEdge::const_iterator it = _nodes[u].find(v);
108  if (it == _nodes[u].end()) {
109  DRWN_ASSERT(cap_uv + cap_vu >= 0.0);
110  if (cap_uv < 0.0) {
111  _nodes[u].insert(make_pair(v, make_pair(_edgeWeights.size(), _edgeWeights.size() + 1)));
112  _nodes[v].insert(make_pair(u, make_pair(_edgeWeights.size() + 1, _edgeWeights.size())));
113  _edgeWeights.push_back(0.0);
114  _edgeWeights.push_back(cap_uv + cap_vu);
115  _sourceEdges[u] -= cap_uv;
116  _targetEdges[v] -= cap_uv;
117  _flowValue += cap_uv;
118  } else if (cap_vu < 0.0) {
119  _nodes[u].insert(make_pair(v, make_pair(_edgeWeights.size(), _edgeWeights.size() + 1)));
120  _nodes[v].insert(make_pair(u, make_pair(_edgeWeights.size() + 1, _edgeWeights.size())));
121  _edgeWeights.push_back(cap_uv + cap_vu);
122  _edgeWeights.push_back(0.0);
123  _sourceEdges[v] -= cap_vu;
124  _targetEdges[u] -= cap_vu;
125  _flowValue += cap_vu;
126  } else {
127  _nodes[u].insert(make_pair(v, make_pair(_edgeWeights.size(), _edgeWeights.size() + 1)));
128  _nodes[v].insert(make_pair(u, make_pair(_edgeWeights.size() + 1, _edgeWeights.size())));
129  _edgeWeights.push_back(cap_uv);
130  _edgeWeights.push_back(cap_vu);
131  }
132  } else {
133  const double w_u = _edgeWeights[it->second.first] += cap_uv;
134  const double w_v = _edgeWeights[it->second.second] += cap_vu;
135  DRWN_ASSERT(w_u + w_v >= 0.0);
136  if (w_u < 0.0) {
137  _edgeWeights[it->second.first] = 0.0;
138  _edgeWeights[it->second.second] += w_u;
139  _sourceEdges[u] -= w_u;
140  _targetEdges[v] -= w_u;
141  _flowValue += w_u;
142  } else if (w_v < 0.0) {
143  _edgeWeights[it->second.first] += w_v;
144  _edgeWeights[it->second.second] = 0.0;
145  _sourceEdges[v] -= w_v;
146  _targetEdges[u] -= w_v;
147  _flowValue += w_v;
148  }
149  }
150  }
151 
153  virtual double solve() = 0;
154 
157  bool inSetS(int u) const { return (_cut[u] == SOURCE); }
160  bool inSetT(int u) const { return (_cut[u] == TARGET); }
161 
164  double operator()(int u, int v) const;
165 
166  protected:
168  void preAugmentPaths();
169 };
170 
171 // drwnEdmondsKarpMaxFlow ---------------------------------------------------
173 
175  public:
176  drwnEdmondsKarpMaxFlow(unsigned maxNodes = 0) : drwnMaxFlow(maxNodes) {
177  // do nothing
178  }
179  virtual ~drwnEdmondsKarpMaxFlow() {
180  // do nothing
181  }
182 
183  virtual double solve();
184 
185  protected:
186  void findCuts();
187 };
188 
189 // drwnBKMaxFlow ------------------------------------------------------------
196 
197 class drwnBKMaxFlow : public drwnMaxFlow {
198  protected:
199  static const int TERMINAL = -1;
200 
202  vector<int> _parents;
203  vector<pair<double *, double *> > _weightptrs;
204  drwnIndexQueue _activeList;
205 
206  public:
207  drwnBKMaxFlow(unsigned maxNodes = 0) : drwnMaxFlow(maxNodes) {
208  // do nothing
209  }
210  virtual ~drwnBKMaxFlow() {
211  // do nothing
212  }
213 
214  virtual void reset();
215  virtual void clear();
216  virtual double solve();
217 
218  protected:
220  void initializeTrees();
222  pair<int, int> expandTrees();
224  void augmentBKPath(const pair<int, int>& path, deque<int>& orphans);
226  void adoptOrphans(deque<int>& orphans);
228  bool isAncestor(int u, int v) const;
229 };
void addEdge(int u, int v, double cap_uv, double cap_vu=0.0)
add edge from u to v and edge from v to u (requires cap_uv + cap_vu >= 0)
Definition: drwnMaxFlow.h:102
bool inSetT(int u) const
return true if u is in the t-set after calling solve (note that sometimes a node can be in either S o...
Definition: drwnMaxFlow.h:160
int addNodes(unsigned n=1)
add nodes to the graph (returns the id of the first node added)
Definition: drwnMaxFlow.h:73
drwnMaxFlow(unsigned maxNodes=0)
construct a maxflow/mincut problem with estimated maxNodes
Definition: drwnMaxFlow.h:52
virtual ~drwnMaxFlow()
destructor
Definition: drwnMaxFlow.h:60
Implementation of Boykov and Kolmogorov's maxflow algorithm.
Definition: drwnMaxFlow.h:197
vector< double > _targetEdges
edges entering the target
Definition: drwnMaxFlow.h:43
vector< _drwnCapacitatedEdge > _nodes
nodes and their outgoing internal edges
Definition: drwnMaxFlow.h:45
vector< double > _edgeWeights
internal edge weights
Definition: drwnMaxFlow.h:44
void addTargetEdge(int u, double cap)
add edge from nodeId to t
Definition: drwnMaxFlow.h:94
bool inSetS(int u) const
return true if u is in the s-set after calling solve. (note that sometimes a node can be in either S ...
Definition: drwnMaxFlow.h:157
void addSourceEdge(int u, double cap)
add edge from s to nodeId
Definition: drwnMaxFlow.h:87
map< int, pair< unsigned, unsigned > > _drwnCapacitatedEdge
references target node j and edge weights (i,j) and (j,i)
Definition: drwnMaxFlow.h:40
Implementation of Edmonds-Karp maxflow/min-cut algorithm.
Definition: drwnMaxFlow.h:174
vector< int > _parents
_parents flag for terminal state
Definition: drwnMaxFlow.h:202
Provides a queue datastructure on a fixed number of indexes. At most one copy of each index can appea...
Definition: drwnIndexQueue.h:38
Interface for maxflow/min-cut algorithms (for minimizing submodular quadratic pseudo-Boolean function...
Definition: drwnMaxFlow.h:32
vector< double > _sourceEdges
edges leaving the source
Definition: drwnMaxFlow.h:42
size_t numNodes() const
get number of nodes in the graph
Definition: drwnMaxFlow.h:65
double _flowValue
current flow value (includes constant)
Definition: drwnMaxFlow.h:46
vector< unsigned char > _cut
identifies which side of the cut a node falls
Definition: drwnMaxFlow.h:48
void addConstant(double c)
add constant flow to graph
Definition: drwnMaxFlow.h:82