From 4ed7b77ceb45aae27c2b201bb92abbc30eac5b50 Mon Sep 17 00:00:00 2001 From: Darij Grinberg Date: Fri, 31 May 2024 00:23:41 -0400 Subject: [PATCH 1/3] fix hashing for Weyl algebra elements --- src/sage/algebras/weyl_algebra.py | 37 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/sage/algebras/weyl_algebra.py b/src/sage/algebras/weyl_algebra.py index e439f3c3217..ce2fe1aaf9b 100644 --- a/src/sage/algebras/weyl_algebra.py +++ b/src/sage/algebras/weyl_algebra.py @@ -34,6 +34,7 @@ from sage.rings.polynomial.multi_polynomial_ring_base import MPolynomialRing_base from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.structure.global_options import GlobalOptions +from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement def repr_from_monomials(monomials, term_repr, use_latex=False) -> str: @@ -231,7 +232,7 @@ def repr_dx(k): return ret -class DifferentialWeylAlgebraElement(Element): +class DifferentialWeylAlgebraElement(IndexedFreeModuleElement): """ An element in a differential Weyl algebra. """ @@ -245,9 +246,11 @@ def __init__(self, parent, monomials) -> None: sage: dx,dy,dz = W.differentials() sage: elt = ((x^3-z)*dx + dy)^2 sage: TestSuite(elt).run() + + sage: hash(dx) == hash(dx) # hashing works + True """ - Element.__init__(self, parent) - self.__monomials = monomials + IndexedFreeModuleElement.__init__(self, parent, monomials) def _repr_(self) -> str: r""" @@ -355,7 +358,7 @@ def _richcmp_(self, other, op) -> bool: sage: W.one() != 1 False """ - return richcmp(self.__monomials, other.__monomials, op) + return richcmp(self._monomial_coefficients, other._monomial_coefficients, op) def __neg__(self): """ @@ -369,7 +372,7 @@ def __neg__(self): dy + z*dx - 3*x*dx """ return self.__class__(self.parent(), - {m: -c for m, c in self.__monomials.items()}) + {m: -c for m, c in self._monomial_coefficients.items()}) def _add_(self, other): """ @@ -383,7 +386,7 @@ def _add_(self, other): dx*dy + dz + x^3 - 2 """ F = self.parent() - return self.__class__(F, blas.add(self.__monomials, other.__monomials)) + return self.__class__(F, blas.add(self._monomial_coefficients, other._monomial_coefficients)) def _mul_(self, other): """ @@ -406,10 +409,10 @@ def add_tuples(x, y): n = self.parent()._n t = tuple([0] * n) zero = self.parent().base_ring().zero() - for ml in self.__monomials: - cl = self.__monomials[ml] - for mr in other.__monomials: - cr = other.__monomials[mr] + for ml in self._monomial_coefficients: + cl = self._monomial_coefficients[ml] + for mr in other._monomial_coefficients: + cr = other._monomial_coefficients[mr] cur = [((mr[0], t), cl * cr)] for i, p in enumerate(ml[1]): for _ in range(p): @@ -447,7 +450,7 @@ def _rmul_(self, other): """ if other == 0: return self.parent().zero() - M = self.__monomials + M = self._monomial_coefficients return self.__class__(self.parent(), {t: other * M[t] for t in M}) def _lmul_(self, other): @@ -464,7 +467,7 @@ def _lmul_(self, other): """ if other == 0: return self.parent().zero() - M = self.__monomials + M = self._monomial_coefficients return self.__class__(self.parent(), {t: M[t] * other for t in M}) def monomial_coefficients(self, copy=True) -> dict: @@ -491,8 +494,8 @@ def monomial_coefficients(self, copy=True) -> dict: (((1, 0, 0), (1, 0, 0)), -3)] """ if copy: - return dict(self.__monomials) - return self.__monomials + return dict(self._monomial_coefficients) + return self._monomial_coefficients def __iter__(self): """ @@ -530,7 +533,7 @@ def list(self) -> list: (((0, 0, 1), (1, 0, 0)), 1), (((1, 0, 0), (1, 0, 0)), -3)] """ - return sorted(self.__monomials.items(), + return sorted(self._monomial_coefficients.items(), key=lambda x: (-sum(x[0][1]), x[0][1], -sum(x[0][0]), x[0][0])) def support(self) -> list: @@ -548,7 +551,7 @@ def support(self) -> list: ((0, 0, 1), (1, 0, 0)), ((1, 0, 0), (1, 0, 0))] """ - return list(self.__monomials) + return list(self._monomial_coefficients) # This is essentially copied from # sage.combinat.free_module.CombinatorialFreeModuleElement @@ -567,7 +570,7 @@ def __truediv__(self, x): 2*y*z + x """ F = self.parent() - D = self.__monomials + D = self._monomial_coefficients if F.base_ring().is_field(): x = F.base_ring()(x) x_inv = x**-1 From d3c608e76f8e1de1e986df492a2f113ecf819c98 Mon Sep 17 00:00:00 2001 From: Darij Grinberg Date: Fri, 31 May 2024 20:46:28 -0400 Subject: [PATCH 2/3] remove redundant methods --- src/sage/algebras/weyl_algebra.py | 170 ++++++++++-------------------- 1 file changed, 55 insertions(+), 115 deletions(-) diff --git a/src/sage/algebras/weyl_algebra.py b/src/sage/algebras/weyl_algebra.py index ce2fe1aaf9b..bf30b7153d5 100644 --- a/src/sage/algebras/weyl_algebra.py +++ b/src/sage/algebras/weyl_algebra.py @@ -235,23 +235,65 @@ def repr_dx(k): class DifferentialWeylAlgebraElement(IndexedFreeModuleElement): """ An element in a differential Weyl algebra. - """ - def __init__(self, parent, monomials) -> None: - """ - Initialize ``self``. - TESTS:: + TESTS: - sage: W. = DifferentialWeylAlgebra(QQ) - sage: dx,dy,dz = W.differentials() - sage: elt = ((x^3-z)*dx + dy)^2 - sage: TestSuite(elt).run() + Some computations in the Weyl algebra, using the implicit + coercion from the polynomial ring into the Weyl algebra:: - sage: hash(dx) == hash(dx) # hashing works - True - """ - IndexedFreeModuleElement.__init__(self, parent, monomials) + sage: W. = DifferentialWeylAlgebra(QQ) + sage: dx,dy,dz = W.differentials() + sage: elt = ((x^3-z)*dx + dy)^2 + sage: TestSuite(elt).run() + sage: R. = QQ[] + sage: W = DifferentialWeylAlgebra(R) + sage: dx,dy,dz = W.differentials() + sage: dy*(x^3-y*z)*dx == -z*dx + x^3*dx*dy - y*z*dx*dy + True + sage: W.zero() == 0 + True + sage: W.one() == 1 + True + sage: x == 1 + False + sage: x + 1 == 1 + False + sage: W(x^3 - y*z) == x^3 - y*z + True + sage: W. = DifferentialWeylAlgebra(QQ) + sage: dx,dy,dz = W.differentials() + sage: dx != dy + True + sage: W.one() != 1 + False + sage: dy - (3*x - z)*dx + dy + z*dx - 3*x*dx + sage: (dx*dy) + dz + x^3 - 2 + dx*dy + dz + x^3 - 2 + sage: elt = (dy - (3*x - z)*dx) + sage: sorted(elt.monomial_coefficients().items()) + [(((0, 0, 0), (0, 1, 0)), 1), + (((0, 0, 1), (1, 0, 0)), 1), + (((1, 0, 0), (1, 0, 0)), -3)] + sage: elt = dy - (3*x - z)*dx + 1 + sage: sorted(elt.support()) + [((0, 0, 0), (0, 0, 0)), + ((0, 0, 0), (0, 1, 0)), + ((0, 0, 1), (1, 0, 0)), + ((1, 0, 0), (1, 0, 0))] + + Hashing works:: + + sage: hash(dx) == hash(dx) # hashing works + True + + Comparison works, even if mathematically meaningless + (but useful e.g. for sorting):: + + sage: dx < dy or dy < dx + True + """ def _repr_(self) -> str: r""" Return a string representation of ``self``. @@ -330,64 +372,6 @@ def half_term(mon, polynomial): return p + ' ' + d return repr_from_monomials(self.list(), term, True) - def _richcmp_(self, other, op) -> bool: - """ - Rich comparison for equal parents. - - TESTS:: - - sage: R. = QQ[] - sage: W = DifferentialWeylAlgebra(R) - sage: dx,dy,dz = W.differentials() - sage: dy*(x^3-y*z)*dx == -z*dx + x^3*dx*dy - y*z*dx*dy - True - sage: W.zero() == 0 - True - sage: W.one() == 1 - True - sage: x == 1 - False - sage: x + 1 == 1 - False - sage: W(x^3 - y*z) == x^3 - y*z - True - sage: W. = DifferentialWeylAlgebra(QQ) - sage: dx,dy,dz = W.differentials() - sage: dx != dy - True - sage: W.one() != 1 - False - """ - return richcmp(self._monomial_coefficients, other._monomial_coefficients, op) - - def __neg__(self): - """ - Return the negative of ``self``. - - EXAMPLES:: - - sage: W. = DifferentialWeylAlgebra(QQ) - sage: dx,dy,dz = W.differentials() - sage: dy - (3*x - z)*dx - dy + z*dx - 3*x*dx - """ - return self.__class__(self.parent(), - {m: -c for m, c in self._monomial_coefficients.items()}) - - def _add_(self, other): - """ - Return ``self`` added to ``other``. - - EXAMPLES:: - - sage: W. = DifferentialWeylAlgebra(QQ) - sage: dx,dy,dz = W.differentials() - sage: (dx*dy) + dz + x^3 - 2 - dx*dy + dz + x^3 - 2 - """ - F = self.parent() - return self.__class__(F, blas.add(self._monomial_coefficients, other._monomial_coefficients)) - def _mul_(self, other): """ Return ``self`` multiplied by ``other``. @@ -470,33 +454,6 @@ def _lmul_(self, other): M = self._monomial_coefficients return self.__class__(self.parent(), {t: M[t] * other for t in M}) - def monomial_coefficients(self, copy=True) -> dict: - """ - Return a dictionary which has the basis keys in the support - of ``self`` as keys and their corresponding coefficients - as values. - - INPUT: - - - ``copy`` -- (default: ``True``) if ``self`` is internally - represented by a dictionary ``d``, then make a copy of ``d``; - if ``False``, then this can cause undesired behavior by - mutating ``d`` - - EXAMPLES:: - - sage: W. = DifferentialWeylAlgebra(QQ) - sage: dx,dy,dz = W.differentials() - sage: elt = (dy - (3*x - z)*dx) - sage: sorted(elt.monomial_coefficients().items()) - [(((0, 0, 0), (0, 1, 0)), 1), - (((0, 0, 1), (1, 0, 0)), 1), - (((1, 0, 0), (1, 0, 0)), -3)] - """ - if copy: - return dict(self._monomial_coefficients) - return self._monomial_coefficients - def __iter__(self): """ Return an iterator of ``self``. @@ -536,23 +493,6 @@ def list(self) -> list: return sorted(self._monomial_coefficients.items(), key=lambda x: (-sum(x[0][1]), x[0][1], -sum(x[0][0]), x[0][0])) - def support(self) -> list: - """ - Return the support of ``self``. - - EXAMPLES:: - - sage: W. = DifferentialWeylAlgebra(QQ) - sage: dx,dy,dz = W.differentials() - sage: elt = dy - (3*x - z)*dx + 1 - sage: sorted(elt.support()) - [((0, 0, 0), (0, 0, 0)), - ((0, 0, 0), (0, 1, 0)), - ((0, 0, 1), (1, 0, 0)), - ((1, 0, 0), (1, 0, 0))] - """ - return list(self._monomial_coefficients) - # This is essentially copied from # sage.combinat.free_module.CombinatorialFreeModuleElement def __truediv__(self, x): From 12162b2891a9953e1bc5a91fa2d5384a5fc63815 Mon Sep 17 00:00:00 2001 From: Darij Grinberg Date: Fri, 31 May 2024 20:49:03 -0400 Subject: [PATCH 3/3] remove import --- src/sage/algebras/weyl_algebra.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/algebras/weyl_algebra.py b/src/sage/algebras/weyl_algebra.py index bf30b7153d5..247b6107e0f 100644 --- a/src/sage/algebras/weyl_algebra.py +++ b/src/sage/algebras/weyl_algebra.py @@ -21,7 +21,6 @@ from sage.misc.latex import latex, LatexExpr from sage.misc.lazy_attribute import lazy_attribute from sage.misc.misc_c import prod -from sage.structure.richcmp import richcmp from sage.structure.element import Element from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation