From 0e80ea5d6fbf079d356a9f5c8056fe328d4d1f26 Mon Sep 17 00:00:00 2001 From: manueldilullo Date: Fri, 15 Oct 2021 15:13:35 +0200 Subject: [PATCH 1/6] matching algorithm for min vertex cover problem --- graphs/matching_min_vertex_cover.py | 56 +++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 graphs/matching_min_vertex_cover.py diff --git a/graphs/matching_min_vertex_cover.py b/graphs/matching_min_vertex_cover.py new file mode 100644 index 000000000000..18dc90fecb04 --- /dev/null +++ b/graphs/matching_min_vertex_cover.py @@ -0,0 +1,56 @@ +""" +* Author: Manuel Di Lullo (https://github.com/manueldilullo) +* Description: Approximization algorithm for minimum vertex cover problem. + Matching Approach. Uses graphs represented with an adjacency list + +URL: https://mathworld.wolfram.com/MinimumVertexCover.html +URL: https://www.princeton.edu/~aaa/Public/Teaching/ORF523/ORF523_Lec6.pdf +""" + +def matching_min_vertex_cover(graph: dict) -> set: + """ + APX Algorithm for min Vertex Cover using Matching Approach + @input: graph (graph stored in an adjacency list where each vertex + is represented with an integer) + @example: + >>> graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} + >>> matching_min_vertex_cover(graph) + {0, 1, 2, 4} + """ + # chosen_vertices = set of chosen vertices + chosen_vertices = set() + # edges = list of graph's edges + edges = get_edges(graph) + + # while there are still elements in edges' list + # take an arbitrary edge (u,v) and add his extremity to s + # then remove all arcs adjacent to the u and v + while edges: + u, v = edges.pop() + chosen_vertices.add(u) + chosen_vertices.add(v) + for edge in edges.copy(): + if (u in edge) or (v in edge): + edges.discard(edge) + return chosen_vertices + +def get_edges(graph: dict) -> tuple: + """ + Function that returns a set of couples that represents + the set of all the edges + @input: graph (graph stored in an adjacency list where each vertex + is represented with an integer) + """ + edges = set() + for node_from in graph.keys(): + for node_to in graph[node_from]: + edges.add((node_from, node_to)) + return edges + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + # graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} + # print(f"Matching vertex cover:\n{matching_min_vertex_cover(graph)}") \ No newline at end of file From b04e61504dadfb4856a1a3662e4167f40be02681 Mon Sep 17 00:00:00 2001 From: manueldilullo Date: Fri, 15 Oct 2021 15:16:03 +0200 Subject: [PATCH 2/6] fixed hint on row 37 --- graphs/matching_min_vertex_cover.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/matching_min_vertex_cover.py b/graphs/matching_min_vertex_cover.py index 18dc90fecb04..17994e48599e 100644 --- a/graphs/matching_min_vertex_cover.py +++ b/graphs/matching_min_vertex_cover.py @@ -34,7 +34,7 @@ def matching_min_vertex_cover(graph: dict) -> set: edges.discard(edge) return chosen_vertices -def get_edges(graph: dict) -> tuple: +def get_edges(graph: dict) -> set: """ Function that returns a set of couples that represents the set of all the edges From 97ba99fe366b34552ae9d48f930f9967ee869668 Mon Sep 17 00:00:00 2001 From: manueldilullo Date: Fri, 15 Oct 2021 15:18:07 +0200 Subject: [PATCH 3/6] changed variable names --- graphs/matching_min_vertex_cover.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/graphs/matching_min_vertex_cover.py b/graphs/matching_min_vertex_cover.py index 17994e48599e..d467af6b3d06 100644 --- a/graphs/matching_min_vertex_cover.py +++ b/graphs/matching_min_vertex_cover.py @@ -7,6 +7,7 @@ URL: https://www.princeton.edu/~aaa/Public/Teaching/ORF523/ORF523_Lec6.pdf """ + def matching_min_vertex_cover(graph: dict) -> set: """ APX Algorithm for min Vertex Cover using Matching Approach @@ -23,17 +24,18 @@ def matching_min_vertex_cover(graph: dict) -> set: edges = get_edges(graph) # while there are still elements in edges' list - # take an arbitrary edge (u,v) and add his extremity to s - # then remove all arcs adjacent to the u and v + # take an arbitrary edge (node_from,node_to) and add his extremity to s + # then remove all arcs adjacent to the node_from and node_to while edges: - u, v = edges.pop() - chosen_vertices.add(u) - chosen_vertices.add(v) + node_from, node_to = edges.pop() + chosen_vertices.add(node_from) + chosen_vertices.add(node_to) for edge in edges.copy(): - if (u in edge) or (v in edge): + if (node_from in edge) or (node_to in edge): edges.discard(edge) return chosen_vertices + def get_edges(graph: dict) -> set: """ Function that returns a set of couples that represents @@ -47,10 +49,11 @@ def get_edges(graph: dict) -> set: edges.add((node_from, node_to)) return edges + if __name__ == "__main__": import doctest doctest.testmod() # graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} - # print(f"Matching vertex cover:\n{matching_min_vertex_cover(graph)}") \ No newline at end of file + # print(f"Matching vertex cover:\n{matching_min_vertex_cover(graph)}") From 014c4cd10a46524104d0a7107ddbfb35da00b4a5 Mon Sep 17 00:00:00 2001 From: manueldilullo Date: Fri, 15 Oct 2021 15:21:25 +0200 Subject: [PATCH 4/6] provided doctest for get_edges function --- graphs/matching_min_vertex_cover.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/graphs/matching_min_vertex_cover.py b/graphs/matching_min_vertex_cover.py index d467af6b3d06..19e5384b815e 100644 --- a/graphs/matching_min_vertex_cover.py +++ b/graphs/matching_min_vertex_cover.py @@ -42,6 +42,10 @@ def get_edges(graph: dict) -> set: the set of all the edges @input: graph (graph stored in an adjacency list where each vertex is represented with an integer) + @example: + >>> graph = {0: [1, 3], 1: [0, 3], 2: [0, 3], 3: [0, 1, 2]} + >>> get_edges(graph) + {(0, 1), (3, 1), (0, 3), (2, 0), (3, 0), (2, 3), (1, 0), (3, 2), (1, 3)} """ edges = set() for node_from in graph.keys(): From 5c486031a9ecc2a34062c04bc66b3910501ca4e6 Mon Sep 17 00:00:00 2001 From: manueldilullo Date: Fri, 15 Oct 2021 16:37:56 +0200 Subject: [PATCH 5/6] Removed dict.keys() iteration --- graphs/matching_min_vertex_cover.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/graphs/matching_min_vertex_cover.py b/graphs/matching_min_vertex_cover.py index 19e5384b815e..3ea272df953a 100644 --- a/graphs/matching_min_vertex_cover.py +++ b/graphs/matching_min_vertex_cover.py @@ -24,14 +24,14 @@ def matching_min_vertex_cover(graph: dict) -> set: edges = get_edges(graph) # while there are still elements in edges' list - # take an arbitrary edge (node_from,node_to) and add his extremity to s - # then remove all arcs adjacent to the node_from and node_to + # take an arbitrary edge (from_node,to_node) and add his extremity to s + # then remove all arcs adjacent to the from_node and to_node while edges: - node_from, node_to = edges.pop() - chosen_vertices.add(node_from) - chosen_vertices.add(node_to) + from_node, to_node = edges.pop() + chosen_vertices.add(from_node) + chosen_vertices.add(to_node) for edge in edges.copy(): - if (node_from in edge) or (node_to in edge): + if (from_node in edge) or (to_node in edge): edges.discard(edge) return chosen_vertices @@ -48,9 +48,9 @@ def get_edges(graph: dict) -> set: {(0, 1), (3, 1), (0, 3), (2, 0), (3, 0), (2, 3), (1, 0), (3, 2), (1, 3)} """ edges = set() - for node_from in graph.keys(): - for node_to in graph[node_from]: - edges.add((node_from, node_to)) + for from_node, to_nodes in graph.items(): + for to_node in to_nodes: + edges.add((from_node, to_node)) return edges From 1e7c9bc93c610f6e23ef79448245fcbd805dbe98 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 15 Oct 2021 16:47:07 +0200 Subject: [PATCH 6/6] Update matching_min_vertex_cover.py --- graphs/matching_min_vertex_cover.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/graphs/matching_min_vertex_cover.py b/graphs/matching_min_vertex_cover.py index 3ea272df953a..5ac944ec1a07 100644 --- a/graphs/matching_min_vertex_cover.py +++ b/graphs/matching_min_vertex_cover.py @@ -12,7 +12,7 @@ def matching_min_vertex_cover(graph: dict) -> set: """ APX Algorithm for min Vertex Cover using Matching Approach @input: graph (graph stored in an adjacency list where each vertex - is represented with an integer) + is represented as an integer) @example: >>> graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} >>> matching_min_vertex_cover(graph) @@ -23,25 +23,24 @@ def matching_min_vertex_cover(graph: dict) -> set: # edges = list of graph's edges edges = get_edges(graph) - # while there are still elements in edges' list - # take an arbitrary edge (from_node,to_node) and add his extremity to s - # then remove all arcs adjacent to the from_node and to_node + # While there are still elements in edges list, take an arbitrary edge + # (from_node, to_node) and add his extremity to chosen_vertices and then + # remove all arcs adjacent to the from_node and to_node while edges: from_node, to_node = edges.pop() chosen_vertices.add(from_node) chosen_vertices.add(to_node) for edge in edges.copy(): - if (from_node in edge) or (to_node in edge): + if from_node in edge or to_node in edge: edges.discard(edge) return chosen_vertices def get_edges(graph: dict) -> set: """ - Function that returns a set of couples that represents - the set of all the edges - @input: graph (graph stored in an adjacency list where each vertex - is represented with an integer) + Return a set of couples that represents all of the edges. + @input: graph (graph stored in an adjacency list where each vertex is + represented as an integer) @example: >>> graph = {0: [1, 3], 1: [0, 3], 2: [0, 3], 3: [0, 1, 2]} >>> get_edges(graph)