-
Notifications
You must be signed in to change notification settings - Fork 1
/
flow_network.py
189 lines (146 loc) · 5.41 KB
/
flow_network.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
from random import randint
class FlowNetwork:
"""
Flow-Network data structure.
"""
def __init__(self):
"""
Generates a flow network.
"""
self.adjacent = {}
self.capacity = {}
self.flow = {}
def getCapacity(self, edge):
"""
Returns edge's capacity.
"""
return self.capacity.get(edge, 0)
def getFlow(self, edge):
"""
Returns edge's flow.
"""
return self.flow.get(edge, 0)
def getFlowAcrossVertex(self, vertex):
"""
Returns the flow crossing vertex
"""
return sum(self.getFlow((vertex, toVertex)) for toVertex in self.adjacent[vertex])
def getResidualCapacity(self, edge):
"""
Returns edge's residual capacity.
"""
return self.getCapacity(edge) - self.getFlow(edge)
def setFlow(self, edge, value):
"""
Sets edge's flow to value.
"""
self.flow[edge] = value
self.flow[edge[::-1]] = - value
def increaseFlow(self, edge, value):
"""
Increases edge's flow value units.
"""
self.flow[edge] += value
self.flow[edge[::-1]] -= value
def vertices(self):
"""
Returns the set of vertices in the network.
"""
return self.adjacent.keys()
def edges(self):
"""
Returns the set of edges in the network.
"""
return self.capacity.keys()
def neighbors(self, u):
"""
Returns the vertices adjacent to u in the network.
"""
return filter(lambda v: self.getCapacity((u,v)) > 0, self.adjacent[u])
def residualNeighbors(self, u):
"""
Returns the vertices adjacent to u in the resigual network.
"""
return filter(lambda v: self.getResidualCapacity((u,v)) > 0, self.adjacent[u])
def loadNetworkFromFile(self, file):
"""
Loads a flow network from a file containing a list of edges
of the form: fromVertex, toVertex, capacity
"""
for line in open(file, 'r'):
fromVertex, toVertex, capacity = map(int, line.split())
self.addEdge(fromVertex, toVertex, capacity)
def randomNetwork(self, numVertices, numEdges, capacityRange):
"""
Generates a random flow network with the given parameters.
"""
for _ in range(numEdges):
fromVertex, toVertex = None, None
while fromVertex == toVertex or (fromVertex, toVertex) in self.capacity:
fromVertex = randint(1, numVertices)
toVertex = randint(1, numVertices)
capacity = randint(1, capacityRange)
self.addEdge(fromVertex, toVertex, capacity)
def addVertex(self, v):
"""
Inserts a vertex into the network.
"""
self.adjacent.setdefault(v, list())
def addEdge(self, fromVertex, toVertex, capacity):
"""
Inserts an edge into the network.
"""
if self.isValidEdge(fromVertex, toVertex, capacity):
self.adjacent.setdefault(fromVertex, []).append(toVertex)
self.adjacent.setdefault(toVertex, []).append(fromVertex)
self.capacity[(fromVertex, toVertex)] = capacity
self.flow[(fromVertex, toVertex)] = 0
self.flow[(toVertex, fromVertex)] = 0
def isValidEdge(self, fromVertex, toVertex, capacity):
"""
Verifies the validity of an edge.
"""
return fromVertex != toVertex \
and capacity > 0 \
and (toVertex, fromVertex) not in self.capacity
def showFlow(self):
"""
Represents the flow across the network.
"""
def edgesFromVertex(u):
"""
Represents the flow across the given vertex.
"""
edgeRepresentation = lambda v: f"({u}, {v}, {self.getCapacity((u, v))}, {self.getFlow((u,v))})"
return ", ".join(map(edgeRepresentation, sorted(self.adjacent[u])))
def adjacencyLists():
"""
Represents the flow across all relevant vertices.
"""
anyNeighbor = lambda u: any(self.neighbors(u))
verticesWithNeighbors = filter(anyNeighbor, sorted(self.vertices()))
return map(edgesFromVertex, verticesWithNeighbors)
return print("\n".join(adjacencyLists()))
def __str__(self):
"""
Returns a string that represents the network.
"""
def edgesFromVertex(u):
"""
Represents edges incident to the given vertex.
"""
edgeRepresentation = lambda v: f"({u}, {v}, {self.capacity[(u, v)]})"
return ", ".join(map(edgeRepresentation, self.residualNeighbors(u)))
def adjacencyLists():
"""
Represents edges incident to relevant vertices
"""
anyNeighbor = lambda u: any(self.neighbors(u))
verticesWithNeighbors = filter(anyNeighbor, sorted(self.vertices()))
return map(edgesFromVertex, verticesWithNeighbors)
return "\n".join(adjacencyLists())
def __repr__(self):
"""
Represents the flow network.
"""
return str(self)