@@ -3072,6 +3072,31 @@ def plethysm(self, x, include=None, exclude=None):
3072
3072
sage: sum(s[mu](X)*s[mu.conjugate()](Y) for mu in P5) == sum(m[mu](X)*e[mu](Y) for mu in P5)
3073
3073
True
3074
3074
3075
+ Sage can also do the plethysm with an element in the completion::
3076
+
3077
+ sage: L = LazySymmetricFunctions(s)
3078
+ sage: f = s[2,1]
3079
+ sage: g = L(s[1]) / (1 - L(s[1])); g
3080
+ s[1] + (s[1,1]+s[2]) + (s[1,1,1]+2*s[2,1]+s[3])
3081
+ + (s[1,1,1,1]+3*s[2,1,1]+2*s[2,2]+3*s[3,1]+s[4])
3082
+ + (s[1,1,1,1,1]+4*s[2,1,1,1]+5*s[2,2,1]+6*s[3,1,1]+5*s[3,2]+4*s[4,1]+s[5])
3083
+ + ... + O^8
3084
+ sage: fog = f(g)
3085
+ sage: fog[:8]
3086
+ [s[2, 1],
3087
+ s[1, 1, 1, 1] + 3*s[2, 1, 1] + 2*s[2, 2] + 3*s[3, 1] + s[4],
3088
+ 2*s[1, 1, 1, 1, 1] + 8*s[2, 1, 1, 1] + 10*s[2, 2, 1]
3089
+ + 12*s[3, 1, 1] + 10*s[3, 2] + 8*s[4, 1] + 2*s[5],
3090
+ 3*s[1, 1, 1, 1, 1, 1] + 17*s[2, 1, 1, 1, 1] + 30*s[2, 2, 1, 1]
3091
+ + 16*s[2, 2, 2] + 33*s[3, 1, 1, 1] + 54*s[3, 2, 1] + 16*s[3, 3]
3092
+ + 33*s[4, 1, 1] + 30*s[4, 2] + 17*s[5, 1] + 3*s[6],
3093
+ 5*s[1, 1, 1, 1, 1, 1, 1] + 30*s[2, 1, 1, 1, 1, 1] + 70*s[2, 2, 1, 1, 1]
3094
+ + 70*s[2, 2, 2, 1] + 75*s[3, 1, 1, 1, 1] + 175*s[3, 2, 1, 1]
3095
+ + 105*s[3, 2, 2] + 105*s[3, 3, 1] + 100*s[4, 1, 1, 1] + 175*s[4, 2, 1]
3096
+ + 70*s[4, 3] + 75*s[5, 1, 1] + 70*s[5, 2] + 30*s[6, 1] + 5*s[7]]
3097
+ sage: parent(fog)
3098
+ Lazy completion of Symmetric Functions over Rational Field in the Schur basis
3099
+
3075
3100
.. SEEALSO::
3076
3101
3077
3102
:meth:`frobenius`
@@ -3080,66 +3105,100 @@ def plethysm(self, x, include=None, exclude=None):
3080
3105
3081
3106
sage: (1+p[2]).plethysm(p[2])
3082
3107
p[] + p[4]
3108
+
3109
+ Check that degree one elements are treated in the correct way::
3110
+
3111
+ sage: R.<a1,a2,a11,b1,b21,b111> = QQ[]
3112
+ sage: p = SymmetricFunctions(R).p()
3113
+ sage: f = a1*p[1] + a2*p[2] + a11*p[1,1]
3114
+ sage: g = b1*p[1] + b21*p[2,1] + b111*p[1,1,1]
3115
+ sage: r = f(g); r
3116
+ a1*b1*p[1] + a11*b1^2*p[1, 1] + a1*b111*p[1, 1, 1]
3117
+ + 2*a11*b1*b111*p[1, 1, 1, 1] + a11*b111^2*p[1, 1, 1, 1, 1, 1]
3118
+ + a2*b1^2*p[2] + a1*b21*p[2, 1] + 2*a11*b1*b21*p[2, 1, 1]
3119
+ + 2*a11*b21*b111*p[2, 1, 1, 1, 1] + a11*b21^2*p[2, 2, 1, 1]
3120
+ + a2*b111^2*p[2, 2, 2] + a2*b21^2*p[4, 2]
3121
+ sage: r - f(g, include=[])
3122
+ (a2*b1^2-a2*b1)*p[2] + (a2*b111^2-a2*b111)*p[2, 2, 2] + (a2*b21^2-a2*b21)*p[4, 2]
3123
+
3124
+ Check that we can compute the plethysm with a constant::
3125
+
3126
+ sage: p[2,2,1](2)
3127
+ 8*p[]
3128
+
3129
+ sage: p[2,2,1](int(2))
3130
+ 8*p[]
3131
+
3132
+ sage: p[2,2,1](a1)
3133
+ a1^5*p[]
3134
+
3135
+ sage: X = algebras.Shuffle(QQ, 'ab')
3136
+ sage: Y = algebras.Shuffle(QQ, 'bc')
3137
+ sage: T = tensor([X,Y])
3138
+ sage: s = SymmetricFunctions(T).s()
3139
+ sage: s(2*T.one())
3140
+ (2*B[word:]#B[word:])*s[]
3141
+
3142
+ .. TODO::
3143
+
3144
+ The implementation of plethysm in
3145
+ :class:`sage.data_structures.stream.Stream_plethysm` seems
3146
+ to be faster. This should be investigated.
3083
3147
"""
3084
3148
parent = self .parent ()
3085
- R = parent .base_ring ()
3086
- tHA = HopfAlgebrasWithBasis (R ).TensorProducts ()
3087
- tensorflag = tHA in x .parent ().categories ()
3088
- if not (is_SymmetricFunction (x ) or tensorflag ):
3089
- raise TypeError ("only know how to compute plethysms "
3090
- "between symmetric functions or tensors "
3091
- "of symmetric functions" )
3092
- p = parent .realization_of ().power ()
3093
- if self == parent .zero ():
3149
+ if not self :
3094
3150
return self
3095
3151
3096
- # Handle degree one elements
3097
- if include is not None and exclude is not None :
3098
- raise RuntimeError ("include and exclude cannot both be specified" )
3099
-
3100
- try :
3101
- degree_one = [R (g ) for g in R .variable_names_recursive ()]
3102
- except AttributeError :
3103
- try :
3104
- degree_one = R .gens ()
3105
- except NotImplementedError :
3106
- degree_one = []
3107
-
3108
- if include :
3109
- degree_one = [R (g ) for g in include ]
3110
- if exclude :
3111
- degree_one = [g for g in degree_one if g not in exclude ]
3152
+ R = parent .base_ring ()
3153
+ tHA = HopfAlgebrasWithBasis (R ).TensorProducts ()
3154
+ from sage .structure .element import parent as get_parent
3155
+ Px = get_parent (x )
3156
+ tensorflag = Px in tHA
3157
+ if not is_SymmetricFunction (x ):
3158
+ if Px is R : # Handle stuff that is directly in the base ring
3159
+ x = parent (x )
3160
+ elif (not tensorflag or any (not isinstance (factor , SymmetricFunctionAlgebra_generic )
3161
+ for factor in Px ._sets )):
3162
+ from sage .rings .lazy_series import LazySymmetricFunction
3163
+ if isinstance (x , LazySymmetricFunction ):
3164
+ from sage .rings .lazy_series_ring import LazySymmetricFunctions
3165
+ L = LazySymmetricFunctions (parent )
3166
+ return L (self )(x )
3167
+
3168
+ # Try to coerce into a symmetric function
3169
+ phi = parent .coerce_map_from (Px )
3170
+ if phi is not None :
3171
+ x = phi (x )
3172
+ elif not tensorflag :
3173
+ raise TypeError ("only know how to compute plethysms "
3174
+ "between symmetric functions or tensors "
3175
+ "of symmetric functions" )
3112
3176
3113
- degree_one = [ g for g in degree_one if g != R . one ()]
3177
+ p = parent . realization_of (). power ()
3114
3178
3115
- def raise_c (n ):
3116
- return lambda c : c .subs (** {str (g ): g ** n for g in degree_one })
3179
+ degree_one = _variables_recursive (R , include = include , exclude = exclude )
3117
3180
3118
3181
if tensorflag :
3119
- tparents = x .parent ()._sets
3120
- return tensor ([parent ]* len (tparents ))(sum (d * prod (sum (raise_c (r )(c )
3121
- * tensor ([p [r ].plethysm (base (la ))
3122
- for (base ,la ) in zip (tparents ,trm )])
3123
- for (trm ,c ) in x )
3124
- for r in mu )
3125
- for (mu , d ) in p (self )))
3126
-
3127
- # Takes in n, and returns a function which takes in a partition and
3128
- # scales all of the parts of that partition by n
3129
- def scale_part (n ):
3130
- return lambda m : m .__class__ (m .parent (), [i * n for i in m ])
3131
-
3132
- # Takes n an symmetric function f, and an n and returns the
3182
+ tparents = Px ._sets
3183
+ s = sum (d * prod (sum (_raise_variables (c , r , degree_one )
3184
+ * tensor ([p [r ].plethysm (base (la ))
3185
+ for base , la in zip (tparents , trm )])
3186
+ for trm , c in x )
3187
+ for r in mu )
3188
+ for mu , d in p (self ))
3189
+ return tensor ([parent ]* len (tparents ))(s )
3190
+
3191
+ # Takes a symmetric function f, and an n and returns the
3133
3192
# symmetric function with all of its basis partitions scaled
3134
3193
# by n
3135
3194
def pn_pleth (f , n ):
3136
- return f .map_support (scale_part (n ))
3195
+ return f .map_support (lambda mu : mu . stretch (n ))
3137
3196
3138
3197
# Takes in a partition and applies
3139
3198
p_x = p (x )
3140
3199
3141
3200
def f (part ):
3142
- return p .prod (pn_pleth (p_x .map_coefficients (raise_c ( i )), i )
3201
+ return p .prod (pn_pleth (p_x .map_coefficients (lambda c : _raise_variables ( c , i , degree_one )), i )
3143
3202
for i in part )
3144
3203
return parent (p ._apply_module_morphism (p (self ), f , codomain = p ))
3145
3204
@@ -4917,9 +4976,7 @@ def frobenius(self, n):
4917
4976
# then convert back.
4918
4977
parent = self .parent ()
4919
4978
m = parent .realization_of ().monomial ()
4920
- from sage .combinat .partition import Partition
4921
- dct = {Partition ([n * i for i in lam ]): coeff
4922
- for (lam , coeff ) in m (self )}
4979
+ dct = {lam .stretch (n ): coeff for lam , coeff in m (self )}
4923
4980
result_in_m_basis = m ._from_dict (dct )
4924
4981
return parent (result_in_m_basis )
4925
4982
@@ -6125,3 +6182,82 @@ def _nonnegative_coefficients(x):
6125
6182
return all (c >= 0 for c in x .coefficients (sparse = False ))
6126
6183
else :
6127
6184
return x >= 0
6185
+
6186
+ def _variables_recursive (R , include = None , exclude = None ):
6187
+ """
6188
+ Return all variables appearing in the ring ``R``.
6189
+
6190
+ INPUT:
6191
+
6192
+ - ``R`` -- a :class:`Ring`
6193
+ - ``include``, ``exclude`` (optional, default ``None``) --
6194
+ iterables of variables in ``R``
6195
+
6196
+ OUTPUT:
6197
+
6198
+ - If ``include`` is specified, only these variables are returned
6199
+ as elements of ``R``. Otherwise, all variables in ``R``
6200
+ (recursively) with the exception of those in ``exclude`` are
6201
+ returned.
6202
+
6203
+ EXAMPLES::
6204
+
6205
+ sage: from sage.combinat.sf.sfa import _variables_recursive
6206
+ sage: R.<a, b> = QQ[]
6207
+ sage: S.<t> = R[]
6208
+ sage: _variables_recursive(S)
6209
+ [a, b, t]
6210
+
6211
+ sage: _variables_recursive(S, exclude=[b])
6212
+ [a, t]
6213
+
6214
+ sage: _variables_recursive(S, include=[b])
6215
+ [b]
6216
+
6217
+ TESTS::
6218
+
6219
+ sage: _variables_recursive(R.fraction_field(), exclude=[b])
6220
+ [a]
6221
+
6222
+ sage: _variables_recursive(S.fraction_field(), exclude=[b]) # known bug
6223
+ [a, t]
6224
+ """
6225
+ if include is not None and exclude is not None :
6226
+ raise RuntimeError ("include and exclude cannot both be specified" )
6227
+
6228
+ if include is not None :
6229
+ degree_one = [R (g ) for g in include ]
6230
+ else :
6231
+ try :
6232
+ degree_one = [R (g ) for g in R .variable_names_recursive ()]
6233
+ except AttributeError :
6234
+ try :
6235
+ degree_one = R .gens ()
6236
+ except NotImplementedError :
6237
+ degree_one = []
6238
+ if exclude is not None :
6239
+ degree_one = [g for g in degree_one if g not in exclude ]
6240
+
6241
+ return [g for g in degree_one if g != R .one ()]
6242
+
6243
+ def _raise_variables (c , n , variables ):
6244
+ """
6245
+ Replace the given variables in the ring element ``c`` with their
6246
+ ``n``-th power.
6247
+
6248
+ INPUT:
6249
+
6250
+ - ``c`` -- an element of a ring
6251
+ - ``n`` -- the power to raise the given variables to
6252
+ - ``variables`` -- the variables to raise
6253
+
6254
+ EXAMPLES::
6255
+
6256
+ sage: from sage.combinat.sf.sfa import _raise_variables
6257
+ sage: R.<a, b> = QQ[]
6258
+ sage: S.<t> = R[]
6259
+ sage: _raise_variables(2*a + 3*b*t, 2, [a, t])
6260
+ 3*b*t^2 + 2*a^2
6261
+
6262
+ """
6263
+ return c .subs (** {str (g ): g ** n for g in variables })
0 commit comments