Satsuma
a delicious .NET graph library
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Pages
Preflow.cs
Go to the documentation of this file.
1 #region License
2 /*This file is part of Satsuma Graph Library
3 Copyright © 2013 Balázs Szalkai
4 
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17 
18  2. Altered source versions must be plainly marked as such, and must not be
19  misrepresented as being the original software.
20 
21  3. This notice may not be removed or altered from any source
22  distribution.*/
23 #endregion
24 
25 using System;
26 using System.Collections.Generic;
27 using System.Linq;
28 
29 namespace Satsuma
30 {
34  public interface IFlow<TCapacity>
35  {
37  IGraph Graph { get; }
40  Func<Arc, TCapacity> Capacity { get; }
42  Node Source { get; }
44  Node Target { get; }
46  TCapacity FlowSize { get; }
49  IEnumerable<KeyValuePair<Arc, TCapacity>> NonzeroArcs { get; }
53  TCapacity Flow(Arc arc);
54  }
55 
61  public sealed class Preflow : IFlow<double>
62  {
63  public IGraph Graph { get; private set; }
64  public Func<Arc, double> Capacity { get; private set; }
65  public Node Source { get; private set; }
66  public Node Target { get; private set; }
67 
68  public double FlowSize { get; private set; }
69  private Dictionary<Arc, double> flow;
70 
74  public double Error { get; private set; }
75 
76  public Preflow(IGraph graph, Func<Arc, double> capacity, Node source, Node target)
77  {
78  Graph = graph;
79  Capacity = capacity;
80  Source = source;
81  Target = target;
82 
83  flow = new Dictionary<Arc, double>();
84 
85  // calculate bottleneck capacity to get an upper bound for the flow value
86  Dijkstra dijkstra = new Dijkstra(Graph, a => -Capacity(a), DijkstraMode.Maximum);
87  dijkstra.AddSource(Source);
88  dijkstra.RunUntilFixed(Target);
89  double bottleneckCapacity = -dijkstra.GetDistance(Target);
90 
91  if (double.IsPositiveInfinity(bottleneckCapacity))
92  {
93  // flow value is infinity
94  FlowSize = double.PositiveInfinity;
95  Error = 0;
96  for (Node n = Target, n2 = Node.Invalid; n != Source; n = n2)
97  {
98  Arc arc = dijkstra.GetParentArc(n);
99  flow[arc] = double.PositiveInfinity;
100  n2 = Graph.Other(arc, n);
101  }
102  }
103  else
104  {
105  // flow value is finite
106  if (double.IsNegativeInfinity(bottleneckCapacity))
107  bottleneckCapacity = 0; // Target is not accessible
108  U = Graph.ArcCount() * bottleneckCapacity;
109 
110  // calculate other upper bounds for the flow
111  double USource = 0;
112  foreach (var arc in Graph.Arcs(Source, ArcFilter.Forward))
113  if (Graph.Other(arc, Source) != Source)
114  {
115  USource += Capacity(arc);
116  if (USource > U) break;
117  }
118  U = Math.Min(U, USource);
119  double UTarget = 0;
120  foreach (var arc in Graph.Arcs(Target, ArcFilter.Backward))
121  if (Graph.Other(arc, Target) != Target)
122  {
123  UTarget += Capacity(arc);
124  if (UTarget > U) break;
125  }
126  U = Math.Min(U, UTarget);
127 
128  Supergraph sg = new Supergraph(Graph);
129  Node newSource = sg.AddNode();
130  artificialArc = sg.AddArc(newSource, Source, Directedness.Directed);
131 
132  CapacityMultiplier = Utils.LargestPowerOfTwo(long.MaxValue / U);
133  if (CapacityMultiplier == 0) CapacityMultiplier = 1;
134 
135  var p = new IntegerPreflow(sg, IntegralCapacity, newSource, Target);
136  FlowSize = p.FlowSize / CapacityMultiplier;
137  Error = Graph.ArcCount() / CapacityMultiplier;
138  foreach (var kv in p.NonzeroArcs) flow[kv.Key] = kv.Value / CapacityMultiplier;
139  }
140  }
141 
142  private Arc artificialArc;
143  private double U, CapacityMultiplier;
144  private long IntegralCapacity(Arc arc)
145  {
146  return (long)( CapacityMultiplier * (arc == artificialArc ? U : Math.Min(U, Capacity(arc))) );
147  }
148 
149  public IEnumerable<KeyValuePair<Arc, double>> NonzeroArcs
150  {
151  get
152  {
153  return flow.Where(kv => kv.Value != 0.0);
154  }
155  }
156 
157  public double Flow(Arc arc)
158  {
159  double result;
160  flow.TryGetValue(arc, out result);
161  return result;
162  }
163  }
164 
168  public sealed class IntegerPreflow : IFlow<long>
169  {
170  public IGraph Graph { get; private set; }
171  public Func<Arc, long> Capacity { get; private set; }
172  public Node Source { get; private set; }
173  public Node Target { get; private set; }
174 
175  public long FlowSize { get; private set; }
176 
177  private readonly Dictionary<Arc, long> flow;
178  private readonly Dictionary<Node, long> excess;
179  private readonly Dictionary<Node, long> label;
180  private readonly PriorityQueue<Node, long> active;
181 
182  public IntegerPreflow(IGraph graph, Func<Arc, long> capacity, Node source, Node target)
183  {
184  Graph = graph;
185  Capacity = capacity;
186  Source = source;
187  Target = target;
188 
189  flow = new Dictionary<Arc, long>();
190  excess = new Dictionary<Node, long>();
191  label = new Dictionary<Node, long>();
192  active = new PriorityQueue<Node, long>();
193 
194  Run();
195 
196  excess = null;
197  label = null;
198  active = null;
199  }
200 
201  private void Run()
202  {
203  foreach (var node in Graph.Nodes())
204  {
205  label[node] = (node == Source ? -Graph.NodeCount() : 0);
206  excess[node] = 0;
207  }
208  long outgoing = 0;
209  foreach (var arc in Graph.Arcs(Source, ArcFilter.Forward))
210  {
211  Node other = Graph.Other(arc, Source);
212  if (other == Source) continue;
213 
214  long initialFlow = (Graph.U(arc) == Source ? Capacity(arc) : -Capacity(arc));
215  if (initialFlow == 0) continue;
216  flow[arc] = initialFlow;
217  initialFlow = Math.Abs(initialFlow);
218  checked { outgoing += initialFlow; } // throws if outgoing source capacity is too large
219  excess[other] += initialFlow;
220  if (other != Target) active[other] = 0;
221  }
222  excess[Source] = -outgoing;
223 
224  while (active.Count > 0)
225  {
226  long label_z;
227  Node z = active.Peek(out label_z);
228  active.Pop();
229  long e = excess[z];
230  long newlabel_z = long.MinValue;
231 
232  foreach (var arc in Graph.Arcs(z))
233  {
234  Node u = Graph.U(arc), v = Graph.V(arc);
235  if (u == v) continue;
236  Node other = (z == u ? v : u);
237  bool isEdge = Graph.IsEdge(arc);
238 
239  long f;
240  flow.TryGetValue(arc, out f);
241  long c = Capacity(arc);
242  long lowerBound = (isEdge ? -Capacity(arc) : 0);
243 
244  if (u == z)
245  {
246  if (f == c) continue; // saturated, cannot push
247 
248  long label_other = label[other];
249  if (label_other <= label_z)
250  newlabel_z = Math.Max(newlabel_z, label_other - 1);
251  else
252  {
253  long amount = (long)Math.Min((ulong)e, (ulong)(c - f));
254  flow[arc] = f + amount;
255  excess[v] += amount;
256  if (v != Source && v != Target) active[v] = label[v];
257  e -= amount;
258  if (e == 0) break;
259  }
260  }
261  else
262  {
263  if (f == lowerBound) continue; // cannot pull
264 
265  long label_other = label[other];
266  if (label_other <= label_z)
267  newlabel_z = Math.Max(newlabel_z, label_other - 1);
268  else
269  {
270  long amount = (long)Math.Min((ulong)e, (ulong)(f - lowerBound));
271  flow[arc] = f - amount;
272  excess[u] += amount;
273  if (u != Source && u != Target) active[u] = label[u];
274  e -= amount;
275  if (e == 0) break;
276  }
277  }
278  }
279 
280  excess[z] = e;
281  if (e > 0)
282  {
283  if (newlabel_z == long.MinValue) throw new InvalidOperationException("Internal error.");
284  active[z] = label[z] = label_z = newlabel_z;
285  }
286  }
287 
288  FlowSize = 0;
289  foreach (var arc in Graph.Arcs(Source))
290  {
291  Node u = Graph.U(arc), v = Graph.V(arc);
292  if (u == v) continue;
293  long f;
294  if (!flow.TryGetValue(arc, out f)) continue;
295  if (u == Source) FlowSize += f; else FlowSize -= f;
296  }
297  }
298 
299  public IEnumerable<KeyValuePair<Arc, long>> NonzeroArcs
300  {
301  get
302  {
303  return flow.Where(kv => kv.Value != 0);
304  }
305  }
306 
307  public long Flow(Arc arc)
308  {
309  long result;
310  flow.TryGetValue(arc, out result);
311  return result;
312  }
313  }
314 }