From 079fc8c944fdc2191a24155d99cea368ec717a5e Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 14 Aug 2024 09:51:30 +0900 Subject: [PATCH 1/4] Adding a hash to affine group elements and making sure the elements are immutable. --- src/sage/groups/affine_gps/group_element.py | 56 ++++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/src/sage/groups/affine_gps/group_element.py b/src/sage/groups/affine_gps/group_element.py index b1e3cd1e0cb..7bd4ecc15d1 100644 --- a/src/sage/groups/affine_gps/group_element.py +++ b/src/sage/groups/affine_gps/group_element.py @@ -119,15 +119,17 @@ def __init__(self, parent, A, b=0, convert=True, check=True): A = A.matrix() except AttributeError: pass - if isinstance(A, Matrix) and A.nrows() == A.ncols() == parent.degree()+1: + if isinstance(A, Matrix) and A.nrows() == A.ncols() == parent.degree() + 1: g = A d = parent.degree() A = g.submatrix(0, 0, d, d) - b = [ g[i,d] for i in range(d) ] + b = [g[i,d] for i in range(d)] convert = True if convert: A = parent.matrix_space()(A) b = parent.vector_space()(b) + A.set_immutable() + b.set_immutable() if check: # Note: the coercion framework expects that we raise TypeError for invalid input if not isinstance(A, Matrix): @@ -138,6 +140,14 @@ def __init__(self, parent, A, b=0, convert=True, check=True): raise TypeError('b must be an element of ' + str(parent.vector_space())) parent._element_constructor_check(A, b) super().__init__(parent) + if not A.is_immutable(): + from copy import copy + A = copy(A) + A.set_immutable() + if not b.is_immutable(): + from copy import copy + b = copy(b) + b.set_immutable() self._A = A self._b = b @@ -151,10 +161,12 @@ def A(self): sage: G = AffineGroup(3, QQ) sage: g = G([1,2,3,4,5,6,7,8,0], [10,11,12]) - sage: g.A() + sage: A = g.A(); A [1 2 3] [4 5 6] [7 8 0] + sage: A.is_immutable() + True """ return self._A @@ -168,8 +180,10 @@ def b(self): sage: G = AffineGroup(3, QQ) sage: g = G([1,2,3,4,5,6,7,8,0], [10,11,12]) - sage: g.b() + sage: b = g.b(); b (10, 11, 12) + sage: b.is_immutable() + True """ return self._b @@ -345,7 +359,9 @@ def _mul_(self, other): parent = self.parent() A = self._A * other._A b = self._b + self._A * other._b - return parent.element_class(parent, A, b, check=False) + A.set_immutable() + b.set_immutable() + return parent.element_class(parent, A, b, convert=False, check=False) def __call__(self, v): """ @@ -439,13 +455,14 @@ def _act_on_(self, x, self_on_left): x |-> [0 1] x + [0] sage: v = vector(GF(3), [1,-1]); v (1, 2) - sage: g*v + sage: g * v (1, 2) - sage: g*v == g.A() * v + g.b() + sage: g * v == g.A() * v + g.b() True """ if self_on_left: return self(x) + return None def __invert__(self): """ @@ -472,7 +489,9 @@ def __invert__(self): parent = self.parent() A = parent.matrix_space()(~self._A) b = -A * self.b() - return parent.element_class(parent, A, b, check=False) + A.set_immutable() + b.set_immutable() + return parent.element_class(parent, A, b, convert=False, check=False) def _richcmp_(self, other, op): """ @@ -497,6 +516,27 @@ def _richcmp_(self, other, op): return richcmp(self._b, other._b, op) + def __hash__(self): + """ + Return the hash of ``self``. + + OUTPUT: int + + EXAMPLES:: + + sage: F = AffineGroup(3, QQ) + sage: g = F([1,2,3,4,5,6,7,8,0], [10,11,12]) + sage: h = F([1,2,3,4,5,6,7,8,0], [10,11,0]) + sage: hash(g) == hash(h) + False + sage: hash(g) == hash(copy(g)) + True + sage: f = g * h + sage: hash(f) == hash((f.A(), f.b())) + True + """ + return hash((self._A, self._b)) + def list(self): """ Return list representation of ``self``. From c018e295eed98837117dec81b5afda68c4ea7dd4 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 20 Aug 2024 14:36:33 +0900 Subject: [PATCH 2/4] Moving the copy import. --- src/sage/groups/affine_gps/group_element.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/groups/affine_gps/group_element.py b/src/sage/groups/affine_gps/group_element.py index 7bd4ecc15d1..0bbede1b025 100644 --- a/src/sage/groups/affine_gps/group_element.py +++ b/src/sage/groups/affine_gps/group_element.py @@ -45,6 +45,7 @@ from sage.structure.element import MultiplicativeGroupElement from sage.structure.richcmp import richcmp, richcmp_not_equal +from copy import copy class AffineGroupElement(MultiplicativeGroupElement): r""" @@ -141,11 +142,9 @@ def __init__(self, parent, A, b=0, convert=True, check=True): parent._element_constructor_check(A, b) super().__init__(parent) if not A.is_immutable(): - from copy import copy A = copy(A) A.set_immutable() if not b.is_immutable(): - from copy import copy b = copy(b) b.set_immutable() self._A = A From f3ec5b3ff97d615b9e83e0c4ff678f667db9dc75 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 28 Nov 2024 18:00:03 +0900 Subject: [PATCH 3/4] Addressing reviewer comments. --- src/sage/groups/affine_gps/group_element.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/groups/affine_gps/group_element.py b/src/sage/groups/affine_gps/group_element.py index 0bbede1b025..a3b856a05d5 100644 --- a/src/sage/groups/affine_gps/group_element.py +++ b/src/sage/groups/affine_gps/group_element.py @@ -40,13 +40,13 @@ # http://www.gnu.org/licenses/ #***************************************************************************** +from copy import copy + from sage.structure.element import Matrix from sage.misc.cachefunc import cached_method from sage.structure.element import MultiplicativeGroupElement from sage.structure.richcmp import richcmp, richcmp_not_equal -from copy import copy - class AffineGroupElement(MultiplicativeGroupElement): r""" An affine group element. @@ -531,8 +531,8 @@ def __hash__(self): sage: hash(g) == hash(copy(g)) True sage: f = g * h - sage: hash(f) == hash((f.A(), f.b())) - True + sage: hash(f) == hash(~f) + False """ return hash((self._A, self._b)) From b10beaebe2bbead97aaca9551f5f7a232a492f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 28 Nov 2024 10:57:56 +0100 Subject: [PATCH 4/4] fix minor details --- src/sage/groups/affine_gps/group_element.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sage/groups/affine_gps/group_element.py b/src/sage/groups/affine_gps/group_element.py index a3b856a05d5..190a0180d1b 100644 --- a/src/sage/groups/affine_gps/group_element.py +++ b/src/sage/groups/affine_gps/group_element.py @@ -30,15 +30,15 @@ - Volker Braun """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2013 Volker Braun # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from copy import copy @@ -47,6 +47,7 @@ from sage.structure.element import MultiplicativeGroupElement from sage.structure.richcmp import richcmp, richcmp_not_equal + class AffineGroupElement(MultiplicativeGroupElement): r""" An affine group element.