Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make map_coefficients more general #37271

Closed
Closed
49 changes: 41 additions & 8 deletions src/sage/categories/modules_with_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from sage.categories.fields import Fields
from sage.categories.modules import Modules
from sage.categories.poor_man_map import PoorManMap
from sage.categories.map import Map
from sage.structure.element import Element, parent


Expand Down Expand Up @@ -2062,17 +2063,25 @@ def trailing_term(self, *args, **kwds):
"""
return self.parent().term(*self.trailing_item(*args, **kwds))

def map_coefficients(self, f):
def map_coefficients(self, f, new_base_ring=None):
"""
Mapping a function on coefficients.
Return the element obtained by applying ``f`` to the non-zero
coefficients of ``self``.

If ``f`` is a :class:`sage.categories.map.Map`, then the resulting
polynomial will be defined over the codomain of ``f``. Otherwise, the
resulting polynomial will be over the same ring as ``self``. Set
``new_base_ring`` to override this behaviour.

An error is raised if the coefficients are not in the new base ring.

INPUT:

- ``f`` -- an endofunction on the coefficient ring of the
free module
- ``f`` -- a callable that will be applied to the
coefficients of ``self``.

Return a new element of ``self.parent()`` obtained by applying the
function ``f`` to all of the coefficients of ``self``.
- ``new_base_ring`` (optional) -- if given, the resulting element
will be defined over this ring.

EXAMPLES::

Expand All @@ -2096,8 +2105,32 @@ def map_coefficients(self, f):
sage: a = s([2,1]) + 2*s([3,2]) # needs sage.combinat sage.modules
sage: a.map_coefficients(lambda x: x * 2) # needs sage.combinat sage.modules
2*s[2, 1] + 4*s[3, 2]
"""
return self.parent().sum_of_terms( (m, f(c)) for m,c in self )

We can map into a different base ring::

sage: # needs sage.combinat
sage: e = SymmetricFunctions(QQ).elementary()
sage: a = 1/2*(e([2,1]) + e([1,1,1])); a
1/2*e[1, 1, 1] + 1/2*e[2, 1]
sage: b = a.map_coefficients(lambda c: 2*c, ZZ); b
e[1, 1, 1] + e[2, 1]
sage: b.parent()
Symmetric Functions over Integer Ring in the elementary basis
sage: b.map_coefficients(lambda c: 1/2*c, ZZ)
Traceback (most recent call last):
...
TypeError: no conversion of this rational to integer
"""
R = self.parent()
if new_base_ring is not None:
B = new_base_ring
R = R.change_ring(B)
elif isinstance(f, Map):
B = f.codomain()
R = R.change_ring(B)
else:
B = self.base_ring()
return R.sum_of_terms((m, B(f(c))) for m, c in self)

def map_support(self, f):
"""
Expand Down
2 changes: 2 additions & 0 deletions src/sage/combinat/sf/character.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ def __init__(self, Sym, pfix):
SFA_generic.__init__(self, Sym,
basis_name="induced trivial symmetric group character",
prefix=pfix, graded=False)
self._descriptor = (("ht",),)
self._other = Sym.complete()
self._p = Sym.powersum()

Expand Down Expand Up @@ -451,6 +452,7 @@ def __init__(self, Sym, pfix):
SFA_generic.__init__(self, Sym,
basis_name="irreducible symmetric group character",
prefix=pfix, graded=False)
self._descriptor = (("st",),)
self._other = Sym.Schur()
self._p = Sym.powersum()

Expand Down
5 changes: 4 additions & 1 deletion src/sage/combinat/sf/dual.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@
sage: e = SymmetricFunctions(QQ).e()
sage: f = e.dual_basis(prefix = "m", basis_name="Forgotten symmetric functions"); f
Symmetric Functions over Rational Field in the Forgotten symmetric functions basis
sage: TestSuite(f).run(elements = [f[1,1]+2*f[2], f[1]+3*f[1,1]])
sage: TestSuite(f).run(skip='_test_construction', elements = [f[1,1]+2*f[2], f[1]+3*f[1,1]])
sage: TestSuite(f).run() # long time (11s on sage.math, 2011)

Check failure on line 78 in src/sage/combinat/sf/dual.py

View workflow job for this annotation

GitHub Actions / build

Failed example:

Failed example:: Got: Failure in _test_construction: Traceback (most recent call last): File "/sage/src/sage/misc/sage_unittest.py", line 297, in run test_method(tester=tester) File "/sage/src/sage/categories/sets_cat.py", line 1529, in _test_construction FO = self.construction() ^^^^^^^^^^^^^^^^^^^ File "/sage/src/sage/combinat/sf/dual.py", line 161, in construction raise NotImplementedError NotImplementedError ------------------------------------------------------------ The following tests failed: _test_construction

This class defines canonical coercions between ``self`` and
``self^*``, as follow:
Expand Down Expand Up @@ -157,6 +157,9 @@
self.register_coercion(SetMorphism(Hom(self._dual_basis, self, category), self._dual_to_self))
self._dual_basis.register_coercion(SetMorphism(Hom(self, self._dual_basis, category), self._self_to_dual))

def construction(self):
raise NotImplementedError

def _dual_to_self(self, x):
"""
Coerce an element of the dual of ``self`` canonically into ``self``.
Expand Down
1 change: 1 addition & 0 deletions src/sage/combinat/sf/elementary.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def __init__(self, Sym):
sage: TestSuite(e).run(skip=['_test_associativity', '_test_distributivity', '_test_prod'])
sage: TestSuite(e).run(elements = [e[1,1]+e[2], e[1]+2*e[1,1]])
"""
self._descriptor = (("elementary",),)
classical.SymmetricFunctionAlgebra_classical.__init__(self, Sym, "elementary", 'e')

def _dual_basis_default(self):
Expand Down
10 changes: 9 additions & 1 deletion src/sage/combinat/sf/hall_littlewood.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ def __repr__(self):
"""
return self._name + " over %s" % self._sym.base_ring()

def __init__(self, Sym, t='t'):
@staticmethod
def __classcall__(cls, Sym, t='t'):
return super().__classcall__(cls, Sym, Sym.base_ring()(t))

def __init__(self, Sym, t):
"""
Initialize ``self``.

Expand Down Expand Up @@ -708,6 +712,7 @@ def __init__(self, hall_littlewood):
sage: TestSuite(P).run(elements = [P.t*P[1,1]+P[2], P[1]+(1+P.t)*P[1,1]])
"""
HallLittlewood_generic.__init__(self, hall_littlewood)
self._descriptor = (("hall_littlewood", {"t": self.t}), ("P",))
self._self_to_s_cache = p_to_s_cache
self._s_to_self_cache = s_to_p_cache

Expand Down Expand Up @@ -846,6 +851,7 @@ def __init__(self, hall_littlewood):
(1/(t^2-1))*HLQ[1, 1] - (1/(t-1))*HLQ[2]
"""
HallLittlewood_generic.__init__(self, hall_littlewood)
self._descriptor = (("hall_littlewood", {"t": self.t}), ("Q",))

self._P = self._hall_littlewood.P()
# temporary until Hom(GradedHopfAlgebrasWithBasis work better)
Expand Down Expand Up @@ -942,6 +948,8 @@ def __init__(self, hall_littlewood):
[ 0 0 1]
"""
HallLittlewood_generic.__init__(self, hall_littlewood)
self._descriptor = (("hall_littlewood", {"t": self.t}), ("Qp",))

self._self_to_s_cache = qp_to_s_cache
self._s_to_self_cache = s_to_qp_cache

