Check that unmatched vertices have zero dual
This commit is contained in:
parent
be0f5c3881
commit
4dc7befd9d
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue