From 35b8b6ec6dcbd3dcf25e54937aec668322e5ad1c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 15:33:02 -0700 Subject: [PATCH 01/19] ModulesWithBasis.ElementMethod.support: Return a SupportView --- src/sage/categories/modules_with_basis.py | 8 ++--- src/sage/structure/support_view.py | 44 +++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 src/sage/structure/support_view.py diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 22f5a6d8f07..0664ae33b7d 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -1534,7 +1534,7 @@ def length(self): def support(self): """ - Return a list of the objects indexing the basis of + Return an iterable of the objects indexing the basis of ``self.parent()`` whose corresponding coefficients of ``self`` are non-zero. @@ -1555,9 +1555,9 @@ def support(self): sage: sorted(z.support()) [[1], [1, 1, 1], [2, 1], [4]] """ - zero = self.parent().base_ring().zero() - return [key for key, coeff in self.monomial_coefficients(copy=False).items() - if coeff != zero] + from sage.structure.support_view import SupportView + mc = self.monomial_coefficients(copy=False) + return SupportView(mc) def monomials(self): """ diff --git a/src/sage/structure/support_view.py b/src/sage/structure/support_view.py new file mode 100644 index 00000000000..13631e3d89e --- /dev/null +++ b/src/sage/structure/support_view.py @@ -0,0 +1,44 @@ +r""" +Iterable of the keys of a Mapping associated with nonzero values +""" + +from collections.abc import MappingView, Sequence, Set + + +class SupportView(MappingView, Sequence, Set): + + def __init__(self, mapping, *, zero=None): + self._mapping = mapping + self._zero = zero + + def __len__(self): + length = 0 + for key in self: + length += 1 + return length + + def __getitem__(self, index): + for i, key in enumerate(self): + if i == index: + return key + raise IndexError + + def __iter__(self): + zero = self._zero + if zero is None: + for key, value in self._mapping.items(): + if value: + yield key + else: + for key, value in self._mapping.items(): + if value != zero: + yield key + + def __contains__(self, key): + try: + value = self._mapping[key] + except KeyError: + return False + if zero is None: + return bool(value) + return value != zero From 8ae8f09538745e3388340d9307e2b661eae0148a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 15:34:08 -0700 Subject: [PATCH 02/19] src/sage/combinat/crystals, src/sage/categories/*crystals*: Use collections.abc for isinstance --- src/sage/categories/crystals.py | 15 ++++++++------- src/sage/combinat/crystals/subcrystal.py | 4 +++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py index ec7a5865398..1cfbf9175ab 100644 --- a/src/sage/categories/crystals.py +++ b/src/sage/categories/crystals.py @@ -19,6 +19,7 @@ # https://www.gnu.org/licenses/ #***************************************************************************** +import collections.abc from sage.misc.cachefunc import cached_method from sage.misc.abstract_method import abstract_method @@ -779,10 +780,10 @@ def crystal_morphism(self, on_gens, codomain=None, if codomain is None: if hasattr(on_gens, 'codomain'): codomain = on_gens.codomain() - elif isinstance(on_gens, (list, tuple)): + elif isinstance(on_gens, collections.abc.Sequence): if on_gens: codomain = on_gens[0].parent() - elif isinstance(on_gens, dict): + elif isinstance(on_gens, collections.abc.Mapping): if on_gens: codomain = next(iter(on_gens.values())).parent() else: @@ -1845,7 +1846,7 @@ def __init__(self, parent, cartan_type=None, scaling_factors = {i: 1 for i in index_set} if virtualization is None: virtualization = {i: (i,) for i in index_set} - elif not isinstance(virtualization, dict): + elif not isinstance(virtualization, collections.abc.Mapping): try: virtualization = dict(virtualization) except (TypeError, ValueError): @@ -2057,16 +2058,16 @@ def __init__(self, parent, on_gens, cartan_type=None, virtualization, scaling_factors) if gens is None: - if isinstance(on_gens, dict): + if isinstance(on_gens, collections.abc.Mapping): gens = on_gens.keys() else: gens = parent.domain().module_generators self._gens = tuple(gens) # Make sure on_gens is a function - if isinstance(on_gens, dict): + if isinstance(on_gens, collections.abc.Mapping): f = lambda x: on_gens[x] - elif isinstance(on_gens, (list, tuple)): + elif isinstance(on_gens, collections.abc.Sequence): if len(self._gens) != len(on_gens): raise ValueError("invalid generator images") d = {x: y for x, y in zip(self._gens, on_gens)} @@ -2579,7 +2580,7 @@ def __call__(self, on_gens, cartan_type=None, index_set=None, generators=None, if automorphism is not None: if virtualization is not None: raise ValueError("the automorphism and virtualization cannot both be specified") - if not isinstance(automorphism, dict): + if not isinstance(automorphism, collections.abc.Mapping): try: automorphism = dict(automorphism) virtualization = {i: (automorphism[i],) for i in automorphism} diff --git a/src/sage/combinat/crystals/subcrystal.py b/src/sage/combinat/crystals/subcrystal.py index 9881a021e27..c62815af4be 100644 --- a/src/sage/combinat/crystals/subcrystal.py +++ b/src/sage/combinat/crystals/subcrystal.py @@ -23,6 +23,8 @@ # http://www.gnu.org/licenses/ #**************************************************************************** +import collections.abc + from sage.misc.lazy_attribute import lazy_attribute from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent @@ -126,7 +128,7 @@ def __classcall_private__(cls, ambient, contained=None, generators=None, sage: S1 is S2 True """ - if isinstance(contained, (list, tuple, set, frozenset)): + if isinstance(contained, (collections.abc.Sequence, collections.abc.Set)): contained = frozenset(contained) #elif contained in Sets(): From c5857f82c435f706ddce6ff496949cb3fb9fd242 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 15:35:08 -0700 Subject: [PATCH 03/19] Convert result of support() to list or tuple in two places --- src/sage/categories/loop_crystals.py | 2 +- src/sage/combinat/ncsf_qsym/tutorial.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/loop_crystals.py b/src/sage/categories/loop_crystals.py index aa96f2b5594..e065b7ef4f6 100644 --- a/src/sage/categories/loop_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -456,7 +456,7 @@ def b_sharp(self): bsharp = None for b in self: phi = b.Phi() - if phi.support() == [0] and phi[0] < ell: + if list(phi.support()) == [0] and phi[0] < ell: bsharp = b ell = phi[0] return bsharp diff --git a/src/sage/combinat/ncsf_qsym/tutorial.py b/src/sage/combinat/ncsf_qsym/tutorial.py index 5efc8d43728..78978507cb3 100644 --- a/src/sage/combinat/ncsf_qsym/tutorial.py +++ b/src/sage/combinat/ncsf_qsym/tutorial.py @@ -111,7 +111,7 @@ sage: sorted(z.coefficients()) [1, 2, 3] - sage: sorted(z.monomials(), key=lambda x: x.support()) + sage: sorted(z.monomials(), key=lambda x: tuple(x.support())) [M[1, 2], M[3, 3], M[6]] sage: z.monomial_coefficients() From 12da4ed7451883da43371a0296f0f29a3b9af347 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 15:44:09 -0700 Subject: [PATCH 04/19] ModulesWithBasis.ElementMethod.len: Use support --- src/sage/categories/modules_with_basis.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 0664ae33b7d..79d98764dd8 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -1506,9 +1506,7 @@ def __len__(self): sage: len(z) 4 """ - zero = self.parent().base_ring().zero() - return len([key for key, coeff in self.monomial_coefficients(copy=False).items() - if coeff != zero]) + return len(self.support()) def length(self): """ @@ -1556,8 +1554,9 @@ def support(self): [[1], [1, 1, 1], [2, 1], [4]] """ from sage.structure.support_view import SupportView + zero = self.parent().base_ring().zero() mc = self.monomial_coefficients(copy=False) - return SupportView(mc) + return SupportView(mc, zero=zero) def monomials(self): """ From 1ddb29bcae0394d86153231bf2c4e6090bccd757 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 15:55:27 -0700 Subject: [PATCH 05/19] src/sage/structure/support_view.py: Fix up --- src/sage/structure/support_view.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/structure/support_view.py b/src/sage/structure/support_view.py index 13631e3d89e..1c7babee506 100644 --- a/src/sage/structure/support_view.py +++ b/src/sage/structure/support_view.py @@ -39,6 +39,7 @@ def __contains__(self, key): value = self._mapping[key] except KeyError: return False + zero = self._zero if zero is None: return bool(value) return value != zero From 31559b26eacad4c2d1591bd8212d3b4e4f3fcead Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 15:55:45 -0700 Subject: [PATCH 06/19] IndexedFreeModuleElement.__contains__: Deprecate --- src/sage/modules/with_basis/indexed_element.pyx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/modules/with_basis/indexed_element.pyx b/src/sage/modules/with_basis/indexed_element.pyx index cd1f17112f0..c9b92640d78 100644 --- a/src/sage/modules/with_basis/indexed_element.pyx +++ b/src/sage/modules/with_basis/indexed_element.pyx @@ -25,6 +25,7 @@ from cpython.object cimport Py_NE, Py_EQ from sage.misc.repr import repr_lincomb from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute +from sage.misc.superseded import deprecation from sage.typeset.ascii_art import AsciiArt, empty_ascii_art, ascii_art from sage.typeset.unicode_art import UnicodeArt, empty_unicode_art, unicode_art from sage.categories.all import Category, Sets, ModulesWithBasis @@ -93,7 +94,8 @@ cdef class IndexedFreeModuleElement(ModuleElement): sage: Partition([1,1,1]) in a False """ - return x in self._monomial_coefficients and self._monomial_coefficients[x] != 0 + deprecation(34509, "using 'index in vector' is deprecated; use 'index in vector.support()' instead") + return x in self.support() def __hash__(self): """ From eb2c92d58022493a6b005e4fcca6e982e41f95ad Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 16:09:06 -0700 Subject: [PATCH 07/19] ModulesWithBasis.support: Try to cache the SupportView object --- src/sage/categories/modules_with_basis.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 79d98764dd8..26b51ef4b87 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -1553,10 +1553,19 @@ def support(self): sage: sorted(z.support()) [[1], [1, 1, 1], [2, 1], [4]] """ - from sage.structure.support_view import SupportView - zero = self.parent().base_ring().zero() - mc = self.monomial_coefficients(copy=False) - return SupportView(mc, zero=zero) + try: + return self._support_view + except AttributeError: + from sage.structure.support_view import SupportView + zero = self.parent().base_ring().zero() + mc = self.monomial_coefficients(copy=False) + support_view = SupportView(mc, zero=zero) + try: + # Try to cache it for next time, but this may fail for Cython classes + self._support_view = support_view + except AttributeError: + pass + return support_view def monomials(self): """ From bf91ea48ff7409cc2de2fecd236808bb1abd1a06 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 16:09:32 -0700 Subject: [PATCH 08/19] src/sage/combinat/ncsf_qsym/generic_basis_code.py: Replace deprecated 'index in vector' --- src/sage/combinat/ncsf_qsym/generic_basis_code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/ncsf_qsym/generic_basis_code.py b/src/sage/combinat/ncsf_qsym/generic_basis_code.py index 98ebd37a0de..87364ac04c6 100644 --- a/src/sage/combinat/ncsf_qsym/generic_basis_code.py +++ b/src/sage/combinat/ncsf_qsym/generic_basis_code.py @@ -472,7 +472,7 @@ def skew(self, x, y, side='left'): y = self.dual()(y) v = 1 if side == 'left' else 0 return self.sum(coeff * y[IJ[1-v]] * self[IJ[v]] \ - for (IJ, coeff) in x.coproduct() if IJ[1-v] in y) + for (IJ, coeff) in x.coproduct() if IJ[1-v] in y.support()) else: return self._skew_by_coercion(x, y, side=side) From b3abc6c4094959e0ab6b75a67c06c8ce1acb004d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 16:14:52 -0700 Subject: [PATCH 09/19] src/sage/combinat/sf/sfa.py: Replace deprecated 'index in vector' --- src/sage/combinat/sf/sfa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index afeaf70a3e0..7eac828fa4b 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -2601,7 +2601,7 @@ def _inner_plethysm_pk_g(self, k, g, cache): for d in degrees: for mu in Partitions_n(d): mu_k = mu.power(k) - if mu_k in g: + if mu_k in g.support(): res += g.coefficient(mu_k)*mu_k.centralizer_size()/mu.centralizer_size()*p(mu) cache[(k,g)] = res From 82d8b62091f58f3ff68a8287be7e30515000f61f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 16:41:35 -0700 Subject: [PATCH 10/19] src/sage/structure/support_view.py: Add tests --- src/sage/structure/support_view.py | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/sage/structure/support_view.py b/src/sage/structure/support_view.py index 1c7babee506..ea7d38cf096 100644 --- a/src/sage/structure/support_view.py +++ b/src/sage/structure/support_view.py @@ -6,8 +6,56 @@ class SupportView(MappingView, Sequence, Set): + r""" + Dynamic view of the set of keys of a dictionary that are associated with nonzero values + + It behaves like the objects returned by the :meth:`keys`, :meth:`values`, + :meth:`items` of a dictionary (or other :class:`collections.abc.Mapping` + classes). + + INPUT: + + - ``mapping`` -- a :class:`dict` or another :class:`collections.abc.Mapping`. + + - ``zero`` -- (optional) test for zeroness by comparing with this value. + + EXAMPLES:: + + sage: d = {'a': 47, 'b': 0, 'c': 11} + sage: from sage.structure.support_view import SupportView + sage: supp = SupportView(d); supp + SupportView({'a': 47, 'b': 0, 'c': 11}) + sage: 'a' in supp, 'b' in supp, 'z' in supp + (True, False, False) + sage: len(supp) + 2 + sage: list(supp) + ['a', 'c'] + sage: supp[0], supp[1] + ('a', 'c') + sage: supp[-1] + 'c' + sage: supp[:] + ('a', 'c') + sage: supp[2] + Traceback (most recent call last): + ... + IndexError + + sage: d['b'] = 815 + sage: len(supp) + 3 + """ def __init__(self, mapping, *, zero=None): + r""" + TESTS:: + + sage: from sage.structure.support_view import SupportView + sage: supp = SupportView({'a': 'b', 'c': ''}, zero='') + sage: len(supp) + 1 + """ self._mapping = mapping self._zero = zero @@ -18,6 +66,10 @@ def __len__(self): return length def __getitem__(self, index): + if isinstance(index, slice): + return tuple(self)[index] + if index < 0: + return tuple(self)[index] for i, key in enumerate(self): if i == index: return key From 1f48aa0a04db254a63ad3eb953d64f167a2295cc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 16:57:32 -0700 Subject: [PATCH 11/19] src/sage/structure/support_view.py: Add more tests --- src/sage/structure/support_view.py | 48 +++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/sage/structure/support_view.py b/src/sage/structure/support_view.py index ea7d38cf096..49fc788868d 100644 --- a/src/sage/structure/support_view.py +++ b/src/sage/structure/support_view.py @@ -37,10 +37,8 @@ class SupportView(MappingView, Sequence, Set): 'c' sage: supp[:] ('a', 'c') - sage: supp[2] - Traceback (most recent call last): - ... - IndexError + + It reflects changes to the underlying dictionary:: sage: d['b'] = 815 sage: len(supp) @@ -60,12 +58,34 @@ def __init__(self, mapping, *, zero=None): self._zero = zero def __len__(self): + r""" + TESTS:: + + sage: d = {'a': 47, 'b': 0, 'c': 11} + sage: from sage.structure.support_view import SupportView + sage: supp = SupportView(d); supp + SupportView({'a': 47, 'b': 0, 'c': 11}) + sage: len(supp) + 2 + """ length = 0 for key in self: length += 1 return length def __getitem__(self, index): + r""" + TESTS:: + + sage: d = {'a': 47, 'b': 0, 'c': 11} + sage: from sage.structure.support_view import SupportView + sage: supp = SupportView(d); supp + SupportView({'a': 47, 'b': 0, 'c': 11}) + sage: supp[2] + Traceback (most recent call last): + ... + IndexError + """ if isinstance(index, slice): return tuple(self)[index] if index < 0: @@ -76,6 +96,16 @@ def __getitem__(self, index): raise IndexError def __iter__(self): + r""" + TESTS:: + + sage: d = {'a': 47, 'b': 0, 'c': 11} + sage: from sage.structure.support_view import SupportView + sage: supp = SupportView(d); supp + SupportView({'a': 47, 'b': 0, 'c': 11}) + sage: iter(supp) + + """ zero = self._zero if zero is None: for key, value in self._mapping.items(): @@ -87,6 +117,16 @@ def __iter__(self): yield key def __contains__(self, key): + r""" + TESTS:: + + sage: d = {'a': 47, 'b': 0, 'c': 11} + sage: from sage.structure.support_view import SupportView + sage: supp = SupportView(d); supp + SupportView({'a': 47, 'b': 0, 'c': 11}) + sage: 'a' in supp, 'b' in supp, 'z' in supp + (True, False, False) + """ try: value = self._mapping[key] except KeyError: From 2583a37c57bf2ea04c48eec6cc65a45b02c4938d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 17:05:30 -0700 Subject: [PATCH 12/19] IndexedFreeModuleElement: Add doc --- .../modules/with_basis/indexed_element.pyx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/sage/modules/with_basis/indexed_element.pyx b/src/sage/modules/with_basis/indexed_element.pyx index c9b92640d78..22309d2d364 100644 --- a/src/sage/modules/with_basis/indexed_element.pyx +++ b/src/sage/modules/with_basis/indexed_element.pyx @@ -32,6 +32,23 @@ from sage.categories.all import Category, Sets, ModulesWithBasis from sage.data_structures.blas_dict cimport add, negate, scal, axpy cdef class IndexedFreeModuleElement(ModuleElement): + r""" + Element class for :class:`~sage.combinat.free_module.CombinatorialFreeModule` + + TESTS:: + + sage: import collections.abc + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c']; f + B['a'] + 3*B['c'] + sage: isinstance(f, collections.abc.Sized) + True + sage: isinstance(f, collections.abc.Iterable) + True + sage: isinstance(f, collections.abc.Collection) # known bug - will be fixed by removing __contains__ + False + """ def __init__(self, M, x): """ Create a combinatorial module element. This should never be @@ -81,6 +98,9 @@ cdef class IndexedFreeModuleElement(ModuleElement): sage: B = F.basis() sage: f = B['a'] + 3*B['c'] sage: 'a' in f + doctest:warning... + DeprecationWarning: using 'index in vector' is deprecated; use 'index in vector.support()' instead + See https://trac.sagemath.org/34509 for details. True sage: 'b' in f False From 88fe278795354296ad74dcc41b61b2aeb301d900 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 17:12:19 -0700 Subject: [PATCH 13/19] src/sage/structure/support_view.py: Fix doctest output --- src/sage/structure/support_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/structure/support_view.py b/src/sage/structure/support_view.py index 49fc788868d..6af9408bd29 100644 --- a/src/sage/structure/support_view.py +++ b/src/sage/structure/support_view.py @@ -104,7 +104,7 @@ def __iter__(self): sage: supp = SupportView(d); supp SupportView({'a': 47, 'b': 0, 'c': 11}) sage: iter(supp) - + """ zero = self._zero if zero is None: From 026d8a5061f8d7de5e6366679f7047e4a83f541e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 17:54:09 -0700 Subject: [PATCH 14/19] src/sage/algebras/steenrod/steenrod_algebra.py: Use key=...tuple(....support()) for sorting by lex support --- src/sage/algebras/steenrod/steenrod_algebra.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index 9e9ad450358..8feec0d6d98 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -402,13 +402,13 @@ (1, (2, 1)) sage: c.monomial_coefficients() == {(2, 1): 1, (5,): 1} True - sage: sorted(c.monomials(), key=lambda x: x.support()) + sage: sorted(c.monomials(), key=lambda x: tuple(x.support())) [Sq(2,1), Sq(5)] sage: sorted(c.support()) [(2, 1), (5,)] sage: Adem = SteenrodAlgebra(basis='adem') sage: elt = Adem.Sq(10) + Adem.Sq(9) * Adem.Sq(1) - sage: sorted(elt.monomials(), key=lambda x: x.support()) + sage: sorted(elt.monomials(), key=lambda x: tuple(x.support())) [Sq^9 Sq^1, Sq^10] sage: A7 = SteenrodAlgebra(p=7) @@ -3100,7 +3100,7 @@ class Element(CombinatorialFreeModule.Element): (1, (2, 1)) sage: c.monomial_coefficients() == {(2, 1): 1, (5,): 1} True - sage: sorted(c.monomials(), key=lambda x: x.support()) + sage: sorted(c.monomials(), key=lambda x: tuple(x.support())) [Sq(2,1), Sq(5)] sage: sorted(c.support()) [(2, 1), (5,)] @@ -3458,7 +3458,7 @@ def excess(self): sage: (Sq(0,0,1) + Sq(4,1) + Sq(7)).excess() 1 sage: elt = Sq(0,0,1) + Sq(4,1) + Sq(7) - sage: M = sorted(elt.monomials(), key=lambda x: x.support()) + sage: M = sorted(elt.monomials(), key=lambda x: tuple(x.support())) sage: [m.excess() for m in M] [1, 5, 7] sage: [m for m in M] From a4174115ef0899344ecfb301c42f032de5b1950e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 18:06:12 -0700 Subject: [PATCH 15/19] SupportView.__eq__, __ne__: New --- src/sage/structure/support_view.py | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/sage/structure/support_view.py b/src/sage/structure/support_view.py index 6af9408bd29..0212afb5414 100644 --- a/src/sage/structure/support_view.py +++ b/src/sage/structure/support_view.py @@ -4,6 +4,8 @@ from collections.abc import MappingView, Sequence, Set +from sage.misc.superseded import deprecation + class SupportView(MappingView, Sequence, Set): r""" @@ -135,3 +137,41 @@ def __contains__(self, key): if zero is None: return bool(value) return value != zero + + def __eq__(self, other): + r""" + TESTS:: + + sage: d = {1: 17, 2: 0} + sage: from sage.structure.support_view import SupportView + sage: supp = SupportView(d); supp + SupportView({1: 17, 2: 0}) + sage: supp == [1] + doctest:warning... + DeprecationWarning: comparing a SupportView with a list is deprecated + See https://trac.sagemath.org/34509 for details. + True + """ + if isinstance(other, list): + deprecation(34509, 'comparing a SupportView with a list is deprecated') + return list(self) == other + return NotImplemented + + def __ne__(self, other): + r""" + TESTS:: + + sage: d = {1: 17, 2: 0} + sage: from sage.structure.support_view import SupportView + sage: supp = SupportView(d); supp + SupportView({1: 17, 2: 0}) + sage: supp != [1] + doctest:warning... + DeprecationWarning: comparing a SupportView with a list is deprecated + See https://trac.sagemath.org/34509 for details. + False + """ + if isinstance(other, list): + deprecation(34509, 'comparing a SupportView with a list is deprecated') + return list(self) != other + return NotImplemented From b80989ff00667e5578f04a28a3d7ec6ff679c498 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 18:08:31 -0700 Subject: [PATCH 16/19] src/sage/combinat/sf/character.py: Use list(....support()) --- src/sage/combinat/sf/character.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/sf/character.py b/src/sage/combinat/sf/character.py index e55f356f5d1..e5752c307eb 100644 --- a/src/sage/combinat/sf/character.py +++ b/src/sage/combinat/sf/character.py @@ -104,7 +104,7 @@ def _other_to_self(self, sexpr): """ if sexpr == 0: return self(0) - if sexpr.support() == [[]]: + if list(sexpr.support()) == [[]]: return self._from_dict({self.one_basis(): sexpr.coefficient([])}, remove_zeros=False) out = self.zero() From 57273ea3262a27501953d1af04f6d8f35110b0da Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 21:13:33 -0700 Subject: [PATCH 17/19] src/doc/en/thematic_tutorials/lie/weyl_character_ring.rst: Use key=...tuple(....support()) for sorting by lex support --- src/doc/en/thematic_tutorials/lie/weyl_character_ring.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/en/thematic_tutorials/lie/weyl_character_ring.rst b/src/doc/en/thematic_tutorials/lie/weyl_character_ring.rst index a7052507284..ddc33a325a8 100644 --- a/src/doc/en/thematic_tutorials/lie/weyl_character_ring.rst +++ b/src/doc/en/thematic_tutorials/lie/weyl_character_ring.rst @@ -164,7 +164,7 @@ coefficients) through the usual free module accessors:: [((0, 0, 0), 1), ((1, 0, 0), 1), ((1, 1, 0), 1), ((1, 1, 1), 1)] sage: pprint(dict(chi)) {(0, 0, 0): 1, (1, 0, 0): 1, (1, 1, 0): 1, (1, 1, 1): 1} - sage: M = sorted(chi.monomials(), key=lambda x: x.support()); M + sage: M = sorted(chi.monomials(), key=lambda x: tuple(x.support())); M [B3(0,0,0), B3(1,0,0), B3(1,1,0), B3(1,1,1)] sage: sorted(chi.support()) [(0, 0, 0), (1, 0, 0), (1, 1, 0), (1, 1, 1)] @@ -485,7 +485,7 @@ itself, that is, the integral of `|tr(g)|^{10}`:: sage: tr^5 5*A2(2,2,1) + 6*A2(3,1,1) + 5*A2(3,2,0) + 4*A2(4,1,0) + A2(5,0,0) - sage: sorted((tr^5).monomials(), key=lambda x: x.support()) + sage: sorted((tr^5).monomials(), key=lambda x: tuple(x.support())) [A2(2,2,1), A2(3,1,1), A2(3,2,0), A2(4,1,0), A2(5,0,0)] sage: sorted((tr^5).coefficients()) [1, 4, 5, 5, 6] From 6ce669c687776a781f01c86439fc8739a25eb4cc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 21:14:26 -0700 Subject: [PATCH 18/19] src/sage/modules/tutorial_free_modules.py: Fix doctest output --- src/sage/modules/tutorial_free_modules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/modules/tutorial_free_modules.py b/src/sage/modules/tutorial_free_modules.py index 88810b2e42b..d58acd4ae9f 100644 --- a/src/sage/modules/tutorial_free_modules.py +++ b/src/sage/modules/tutorial_free_modules.py @@ -162,7 +162,7 @@ (2, 3) sage: f.support() - [0, 1, 2] + SupportView({0: 2, 1: 2, 2: 3}) sage: f.monomials() [a[0], a[1], a[2]] sage: f.coefficients() From 2fe3b981c7ebf07dfe8992d5f591b3bb73841ede Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Sep 2022 21:17:48 -0700 Subject: [PATCH 19/19] src/sage/algebras/quantum_groups/fock_space.py: Use sorted() with support, not sort --- src/sage/algebras/quantum_groups/fock_space.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/sage/algebras/quantum_groups/fock_space.py b/src/sage/algebras/quantum_groups/fock_space.py index dea28fd1760..3352f143a7c 100644 --- a/src/sage/algebras/quantum_groups/fock_space.py +++ b/src/sage/algebras/quantum_groups/fock_space.py @@ -1354,9 +1354,8 @@ def _G_to_fock_basis(self, la): return fock.sum_of_terms((fock._indices([[]]*k + list(pt)), c) for pt,c in cur) cur = R.A()._A_to_fock_basis(la) - s = cur.support() - s.sort() # Sort lex, which respects dominance order - s.pop() # Remove the largest + s = sorted(cur.support()) # Sort lex, which respects dominance order + s.pop() # Remove the largest q = R._q while s: @@ -2189,9 +2188,8 @@ def add_cols(nu): # Perform the triangular reduction cur = self.realization_of().A(algorithm)._A_to_fock_basis(la) - s = cur.support() - s.sort() # Sort lex, which respects dominance order - s.pop() # Remove the largest + s = sorted(cur.support()) # Sort lex, which respects dominance order + s.pop() # Remove the largest q = self.realization_of()._q while s: