Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
correct an_element and some_elements, implement is_unit, _test_invert
Browse files Browse the repository at this point in the history
  • Loading branch information
mantepse committed Sep 17, 2022
1 parent 08baf9a commit 5bd0331
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 37 deletions.
17 changes: 17 additions & 0 deletions src/sage/combinat/sf/sfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -1722,6 +1722,23 @@ def degree_zero_coefficient(self):
"""
return self.coefficient([])

def is_unit(self):
"""
Return whether this element is a unit in the ring.
EXAMPLES::
sage: Sym = SymmetricFunctions(QQ)
sage: m = Sym.monomial()
sage: (2*m[2,1] + 3*m[[]]).is_unit()
False
sage: (3/2*m([])).is_unit()
True
"""
return self.coefficient([]).is_unit()


#SymmetricFunctionsBases.Filtered = FilteredSymmetricFunctionsBases
#SymmetricFunctionsBases.Graded = GradedSymmetricFunctionsBases

Expand Down
5 changes: 3 additions & 2 deletions src/sage/data_structures/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -1575,9 +1575,10 @@ def __init__(self, series):
sage: g = Stream_dirichlet_invert(f)
Traceback (most recent call last):
...
AssertionError: the Dirichlet inverse only exists if the coefficient with index 1 is non-zero
ZeroDivisionError: the Dirichlet inverse only exists if the coefficient with index 1 is non-zero
"""
assert series[1], "the Dirichlet inverse only exists if the coefficient with index 1 is non-zero"
if not series[1]:
raise ZeroDivisionError("the Dirichlet inverse only exists if the coefficient with index 1 is non-zero")
super().__init__(series, series._is_sparse, 1)

self._ainv = ~series[1]
Expand Down
97 changes: 97 additions & 0 deletions src/sage/rings/lazy_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2998,6 +2998,27 @@ class LazyLaurentSeries(LazyCauchyProductSeries):
sage: f = 1 / (1 - z - z^2)
sage: TestSuite(f).run()
"""
def is_unit(self):
"""
Return whether this element is a unit in the ring.
EXAMPLES::
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
sage: (2*z).is_unit()
False
sage: (1+2*z).is_unit()
True
sage: (1+2*z^-1).is_unit()
False
"""
if self.is_zero(): # now 0 != 1
return False
a = self[self.valuation()]
return a.is_unit()

def _im_gens_(self, codomain, im_gens, base_map=None):
"""
Return the image of ``self`` under the map that sends the
Expand Down Expand Up @@ -3896,6 +3917,30 @@ class LazyPowerSeries(LazyCauchyProductSeries):
sage: g == f
True
"""
def is_unit(self):
"""
Return whether this element is a unit in the ring.
EXAMPLES::
sage: L.<z> = LazyPowerSeriesRing(ZZ)
sage: (2*z).is_unit()
False
sage: (1+2*z).is_unit()
True
sage: (3+2*z).is_unit()
False
sage: L.<x,y> = LazyPowerSeriesRing(ZZ)
sage: (1+2*x+3*x*y).is_unit()
True
"""
if self.is_zero(): # now 0 != 1
return False
return not self.valuation() and self[0].is_unit()

def exponential(self):
r"""
Return the exponential series of ``self``.
Expand Down Expand Up @@ -4705,6 +4750,34 @@ class LazySymmetricFunction(LazyCompletionGradedAlgebraElement):
sage: s = SymmetricFunctions(ZZ).s()
sage: L = LazySymmetricFunctions(s)
"""
def is_unit(self):
"""
Return whether this element is a unit in the ring.
EXAMPLES::
sage: m = SymmetricFunctions(ZZ).m()
sage: L = LazySymmetricFunctions(m)
sage: L(2*m[1]).is_unit()
False
sage: L(1+2*m[1]).is_unit()
True
sage: L(2+3*m[1]).is_unit()
False
sage: m = SymmetricFunctions(QQ).m()
sage: L = LazySymmetricFunctions(m)
sage: L(2+3*m[1]).is_unit()
True
"""
if self.is_zero(): # now 0 != 1
return False
return not self.valuation() and self[0].is_unit()

def __call__(self, *args, check=True):
r"""
Return the composition of ``self`` with ``g``.
Expand Down Expand Up @@ -5569,6 +5642,30 @@ class LazyDirichletSeries(LazyModuleElement):
sage: g == f
True
"""
def is_unit(self):
"""
Return whether this element is a unit in the ring.
EXAMPLES::
sage: D = LazyDirichletSeriesRing(ZZ, "s")
sage: D([0,2]).is_unit()
False
sage: D([1,2]).is_unit()
True
sage: D([3,2]).is_unit()
False
sage: D = LazyDirichletSeriesRing(QQ, "s")
sage: D([3,2]).is_unit()
True
"""
if self.is_zero(): # now 0 != 1
return False
return not self.valuation() and self[0].is_unit()

def valuation(self):
r"""
Return the valuation of ``self``.
Expand Down
134 changes: 99 additions & 35 deletions src/sage/rings/lazy_series_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,12 +391,6 @@ def _element_constructor_(self, x=None, valuation=None, degree=None, constant=No
constant = BR(constant)

if coefficients is None:
# if isinstance(x, (list, tuple)) and degree is None:
# if valuation is None:
# degree = len(x)
# else:
# degree = valuation + len(x)

# Try to build stuff using the internal polynomial ring constructor
R = self._internal_poly_ring
try:
Expand Down Expand Up @@ -759,6 +753,35 @@ def is_exact(self):
"""
return self.base_ring().is_exact()

def _test_invert(self, **options):
"""
Test multiplicative inversion of elements of this ring.
INPUT:
- ``options`` -- any keyword arguments accepted by :meth:`_tester`
EXAMPLES::
sage: Zp(3)._test_invert()
.. SEEALSO::
:class:`TestSuite`
"""
tester = self._tester(**options)

elements = tester.some_elements()
for x in elements:
try:
y = ~x
except (ZeroDivisionError, ValueError):
tester.assertFalse(x.is_unit())
else:
e = y * x
tester.assertFalse(x.is_zero())
tester.assertTrue(e.is_one())
tester.assertEqual(y.valuation(), -x.valuation())

class LazyLaurentSeriesRing(LazySeriesRing):
r"""
Expand Down Expand Up @@ -1287,9 +1310,12 @@ def __init__(self, base_ring, names, sparse=True, category=None):
sage: L in PrincipalIdealDomains
False
The ideal generated by `s` and `t` is not principal::
sage: L = LazyPowerSeriesRing(QQ, 's, t')
sage: L in PrincipalIdealDomains
False
"""
from sage.structure.category_object import normalize_names
names = normalize_names(-1, names)
Expand Down Expand Up @@ -1636,12 +1662,13 @@ def _an_element_(self):
sage: L = LazyPowerSeriesRing(ZZ, 'z')
sage: L.an_element()
z + z^2 + z^3 + O(z^4)
z
sage: L = LazyPowerSeriesRing(ZZ, 'x, y')
sage: L.an_element()
x
"""
c = self.base_ring().an_element()
R = self._laurent_poly_ring
coeff_stream = Stream_exact([R.one()], self._sparse, order=1, constant=c)
return self.element_class(self, coeff_stream)
return self(self._laurent_poly_ring.an_element())

def uniformizer(self):
"""
Expand Down Expand Up @@ -1685,35 +1712,30 @@ def some_elements(self):
sage: L = LazyPowerSeriesRing(ZZ, 'z')
sage: L.some_elements()
[0,
1,
z,
z + z^2 + z^3 + O(z^4),
[0, 1, z,
-12 - 8*z + z^2 + z^3,
1 + z - 2*z^2 - 7*z^3 - z^4 + 20*z^5 + 23*z^6 + O(z^7),
z + 4*z^2 + 9*z^3 + 16*z^4 + 25*z^5 + 36*z^6 + O(z^7)]
sage: L = LazyPowerSeriesRing(GF(3)["q"], 'z')
sage: L.some_elements()
[0,
1,
z,
z + q*z^2 + q*z^3 + q*z^4 + O(z^5),
[0, 1, z,
z + z^2 + z^3,
1 + z + z^2 + 2*z^3 + 2*z^4 + 2*z^5 + O(z^6),
z + z^2 + z^4 + z^5 + O(z^7)]
sage: L = LazyPowerSeriesRing(GF(3), 'q, t')
sage: L.some_elements()
[0, 1, q, 1, q + q^2 + q^3,
[0, 1, q,
q + q^2 + q^3,
1 + q + q^2 + (-q^3) + (-q^4) + (-q^5) + (-q^6) + O(q,t)^7,
1 + (q+t) + (q^2-q*t+t^2) + (q^3+t^3)
+ (q^4+q^3*t+q*t^3+t^4)
+ (q^5-q^4*t+q^3*t^2+q^2*t^3-q*t^4+t^5)
+ (q^6-q^3*t^3+t^6) + O(q,t)^7]
"""
z = self.gen(0)
elts = [self.zero(), self.one(), z, self.an_element()]
elts = [self.zero(), self.one(), self.an_element()]
if self._arity == 1:
elts.extend([(z-3)*(2+z)**2, (1 - 2*z**3)/(1 - z + 3*z**2), self(lambda n: n**2)])
else:
Expand Down Expand Up @@ -1773,7 +1795,7 @@ def __init__(self, basis, sparse=True, category=None):
TESTS::
sage: LazySymmetricFunctions.options.halting_precision(15)
sage: LazySymmetricFunctions.options.halting_precision(7)
sage: s = SymmetricFunctions(ZZ).s()
sage: L = LazySymmetricFunctions(s)
Expand All @@ -1787,9 +1809,10 @@ def __init__(self, basis, sparse=True, category=None):
sage: LazySymmetricFunctions.options.halting_precision(None)
Check that :trac:`34470` is fixed::
Check that :trac:`34470` is fixed. The ideal generated by
`p[1]` and `p[2]` is not principal::
sage: s = SymmetricFunctions(QQ).s()
sage: p = SymmetricFunctions(QQ).p()
sage: L = LazySymmetricFunctions(s)
sage: L in PrincipalIdealDomains
False
Expand All @@ -1802,12 +1825,6 @@ def __init__(self, basis, sparse=True, category=None):
...
ValueError: basis should be in GradedAlgebrasWithBasis
Check that :trac:`34470` is fixed::
sage: s = SymmetricFunctions(QQ).s()
sage: L = LazySymmetricFunctions(s)
sage: L in PrincipalIdealDomains
False
"""
base_ring = basis.base_ring()
self._minimal_valuation = 0
Expand Down Expand Up @@ -2074,12 +2091,44 @@ def _an_element_(self):
sage: m = SymmetricFunctions(ZZ).m()
sage: L = LazySymmetricFunctions(m)
sage: L.an_element()
m[]
2*m[] + 2*m[1] + 3*m[2]
"""
R = self._laurent_poly_ring
coeff_stream = Stream_exact([R.one()], self._sparse, order=1, constant=0)
return self.element_class(self, coeff_stream)
return self(self._laurent_poly_ring.an_element())

def some_elements(self):
"""
Return a list of elements of ``self``.
EXAMPLES::
sage: m = SymmetricFunctions(GF(5)).m()
sage: L = LazySymmetricFunctions(m)
sage: L.some_elements()
[0, m[], 2*m[] + 2*m[1] + 3*m[2],
3*m[] + 2*m[1] + (m[1,1]+m[2])
+ (2*m[1,1,1]+m[3])
+ (2*m[1,1,1,1]+4*m[2,1,1]+2*m[2,2])
+ (3*m[2,1,1,1]+3*m[3,1,1]+4*m[3,2]+m[5])
+ (2*m[2,2,1,1]+m[2,2,2]+2*m[3,2,1]+2*m[3,3]+m[4,1,1]+3*m[4,2]+4*m[5,1]+4*m[6])
+ O^7]
sage: NCSF = NonCommutativeSymmetricFunctions(QQ)
sage: S = NCSF.Complete()
sage: L = S.formal_series_ring()
sage: L.some_elements()
[0, S[], 2*S[] + 2*S[1] + (3*S[1,1])]
"""
elt = self.an_element()
elts = [self.zero(), self.one(), elt]
try:
if elt.is_unit():
elts.append(~elt)
else:
elts.append(~(1-elt[0]+elt))
except NotImplementedError:
pass
return elts

######################################################################

Expand Down Expand Up @@ -2142,6 +2191,21 @@ def __init__(self, base_ring, names, sparse=True, category=None):
Options are remembered across doctests::
sage: LazyDirichletSeriesRing.options.halting_precision(None)
The ideal generated by `2^-s` and `3^-s` is not principal::
sage: L = LazyDirichletSeriesRing(QQ, 's')
sage: L in PrincipalIdealDomains
False
In particular, it is not a :wikipedia:`discrete_valuation_ring`.
.. TODO::
According to the answers in
https://mathoverflow.net/questions/5522/dirichlet-series-with-integer-coefficients-as-a-ufd,
the ring of formal Dirichlet series is actually a
UniqueFactorizationDomain.
"""
if base_ring.characteristic() > 0:
raise ValueError("positive characteristic not allowed for Dirichlet series")
Expand Down Expand Up @@ -2358,7 +2422,7 @@ def some_elements(self):
some_numbers = [c for c, _ in zip(R.some_elements(), range(9))]
elts = [self.zero(), self.one(), self.an_element(),
self(some_numbers),
self(some_numbers, constant = R.an_element()),
self(some_numbers, constant=R.an_element()),
self(lambda n: n**2)]
return elts

Expand Down

0 comments on commit 5bd0331

Please sign in to comment.