Simplify slack handling in delta2 tracking
This commit is contained in:
parent
9ee26584ab
commit
3a77749425
|
@ -613,7 +613,24 @@ class _MatchingContext:
|
|||
blossom.vertex_set.clear()
|
||||
del blossom.vertex_set
|
||||
|
||||
def edge_slack_2x_info(
|
||||
def edge_pseudo_slack_2x(self, e: int) -> float:
|
||||
"""Return 2 times the pseudo-slack of the specified edge.
|
||||
|
||||
The pseudo-slack of an edge ignores pending changes to vertex duals.
|
||||
|
||||
For an edge between two S-vertices (in different top-level blossoms),
|
||||
the true slack is the pseudo-slack minus 2 times the running sum
|
||||
of delta steps.
|
||||
|
||||
For an edge between an S-vertex and unlabeled vertex,
|
||||
the true slack is the pseudo-slack minus the running sum of delta
|
||||
steps, plus the pending offset of the top-level blossom that contains
|
||||
the unlabeled vertex.
|
||||
"""
|
||||
(x, y, w) = self.graph.edges[e]
|
||||
return self.vertex_dual_2x[x] + self.vertex_dual_2x[y] - 2 * w
|
||||
|
||||
def edge_slack_2x(
|
||||
self,
|
||||
x: int,
|
||||
y: int,
|
||||
|
@ -645,13 +662,6 @@ class _MatchingContext:
|
|||
dual_2x += by.vertex_dual_offset
|
||||
return dual_2x - 2 * w
|
||||
|
||||
def edge_slack_2x(self, e: int) -> float:
|
||||
"""Return 2 times the slack of the edge with index "e"."""
|
||||
(x, y, w) = self.graph.edges[e]
|
||||
bx = self.vertex_set_node[x].find()
|
||||
by = self.vertex_set_node[y].find()
|
||||
return self.edge_slack_2x_info(x, y, bx, by, w)
|
||||
|
||||
#
|
||||
# Least-slack edge tracking:
|
||||
#
|
||||
|
@ -689,36 +699,26 @@ class _MatchingContext:
|
|||
for blossom in self.trivial_blossom + self.nontrivial_blossom:
|
||||
blossom.delta2_node = None
|
||||
|
||||
def lset_add_vertex_edge(
|
||||
self,
|
||||
y: int,
|
||||
by: _Blossom,
|
||||
e: int,
|
||||
slack: float
|
||||
) -> None:
|
||||
def lset_add_vertex_edge(self, y: int, by: _Blossom, e: int) -> None:
|
||||
"""Add edge "e" from an S-vertex to unlabeled vertex or T-vertex "y".
|
||||
|
||||
This function takes time O(log(n)).
|
||||
"""
|
||||
|
||||
# TODO -- Simplify: We don't need to know the true slack of the edge,
|
||||
# only the pseudo-slack based on raw vertex duals and weight.
|
||||
prio = self.edge_pseudo_slack_2x(e)
|
||||
|
||||
best_edge = self.vertex_best_edge[y]
|
||||
if best_edge != -1:
|
||||
best_slack = self.edge_slack_2x(best_edge)
|
||||
if slack >= best_slack:
|
||||
best_prio = self.edge_pseudo_slack_2x(best_edge)
|
||||
if prio >= best_prio:
|
||||
return
|
||||
|
||||
self.vertex_best_edge[y] = e
|
||||
|
||||
(p, q, w) = self.graph.edges[e]
|
||||
prio = self.vertex_dual_2x[p] + self.vertex_dual_2x[q] - 2 * w
|
||||
prev_min = by.vertex_set.min_prio()
|
||||
self.vertex_set_node[y].set_prio(prio)
|
||||
|
||||
if (by.label == _LABEL_NONE) and (prio < prev_min):
|
||||
prio = slack + self.delta_sum_2x
|
||||
prio += by.vertex_dual_offset
|
||||
if by.delta2_node is None:
|
||||
by.delta2_node = self.delta2_queue.insert(prio, by)
|
||||
elif prio < by.delta2_node.prio:
|
||||
|
@ -1476,7 +1476,7 @@ class _MatchingContext:
|
|||
|
||||
# Check whether this edge is tight (has zero slack).
|
||||
# Only tight edges may be part of an alternating tree.
|
||||
slack = self.edge_slack_2x_info(x, y, bx, by, w)
|
||||
slack = self.edge_slack_2x(x, y, bx, by, w)
|
||||
if slack <= 0:
|
||||
if ylabel == _LABEL_NONE:
|
||||
# Assign label T to the blossom that contains "y".
|
||||
|
@ -1509,7 +1509,7 @@ class _MatchingContext:
|
|||
# any S-vertex. We do this for T-vertices and unlabeled
|
||||
# vertices. Edges which already have zero slack are still
|
||||
# tracked.
|
||||
self.lset_add_vertex_edge(y, by, e, slack)
|
||||
self.lset_add_vertex_edge(y, by, e)
|
||||
|
||||
# No further S vertices to scan, and no augmenting path found.
|
||||
return None
|
||||
|
|
Loading…
Reference in New Issue