From 4362765128bb43080c9fc7ae4e9552a94ebd585e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?= <slabqc@gmail.com> Date: Mon, 24 Feb 2025 16:11:59 +0100 Subject: [PATCH] ajout has_claw_decomposition --- slabbe/graph.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/slabbe/graph.py b/slabbe/graph.py index b5fcde2..e703080 100644 --- a/slabbe/graph.py +++ b/slabbe/graph.py @@ -1048,3 +1048,77 @@ def minimal_eulerian_paths(G, cost=None): return paths + +def has_claw_decomposition(G, certificate=False): + r""" + Return whether a graph has a claw decomposition. + + This is an answer to the question posted at + https://ask.sagemath.org/question/81610/test-if-a-graph-has-a-claw-decomposition/ + + INPUT: + + - ``G`` -- undirected graph + - ``certificate`` -- boolean + + OUTPUT: + + a boolean or 2-tuple (boolean, solution) if certificate is True + + EXAMPLES:: + + sage: from slabbe.graph import has_claw_decomposition + sage: G1 = Graph( [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), + ....: (1, 5), (2, 3), (2, 4), (3, 5), (4, 6), (4, 7), (5, 6), (5, 7), (6, 8), + ....: (6, 10), (7, 9), (7, 11), (8, 9), (8, 10), (9, 11), (10, 11)]) + sage: has_claw_decomposition(G1) + False + sage: has_claw_decomposition(G1, certificate=True) + (False, None) + + :: + + sage: G2 = Graph([(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), + ....: (1, 5), (2, 4), (2, 5), (3, 5), (4, 5)]) + sage: has_claw_decomposition(G2) + True + sage: has_claw_decomposition(G2, certificate=True) # random + (True, + [[(0, 1), (1, 2), (1, 5)], + [(0, 3), (1, 3), (3, 5)], + [(0, 2), (2, 4), (2, 5)], + [(0, 4), (1, 4), (4, 5)]]) + + """ + import itertools + from sage.combinat.matrices.dancing_links import dlx_solver + + rows = [] + + id_to_edge = [frozenset(edge) for edge in G.edges(labels=False)] + edge_to_id = {edge:i for (i,edge) in enumerate(id_to_edge)} + + for u in G: + u_neighbors = G.neighbors(u) + + for three_neighbors in itertools.combinations(u_neighbors, 3): + L = [edge_to_id[frozenset((u,v))] for v in three_neighbors] + L.sort() + rows.append(L) + + d = dlx_solver(rows) + + solution = d.one_solution() + has_solution = not solution is None + + if not certificate: + return has_solution + else: + if has_solution: + solution_vertices = [[tuple(id_to_edge[id]) for id in rows[row_number]] + for row_number in solution] + return (has_solution, solution_vertices) + else: + return (has_solution, solution) + + -- GitLab