Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit dcae258

Browse files
Release Managervbraun
authored andcommitted
Trac #19440: cluster seed is no longer hashable
With the recent change in the cluster code, {{{ sage: Q= ClusterQuiver(['D',4]) sage: hash(Q) Traceback (most recent call last): ... TypeError: <class 'sage.combinat.cluster_algebra_quiver.quiver.ClusterQuiver'> is not hashable }}} And this has very bad consequences ! URL: http://trac.sagemath.org/19440 Reported by: chapoton Ticket author(s): Frédéric Chapoton Reviewer(s): Christian Stump
2 parents dddc357 + be4fa45 commit dcae258

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

src/sage/combinat/cluster_algebra_quiver/cluster_seed.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ def __init__(self, data, frozen=None, is_principal=False, user_labels=None, user
213213

214214
# Copy the following attributes from data
215215
self._M = copy( data._M )
216+
self._M.set_immutable()
216217
self._B = copy( data._B )
217218
self._n = data._n
218219
self._m = data._m
@@ -269,6 +270,7 @@ def __init__(self, data, frozen=None, is_principal=False, user_labels=None, user
269270
quiver = ClusterQuiver( data )
270271

271272
self._M = copy(quiver._M) # B-tilde exchange matrix
273+
self._M.set_immutable()
272274
self._n = quiver._n
273275
self._m = quiver._m
274276
self._B = copy(self._M[:self._n,:self._n]) # Square Part of the B_matrix
@@ -397,6 +399,7 @@ def use_c_vectors(self, use=True, bot_is_c=False, force=False):
397399
self._C = copy(self._M[self._m:(self._n+self._m),:self._n])
398400
self._BC = copy(self._M)
399401
self._M = self._M[:self._m:self._n]
402+
self._M.set_immutable()
400403
self._bot_is_c = False
401404

402405
def use_g_vectors(self, use=True, force=False):
@@ -858,6 +861,27 @@ def __eq__(self, other):
858861
d_vec = self.d_matrix() == other.d_matrix()
859862
return g_vec and c_vec and d_vec and clusters and ExMat
860863

864+
def __hash__(self):
865+
"""
866+
Return a hash of ``self``.
867+
868+
EXAMPLES::
869+
870+
sage: Q = ClusterSeed(['A',5])
871+
sage: hash(Q) # indirect doctest
872+
-5649412990944896369 # 64-bit
873+
222337679 # 32-bit
874+
"""
875+
# mat_hash = self._M.__hash__()
876+
if self._use_fpolys:
877+
return tuple(self.cluster()).__hash__()
878+
elif self._use_g_vec:
879+
return self.g_matrix().__hash__()
880+
elif self._use_c_vec:
881+
return self.c_matrix().__hash__()
882+
elif self._use_d_vec:
883+
return self.d_matrix().__hash__()
884+
861885
def _repr_(self):
862886
r"""
863887
Returns the description of ``self``.
@@ -1077,7 +1101,7 @@ def b_matrix(self):
10771101
[ 0 0 0 1]
10781102
[ 0 0 -2 0]
10791103
"""
1080-
return copy( self._M )
1104+
return copy(self._M)
10811105

10821106
def ground_field(self):
10831107
r"""
@@ -2359,6 +2383,7 @@ def mutate(self, sequence, inplace=True):
23592383

23602384
seed._BC.mutate(k)
23612385
seed._M = copy(seed._BC[:n+m,:n])
2386+
self._M.set_immutable()
23622387

23632388
if seed._use_c_vec:
23642389
seed._C = seed._BC[n+m:2*n+m,:n+m]
@@ -3050,15 +3075,19 @@ def reset_coefficients( self ):
30503075
[ 0 1 0]
30513076
[ 0 0 1]
30523077
"""
3053-
n,m = self._n, self._m
3078+
n, m = self._n, self._m
30543079
if not n == m:
3055-
raise ValueError("The numbers of cluster variables and of frozen variables do not coincide.")
3080+
raise ValueError("The numbers of cluster variables "
3081+
"and of frozen variables do not coincide.")
3082+
newM = copy(self._M)
30563083
for i in xrange(m):
30573084
for j in xrange(n):
30583085
if i == j:
3059-
self._M[i+n,j] = 1
3086+
newM[i + n, j] = 1
30603087
else:
3061-
self._M[i+n,j] = 0
3088+
newM[i + n, j] = 0
3089+
self._M = newM
3090+
self._M.set_immutable()
30623091
self._quiver = None
30633092
self._is_principal = None
30643093

src/sage/combinat/cluster_algebra_quiver/quiver.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ def __init__( self, data, frozen=None ):
265265
print 'The input data is a quiver, therefore the additional parameter frozen is ignored.'
266266

267267
self._M = copy(data._M)
268+
self._M.set_immutable()
268269
self._n = data._n
269270
self._m = data._m
270271
self._digraph = copy( data._digraph )
@@ -280,6 +281,7 @@ def __init__( self, data, frozen=None ):
280281
print 'The input data is a matrix, therefore the additional parameter frozen is ignored.'
281282

282283
self._M = copy(data).sparse_matrix()
284+
self._M.set_immutable()
283285
self._n = n = self._M.ncols()
284286
self._m = m = self._M.nrows() - self._n
285287
self._digraph = _matrix_to_digraph( self._M )
@@ -344,6 +346,7 @@ def __init__( self, data, frozen=None ):
344346
self._digraph = dg
345347
self._vertex_dictionary = {}
346348
self._M = M
349+
self._M.set_immutable()
347350
if n+m == 0:
348351
self._description = 'Quiver without vertices'
349352
elif n+m == 1:
@@ -378,6 +381,18 @@ def __eq__(self, other):
378381
"""
379382
return isinstance(other, ClusterQuiver) and self._M == other._M
380383

384+
def __hash__(self):
385+
"""
386+
Return a hash of ``self``.
387+
388+
EXAMPLES::
389+
390+
sage: Q = ClusterQuiver(['A',5])
391+
sage: hash(Q) # indirect doctest
392+
16
393+
"""
394+
return self._M.__hash__()
395+
381396
def _repr_(self):
382397
"""
383398
Returns the description of ``self``.
@@ -715,7 +730,7 @@ def b_matrix(self):
715730
[ 0 0 0 1]
716731
[ 0 0 -2 0]
717732
"""
718-
return copy( self._M )
733+
return copy(self._M)
719734

720735
def digraph(self):
721736
"""
@@ -1292,6 +1307,7 @@ def mutate(self, data, inplace=True):
12921307
M = _edge_list_to_matrix( dg.edge_iterator(), n, m )
12931308
if inplace:
12941309
self._M = M
1310+
self._M.set_immutable()
12951311
self._digraph = dg
12961312
else:
12971313
Q = ClusterQuiver( M )
@@ -1402,6 +1418,7 @@ def reorient( self, data ):
14021418
dg_new.add_edge( edge[1],edge[0],edge[2] )
14031419
self._digraph = dg_new
14041420
self._M = _edge_list_to_matrix( dg_new.edges(), self._n, self._m )
1421+
self._M.set_immutable()
14051422
self._mutation_type = None
14061423
elif all( type(edge) in [list,tuple] and len(edge)==2 for edge in data ):
14071424
edges = self._digraph.edges(labels=False)
@@ -1411,6 +1428,7 @@ def reorient( self, data ):
14111428
self._digraph.delete_edge(edge[1],edge[0])
14121429
self._digraph.add_edge(edge[0],edge[1],label)
14131430
self._M = _edge_list_to_matrix( self._digraph.edges(), self._n, self._m )
1431+
self._M.set_immutable()
14141432
self._mutation_type = None
14151433
else:
14161434
raise ValueError('The order is no total order on the vertices of the quiver or a list of edges to be oriented.')

0 commit comments

Comments
 (0)