Skip to content

Commit 8a41fd6

Browse files
author
Release Manager
committed
Trac #32324: Lazy Taylor Series
We implement (multivariate) Taylor series. Note that there is no easy well-defined notion of multivariate Laurent series, which is why we create a new class. URL: https://trac.sagemath.org/32324 Reported by: mantepse Ticket author(s): Martin Rubey Reviewer(s): Travis Scrimshaw
2 parents ae8a36d + e780472 commit 8a41fd6

File tree

5 files changed

+2053
-396
lines changed

5 files changed

+2053
-396
lines changed

src/sage/data_structures/stream.py

+144-13
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
This module provides lazy implementations of basic operators on
55
streams. The classes implemented in this module can be used to build
66
up more complex streams for different kinds of series (Laurent,
7-
Dirichlet, etc).
7+
Dirichlet, etc.).
88
99
EXAMPLES:
1010
@@ -85,6 +85,8 @@
8585

8686
# ****************************************************************************
8787
# Copyright (C) 2019 Kwankyu Lee <[email protected]>
88+
# 2022 Martin Rubey <martin.rubey at tuwien.ac.at>
89+
# 2022 Travis Scrimshaw <tcscrims at gmail.com>
8890
#
8991
# This program is free software: you can redistribute it and/or modify
9092
# it under the terms of the GNU General Public License as published by
@@ -96,6 +98,7 @@
9698
from sage.rings.integer_ring import ZZ
9799
from sage.rings.infinity import infinity
98100
from sage.arith.misc import divisors
101+
from sage.combinat.integer_vector_weighted import iterator_fast as wt_int_vec_iter
99102

100103
class Stream():
101104
"""
@@ -505,7 +508,7 @@ class Stream_exact(Stream):
505508
"""
506509
def __init__(self, initial_coefficients, is_sparse, constant=None, degree=None, order=None):
507510
"""
508-
Initialize a series that is known to be eventually geometric.
511+
Initialize a stream with eventually constant coefficients.
509512
510513
TESTS::
511514
@@ -837,6 +840,7 @@ def __init__(self, is_sparse, approximate_order):
837840
sage: TestSuite(C).run(skip="_test_pickling")
838841
"""
839842
self._target = None
843+
assert approximate_order is not None, "calling Stream_uninitialized with None as approximate order"
840844
super().__init__(is_sparse, approximate_order)
841845

842846
def get_coefficient(self, n):
@@ -1023,7 +1027,7 @@ def __eq__(self, other):
10231027
10241028
INPUT:
10251029
1026-
- ``other`` -- a stream of coefficients
1030+
- ``other`` -- a :class:`Stream` of coefficients
10271031
10281032
EXAMPLES::
10291033
@@ -1086,7 +1090,7 @@ def __eq__(self, other):
10861090
10871091
INPUT:
10881092
1089-
- ``other`` -- a stream of coefficients
1093+
- ``other`` -- a :class:`Stream` of coefficients
10901094
10911095
EXAMPLES::
10921096
@@ -1211,8 +1215,8 @@ class Stream_add(Stream_binaryCommutative):
12111215
12121216
INPUT:
12131217
1214-
- ``left`` -- stream of coefficients on the left side of the operator
1215-
- ``right`` -- stream of coefficients on the right side of the operator
1218+
- ``left`` -- :class:`Stream` of coefficients on the left side of the operator
1219+
- ``right`` -- :class:`Stream` of coefficients on the right side of the operator
12161220
12171221
EXAMPLES::
12181222
@@ -1271,8 +1275,8 @@ class Stream_sub(Stream_binary):
12711275
12721276
INPUT:
12731277
1274-
- ``left`` -- stream of coefficients on the left side of the operator
1275-
- ``right`` -- stream of coefficients on the right side of the operator
1278+
- ``left`` -- :class:`Stream` of coefficients on the left side of the operator
1279+
- ``right`` -- :class:`Stream` of coefficients on the right side of the operator
12761280
12771281
EXAMPLES::
12781282
@@ -1336,8 +1340,8 @@ class Stream_cauchy_mul(Stream_binary):
13361340
13371341
INPUT:
13381342
1339-
- ``left`` -- stream of coefficients on the left side of the operator
1340-
- ``right`` -- stream of coefficients on the right side of the operator
1343+
- ``left`` -- :class:`Stream` of coefficients on the left side of the operator
1344+
- ``right`` -- :class:`Stream` of coefficients on the right side of the operator
13411345
13421346
EXAMPLES::
13431347
@@ -1422,8 +1426,8 @@ class Stream_dirichlet_convolve(Stream_binary):
14221426
14231427
INPUT:
14241428
1425-
- ``left`` -- stream of coefficients on the left side of the operator
1426-
- ``right`` -- stream of coefficients on the right side of the operator
1429+
- ``left`` -- :class:`Stream` of coefficients on the left side of the operator
1430+
- ``right`` -- :class:`Stream` of coefficients on the right side of the operator
14271431
14281432
The coefficient of `n^{-s}` in the convolution of `l` and `r`
14291433
equals `\sum_{k | n} l_k r_{n/k}`.
@@ -1598,7 +1602,7 @@ def __init__(self, f, g):
15981602
sage: g = Stream_function(lambda n: n^2, ZZ, True, 1)
15991603
sage: h = Stream_cauchy_compose(f, g)
16001604
"""
1601-
assert g._approximate_order > 0
1605+
#assert g._approximate_order > 0
16021606
self._fv = f._approximate_order
16031607
self._gv = g._approximate_order
16041608
if self._fv < 0:
@@ -1643,6 +1647,132 @@ def get_coefficient(self, n):
16431647
return ret + sum(self._left[i] * self._pos_powers[i][n] for i in range(1, n // self._gv+1))
16441648

16451649

1650+
class Stream_plethysm(Stream_binary):
1651+
r"""
1652+
Return the plethysm of ``f`` composed by ``g``.
1653+
1654+
This is the plethysm `f \circ g = f(g)` when `g` is an element of
1655+
the ring of symmetric functions.
1656+
1657+
INPUT:
1658+
1659+
- ``f`` -- a :class:`Stream`
1660+
- ``g`` -- a :class:`Stream` with positive order
1661+
- ``p`` -- the powersum symmetric functions
1662+
1663+
EXAMPLES::
1664+
1665+
sage: from sage.data_structures.stream import Stream_function, Stream_plethysm
1666+
sage: s = SymmetricFunctions(QQ).s()
1667+
sage: p = SymmetricFunctions(QQ).p()
1668+
sage: f = Stream_function(lambda n: s[n], s, True, 1)
1669+
sage: g = Stream_function(lambda n: s[[1]*n], s, True, 1)
1670+
sage: h = Stream_plethysm(f, g, p)
1671+
sage: [s(h[i]) for i in range(5)]
1672+
[0,
1673+
s[1],
1674+
s[1, 1] + s[2],
1675+
2*s[1, 1, 1] + s[2, 1] + s[3],
1676+
3*s[1, 1, 1, 1] + 2*s[2, 1, 1] + s[2, 2] + s[3, 1] + s[4]]
1677+
sage: u = Stream_plethysm(g, f, p)
1678+
sage: [s(u[i]) for i in range(5)]
1679+
[0,
1680+
s[1],
1681+
s[1, 1] + s[2],
1682+
s[1, 1, 1] + s[2, 1] + 2*s[3],
1683+
s[1, 1, 1, 1] + s[2, 1, 1] + 3*s[3, 1] + 2*s[4]]
1684+
"""
1685+
def __init__(self, f, g, p):
1686+
r"""
1687+
Initialize ``self``.
1688+
1689+
TESTS::
1690+
1691+
sage: from sage.data_structures.stream import Stream_function, Stream_plethysm
1692+
sage: s = SymmetricFunctions(QQ).s()
1693+
sage: p = SymmetricFunctions(QQ).p()
1694+
sage: f = Stream_function(lambda n: s[n], s, True, 1)
1695+
sage: g = Stream_function(lambda n: s[n-1,1], s, True, 2)
1696+
sage: h = Stream_plethysm(f, g, p)
1697+
"""
1698+
#assert g._approximate_order > 0
1699+
self._fv = f._approximate_order
1700+
self._gv = g._approximate_order
1701+
self._p = p
1702+
val = self._fv * self._gv
1703+
super().__init__(f, g, f._is_sparse, val)
1704+
1705+
def get_coefficient(self, n):
1706+
r"""
1707+
Return the ``n``-th coefficient of ``self``.
1708+
1709+
INPUT:
1710+
1711+
- ``n`` -- integer; the degree for the coefficient
1712+
1713+
EXAMPLES::
1714+
1715+
sage: from sage.data_structures.stream import Stream_function, Stream_plethysm
1716+
sage: s = SymmetricFunctions(QQ).s()
1717+
sage: p = SymmetricFunctions(QQ).p()
1718+
sage: f = Stream_function(lambda n: s[n], s, True, 1)
1719+
sage: g = Stream_function(lambda n: s[[1]*n], s, True, 1)
1720+
sage: h = Stream_plethysm(f, g, p)
1721+
sage: s(h.get_coefficient(5))
1722+
4*s[1, 1, 1, 1, 1] + 4*s[2, 1, 1, 1] + 2*s[2, 2, 1] + 2*s[3, 1, 1] + s[3, 2] + s[4, 1] + s[5]
1723+
sage: [s(h.get_coefficient(i)) for i in range(6)]
1724+
[0,
1725+
s[1],
1726+
s[1, 1] + s[2],
1727+
2*s[1, 1, 1] + s[2, 1] + s[3],
1728+
3*s[1, 1, 1, 1] + 2*s[2, 1, 1] + s[2, 2] + s[3, 1] + s[4],
1729+
4*s[1, 1, 1, 1, 1] + 4*s[2, 1, 1, 1] + 2*s[2, 2, 1] + 2*s[3, 1, 1] + s[3, 2] + s[4, 1] + s[5]]
1730+
"""
1731+
if not n: # special case of 0
1732+
return self._left[0]
1733+
1734+
# We assume n > 0
1735+
p = self._p
1736+
ret = p.zero()
1737+
for k in range(n+1):
1738+
temp = p(self._left[k])
1739+
for la, c in temp:
1740+
inner = self._compute_product(n, la, c)
1741+
if inner is not None:
1742+
ret += inner
1743+
return ret
1744+
1745+
def _compute_product(self, n, la, c):
1746+
"""
1747+
Compute the product ``c * p[la](self._right)`` in degree ``n``.
1748+
1749+
EXAMPLES::
1750+
1751+
sage: from sage.data_structures.stream import Stream_plethysm, Stream_exact, Stream_function
1752+
sage: s = SymmetricFunctions(QQ).s()
1753+
sage: p = SymmetricFunctions(QQ).p()
1754+
sage: f = Stream_function(lambda n: s[n], s, True, 1)
1755+
sage: g = Stream_exact([s[2], s[3]], False, 0, 4, 2)
1756+
sage: h = Stream_plethysm(f, g, p)
1757+
sage: ret = h._compute_product(7, [2, 1], 1); ret
1758+
1/12*p[2, 2, 1, 1, 1] + 1/4*p[2, 2, 2, 1] + 1/6*p[3, 2, 2]
1759+
+ 1/12*p[4, 1, 1, 1] + 1/4*p[4, 2, 1] + 1/6*p[4, 3]
1760+
sage: ret == p[2,1](s[2] + s[3]).homogeneous_component(7)
1761+
True
1762+
"""
1763+
p = self._p
1764+
ret = p.zero()
1765+
for mu in wt_int_vec_iter(n, la):
1766+
temp = c
1767+
for i, j in zip(la, mu):
1768+
gs = self._right[j]
1769+
if not gs:
1770+
temp = p.zero()
1771+
break
1772+
temp *= p[i](gs)
1773+
ret += temp
1774+
return ret
1775+
16461776
#####################################################################
16471777
# Unary operations
16481778

@@ -2194,3 +2324,4 @@ def is_nonzero(self):
21942324
True
21952325
"""
21962326
return self._series.is_nonzero()
2327+

src/sage/rings/all.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@
146146
lazy_import('sage.rings.laurent_series_ring_element', 'LaurentSeries', deprecation=33602)
147147

148148
# Lazy Laurent series ring
149-
lazy_import('sage.rings.lazy_series_ring', ['LazyLaurentSeriesRing', 'LazyDirichletSeriesRing'])
149+
lazy_import('sage.rings.lazy_series_ring', ['LazyLaurentSeriesRing', 'LazyTaylorSeriesRing',
150+
'LazySymmetricFunctions', 'LazyDirichletSeriesRing'])
150151

151152
# Tate algebras
152153
from .tate_algebra import TateAlgebra

0 commit comments

Comments
 (0)