Expand Down
8 changes: 6 additions & 2 deletions src/sage/combinat/sf/hecke.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,11 @@ class HeckeCharacter(SymmetricFunctionAlgebra_multiplicative):
- [Ram1991]_
- [RR1997]_
"""
@staticmethod
def __classcall__(cls, Sym, q='q'):
return super().__classcall__(cls, Sym, Sym.base_ring()(q))

def __init__(self, sym, q='q'):
def __init__(self, sym, q):
r"""
Initialize ``self``.

Expand Down Expand Up @@ -156,10 +159,11 @@ def __init__(self, sym, q='q'):
....: for mu in Partitions(n))
True
"""
self.q = sym.base_ring()(q)
self.q = q
SymmetricFunctionAlgebra_multiplicative.__init__(self, sym,
basis_name="Hecke character with q={}".format(self.q),
prefix="qbar")
self._descriptor = (("qbar", {"q": self.q}),)
self._p = sym.power()

# temporary until Hom(GradedHopfAlgebrasWithBasis work better)
Expand Down
1 change: 1 addition & 0 deletions src/sage/combinat/sf/homogeneous.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def __init__(self, Sym):
sage: TestSuite(h).run(skip=['_test_associativity', '_test_distributivity', '_test_prod'])
sage: TestSuite(h).run(elements = [h[1,1]+h[2], h[1]+2*h[1,1]])
"""
self._descriptor = (("homogeneous",),)
classical.SymmetricFunctionAlgebra_classical.__init__(self, Sym, "homogeneous", 'h')

def _dual_basis_default(self):
Expand Down
12 changes: 10 additions & 2 deletions src/sage/combinat/sf/jack.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,11 @@


class Jack(UniqueRepresentation):
@staticmethod
def __classcall__(cls, Sym, t='t'):
return super().__classcall__(cls, Sym, Sym.base_ring()(t))

def __init__(self, Sym, t='t'):
def __init__(self, Sym, t):
r"""
The family of Jack symmetric functions including the `P`, `Q`, `J`, `Qp`
bases. The default parameter is ``t``.
Expand All @@ -70,7 +73,7 @@ def __init__(self, Sym, t='t'):
Jack polynomials with t=1 over Rational Field
"""
self._sym = Sym
self.t = Sym.base_ring()(t)
self.t = t
self._name_suffix = ""
if str(t) != 't':
self._name_suffix += " with t=%s" % t
Expand Down Expand Up @@ -874,6 +877,7 @@ def __init__(self, jack):
self._m_to_self_cache = m_to_p_cache
self._self_to_m_cache = p_to_m_cache
JackPolynomials_generic.__init__(self, jack)
self._descriptor = (("jack", {"t": self.t}), ("P",))

def _m_cache(self, n):
r"""
Expand Down Expand Up @@ -1076,6 +1080,7 @@ def __init__(self, jack):
self._name = "Jack polynomials in the J basis"
self._prefix = "JackJ"
JackPolynomials_generic.__init__(self, jack)
self._descriptor = (("jack", {"t": self.t}), ("J",))

# Should be shared with _q (and possibly other bases in Macdo/HL) as BasesByRenormalization
self._P = self._jack.P()
Expand Down Expand Up @@ -1112,6 +1117,7 @@ def __init__(self, jack):
self._name = "Jack polynomials in the Q basis"
self._prefix = "JackQ"
JackPolynomials_generic.__init__(self, jack)
self._descriptor = (("jack", {"t": self.t}), ("Q",))

# Should be shared with _j (and possibly other bases in Macdo/HL) as BasesByRenormalization
self._P = self._jack.P()
Expand Down Expand Up @@ -1150,6 +1156,7 @@ def __init__(self, jack):
self._name = "Jack polynomials in the Qp basis"
self._prefix = "JackQp"
JackPolynomials_generic.__init__(self, jack)
self._descriptor = (("jack", {"t": self.t}), ("Qp",))
self._P = self._jack.P()
self._self_to_h_cache = qp_to_h_cache
self._h_to_self_cache = h_to_qp_cache
Expand Down Expand Up @@ -1354,6 +1361,7 @@ def __init__(self, Sym):
#self._self_to_m_cache = {} and we don't need to compute it separately for zonals
sfa.SymmetricFunctionAlgebra_generic.__init__(self, self._sym,
prefix="Z", basis_name="zonal")
self._descriptor = (("zonal",),)
category = sage.categories.all.ModulesWithBasis(self._sym.base_ring())
self .register_coercion(SetMorphism(Hom(self._P, self, category), self.sum_of_terms))
self._P.register_coercion(SetMorphism(Hom(self, self._P, category), self._P.sum_of_terms))
Expand Down
16 changes: 13 additions & 3 deletions src/sage/combinat/sf/macdonald.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ def __repr__(self):
"""
return self._name

