@@ -2706,7 +2706,7 @@ def __call__(self, g, *, check=True):
2706
2706
r"""
2707
2707
Return the composition of ``self`` with ``g``.
2708
2708
2709
- Given two Laurent Series `f` and `g` over the same base ring, the
2709
+ Given two Laurent series `f` and `g` over the same base ring, the
2710
2710
composition `(f \circ g)(z) = f(g(z))` is defined if and only if:
2711
2711
2712
2712
- `g = 0` and `val(f) >= 0`,
@@ -2907,7 +2907,7 @@ def __call__(self, g, *, check=True):
2907
2907
ZeroDivisionError: the valuation of the series must be nonnegative
2908
2908
2909
2909
`g \neq 0` and `val(g) \leq 0` and `f` has infinitely many
2910
- non-zero coefficients` ::
2910
+ non-zero coefficients::
2911
2911
2912
2912
sage: g = z^-1 + z^-2
2913
2913
sage: g.valuation() <= 0
@@ -3110,8 +3110,8 @@ def revert(self):
3110
3110
r"""
3111
3111
Return the compositional inverse of ``self``.
3112
3112
3113
- Given a Laurent Series `f`. the compositional inverse is a
3114
- Laurent Series `g` over the same base ring, such that
3113
+ Given a Laurent series `f`, the compositional inverse is a
3114
+ Laurent series `g` over the same base ring, such that
3115
3115
`(f \circ g)(z) = f(g(z)) = z`.
3116
3116
3117
3117
The compositional inverse exists if and only if:
@@ -3343,10 +3343,10 @@ def polynomial(self, degree=None, name=None):
3343
3343
A Laurent polynomial if the valuation of the series is negative or
3344
3344
a polynomial otherwise.
3345
3345
3346
- If ``degree`` is not ``None``, the terms of the series of degree
3347
- greater than ``degree`` are truncated first. If ``degree`` is ``None``
3348
- and the series is not a polynomial or a Laurent polynomial, a
3349
- ``ValueError`` is raised.
3346
+ If ``degree`` is not ``None``, the terms of the series of
3347
+ degree greater than ``degree`` are first truncated. If
3348
+ ``degree`` is ``None`` and the series is not a polynomial or
3349
+ a Laurent polynomial, a ``ValueError`` is raised.
3350
3350
3351
3351
EXAMPLES::
3352
3352
@@ -3387,6 +3387,7 @@ def polynomial(self, degree=None, name=None):
3387
3387
3388
3388
sage: L.zero().polynomial()
3389
3389
0
3390
+
3390
3391
"""
3391
3392
S = self .parent ()
3392
3393
@@ -3481,12 +3482,21 @@ def __call__(self, *g, check=True):
3481
3482
The arity of ``self`` must be equal to the number of
3482
3483
arguments provided.
3483
3484
3484
- Given two Taylor Series `f` and `g` over the same base ring, the
3485
- composition `(f \circ g)(z) = f(g(z))` is defined if and only if:
3485
+ Given a Taylor series `f` of arity `n` and a tuple of Taylor
3486
+ series `g = (g_1,\dots, g_n)` over the same base ring, the
3487
+ composition `f \circ g` is defined if and only if for each
3488
+ `1\leq k\leq n`:
3486
3489
3487
- - `g = 0` and `val(f) >= 0`,
3488
- - `g` is non-zero and `f` has only finitely many non-zero coefficients,
3489
- - `g` is non-zero and `val(g) > 0`.
3490
+ - `g_i` is zero, or
3491
+ - setting all variables except the `i`th in `f` to zero
3492
+ yields a polynomial, or
3493
+ - `val(g_i) > 0`.
3494
+
3495
+ If `f` is a univariate 'exact' series, we can check whether
3496
+ `f` is a actually a polynomial. However, if `f` is a
3497
+ multivariate series, we have no way to test whether setting
3498
+ all but one variable of `f` to zero yields a polynomial,
3499
+ except if `f` itself is 'exact' and therefore a polynomial.
3490
3500
3491
3501
INPUT:
3492
3502
@@ -3615,17 +3625,54 @@ def __call__(self, *g, check=True):
3615
3625
sage: gp.define(z / f(gp))
3616
3626
sage: gp
3617
3627
z + z^2 + 2*z^3 + 5*z^4 + 14*z^5 + 42*z^6 + 132*z^7 + O(z^8)
3628
+
3629
+ Check that composing the zero series with anything yields zero::
3630
+
3631
+ sage: T.<x,y> = LazyTaylorSeriesRing(QQ)
3632
+ sage: M.<a, b> = LazyTaylorSeriesRing(QQ)
3633
+ sage: T(0)(1/(1-a), a+b)
3634
+ 0
3635
+
3636
+ Check that composing `f` with zero series yields the constant term of `f`::
3637
+
3638
+ sage: T(3/(1-x-2*y))(0, 0)
3639
+ 3
3640
+
3641
+ Check that we can compose a polynomial with anything::
3642
+
3643
+ sage: T(1-x-2*y + x*y^2)(1, 3)
3644
+ 3
3645
+
3646
+ sage: T(1-x-2*y + x*y^2)(1 + a, 3)
3647
+ 3 + 8*a
3648
+
3649
+ sage: T(1-x-2*y + x*y^2)(1/(1-a), 3)
3650
+ 3 + 8*a + 8*a^2 + 8*a^3 + 8*a^4 + 8*a^5 + 8*a^6 + O(a,b)^7
3651
+
3618
3652
"""
3619
- if len (g ) != len (self .parent ().variable_names ()):
3653
+ fP = parent (self )
3654
+ if len (g ) != fP ._arity :
3620
3655
raise ValueError ("arity of must be equal to the number of arguments provided" )
3621
3656
3622
3657
# Find a good parent for the result
3623
3658
from sage .structure .element import get_coercion_model
3624
3659
cm = get_coercion_model ()
3625
3660
P = cm .common_parent (self .base_ring (), * [parent (h ) for h in g ])
3626
3661
3627
- # f has finite length
3628
- if isinstance (self ._coeff_stream , Stream_exact ) and not self ._coeff_stream ._constant :
3662
+ # f = 0
3663
+ if isinstance (self ._coeff_stream , Stream_zero ):
3664
+ return P .zero ()
3665
+
3666
+ # g = (0, ..., 0)
3667
+ if all ((not isinstance (h , LazyModuleElement ) and not h )
3668
+ or (isinstance (h , LazyModuleElement )
3669
+ and isinstance (h ._coeff_stream , Stream_zero ))
3670
+ for h in g ):
3671
+ return P (self [0 ])
3672
+
3673
+ # f has finite length and f != 0
3674
+ if (isinstance (self ._coeff_stream , Stream_exact )
3675
+ and not self ._coeff_stream ._constant ):
3629
3676
# constant polynomial
3630
3677
poly = self .polynomial ()
3631
3678
if poly .is_constant ():
@@ -3640,7 +3687,6 @@ def __call__(self, *g, check=True):
3640
3687
from sage .rings .polynomial .laurent_polynomial_ring import LaurentPolynomialRing_univariate
3641
3688
from sage .rings .lazy_series_ring import LazySeriesRing
3642
3689
if not isinstance (P , LazySeriesRing ):
3643
- fP = parent (self )
3644
3690
if fP ._laurent_poly_ring .has_coerce_map_from (P ):
3645
3691
S = fP ._laurent_poly_ring
3646
3692
P = fP
@@ -3708,8 +3754,8 @@ def revert(self):
3708
3754
r"""
3709
3755
Return the compositional inverse of ``self``.
3710
3756
3711
- Given a Taylor Series `f`. the compositional inverse is a
3712
- Laurent Series `g` over the same base ring, such that
3757
+ Given a Taylor series `f`, the compositional inverse is a
3758
+ Laurent series `g` over the same base ring, such that
3713
3759
`(f \circ g)(z) = f(g(z)) = z`.
3714
3760
3715
3761
The compositional inverse exists if and only if:
@@ -3932,9 +3978,10 @@ def polynomial(self, degree=None, names=None):
3932
3978
3933
3979
OUTPUT:
3934
3980
3935
- If ``degree`` is not ``None``, the terms of the series of degree greater
3936
- than ``degree`` are truncated first. If ``degree`` is ``None`` and the
3937
- series is not a polynomial polynomial, a ``ValueError`` is raised.
3981
+ If ``degree`` is not ``None``, the terms of the series of
3982
+ degree greater than ``degree`` are first truncated. If
3983
+ ``degree`` is ``None`` and the series is not a polynomial
3984
+ polynomial, a ``ValueError`` is raised.
3938
3985
3939
3986
EXAMPLES::
3940
3987
@@ -3966,6 +4013,7 @@ def polynomial(self, degree=None, names=None):
3966
4013
sage: f = z-z^2
3967
4014
sage: f.polynomial()
3968
4015
-z^2 + z
4016
+
3969
4017
"""
3970
4018
from sage .rings .polynomial .polynomial_ring_constructor import PolynomialRing
3971
4019
S = self .parent ()
@@ -4077,24 +4125,35 @@ class LazySymmetricFunction(LazyCompletionGradedAlgebraElement):
4077
4125
sage: s = SymmetricFunctions(ZZ).s()
4078
4126
sage: L = LazySymmetricFunctions(s)
4079
4127
"""
4080
- def __call__ (self , * args , check = True ):
4128
+ def __call__ (self , * g , check = True ):
4081
4129
r"""
4082
- Return the composition of ``self`` with ``args ``.
4130
+ Return the composition of ``self`` with ``g ``.
4083
4131
4084
4132
The arity of ``self`` must be equal to the number of
4085
4133
arguments provided.
4086
4134
4087
- Given two lazy symmetric functions `f` and `g` over the same
4088
- base ring, the composition (or plethysm) `(f \circ g)` is
4089
- defined if and only if:
4090
-
4091
- - `g = 0`,
4092
- - `g` is non-zero and `f` has only finitely many non-zero coefficients,
4093
- - `g` is non-zero and `val(g) > 0`.
4135
+ Given a lazy symmetric function `f` of arity `n` and a tuple
4136
+ of lazy symmetric functions `g = (g_1,\dots, g_n)` over the
4137
+ same base ring, the composition (or plethysm) `(f \circ g)`
4138
+ is defined if and only if for each `1\leq k\leq n`:
4139
+
4140
+ - `g_i = 0`, or
4141
+ - setting all alphabets except the `i`th in `f` to zero
4142
+ yields a symmetric function with only finitely many
4143
+ non-zero coefficients, or
4144
+ - `val(g) > 0`.
4145
+
4146
+ If `f` is a univariate 'exact' lazy symmetric function, we
4147
+ can check whether `f` has only finitely many non-zero
4148
+ coefficients. However, if `f` has larger arity, we have no
4149
+ way to test whether setting all but one alphabets of `f` to
4150
+ zero yields a polynomial, except if `f` itself is 'exact' and
4151
+ therefore a symmetric function with only finitely many
4152
+ non-zero coefficients.
4094
4153
4095
4154
INPUT:
4096
4155
4097
- - ``args `` -- other (lazy) symmetric functions
4156
+ - ``g `` -- other (lazy) symmetric functions
4098
4157
4099
4158
.. TODO::
4100
4159
@@ -4176,28 +4235,64 @@ def __call__(self, *args, check=True):
4176
4235
Traceback (most recent call last):
4177
4236
...
4178
4237
ValueError: can only compose with a positive valuation series
4238
+
4239
+ Check that composing the zero series with anything yields
4240
+ zero in the correct parent::
4241
+
4242
+ sage: e = SymmetricFunctions(QQ).e()
4243
+ sage: h = SymmetricFunctions(QQ).h()
4244
+ sage: s = SymmetricFunctions(QQ).s()
4245
+ sage: p = SymmetricFunctions(QQ).p()
4246
+ sage: L = LazySymmetricFunctions(tensor([e, h]))
4247
+ sage: r = (L(0)(s[1], p[1])); r
4248
+ 0
4249
+ sage: r.parent()
4250
+ Symmetric Functions over Rational Field in the Schur basis
4251
+
4252
+ Check that composing `f` with zero series yields the constant term of `f`::
4253
+
4254
+ sage: f = 3*L(tensor([s[1], s[1]]))
4255
+ sage: f(0, 0)
4256
+ 0
4257
+ sage: (3+f)(0, 0)
4258
+ 3
4179
4259
"""
4180
- if len (args ) != self .parent ()._arity :
4260
+ fP = parent (self )
4261
+ if len (g ) != fP ._arity :
4181
4262
raise ValueError ("arity must be equal to the number of arguments provided" )
4263
+
4264
+ # we actually do not need this
4182
4265
from sage .combinat .sf .sfa import is_SymmetricFunction
4183
- if not all (isinstance (g , LazySymmetricFunction ) or is_SymmetricFunction (g ) or not g for g in args ):
4184
- raise ValueError ("all arguments must be (possibly lazy) symmetric functions" )
4266
+ # if not all(isinstance(h, LazySymmetricFunction)
4267
+ # or is_SymmetricFunction(h) or not h for h in g):
4268
+ # raise ValueError("all arguments must be (possibly lazy) symmetric functions")
4185
4269
4186
- if isinstance (self ._coeff_stream , Stream_zero ):
4187
- return self
4270
+ # Find a good parent for the result
4271
+ from sage .structure .element import get_coercion_model
4272
+ cm = get_coercion_model ()
4273
+ P = cm .common_parent (self .base_ring (), * [parent (h ) for h in g ])
4188
4274
4189
- if len ( args ) == 1 :
4190
- g = args [ 0 ]
4191
- P = g . parent ()
4275
+ # f = 0
4276
+ if isinstance ( self . _coeff_stream , Stream_zero ):
4277
+ return P . zero ()
4192
4278
4193
- # Handle other types of 0s
4194
- if not isinstance (g , LazySymmetricFunction ) and not g :
4195
- return P (self [0 ].leading_coefficient ())
4279
+ # g = (0, ..., 0)
4280
+ if all ((not isinstance (h , LazyModuleElement ) and not h )
4281
+ or (isinstance (h , LazyModuleElement )
4282
+ and isinstance (h ._coeff_stream , Stream_zero ))
4283
+ for h in g ):
4284
+ f = self [0 ]
4285
+ # FIXME: TypeError: unable to convert 0 to a rational
4286
+ if f :
4287
+ return P (f .leading_coefficient ())
4288
+ return P .zero ()
4196
4289
4290
+ if len (g ) == 1 :
4291
+ g = g [0 ]
4197
4292
if (isinstance (self ._coeff_stream , Stream_exact )
4198
4293
and not self ._coeff_stream ._constant ):
4199
4294
f = self .symmetric_function ()
4200
- if is_SymmetricFunction ( g ):
4295
+ if not isinstance ( g , LazySymmetricFunction ):
4201
4296
return f (g )
4202
4297
# g must be a LazySymmetricFunction
4203
4298
if (isinstance (g ._coeff_stream , Stream_exact )
@@ -4422,9 +4517,10 @@ def symmetric_function(self, degree=None):
4422
4517
4423
4518
OUTPUT:
4424
4519
4425
- If ``degree`` is not ``None``, the terms of the series of degree greater
4426
- than ``degree`` are truncated first. If ``degree`` is ``None`` and the
4427
- series is not a polynomial polynomial, a ``ValueError`` is raised.
4520
+ If ``degree`` is not ``None``, the terms of the series of
4521
+ degree greater than ``degree`` are first truncated. If
4522
+ ``degree`` is ``None`` and the series is not a polynomial
4523
+ polynomial, a ``ValueError`` is raised.
4428
4524
4429
4525
EXAMPLES::
4430
4526
@@ -4459,6 +4555,7 @@ def symmetric_function(self, degree=None):
4459
4555
0
4460
4556
sage: f4.symmetric_function(0)
4461
4557
s[]
4558
+
4462
4559
"""
4463
4560
S = self .parent ()
4464
4561
R = S ._laurent_poly_ring
0 commit comments