1
0
Fork 0

Check that unmatched vertices have zero dual

This commit is contained in:
Joris van Rantwijk 2023-02-12 22:55:08 +01:00
parent be0f5c3881
commit 4dc7befd9d
1 changed files with 22 additions and 11 deletions

View File

@ -1758,15 +1758,14 @@ def _verify_blossom_edges(
blossom_vertices = blossom.vertices() blossom_vertices = blossom.vertices()
blossom_num_vertex = len(blossom_vertices) blossom_num_vertex = len(blossom_vertices)
# Check that all blossoms with positive dual are "full". # Check that all blossoms are "full".
# A blossom is full if all except one of its vertices are # A blossom is full if all except one of its vertices are
# matched to another vertex in the blossom. # matched to another vertex in the blossom.
if blossom.dual_var > 0:
blossom_num_matched = path_num_matched[depth] blossom_num_matched = path_num_matched[depth]
if blossom_num_vertex != 2 * blossom_num_matched + 1: if blossom_num_vertex != 2 * blossom_num_matched + 1:
raise MatchingError( raise MatchingError(
"Verification failed:" "Verification failed: blossom non-full"
f" blossom with dual={blossom.dual_var}" f" dual={blossom.dual_var}"
f" nvertex={blossom_num_vertex}" f" nvertex={blossom_num_vertex}"
f" nmatched={blossom_num_matched}") f" nmatched={blossom_num_matched}")
@ -1821,12 +1820,24 @@ def _verify_optimum(ctx: _MatchingContext) -> None:
f" inconsistent with {num_matched_edge} matched edges") f" inconsistent with {num_matched_edge} matched edges")
# Check that all dual variables are non-negative. # Check that all dual variables are non-negative.
assert min(ctx.vertex_dual_2x) >= 0 for x in range(num_vertex):
if ctx.vertex_dual_2x[x] < 0:
raise MatchingError(
"Verification failed:"
f" vertex {x} has negative dual {ctx.vertex_dual_2x[x]/2}")
for blossom in ctx.nontrivial_blossom: for blossom in ctx.nontrivial_blossom:
if blossom.dual_var < 0: if blossom.dual_var < 0:
raise MatchingError("Verification failed:" raise MatchingError("Verification failed:"
f" negative blossom dual {blossom.dual_var}") f" negative blossom dual {blossom.dual_var}")
# Check that all unmatched vertices have zero dual.
for x in range(num_vertex):
if ctx.vertex_mate[x] == -1 and ctx.vertex_dual_2x[x] != 0:
raise MatchingError(
f"Verification failed: Unmatched vertex {x}"
f" has non-zero dual {ctx.vertex_dual_2x[x]/2}")
# Calculate the slack of each edge. # Calculate the slack of each edge.
# A correction will be needed for edges inside blossoms. # A correction will be needed for edges inside blossoms.
edge_slack_2x: list[int|float] = [ edge_slack_2x: list[int|float] = [
@ -1835,7 +1846,7 @@ def _verify_optimum(ctx: _MatchingContext) -> None:
# Descend down each top-level blossom. # Descend down each top-level blossom.
# Adjust edge slacks to account for the duals of its containing blossoms. # Adjust edge slacks to account for the duals of its containing blossoms.
# And check that blossoms with non-zero dual are full. # And check that all blossoms are full.
# This takes total time O(n**2). # This takes total time O(n**2).
for blossom in ctx.nontrivial_blossom: for blossom in ctx.nontrivial_blossom:
if blossom.parent is None: if blossom.parent is None: