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()
|
blossom.vertex_set.clear()
|
||||||
del blossom.vertex_set
|
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,
|
self,
|
||||||
x: int,
|
x: int,
|
||||||
y: int,
|
y: int,
|
||||||
|
@ -645,13 +662,6 @@ class _MatchingContext:
|
||||||
dual_2x += by.vertex_dual_offset
|
dual_2x += by.vertex_dual_offset
|
||||||
return dual_2x - 2 * w
|
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:
|
# Least-slack edge tracking:
|
||||||
#
|
#
|
||||||
|
@ -689,36 +699,26 @@ class _MatchingContext:
|
||||||
for blossom in self.trivial_blossom + self.nontrivial_blossom:
|
for blossom in self.trivial_blossom + self.nontrivial_blossom:
|
||||||
blossom.delta2_node = None
|
blossom.delta2_node = None
|
||||||
|
|
||||||
def lset_add_vertex_edge(
|
def lset_add_vertex_edge(self, y: int, by: _Blossom, e: int) -> None:
|
||||||
self,
|
|
||||||
y: int,
|
|
||||||
by: _Blossom,
|
|
||||||
e: int,
|
|
||||||
slack: float
|
|
||||||
) -> None:
|
|
||||||
"""Add edge "e" from an S-vertex to unlabeled vertex or T-vertex "y".
|
"""Add edge "e" from an S-vertex to unlabeled vertex or T-vertex "y".
|
||||||
|
|
||||||
This function takes time O(log(n)).
|
This function takes time O(log(n)).
|
||||||
"""
|
"""
|
||||||
|
prio = self.edge_pseudo_slack_2x(e)
|
||||||
# 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.
|
|
||||||
|
|
||||||
best_edge = self.vertex_best_edge[y]
|
best_edge = self.vertex_best_edge[y]
|
||||||
if best_edge != -1:
|
if best_edge != -1:
|
||||||
best_slack = self.edge_slack_2x(best_edge)
|
best_prio = self.edge_pseudo_slack_2x(best_edge)
|
||||||
if slack >= best_slack:
|
if prio >= best_prio:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.vertex_best_edge[y] = e
|
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()
|
prev_min = by.vertex_set.min_prio()
|
||||||
self.vertex_set_node[y].set_prio(prio)
|
self.vertex_set_node[y].set_prio(prio)
|
||||||
|
|
||||||
if (by.label == _LABEL_NONE) and (prio < prev_min):
|
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:
|
if by.delta2_node is None:
|
||||||
by.delta2_node = self.delta2_queue.insert(prio, by)
|
by.delta2_node = self.delta2_queue.insert(prio, by)
|
||||||
elif prio < by.delta2_node.prio:
|
elif prio < by.delta2_node.prio:
|
||||||
|
@ -1476,7 +1476,7 @@ class _MatchingContext:
|
||||||
|
|
||||||
# Check whether this edge is tight (has zero slack).
|
# Check whether this edge is tight (has zero slack).
|
||||||
# Only tight edges may be part of an alternating tree.
|
# 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 slack <= 0:
|
||||||
if ylabel == _LABEL_NONE:
|
if ylabel == _LABEL_NONE:
|
||||||
# Assign label T to the blossom that contains "y".
|
# 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
|
# 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.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.
|
# No further S vertices to scan, and no augmenting path found.
|
||||||
return None
|
return None
|
||||||
|
|
Loading…
Reference in New Issue