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

Implement formal Dirichlet series #38324

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
88f3c66
Initial commit: create class of Dirichlet series
kedlaya May 11, 2024
ba8e876
Use L-polynomials to compute Euler product
kedlaya May 13, 2024
90aade2
Merge branch 'develop' into implement_formal_Dirichlet_series
kedlaya May 13, 2024
c383baa
Merge branch 'sagemath:develop' into implement_formal_Dirichlet_series
kedlaya Jul 1, 2024
2aaea48
Fix whitespace issues
kedlaya Jul 1, 2024
21bded6
Another whitespace issue
kedlaya Jul 1, 2024
32db5ca
Add truncate method
kedlaya Jul 6, 2024
3bbf660
Add new_parent option to truncate
kedlaya Jul 6, 2024
63e3338
Merge branch 'sagemath:develop' into implement_formal_Dirichlet_series
kedlaya Aug 1, 2024
442e11c
Add module docstrings, copyright headers
kedlaya Aug 2, 2024
eacc558
Fix lint issue (module docstring should be literal)
kedlaya Aug 2, 2024
0767e14
Refactor repr using sage.misc.repr.repr_lincomb
kedlaya Aug 10, 2024
918f7a5
Fix lint issue (and remove redundant bit of expression)
kedlaya Aug 10, 2024
fb07129
Merge branch 'sagemath:develop' into implement_formal_Dirichlet_series
kedlaya Aug 21, 2024
33eebfb
details in doc and typing
fchapoton Nov 26, 2024
b23f6cc
use Parent in dirichlet_series_ring.py
fchapoton Feb 5, 2025
1675a6d
use CommutativeAlgebras in dirichlet_series_ring.py
fchapoton Feb 5, 2025
254b9a7
small enhancements in dirichlet_series_ring_element.py
fchapoton Feb 5, 2025
1eefff7
fix my broken repr in dirichlet_series_ring_element.py
fchapoton Feb 5, 2025
49914d6
change __eq__ in dirichlet_series_ring_element.py
fchapoton Feb 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/sage/rings/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,6 @@

# Register classes in numbers abc
from sage.rings import numbers_abc

# Dirichlet series rings
from sage.rings.dirichlet_series_ring import DirichletSeriesRing
152 changes: 152 additions & 0 deletions src/sage/rings/dirichlet_series_ring.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
r"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new modules should be added to the documentation index

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which file(s) do I need to touch to do this? I couldn't find this in the developer's guide.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kedlaya I would put it in src/doc/en/reference/power_series/index.rst.

Rings of formal Dirichlet series

For any ring `R` and any positive integer `n`, we obtain a ring of formal Dirichlet
series over `R` truncated to precision `n` by considering the formal expressions of
the form `\sum_{i=1}^{n-1} a_i i^{-s}` where the `a_i` are elements of `R`, with the
addition and multiplication rules implied by the syntax.

Sage provides dense and sparse implementations of fixed-precision Dirichlet series
over any Sage base ring.

EXAMPLES::

sage: R = DirichletSeriesRing(ZZ, 10)
sage: u = R([1,3,1]); u
1 + 3*2^-s + 3^-s + O(10^-s)
sage: v = 1/u; v

Check failure on line 17 in src/sage/rings/dirichlet_series_ring.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.rings.dirichlet_series_ring[2]>", line 1, in <module> v = Integer(1)/u; v File "sage/rings/integer.pyx", line 2042, in sage.rings.integer.Integer.__truediv__ return coercion_model.bin_op(left, right, operator.truediv) File "sage/structure/coerce.pyx", line 1234, in sage.structure.coerce.CoercionModel.bin_op xy = self.canonical_coercion(x, y) File "sage/structure/coerce.pyx", line 1354, in sage.structure.coerce.CoercionModel.canonical_coercion raise RuntimeError("BUG in map, returned None %s %s %s" % (x, type(x_map), x_map)) RuntimeError: BUG in map, returned None 1 <class 'sage.categories.morphism.SetMorphism'> (map internal to coercion system -- copy before use) Generic morphism: From: Integer Ring To: Dirichlet Series Ring over Integer Ring with fixed precision 10
1 - 3*2^-s - 3^-s + 9*4^-s + 6*6^-s - 27*8^-s + 9^-s + O(10^-s)
sage: u*v

Check failure on line 19 in src/sage/rings/dirichlet_series_ring.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.rings.dirichlet_series_ring[3]>", line 1, in <module> u*v NameError: name 'v' is not defined
1 + O(10^-s)

AUTHORS:

- Kiran Kedlaya (2024-08-01): initial version

"""

# ****************************************************************************
# Copyright (C) 2024 Kiran S. Kedlaya <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# https://www.gnu.org/licenses/
# ****************************************************************************

from sage.misc.misc_c import prod
mkoeppe marked this conversation as resolved.
Show resolved Hide resolved
from sage.structure.parent import Parent
from sage.rings.fast_arith import prime_range
from sage.categories.commutative_algebras import CommutativeAlgebras
from sage.rings.dirichlet_series_ring_element import DirichletSeries_dense, DirichletSeries_sparse

class DirichletSeriesRing(Parent):
"""
A ring of Dirichlet series over a base ring, truncated to a fixed precision.

EXAMPLES::

sage: R = DirichletSeriesRing(ZZ, 10)
sage: u = R([1,3,1]); u
1 + 3*2^-s + 3^-s + O(10^-s)
sage: v = 1/u; v

Check failure on line 53 in src/sage/rings/dirichlet_series_ring.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.rings.dirichlet_series_ring.DirichletSeriesRing[2]>", line 1, in <module> v = Integer(1)/u; v File "sage/rings/integer.pyx", line 2042, in sage.rings.integer.Integer.__truediv__ return coercion_model.bin_op(left, right, operator.truediv) File "sage/structure/coerce.pyx", line 1234, in sage.structure.coerce.CoercionModel.bin_op xy = self.canonical_coercion(x, y) File "sage/structure/coerce.pyx", line 1354, in sage.structure.coerce.CoercionModel.canonical_coercion raise RuntimeError("BUG in map, returned None %s %s %s" % (x, type(x_map), x_map)) RuntimeError: BUG in map, returned None 1 <class 'sage.categories.morphism.SetMorphism'> (map internal to coercion system -- copy before use) Generic morphism: From: Integer Ring To: Dirichlet Series Ring over Integer Ring with fixed precision 10
1 - 3*2^-s - 3^-s + 9*4^-s + 6*6^-s - 27*8^-s + 9^-s + O(10^-s)
sage: u*v

Check failure on line 55 in src/sage/rings/dirichlet_series_ring.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.rings.dirichlet_series_ring.DirichletSeriesRing[3]>", line 1, in <module> u*v NameError: name 'v' is not defined
1 + O(10^-s)
"""
def __init__(self, base_ring, precision, sparse=True):
"""
Create a Dirichlet series ring.

EXAMPLES::

sage: R = DirichletSeriesRing(ZZ, 10, sparse=False)
sage: S = DirichletSeriesRing(ZZ, 10, sparse=True)
sage: R.has_coerce_map_from(ZZ)
True
sage: R.has_coerce_map_from(S)
False
sage: S.has_coerce_map_from(R)
True
"""
self.Element = DirichletSeries_sparse if sparse else DirichletSeries_dense
Parent.__init__(self, base=base_ring, names=None, category=CommutativeAlgebras(base_ring))
self.__precision = precision
self.__is_sparse = sparse

def _repr_(self) -> str:
"""
Return a string representation.

EXAMPLES::

sage: R = DirichletSeriesRing(ZZ, 10)
sage: R
Dirichlet Series Ring over Integer Ring with fixed precision 10
"""
return "Dirichlet Series Ring over {} with fixed precision {}".format(self.base_ring(), self.__precision)

def is_sparse(self) -> bool:
"""
Return ``True`` if this ring uses sparse internal representation.

fchapoton marked this conversation as resolved.
Show resolved Hide resolved
EXAMPLES::

sage: R = DirichletSeriesRing(ZZ, 10, sparse=False)
sage: S = DirichletSeriesRing(ZZ, 10, sparse=True)
sage: R.is_sparse()
False
sage: S.is_sparse()
True
"""
return self.__is_sparse

def precision(self):
"""
Return the specified precision for this ring.

