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

Commit 87cf9da

Browse files
committed
Include an element's parent in _cache_key()
See http://trac.sagemath.org/ticket/16316#comment:8 for a discussion of this.
1 parent 6e09cab commit 87cf9da

File tree

4 files changed

+34
-46
lines changed

4 files changed

+34
-46
lines changed

src/sage/misc/cachefunc.pyx

+7-7
Original file line numberDiff line numberDiff line change
@@ -483,21 +483,21 @@ def _cache_key(o):
483483
sage: a = K(1); a
484484
1 + O(3^20)
485485
sage: _cache_key(a)
486-
(((1,),), 0, 20)
486+
(..., ((1,),), 0, 20)
487487
488488
This function works if ``o`` is a tuple. In this case it unpacks its
489489
entries recursively::
490490
491491
sage: o = (1, 2, (3, a))
492492
sage: _cache_key(o)
493-
(1, 2, (3, (((1,),), 0, 20)))
493+
(1, 2, (3, (..., ((1,),), 0, 20)))
494494
495495
Note that tuples are only partially unpacked if some of its entries are
496496
hashable::
497497
498-
sage: o = (matrix([1, 2, 3]), a)
498+
sage: o = (1/2, a)
499499
sage: _cache_key(o)
500-
([1 2 3], (((1,),), 0, 20))
500+
(1/2, (..., ((1,),), 0, 20))
501501
502502
.. SEEALSO::
503503
@@ -844,7 +844,7 @@ cdef class CachedFunction(object):
844844
sage: f(y)
845845
1 + O(2^2)
846846
sage: f.cache
847-
{(((((1,),), 0, 1),), ()): 1 + O(2), (((((1,),), 0, 2),), ()): 1 + O(2^2)}
847+
{(((..., ((1,),), 0, 2),), ()): 1 + O(2^2), (((..., ((1,),), 0, 1),), ()): 1 + O(2)}
848848
849849
"""
850850
# We shortcut a common case of no arguments
@@ -1192,7 +1192,7 @@ cdef class WeakCachedFunction(CachedFunction):
11921192
sage: f(y)
11931193
(1 + O(2^20))*t + 1 + O(2^2)
11941194
sage: list(f.cache.keys())
1195-
[((((((1,),), 0, 2), (((1,),), 0, 20)),), ()), ((((((1,),), 0, 1), (((1,),), 0, 20)),), ())]
1195+
[(((..., ((..., ((1,),), 0, 1), (..., ((1,),), 0, 20))),), ()), (((..., ((..., ((1,),), 0, 2), (..., ((1,),), 0, 20))),), ())]
11961196
11971197
"""
11981198
# We shortcut a common case of no arguments
@@ -1744,7 +1744,7 @@ cdef class CachedMethodCaller(CachedFunction):
17441744
sage: a.f(y)
17451745
1 + O(2^2)
17461746
sage: a.f.cache
1747-
{(((((1,),), 0, 1),), ()): 1 + O(2), (((((1,),), 0, 2),), ()): 1 + O(2^2)}
1747+
{(((..., ((1,),), 0, 2),), ()): 1 + O(2^2), (((..., ((1,),), 0, 1),), ()): 1 + O(2)}
17481748
17491749
"""
17501750
if self._instance is None:

src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx

+8-9
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,7 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement):
474474

475475
def _cache_key(self):
476476
r"""
477-
Return a hashable key which uniquely identifies this element among all
478-
elements in the parent.
477+
Return a hashable key which identifies this element.
479478
480479
This enables caching for `p`-adic numbers which are not hashable.
481480
@@ -502,26 +501,26 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement):
502501
``_cache_key`` which is hashable and uniquely identifies them::
503502
504503
sage: a._cache_key()
505-
(((0, 1),), 0, 20)
504+
(..., ((0, 1),), 0, 20)
506505
sage: b._cache_key()
507-
(((0, 1),), 0, 1)
506+
(..., ((0, 1),), 0, 1)
508507
509508
TESTS:
510509
511510
Check that zero values are handled correctly::
512511
513512
sage: K.zero()._cache_key()
514-
0
513+
(..., 0)
515514
sage: K(0,1)._cache_key()
516-
(0, 1)
515+
(..., 0, 1)
517516
518517
"""
519518
if self._is_exact_zero():
520-
return 0
519+
return (id(self.parent()), 0)
521520
elif self._is_inexact_zero():
522-
return 0, self.valuation()
521+
return (id(self.parent()), 0, self.valuation())
523522
else:
524-
return tuple(tuple(c) if isinstance(c,list) else c for c in self.unit_part().list()), self.valuation(), self.precision_relative()
523+
return id(self.parent()), tuple(tuple(c) if isinstance(c,list) else c for c in self.unit_part().list()), self.valuation(), self.precision_relative()
525524

526525
cdef int _set_inexact_zero(self, long absprec) except -1:
527526
"""

