Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add hash for free group.
  • Loading branch information
cxzhong committed Dec 8, 2025
commit 82afbf30f51e12f63fb7556085894de77bd0f19c
40 changes: 22 additions & 18 deletions src/sage/groups/finitely_presented.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@
sage: g = a * b
sage: M1 = matrix([[1,0],[0,2]])
sage: M2 = matrix([[0,1],[1,0]])
sage: g(3, 5)
15
sage: g(M1, M1)
[1 0]
[0 4]
sage: M1*M2 == M2*M1 # matrices do not commute
False
sage: g(M1, M2)
Expand Down Expand Up @@ -271,8 +266,9 @@ def __hash__(self):
Return a hash value for this element.

For finite groups, this uses the permutation representation via GAP
to ensure that equal elements have equal hashes. For infinite groups,
a :exc:`NotImplementedError` is raised.
to ensure that equal elements have equal hashes. For free groups
(no relators), the Tietze tuple provides a canonical form.
For other infinite groups, a :exc:`NotImplementedError` is raised.

For finite groups, hashing is based on the permutation representation,
so equal elements have equal hashes::
Expand All @@ -284,14 +280,24 @@ def __hash__(self):
sage: hash(H.one()) == hash(H.gen(0)^2) # a^2 = 1
True

For infinite groups, hashing raises an error::
For free groups (no relators), hashing uses the Tietze tuple since
the reduced word form is canonical::

sage: F.<a,b> = FreeGroup()
sage: G = F / [] # free group, no relations
sage: hash(G.gen(0)) == hash(G.gen(0))
True
sage: hash(G.gen(0)) != hash(G.gen(1))
True

For other infinite groups, hashing raises an error::

sage: F.<a,b> = FreeGroup()
sage: G = F / [a*b*a^-1*b^-1] # Z x Z, infinite
sage: hash(G.gen(0))
Traceback (most recent call last):
...
NotImplementedError: hashing is only supported for finite finitely presented groups
NotImplementedError: hashing is only supported for finite or free finitely presented groups

Test :issue:`40549` is fixed::

Expand All @@ -302,9 +308,13 @@ def __hash__(self):
sage: print(gr.num_verts())
52
"""
if not self.parent().is_finite():
raise NotImplementedError("hashing is only supported for finite finitely presented groups")
gap_iso = libgap.IsomorphismPermGroup(self.parent().gap())
G = self.parent()
# Check if the group is free (no relations) - fast path
if not G.relations():
return hash(self.Tietze())
if not G.is_finite():
raise NotImplementedError("hashing is only supported for finite or free finitely presented groups")
gap_iso = libgap.IsomorphismPermGroup(G.gap())
perm = libgap.Image(gap_iso, self.gap())
return hash(perm)

Expand Down Expand Up @@ -385,16 +395,10 @@ def __call__(self, *values, **kwds):

sage: A, B = H.gens()
sage: w = A^2 * B
sage: w(2,2)
8
sage: w(3,3)
27
sage: w(1,2)
Traceback (most recent call last):
...
ValueError: the values do not satisfy all relations of the group
sage: w(1, 2, check=False) # result depends on presentation of the group element
2
"""
values = list(values)
if kwds.get('check', True):
Expand Down
Loading