From cee4b90aa03808b51b35d76e345a36929a2f63f1 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Wed, 8 Jan 2025 13:00:42 +0100 Subject: [PATCH 1/4] faster method __mul__ for graphs --- src/sage/graphs/generic_graph.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index badd28f4fb8..95e8ec74ebd 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -774,9 +774,17 @@ def __mul__(self, n): raise TypeError('multiplication of a graph and a nonpositive integer is not defined') if n == 1: return copy(self) - return sum([self] * (n - 1), self) - else: - raise TypeError('multiplication of a graph and something other than an integer is not defined') + # Use a logarithmic number of additions to build the result + bits = Integer(n).bits() + parts = [self] + parts.extend(parts[-1] + parts[-1] for _ in range(1, len(bits))) + H, _ = parts.pop(), bits.pop() + while bits: + g, b = parts.pop(), bits.pop() + if b: + H += g + return H + raise TypeError('multiplication of a graph and something other than an integer is not defined') def __ne__(self, other): """ From 6253a319669e644cdba12a0f6178fbe37baa0c07 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Wed, 8 Jan 2025 17:55:29 +0100 Subject: [PATCH 2/4] #39300: add doctests --- src/sage/graphs/generic_graph.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 95e8ec74ebd..22a350f332b 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -768,6 +768,17 @@ def __mul__(self, n): [0, 1, 2, 3, 4, 5, 6, 7, 8] sage: H = G * 1; H Cycle graph: Graph on 3 vertices + + TESTS:: + + sage: Graph(1) * -1 + Traceback (most recent call last) + ... + TypeError: multiplication of a graph and a nonpositive integer is not defined + sage: Graph(1) * 2.5 + Traceback (most recent call last) + ... + TypeError: multiplication of a graph and something other than an integer is not defined """ if isinstance(n, (int, Integer)): if n < 1: From 37729d5470d6de7aaff9314595f6dc449ae44361 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Wed, 8 Jan 2025 18:43:40 +0100 Subject: [PATCH 3/4] #39300: correct doctests --- src/sage/graphs/generic_graph.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 22a350f332b..c2ec7959847 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -772,11 +772,11 @@ def __mul__(self, n): TESTS:: sage: Graph(1) * -1 - Traceback (most recent call last) + Traceback (most recent call last): ... TypeError: multiplication of a graph and a nonpositive integer is not defined sage: Graph(1) * 2.5 - Traceback (most recent call last) + Traceback (most recent call last): ... TypeError: multiplication of a graph and something other than an integer is not defined """ From 8e82bfc20a1f924e00e9fd53646e15218ce8a38a Mon Sep 17 00:00:00 2001 From: dcoudert Date: Thu, 9 Jan 2025 10:10:48 +0100 Subject: [PATCH 4/4] #39300: a faster solution --- src/sage/graphs/generic_graph.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index c2ec7959847..662704b8fbc 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -763,7 +763,7 @@ def __mul__(self, n): sage: G = graphs.CycleGraph(3) sage: H = G * 3; H - Cycle graph disjoint_union Cycle graph disjoint_union Cycle graph: Graph on 9 vertices + Disjoint union of 3 copies of Cycle graph: Graph on 9 vertices sage: H.vertices(sort=True) [0, 1, 2, 3, 4, 5, 6, 7, 8] sage: H = G * 1; H @@ -785,16 +785,17 @@ def __mul__(self, n): raise TypeError('multiplication of a graph and a nonpositive integer is not defined') if n == 1: return copy(self) - # Use a logarithmic number of additions to build the result - bits = Integer(n).bits() - parts = [self] - parts.extend(parts[-1] + parts[-1] for _ in range(1, len(bits))) - H, _ = parts.pop(), bits.pop() - while bits: - g, b = parts.pop(), bits.pop() - if b: - H += g - return H + ns = self.order() + ntot = n * ns + vint = {u: i for i, u in enumerate(self)} + edges = ((i, j, l) for u, v, l in self.edge_iterator() + for i, j in zip(range(vint[u], ntot, ns), + range(vint[v], ntot, ns))) + return self.__class__([range(ntot), edges], format='vertices_and_edges', + loops=self.allows_loops(), + multiedges=self.allows_multiple_edges(), + immutable=self.is_immutable(), + name=f"Disjoint union of {n} copies of {str(self)}") raise TypeError('multiplication of a graph and something other than an integer is not defined') def __ne__(self, other): @@ -828,7 +829,7 @@ def __rmul__(self, n): sage: G = graphs.CycleGraph(3) sage: H = int(3) * G; H - Cycle graph disjoint_union Cycle graph disjoint_union Cycle graph: Graph on 9 vertices + Disjoint union of 3 copies of Cycle graph: Graph on 9 vertices sage: H.vertices(sort=True) [0, 1, 2, 3, 4, 5, 6, 7, 8] """