src/sage/rings/polynomial/polynomial_element.pyx

+4-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ AUTHORS:
1414
- Simon King: Use a faster way of conversion from the base ring.
1515
1616
- Julian Rueth (2012-05-25,2014-05-09): Fixed is_squarefree() for imperfect
17-
fields, fixed division without remainder over QQbar, added ``_cache_key``
17+
fields, fixed division without remainder over QQbar; added ``_cache_key``
1818
for polynomials with unhashable coefficients
1919
2020
- Simon King (2013-10): Implement copying of :class:`PolynomialBaseringInjection`.
@@ -832,8 +832,7 @@ cdef class Polynomial(CommutativeAlgebraElement):
832832

833833
def _cache_key(self):
834834
"""
835-
Return a key which uniquely identifies this element among all elements
836-
in the parent.
835+
Return a key which identifies this element.
837836
838837
.. SEEALSO::
839838
@@ -852,7 +851,7 @@ cdef class Polynomial(CommutativeAlgebraElement):
852851
...
853852
TypeError: unhashable type: 'sage.rings.padics.padic_ZZ_pX_CR_element.pAdicZZpXCRElement'
854853
sage: f._cache_key()
855-
(0, 1 + O(2^20))
854+
(..., (0, 1 + O(2^20)))
856855
857856
sage: @cached_function
858857
....: def foo(t): return t
@@ -861,7 +860,7 @@ cdef class Polynomial(CommutativeAlgebraElement):
861860
(1 + O(2^20))*x
862861
863862
"""
864-
return tuple(self)
863+
return id(self.parent()), tuple(self)
865864

866865
# you may have to replicate this boilerplate code in derived classes if you override
867866
# __richcmp__. The python documentation at http://docs.python.org/api/type-structs.html

src/sage/structure/sage_object.pyx

+15-25
Original file line numberDiff line numberDiff line change
@@ -223,14 +223,13 @@ cdef class SageObject:
223223

224224
def _cache_key(self):
225225
r"""
226-
Return a key which uniquely identifies this objects for caching. The
227-
output must be hashable itself or a tuple of objects which are hashable
228-
or define a ``_cache_key``.
226+
Return a key which identifies this objects for caching. The output must
227+
be hashable itself or a tuple of objects which are hashable or define a
228+
``_cache_key``.
229229
230230
This method will only be called if the object itself is not hashable.
231231
232-
For most objects this will just be the object itself. However, some
233-
immutable objects (such as `p`-adic numbers) can not implement a
232+
Some immutable objects (such as `p`-adic numbers) can not implement a
234233
reasonable hash function because their ``==`` operator has been
235234
modified to return ``True`` for objects which might behave differently
236235
in some computations::
@@ -266,33 +265,24 @@ cdef class SageObject:
266265
False
267266
268267
sage: b._cache_key()
269-
(((0, 1),), 0, 1)
268+
(..., ((0, 1),), 0, 1)
270269
sage: c._cache_key()
271-
(((0, 1), (1,)), 0, 20)
270+
(..., ((0, 1), (1,)), 0, 20)
272271
273-
Note that such ``_cache_key`` often does not uniquely identify an
274-
object in a strict sense::
272+
An implementation must make sure that for elements ``a`` and ``b``, if ``a != b``, then also ``a._cache_key() != b._cache_key()``. In pratice this means that the ``_cache_key`` should always include the ``id`` of the parent.
275273
276274
sage: S.<a> = Qq(4)
277275
sage: d = a + O(2)
278-
sage: b._cache_key() == d._cache_key()
279-
True
280-
281-
However, this kind of behaviour is common for many elements with
282-
different parents. Special care has to be taken when mixing such
283-
elements in caches::
284-
285-
sage: A = matrix([[1]],base_ring=GF(2))
286-
sage: A.set_immutable()
287-
sage: B = matrix([[1]],base_ring=GF(3))
288-
sage: B.set_immutable()
289-
sage: A == B
290-
True
291-
sage: hash(A) == hash(B)
292-
True
276+
sage: b._cache_key() == d._cache_key() # this would be True if the parents were not included
277+
False
293278
294279
"""
295-
return self
280+
try:
281+
hash(self)
282+
except TypeError:
283+
raise NotImplementedError("{} is not hashable and does not implement _cache_key()".format(type(self)))
284+
else:
285+
assert False, "_cache_key() must not be called for hashable elements"
296286

297287
#############################################################################
298288
# DATABASE Related code

0 commit comments

Comments
 (0)