1
0
Fork 0

Avoid redundant calls to edge_slack_2x()

This commit is contained in:
Joris van Rantwijk 2023-02-07 15:46:39 +01:00
parent 14b5a032a7
commit fc31657a56
1 changed files with 23 additions and 12 deletions

View File

@ -433,19 +433,22 @@ class _VertexBestEdgeTracking:
for x in range(self.num_vertex): for x in range(self.num_vertex):
self.vertex_best_edge[x] = -1 self.vertex_best_edge[x] = -1
def add_edge(self, ctx: _MatchingContext, y: int, e: int) -> None: def add_edge(self,
"""Add the edge with index "e" from an S-vertex to unlabeled vertex ctx: _MatchingContext,
or T-vertex "y". y: int,
e: int,
slack: int|float
) -> None:
"""Add edge "e" from an S-vertex to unlabeled vertex or T-vertex "y".
This function takes time O(1) per call. This function takes time O(1) per call.
This function takes total time O(m) per stage. This function is called O(m) times per stage.
""" """
best_edge = self.vertex_best_edge[y] best_edge = self.vertex_best_edge[y]
if best_edge == -1: if best_edge == -1:
self.vertex_best_edge[y] = e self.vertex_best_edge[y] = e
else: else:
best_slack = ctx.edge_slack_2x(best_edge) best_slack = ctx.edge_slack_2x(best_edge)
slack = ctx.edge_slack_2x(e)
if slack < best_slack: if slack < best_slack:
self.vertex_best_edge[y] = e self.vertex_best_edge[y] = e
@ -532,12 +535,17 @@ class _BlossomBestEdgeTracking:
assert self.blossom_best_edge_set[b] is None assert self.blossom_best_edge_set[b] is None
self.blossom_best_edge_set[b] = [] self.blossom_best_edge_set[b] = []
def add_edge(self, ctx: _MatchingContext, b: int, e: int) -> None: def add_edge(
"""Add the edge with index "e" from S-blossom "b" to another self,
S-blossom. ctx: _MatchingContext,
b: int,
e: int,
slack: int|float
) -> None:
"""Add edge "e" from S-blossom "b" to another S-blossom.
This function takes time O(1) per call. This function takes time O(1) per call.
This function takes total time O(m) per stage. This function is called O(m) times per stage.
""" """
# Update the least-slack edge from blossom "b" to any other # Update the least-slack edge from blossom "b" to any other
# S-blossom. # S-blossom.
@ -546,7 +554,6 @@ class _BlossomBestEdgeTracking:
self.blossom_best_edge[b] = e self.blossom_best_edge[b] = e
else: else:
best_slack = ctx.edge_slack_2x(best_edge) best_slack = ctx.edge_slack_2x(best_edge)
slack = ctx.edge_slack_2x(e)
if slack < best_slack: if slack < best_slack:
self.blossom_best_edge[b] = e self.blossom_best_edge[b] = e
@ -799,6 +806,8 @@ class _MatchingContext:
Multiplication by 2 ensures that the return value is an integer Multiplication by 2 ensures that the return value is an integer
if all edge weights are integers. if all edge weights are integers.
This function is called O(m) times per stage.
""" """
(x, y, w) = self.graph.edges[e] (x, y, w) = self.graph.edges[e]
assert self.vertex_blossom[x] != self.vertex_blossom[y] assert self.vertex_blossom[x] != self.vertex_blossom[y]
@ -1417,6 +1426,7 @@ class _MatchingContext:
adjacent_edges = self.graph.adjacent_edges adjacent_edges = self.graph.adjacent_edges
# Process S-vertices waiting to be scanned. # Process S-vertices waiting to be scanned.
# This loop runs through O(n) iterations per stage.
while self.queue: while self.queue:
# Take a vertex from the queue. # Take a vertex from the queue.
@ -1427,6 +1437,7 @@ class _MatchingContext:
assert self.blossom_label[bx] == _LABEL_S assert self.blossom_label[bx] == _LABEL_S
# Scan the edges that are incident on "x". # Scan the edges that are incident on "x".
# This loop runs through O(m) iterations per stage.
for e in adjacent_edges[x]: for e in adjacent_edges[x]:
(p, q, _w) = edges[e] (p, q, _w) = edges[e]
y = p if p != x else q # TODO : consider abstracting this y = p if p != x else q # TODO : consider abstracting this
@ -1461,14 +1472,14 @@ class _MatchingContext:
elif ylabel == _LABEL_S: elif ylabel == _LABEL_S:
# Update tracking of least-slack edges between S-blossoms. # Update tracking of least-slack edges between S-blossoms.
self.blossom_best_edges.add_edge(self, bx, e) self.blossom_best_edges.add_edge(self, bx, e, slack)
if ylabel != _LABEL_S: if ylabel != _LABEL_S:
# Update tracking of least-slack edges from vertex "y" to # Update tracking of least-slack edges from vertex "y" to
# any S-vertex. We do this for T-vertices and unlabeled # any S-vertex. We do this for T-vertices and unlabeled
# vertices. Edges which already have zero slack are still # vertices. Edges which already have zero slack are still
# tracked. # tracked.
self.vertex_best_edges.add_edge(self, y, e) self.vertex_best_edges.add_edge(self, y, e, slack)
# No further S vertices to scan, and no augmenting path found. # No further S vertices to scan, and no augmenting path found.
return None return None