Skip to content

Commit

Permalink
Adding a hash to affine group elements and making sure the elements a…
Browse files Browse the repository at this point in the history
…re immutable.
  • Loading branch information
tscrim committed Aug 14, 2024
1 parent 0f34773 commit 0435f6e
Showing 1 changed file with 48 additions and 8 deletions.
56 changes: 48 additions & 8 deletions src/sage/groups/affine_gps/group_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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

Expand All @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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):
"""
Expand Down Expand Up @@ -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):
"""
Expand All @@ -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):
"""
Expand All @@ -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``.
Expand Down

0 comments on commit 0435f6e

Please sign in to comment.