mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-12-04 18:30:17 +00:00
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
parent
991a37e9ff
commit
d286529fdc
|
@ -2,8 +2,15 @@ from collections import deque
|
||||||
|
|
||||||
|
|
||||||
class BlossomAuxData:
|
class BlossomAuxData:
|
||||||
def __init__(self, queue: deque, parent: list[int], base: list[int],
|
def __init__(
|
||||||
in_blossom: list[bool], match: list[int], in_queue: list[bool]):
|
self,
|
||||||
|
queue: deque,
|
||||||
|
parent: list[int],
|
||||||
|
base: list[int],
|
||||||
|
in_blossom: list[bool],
|
||||||
|
match: list[int],
|
||||||
|
in_queue: list[bool],
|
||||||
|
):
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.base = base
|
self.base = base
|
||||||
|
@ -11,6 +18,7 @@ class BlossomAuxData:
|
||||||
self.match = match
|
self.match = match
|
||||||
self.in_queue = in_queue
|
self.in_queue = in_queue
|
||||||
|
|
||||||
|
|
||||||
class BlossomData:
|
class BlossomData:
|
||||||
def __init__(self, aux_data: BlossomAuxData, u: int, v: int, lca: int):
|
def __init__(self, aux_data: BlossomAuxData, u: int, v: int, lca: int):
|
||||||
self.aux_data = aux_data
|
self.aux_data = aux_data
|
||||||
|
@ -18,6 +26,7 @@ class BlossomData:
|
||||||
self.v = v
|
self.v = v
|
||||||
self.lca = lca
|
self.lca = lca
|
||||||
|
|
||||||
|
|
||||||
class EdmondsBlossomAlgorithm:
|
class EdmondsBlossomAlgorithm:
|
||||||
UNMATCHED = -1 # Constant to represent unmatched vertices
|
UNMATCHED = -1 # Constant to represent unmatched vertices
|
||||||
|
|
||||||
|
@ -72,8 +81,11 @@ class EdmondsBlossomAlgorithm:
|
||||||
parent[y] = current
|
parent[y] = current
|
||||||
augmenting_path_found = True
|
augmenting_path_found = True
|
||||||
# Augment along this path
|
# Augment along this path
|
||||||
(EdmondsBlossomAlgorithm
|
(
|
||||||
.update_matching(match, parent, y))
|
EdmondsBlossomAlgorithm.update_matching(
|
||||||
|
match, parent, y
|
||||||
|
)
|
||||||
|
)
|
||||||
break
|
break
|
||||||
|
|
||||||
# Case 2: y is matched, add y's match to the queue
|
# Case 2: y is matched, add y's match to the queue
|
||||||
|
@ -86,17 +98,25 @@ class EdmondsBlossomAlgorithm:
|
||||||
else:
|
else:
|
||||||
# Case 3: Both current and y have a parent;
|
# Case 3: Both current and y have a parent;
|
||||||
# check for a cycle/blossom
|
# check for a cycle/blossom
|
||||||
base_u = EdmondsBlossomAlgorithm.find_base(base,
|
base_u = EdmondsBlossomAlgorithm.find_base(
|
||||||
parent, current, y)
|
base, parent, current, y
|
||||||
|
)
|
||||||
if base_u != EdmondsBlossomAlgorithm.UNMATCHED:
|
if base_u != EdmondsBlossomAlgorithm.UNMATCHED:
|
||||||
EdmondsBlossomAlgorithm.contract_blossom(BlossomData(
|
EdmondsBlossomAlgorithm.contract_blossom(
|
||||||
BlossomAuxData(queue,
|
BlossomData(
|
||||||
|
BlossomAuxData(
|
||||||
|
queue,
|
||||||
parent,
|
parent,
|
||||||
base,
|
base,
|
||||||
in_blossom,
|
in_blossom,
|
||||||
match,
|
match,
|
||||||
in_queue),
|
in_queue,
|
||||||
current, y, base_u))
|
),
|
||||||
|
current,
|
||||||
|
y,
|
||||||
|
base_u,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Create result list of matched pairs
|
# Create result list of matched pairs
|
||||||
matching_result = []
|
matching_result = []
|
||||||
|
@ -138,15 +158,19 @@ class EdmondsBlossomAlgorithm:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def contract_blossom(blossom_data: BlossomData):
|
def contract_blossom(blossom_data: BlossomData):
|
||||||
for x in range(blossom_data.u,
|
for x in range(
|
||||||
blossom_data.aux_data.base[blossom_data.u] != blossom_data.lca):
|
blossom_data.u,
|
||||||
|
blossom_data.aux_data.base[blossom_data.u] != blossom_data.lca,
|
||||||
|
):
|
||||||
base_x = blossom_data.aux_data.base[x]
|
base_x = blossom_data.aux_data.base[x]
|
||||||
match_base_x = blossom_data.aux_data.base[blossom_data.aux_data.match[x]]
|
match_base_x = blossom_data.aux_data.base[blossom_data.aux_data.match[x]]
|
||||||
blossom_data.aux_data.in_blossom[base_x] = True
|
blossom_data.aux_data.in_blossom[base_x] = True
|
||||||
blossom_data.aux_data.in_blossom[match_base_x] = True
|
blossom_data.aux_data.in_blossom[match_base_x] = True
|
||||||
|
|
||||||
for x in range(blossom_data.v,
|
for x in range(
|
||||||
blossom_data.aux_data.base[blossom_data.v] != blossom_data.lca):
|
blossom_data.v,
|
||||||
|
blossom_data.aux_data.base[blossom_data.v] != blossom_data.lca,
|
||||||
|
):
|
||||||
base_x = blossom_data.aux_data.base[x]
|
base_x = blossom_data.aux_data.base[x]
|
||||||
match_base_x = blossom_data.aux_data.base[blossom_data.aux_data.match[x]]
|
match_base_x = blossom_data.aux_data.base[blossom_data.aux_data.match[x]]
|
||||||
blossom_data.aux_data.in_blossom[base_x] = True
|
blossom_data.aux_data.in_blossom[base_x] = True
|
||||||
|
|
|
@ -4,9 +4,8 @@ from graphs.edmonds_blossom_algorithm import EdmondsBlossomAlgorithm
|
||||||
|
|
||||||
|
|
||||||
class EdmondsBlossomAlgorithmTest(unittest.TestCase):
|
class EdmondsBlossomAlgorithmTest(unittest.TestCase):
|
||||||
|
|
||||||
def convert_matching_to_array(self, matching):
|
def convert_matching_to_array(self, matching):
|
||||||
""" Helper method to convert a
|
"""Helper method to convert a
|
||||||
list of matching pairs into a sorted 2D array.
|
list of matching pairs into a sorted 2D array.
|
||||||
"""
|
"""
|
||||||
# Convert the list of pairs into a list of lists
|
# Convert the list of pairs into a list of lists
|
||||||
|
@ -21,7 +20,7 @@ class EdmondsBlossomAlgorithmTest(unittest.TestCase):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def test_case_1(self):
|
def test_case_1(self):
|
||||||
""" Test Case 1: A triangle graph where vertices 0, 1, and 2 form a cycle. """
|
"""Test Case 1: A triangle graph where vertices 0, 1, and 2 form a cycle."""
|
||||||
edges = [[0, 1], [1, 2], [2, 0]]
|
edges = [[0, 1], [1, 2], [2, 0]]
|
||||||
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 3)
|
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 3)
|
||||||
|
|
||||||
|
@ -29,7 +28,7 @@ class EdmondsBlossomAlgorithmTest(unittest.TestCase):
|
||||||
assert expected == self.convert_matching_to_array(matching)
|
assert expected == self.convert_matching_to_array(matching)
|
||||||
|
|
||||||
def test_case_2(self):
|
def test_case_2(self):
|
||||||
""" Test Case 2: A disconnected graph with two components. """
|
"""Test Case 2: A disconnected graph with two components."""
|
||||||
edges = [[0, 1], [1, 2], [3, 4]]
|
edges = [[0, 1], [1, 2], [3, 4]]
|
||||||
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 5)
|
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 5)
|
||||||
|
|
||||||
|
@ -37,7 +36,7 @@ class EdmondsBlossomAlgorithmTest(unittest.TestCase):
|
||||||
assert expected == self.convert_matching_to_array(matching)
|
assert expected == self.convert_matching_to_array(matching)
|
||||||
|
|
||||||
def test_case_3(self):
|
def test_case_3(self):
|
||||||
""" Test Case 3: A cycle graph with an additional edge outside the cycle. """
|
"""Test Case 3: A cycle graph with an additional edge outside the cycle."""
|
||||||
edges = [[0, 1], [1, 2], [2, 3], [3, 0], [4, 5]]
|
edges = [[0, 1], [1, 2], [2, 3], [3, 0], [4, 5]]
|
||||||
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 6)
|
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 6)
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@ class EdmondsBlossomAlgorithmTest(unittest.TestCase):
|
||||||
assert expected == self.convert_matching_to_array(matching)
|
assert expected == self.convert_matching_to_array(matching)
|
||||||
|
|
||||||
def test_case_no_matching(self):
|
def test_case_no_matching(self):
|
||||||
""" Test Case 4: A graph with no edges. """
|
"""Test Case 4: A graph with no edges."""
|
||||||
edges = [] # No edges
|
edges = [] # No edges
|
||||||
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 3)
|
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 3)
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ class EdmondsBlossomAlgorithmTest(unittest.TestCase):
|
||||||
assert expected == self.convert_matching_to_array(matching)
|
assert expected == self.convert_matching_to_array(matching)
|
||||||
|
|
||||||
def test_case_large_graph(self):
|
def test_case_large_graph(self):
|
||||||
""" Test Case 5: A complex graph with multiple cycles and extra edges. """
|
"""Test Case 5: A complex graph with multiple cycles and extra edges."""
|
||||||
edges = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0], [1, 4], [2, 5]]
|
edges = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0], [1, 4], [2, 5]]
|
||||||
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 6)
|
matching = EdmondsBlossomAlgorithm.maximum_matching(edges, 6)
|
||||||
|
|
||||||
|
@ -69,5 +68,5 @@ class EdmondsBlossomAlgorithmTest(unittest.TestCase):
|
||||||
assert result in (possible_matching_1, possible_matching_2)
|
assert result in (possible_matching_1, possible_matching_2)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user