EXAMPLES::

sage: R = DirichletSeriesRing(ZZ, 10)
sage: R.precision()
10
"""
return self.__precision

def _coerce_map_from_(self, S) -> bool | None:
"""
Implement coercion.

EXAMPLES::

sage: R = DirichletSeriesRing(ZZ, 10, sparse=False)
sage: S = DirichletSeriesRing(ZZ, 10, sparse=True)
sage: R.has_coerce_map_from(ZZ)
True
sage: R.has_coerce_map_from(S)
False
sage: S.has_coerce_map_from(R)
True
"""
base_ring = self.base_ring()
if base_ring.has_coerce_map_from(S):
return True
if isinstance(S, DirichletSeriesRing) and base_ring.has_coerce_map_from(S.base_ring()) and self.precision() <= S.precision() and (self.is_sparse() or not S.is_sparse()):
return True

def euler_product(self, Lpoly):
"""
Construct an Euler product out of `L`-polynomials.

EXAMPLES:

Construct the Riemann zeta function as a formal Dirichlet series::

sage: R = DirichletSeriesRing(ZZ, 10)
sage: P.<T> = ZZ[]
sage: R.euler_product({p: 1-T for p in prime_range(25)})

Check failure on line 148 in src/sage/rings/dirichlet_series_ring.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Exception raised: Traceback (most recent call last): File "/sage/src/sage/doctest/forker.py", line 728, in _run self.compile_and_execute(example, compiler, test.globs) File "/sage/src/sage/doctest/forker.py", line 1152, in compile_and_execute exec(compiled, globs) File "<doctest sage.rings.dirichlet_series_ring.DirichletSeriesRing.euler_product[2]>", line 1, in <module> R.euler_product({p: Integer(1)-T for p in prime_range(Integer(25))}) File "/sage/src/sage/rings/dirichlet_series_ring.py", line 151, in euler_product return prod(1 / self({p**i: j for i, j in Lpoly[p].dict().items()}) File "sage/misc/misc_c.pyx", line 132, in sage.misc.misc_c.prod return iterator_prod(x, z) File "sage/misc/misc_c.pyx", line 214, in sage.misc.misc_c.iterator_prod sub_prods = [next(L)] * 10 File "/sage/src/sage/rings/dirichlet_series_ring.py", line 151, in <genexpr> return prod(1 / self({p**i: j for i, j in Lpoly[p].dict().items()}) File "sage/structure/element.pyx", line 1734, in sage.structure.element.Element.__truediv__ return coercion_model.bin_op(left, right, truediv) File "sage/structure/coerce.pyx", line 1238, in sage.structure.coerce.CoercionModel.bin_op return PyObject_CallObject(op, xy) File "sage/structure/element.pyx", line 1729, in sage.structure.element.Element.__truediv__ return (<Element>left)._div_(right) File "sage/structure/element.pyx", line 2758, in sage.structure.element.RingElement._div_ cpdef _div_(self, other): File "/sage/src/sage/rings/dirichlet_series_ring_element.py", line 256, in _div_ other1 = 1 - inv * other File "sage/rings/integer.pyx", line 1969, in sage.rings.integer.Integer.__mul__ return coercion_model.bin_op(left, right, operator.mul) File "sage/structure/coerce.pyx", line 1234, in sage.structure.coerce.CoercionModel.bin_op xy = self.canonical_coercion(x, y) File "sage/structure/coerce.pyx", line 1354, in sage.structure.coerce.CoercionModel.canonical_coercion raise RuntimeError("BUG in map, returned None %s %s %s" % (x, type(x_map), x_map)) RuntimeError: BUG in map, returned None 1 <class 'sage.categories.morphism.SetMorphism'> (map internal to coercion system -- copy before use) Generic morphism: From: Integer Ring To: Dirichlet Series Ring over Integer Ring with fixed precision 10
1 + 2^-s + 3^-s + 4^-s + 5^-s + 6^-s + 7^-s + 8^-s + 9^-s + O(10^-s)
"""
return prod(1 / self({p**i: j for i, j in Lpoly[p].dict().items()})
for p in prime_range(self.precision()))
Loading
Loading