Open mantepse opened 1 year ago
Hello Martin, Before opening an issue about this, I wanted to check if this is an expected behavior:
sage: L = LazyPowerSeriesRing(QQ, 'z')
sage: f = lambda n: 1 if ZZ(n).is_power_of(2) else 0
sage: lazy_f = L(f); lazy_f
z + z^2 + z^4 + O(z^7)
sage: lazy_f.compositional_inverse()
<repr(<sage.rings.lazy_series_ring.LazyPowerSeriesRing_with_category.element_class at 0x7f3209489720>) failed: ValueError: inverse does not exist>
sage: lazy_f[:2**4]
[1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
sage: lazy_f.compositional_inverse()
z - z^2 + 2*z^3 - 6*z^4 + 20*z^5 - 70*z^6 + 256*z^7 + O(z^8)
It seems that, in this particular case, the compositional inverse can be computed only after the code knows about some coefficients of f
.
This is extremely strange, and almost certainly a bug.
Hello Martin,
I noticed something with the representation of a lazy power series and I wanted to check with you if that's a a normal behavior. Essentially, if you create a Lazy series over a polynomial ring, then their elements seems to be displayed with an extra set of parenthesis (compared to the nonlazy power series):
sage: R.<T> = QQ[]
sage: L.<z> = LazyPowerSeriesRing(R)
sage: T*z
T*z
sage: (T+1)*z # _repr_ gives an extra pair of parenthesis:
((T+1)*z)
sage: P.<w> = PowerSeriesRing(R)
sage: T*w
T*w
sage: (T+1)*w # no extra parenthesis:
(T + 1)*w
I wondered if this is wanted or not, because I find that sometimes it clutters the representation a bit.
By the way, I've been experimenting with lazy series lately and it is very useful! Thank you very much for maintaining this.
Thank you for the thank you :-)
@tscrim, do you remember why the parentheses are done the way they are done?
It is a side effect of the somewhat lazily done implementation of printing (IIRC, homogeneous components always have parentheses). Something smarter could definitely be done, but it would take a little bit of work and string manipulations that I didn’t want to do at the time.
I am wondering if we fix the first bug (some missing attribute that I am not sure it should have) if the second bug will take its place. I would have to dig into the matrix code. Somewhat annoyingly, the matrix code is quite strict when it comes to the subclasses of Element
, but the good news is the fix is fairly easy: just inherit from RingElement
instead of Element
.
Ah, I know why the behavior in the first bug is different. The Laurent series is a field, which results in a different code path. Although it seems to be trying to treat it as an inexact field, which is bad. Although IMO it should do a division-free algorithm by default, but we probably would need to have an additional special case for lazy series.
Here's something I found:
sage: L.<z> = LazyPowerSeriesRing(QQ)
sage: f = z^2 + z^3 + z^4
sage: f
z^2 + z^3 + z^4
sage: list(f)
# infinite loop
Ouch, that’s a pretty bad one. Although I believe it is simply doing the iterator, which is what is leading to the infinite loop. I think the most consistent solution would be to simply raise an error though __len__
(or however other infinite enumerated sets behave). That way an exact versus and inexact element behaves in the same way.
I don't think that this is a bug, actually. The slice should return all coefficients, not just the non-zero ones, so what is list
supposed to do?
@mantepse I say it should raise an error like list(ZZ)
does. Infinite slices are one thing, but we can at least do a basic guard around list(f)
.
Ah! So if the proposal is to always raise an error, I agree! (though -> through, right?)
Yes, that’s right (including about my typo).
More bugs and missing features:
repr
does not work well with series over matrices:
sage: M = MatrixSpace(QQ, 2, 2)
sage: L.<t> = LazyPowerSeriesRing(M)
sage: 1/(1-t-t^2)
([10]
[01]) + ([10]
[01]*t) + ([20]
[02]*t^2) + ([30]
[03]*t^3) + ([50]
[05]*t^4) + ([80]
[08]*t^5) + ([130]
[013]*t^6) + O([10]
[01]*t^7)
repr
does not work with Dirichlet series over matrices:
sage: L = LazyDirichletSeriesRing(M, "t")
sage: M = MatrixSpace(QQ, 2, 2)
sage: L(lambda n: 1)
<repr(<sage.rings.lazy_series_ring.LazyDirichletSeriesRing_with_category.element_class at 0x7f055a805400>) failed: AttributeError: 'ComplexIntervalField_class_with_category' object has no attribute 'complex_field'>
sage: R.<f> = InfinitePolynomialRing(QQ, implementation="dense")
sage: L.<x> = LazyLaurentSeriesRing(R)
sage: F = L(lambda n: f[n] if n else 1, 0)
sage: n=2; c = diff(x^(n-1)*log(F), n)
sage: type(c[2])
<class 'sage.rings.polynomial.infinite_polynomial_element.InfinitePolynomial_sparse'>
but