def __init__(self, Sym, q='q', t='t'):
@staticmethod
def __classcall__(cls, Sym, q='q', t='t'):
return super().__classcall__(cls, Sym, Sym.base_ring()(q), Sym.base_ring()(t))

def __init__(self, Sym, q, t):
r"""
Macdonald Symmetric functions including `P`, `Q`, `J`, `H`, `Ht` bases
also including the S basis which is the plethystic transformation
Expand All @@ -119,8 +123,8 @@ def __init__(self, Sym, q='q', t='t'):
"""
self._sym = Sym
self._s = Sym.s()
self.q = Sym.base_ring()(q)
self.t = Sym.base_ring()(t)
self.q = q
self.t = t
self._name_suffix = ""
if str(q) != 'q':
self._name_suffix += " with q=%s" % q
Expand Down Expand Up @@ -1012,6 +1016,7 @@ def __init__(self, macdonald):
sage: TestSuite(P).run(elements = [P.t*P[1,1]+P.q*P[2], P[1]+(P.q+P.t)*P[1,1]]) # long time (depends on previous)
"""
MacdonaldPolynomials_generic.__init__(self, macdonald)
self._descriptor = (("macdonald", {"q": self.q, "t": self.t}), ("P",))

self._J = macdonald.J()
# temporary until Hom(GradedHopfAlgebrasWithBasis work better)
Expand Down Expand Up @@ -1082,6 +1087,7 @@ def __init__(self, macdonald):
sage: TestSuite(Q).run(elements = [Q.t*Q[1,1]+Q.q*Q[2], Q[1]+(Q.q+Q.t)*Q[1,1]]) # long time (depends on previous)
"""
MacdonaldPolynomials_generic.__init__(self, macdonald)
self._descriptor = (("macdonald", {"q": self.q, "t": self.t}), ("Q",))

self._J = macdonald.J()
self._P = macdonald.P()
Expand Down Expand Up @@ -1118,6 +1124,7 @@ def __init__(self, macdonald):
self._self_to_s_cache = _j_to_s_cache
self._s_to_self_cache = _s_to_j_cache
MacdonaldPolynomials_generic.__init__(self, macdonald)
self._descriptor = (("macdonald", {"q": self.q, "t": self.t}), ("J",))

def _s_cache(self, n):
r"""
Expand Down Expand Up @@ -1218,6 +1225,7 @@ def __init__(self, macdonald):

"""
MacdonaldPolynomials_generic.__init__(self, macdonald)
self._descriptor = (("macdonald", {"q": self.q, "t": self.t}), ("H",))
self._m = self._sym.m()
self._Lmunu = macdonald.Ht()._Lmunu
if not self.t:
Expand Down Expand Up @@ -1440,6 +1448,7 @@ def __init__(self, macdonald):

"""
MacdonaldPolynomials_generic.__init__(self, macdonald)
self._descriptor = (("macdonald", {"q": self.q, "t": self.t}), ("Ht",))
self._self_to_m_cache = _ht_to_m_cache
self._m = self._sym.m()
category = ModulesWithBasis(self.base_ring())
Expand Down Expand Up @@ -1735,6 +1744,7 @@ def __init__(self, macdonald):

"""
MacdonaldPolynomials_generic.__init__(self, macdonald)
self._descriptor = (("macdonald", {"q": self.q, "t": self.t}), ("S",))
self._s = macdonald._s
self._self_to_s_cache = _S_to_s_cache
self._s_to_self_cache = _s_to_S_cache
Expand Down
1 change: 1 addition & 0 deletions src/sage/combinat/sf/monomial.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def __init__(self, Sym):
sage: TestSuite(m).run(skip=['_test_associativity', '_test_distributivity', '_test_prod'])
sage: TestSuite(m).run(elements = [m[1,1]+m[2], m[1]+2*m[1,1]])
"""
self._descriptor = (("monomial",),)
classical.SymmetricFunctionAlgebra_classical.__init__(self, Sym, "monomial", 'm')

def _dual_basis_default(self):
Expand Down
2 changes: 1 addition & 1 deletion src/sage/combinat/sf/orthogonal.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def __init__(self, Sym):
"""
sfa.SymmetricFunctionAlgebra_generic.__init__(self, Sym, "orthogonal",
'o', graded=False)

self._descriptor = (("o",),)
# We make a strong reference since we use it for our computations
# and so we can define the coercion below (only codomains have
# strong references)
Expand Down
7 changes: 5 additions & 2 deletions src/sage/combinat/sf/orthotriang.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ def __init__(self, Sym, base, scalar, prefix, basis_name, leading_coeff=None):

TESTS::

sage: TestSuite(s).run(elements = [s[1,1]+2*s[2], s[1]+3*s[1,1]])
sage: TestSuite(s).run(skip = ["_test_associativity", "_test_prod"]) # long time (7s on sage.math, 2011)
sage: TestSuite(s).run(skip='_test_construction', elements = [s[1,1]+2*s[2], s[1]+3*s[1,1]])
sage: TestSuite(s).run(skip = ["_test_associativity", "_test_prod", '_test_construction']) # long time (7s on sage.math, 2011)

Note: ``s.an_element()`` is of degree 4; so we skip
``_test_associativity`` and ``_test_prod`` which involve
Expand All @@ -102,6 +102,9 @@ def __init__(self, Sym, base, scalar, prefix, basis_name, leading_coeff=None):
self.register_coercion(SetMorphism(Hom(base, self), self._base_to_self))
base.register_coercion(SetMorphism(Hom(self, base), self._self_to_base))

def construction(self):
raise NotImplementedError

def _base_to_self(self, x):
"""
Coerce a symmetric function in base ``x`` into ``self``.
Expand Down
1 change: 1 addition & 0 deletions src/sage/combinat/sf/powersum.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def __init__(self, Sym):
sage: TestSuite(p).run(skip=['_test_associativity', '_test_distributivity', '_test_prod'])
sage: TestSuite(p).run(elements = [p[1,1]+p[2], p[1]+2*p[1,1]])
"""
self._descriptor = (("powersum",),)
classical.SymmetricFunctionAlgebra_classical.__init__(self, Sym, "powersum", 'p')

def coproduct_on_generators(self, i):
Expand Down
1 change: 1 addition & 0 deletions src/sage/combinat/sf/schur.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def __init__(self, Sym):
sage: TestSuite(s).run(skip=['_test_associativity', '_test_distributivity', '_test_prod'])
sage: TestSuite(s).run(elements = [s[1,1]+s[2], s[1]+2*s[1,1]])
"""
self._descriptor = (("schur",),)
classical.SymmetricFunctionAlgebra_classical.__init__(self, Sym, "Schur", 's')

def _dual_basis_default(self):
Expand Down
1 change: 0 additions & 1 deletion src/sage/combinat/sf/sf.py
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,6 @@ class function on the symmetric group where the elements
- Devise a mechanism so that pickling bases of symmetric
functions pickles the coercions which have a cache.
"""

def __init__(self, R):
r"""
Initialization of ``self``.
Expand Down
Loading
Loading