1
0
Fork 0

Use FIFO queue for S-vertices

This commit is contained in:
Joris van Rantwijk 2023-04-06 20:50:06 +02:00
parent caac6825a6
commit 0e79e1d2f6
2 changed files with 30 additions and 13 deletions

View File

@ -6,6 +6,7 @@ from __future__ import annotations
import sys import sys
import math import math
import collections
from collections.abc import Sequence from collections.abc import Sequence
from typing import NamedTuple, Optional from typing import NamedTuple, Optional
@ -545,9 +546,8 @@ class _MatchingContext:
# between "x" and any S-vertex, or -1 if no such edge has been found. # between "x" and any S-vertex, or -1 if no such edge has been found.
self.vertex_best_edge: list[int] = num_vertex * [-1] self.vertex_best_edge: list[int] = num_vertex * [-1]
# "queue" is a list of S-vertices that must be scanned. # Queue of S-vertices to be scanned.
# We call it a queue, but it is actually a stack. self.queue: collections.deque[int] = collections.deque()
self.queue: list[int] = []
def edge_slack_2x(self, e: int) -> int|float: def edge_slack_2x(self, e: int) -> int|float:
"""Return 2 times the slack of the edge with index "e". """Return 2 times the slack of the edge with index "e".
@ -1361,7 +1361,7 @@ class _MatchingContext:
while self.queue: while self.queue:
# Take a vertex from the queue. # Take a vertex from the queue.
x = self.queue.pop() x = self.queue.popleft()
# Double-check that "x" is an S-vertex. # Double-check that "x" is an S-vertex.
bx = self.vertex_top_blossom[x] bx = self.vertex_top_blossom[x]

View File

@ -194,22 +194,22 @@ class TestMaximumWeightMatching(unittest.TestCase):
def test46_expand_unlabeled_blossom(self): def test46_expand_unlabeled_blossom(self):
"""expand blossom before assigning label T""" """expand blossom before assigning label T"""
# #
# 5--[2]--3--[4] # 3--[1]
# / | # / |
# [0]--5--[1] 5 # [2]--1--[4] 7
# \ | # \ |
# 5--[3]--3--[5] # 5--[3]--5--[5]
# #
self.assertEqual( self.assertIn(
mwm([(0,1,5), (1,2,5), (1,3,5), (2,3,5), (2,4,3), (3,5,3)]), mwm([(1,3,7), (1,4,3), (2,4,1), (3,4,5), (3,5,5)]),
[(0,1), (2,4), (3,5)]) ([(1,3), (2,4)], [(1,4), (3,5)]))
def test47_expand_unlabeled_outer(self): def test47_expand_unlabeled_outer(self):
"""expand outer blossom before assigning label T""" """expand outer blossom before assigning label T"""
# #
# [3]--10--[1]--15--[2]--12--[5] # [3]--10--[1]--15--[2]--12--[5]
# _/ \_ | | # _/ \_ | |
# 11 16_ 8 15 # 11 16_ 8 15
# / \ | | # / \ | |
# [4] [6]---7--[7] # [4] [6]---7--[7]
# #
@ -217,6 +217,19 @@ class TestMaximumWeightMatching(unittest.TestCase):
mwm([(1,2,15), (1,3,10), (1,4,11), (1,6,17), (2,5,12), (2,6,8), (5,7,15), (6,7,7)]), mwm([(1,2,15), (1,3,10), (1,4,11), (1,6,17), (2,5,12), (2,6,8), (5,7,15), (6,7,7)]),
[(1,4), (2,6), (5,7)]) [(1,4), (2,6), (5,7)])
def test48_expand_unlabeled_nested(self):
"""expand nested blossom before assigning label T"""
#
# [5]--11--[1]--11 14--[3]
# | \ / |
# 12 [4] 14
# | / \ |
# [6]--11--[2]--12 11--[7]
#
self.assertEqual(
mwm([(1,2,12), (1,4,11), (1,5,11), (2,4,12), (2,6,11), (3,4,14), (3,7,14), (4,7,11)]),
[(1,5), (2,4), (3,7)])
def test_fail_bad_input(self): def test_fail_bad_input(self):
"""bad input values""" """bad input values"""
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
@ -315,6 +328,10 @@ class TestCornerCases(unittest.TestCase):
pairs = mwm([(0,2,13), (1,2,11), (2,3,39), (2,4,17), (3,4,35)]) pairs = mwm([(0,2,13), (1,2,11), (2,3,39), (2,4,17), (3,4,35)])
self.assertEqual(pairs, [(0,2), (3,4)]) self.assertEqual(pairs, [(0,2), (3,4)])
def test17(self):
pairs = mwm([(0,1,48), (0,2,44), (0,4,48), (1,4,36), (3,4,31)])
self.assertEqual(pairs, [(0,2), (1,4)])
class TestAdjustWeightForMaxCardinality(unittest.TestCase): class TestAdjustWeightForMaxCardinality(unittest.TestCase):
"""Test adjust_weights_for_maximum_cardinality_matching() function.""" """Test adjust_weights_for_maximum_cardinality_matching() function."""