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

inverse_series method for polynomials #19005

Closed
videlec opened this issue Aug 9, 2015 · 30 comments
Closed

inverse_series method for polynomials #19005

videlec opened this issue Aug 9, 2015 · 30 comments

Comments

@videlec
Copy link
Contributor

videlec commented Aug 9, 2015

The polynomials in Sage lack many series operation (see #18356 for some motivation). We implement a generic cpdef Polynomial inverse_series(self, long prec) method and specialized ones for polynomials using flint backends.

See also #19006

CC: @sagetrac-pernici @mezzarobba

Component: commutative algebra

Author: Vincent Delecroix

Branch/Commit: 8a09308

Reviewer: Marc Mezzarobba

Issue created by migration from https://trac.sagemath.org/ticket/19005

@videlec videlec added this to the sage-6.9 milestone Aug 9, 2015
@videlec
Copy link
Contributor Author

videlec commented Aug 9, 2015

Branch: u/vdelecroix/19005

@videlec
Copy link
Contributor Author

videlec commented Aug 9, 2015

New commits:

5d2ebb8trac #19005: generic inverse_series
40ff24dtrac #19005: truncate return self for large precision
466fa3ctrac #19005: more flint declaration
e01540bTrac #19005: specialized inverse_series for flint backends

@videlec
Copy link
Contributor Author

videlec commented Aug 9, 2015

Commit: e01540b

@videlec

This comment has been minimized.

@mezzarobba
Copy link
Member

comment:3

Hi Vincent,

Could you please explain why you'd like to have these features as methods of polynomial objects rather than power series objects? Thanks!

@videlec
Copy link
Contributor Author

videlec commented Aug 18, 2015

comment:4

Hi Marc,

Replying to @mezzarobba:

Could you please explain why you'd like to have these features as methods of polynomial objects rather than power series objects? Thanks!

  1. A power series just wraps a polynomial. So it would be better to have specialized algorithms for polynomials and wrap them at the power series level. Would you prefer one power series element per polynomial class? As soon as this is reviewed, I will change the power series implementation to use this method and it will be much faster. I can do that here if you prefer.

  2. Power series are much slower and involving them in a polynomial algorithm implies a creation of parent (which is damn slow). Moreover you only care about the polynomial at the end. You can have a look at special resultants composed_sum and composed_product #18356 for motivation from this side.

Vincent

@mezzarobba
Copy link
Member

comment:5

Replying to @videlec:

Could you please explain why you'd like to have these features as methods of polynomial objects rather than power series objects? Thanks!

  1. A power series just wraps a polynomial. So it would be better to have specialized algorithms for polynomials and wrap them at the power series level. Would you prefer one power series element per polynomial class?

No, as long as the methods you are implementing on polynomials are just helpers for generic implementations on power series, I agree. But I wouldn't want to clutter the interface of polynomials with every possible operation on power series, elements of quotients of polynomial rings, etc.

Anyway, this ticket probably wasn't the right place to make this comment, because I agree that inversion modulo xk is fundamental enough to be part of the interface of polynomials themselves.

  1. Power series are much slower and involving them in a polynomial algorithm implies a creation of parent (which is damn slow).

Well, that's probably something that should be fixed on its own! :-)

@mezzarobba
Copy link
Member

comment:6

The docstring of inverse_series claims that it works over any ring, but after patching matrix0.pyx to make is_unit synonymous with is_invertible, I get:

sage: R.<x> = MatrixSpace(QQ, 2)[]
sage: pol = R.random_element()
sage: list(pol)
[
[   2    0]  [2 1]  [-1  0]
[-1/2 -1/2], [0 2], [ 2 -2]
]
sage: inv = pol.inverse_series(5)
sage: (inv*pol).truncate(5).degree()
4
sage: (pol*inv).truncate(5).degree()
4

Did you intend it to work over non-commutative rings?

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 26, 2015

Changed commit from e01540b to 82d2740

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 26, 2015

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

e51a669trac #19005: generic inverse_series
e594c17trac #19005: truncate return self for large precision
ca2ac91trac #19005: more flint declaration
4705c72Trac #19005: specialized inverse_series for flint backends
740c149Trac 19005: is_unit for matrices
82d2740Trac 19005: inverse_series over noncommutative rings

@videlec
Copy link
Contributor Author

videlec commented Aug 26, 2015

Reviewer: Marc Mezzarobba

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 26, 2015

Changed commit from 82d2740 to 7e775c5

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 26, 2015

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

8098f1aTrac 19005: is_unit for matrices
7e775c5Trac 19005: inverse_series over noncommutative rings

@bgrenet
Copy link

bgrenet commented Aug 27, 2015

comment:11

Though I am not definitive on this, I find it weird to have the two distinct methods inverse_mod and inverse_series with p.inverse_series(10) == p.inverse_mod(x^10). Wouldn't it be possible to make your code a special case of inverse_mod, or to make it a hidden function (_inverse_series) which is called as a special case of inverse_mod? Actually, these are two distinct changes I propose, with two distinct reasons:

  1. It would be make inverse_mod faster for monomials:

    sage: %timeit p.inverse_series(10)
    The slowest run took 24.39 times longer than the fastest. This could mean that an intermediate result is being cached 
    100000 loops, best of 3: 1.96 µs per loop
    sage: %timeit p.inverse_mod(x^10)
    The slowest run took 6.16 times longer than the fastest. This could mean that an intermediate result is being cached 
    10000 loops, best of 3: 26.2 µs per loop
    1. The name inverse_series make me think that the result will be a series, so if I want a truncated series (that is a polynomial), I am more naturally inclined to try the inverse_mod method. And I suspect other users may have the same behavior.

@videlec
Copy link
Contributor Author

videlec commented Aug 27, 2015

comment:12

Hi Bruno,

Replying to @bgrenet:

Though I am not definitive on this, I find it weird to have the two distinct methods inverse_mod and inverse_series with p.inverse_series(10) == p.inverse_mod(x^10). Wouldn't it be possible to make your code a special case of inverse_mod, or to make it a hidden function (_inverse_series) which is called as a special case of inverse_mod? Actually, these are two distinct changes I propose, with two distinct reasons:

I definitely do not want to involve a case search to get the inverse series (the calls to isinstance, from sage.rings.ideal import Ideal all the if takes a lot of time). The function inverse_series has type definition in input that will make it efficient in Cython code (e.g. power series). So I am against having it as a special case of inverse_mod. Thoug, if you think it would be interesting you can add a special case to inverse_mod but I am not sure it is worth it. It might be better to just add a SEEALSO in the documentation.

  1. The name inverse_series make me think that the result will be a series, so if I want a truncated series (that is a polynomial), I am more naturally inclined to try the inverse_mod method. And I suspect other users may have the same behavior.

What about truncated_inverse_series or inverse_series_trunc? (there is already a _mul_trunc_).

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 27, 2015

Changed commit from 7e775c5 to a6c1b39

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 27, 2015

Branch pushed to git repo; I updated commit sha1. New commits:

a6c1b39Trac 19005: fix a doctest

@mezzarobba
Copy link
Member

comment:14

Hi Vincent, hi Bruno,

Replying to @videlec:

I definitely do not want to involve a case search to get the inverse series (the calls to isinstance, from sage.rings.ideal import Ideal all the if takes a lot of time). The function inverse_series has type definition in input that will make it efficient in Cython code (e.g. power series). So I am against having it as a special case of inverse_mod. Thoug, if you think it would be interesting you can add a special case to inverse_mod but I am not sure it is worth it. It might be better to just add a SEEALSO in the documentation.

I tend to agree.

  1. The name inverse_series make me think that the result will be a series, so if I want a truncated series (that is a polynomial), I am more naturally inclined to try the inverse_mod method. And I suspect other users may have the same behavior.

What about truncated_inverse_series or inverse_series_trunc? (there is already a _mul_trunc_).

Ore perhaps inverse_mod_xk? I thought about suggesting a different name when I wrote my comments above, but I didn't find anything that I really liked better than inverse_series...

@bgrenet
Copy link

bgrenet commented Aug 28, 2015

comment:15

Hi Vincent, hi (again) Marc,

Replying to @mezzarobba:

Hi Vincent, hi Bruno,

Replying to @videlec:

I definitely do not want to involve a case search to get the inverse series (the calls to isinstance, from sage.rings.ideal import Ideal all the if takes a lot of time). The function inverse_series has type definition in input that will make it efficient in Cython code (e.g. power series). So I am against having it as a special case of inverse_mod. Thoug, if you think it would be interesting you can add a special case to inverse_mod but I am not sure it is worth it. It might be better to just add a SEEALSO in the documentation.

I tend to agree.

Well, a SEEALSO looks like a good solution to me also.

  1. The name inverse_series make me think that the result will be a series, so if I want a truncated series (that is a polynomial), I am more naturally inclined to try the inverse_mod method. And I suspect other users may have the same behavior.

What about truncated_inverse_series or inverse_series_trunc? (there is already a _mul_trunc_).

Ore perhaps inverse_mod_xk? I thought about suggesting a different name when I wrote my comments above, but I didn't find anything that I really liked better than inverse_series...

My preferred choice goes to inverse_series_trunc (or inverse_series_truncated if you do not find it too long) since it will easily be found using tabulation and describes well the behavior.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 29, 2015

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

d3ca1dbtrac #19005: generic inverse_series
7636b64trac #19005: truncate return self for large precision
2648ba9trac #19005: more flint declaration
cd62420Trac #19005: specialized inverse_series for flint backends
91337f0Trac 19005: is_unit for matrices
e45d880Trac 19005: inverse_series over noncommutative rings
1362ca8Trac 19005: fix a doctest
7294833Trac 19005: a SEEALSO block

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 29, 2015

Changed commit from a6c1b39 to 7294833

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 29, 2015

Changed commit from 7294833 to d16898a

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 29, 2015

Branch pushed to git repo; I updated commit sha1. New commits:

d16898a19005: inverse_series -> inverse_series_trunc

@videlec
Copy link
Contributor Author

videlec commented Aug 29, 2015

comment:18

Rebased and updated with your last remarks.

Vincent

@mezzarobba
Copy link
Member

comment:19
  • The generic version fails when the truncation order is negative (inconsistency with the others versions) or zero (which is a problem by itself):
sage: (1 + polygen(GF(2))).inverse_series_trunc(0)
...
ValueError: N (=0) must be a positive integer

sage: (1 + polygen(ZZ)).inverse_series_trunc(-1)
0
  • I believe the doctest in rings.py that you fixed was meant to test the code path resulting in a NotImplementedError.
  • You may want to change two*current to current + current in the generic implementation? (Not sure if this is a good idea, but it could be much faster for some rings.)
  • Why the blank line in matrix0.py?
  • “The method works over any polynomial ring”?

Otherwise looks good to me.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Sep 1, 2015

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

3d1d7c7Trac 19005: is_unit for matrices
ced7b03Trac 19005: inverse_series over noncommutative rings
74ee015Trac 19005: fix a doctest
d30be7aTrac 19005: a SEEALSO block
464341f19005: inverse_series -> inverse_series_trunc
674a8f8Trac 19005: check that prec is positive
3ded62aTrac 19005: on -> over
8a09308Trac 19005: two * current -> current + current

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Sep 1, 2015

Changed commit from d16898a to 8a09308

@videlec
Copy link
Contributor Author

videlec commented Sep 1, 2015

comment:22

Replying to @mezzarobba:
I fixed everything except

  • I believe the doctest in rings.py that you fixed was meant to test the code path resulting in a NotImplementedError.

Of course. I will not create a dummy ring just for checking this code path anyway.

Vincent

@mezzarobba
Copy link
Member

comment:23

Replying to @videlec:

Replying to @mezzarobba:
I fixed everything except

  • I believe the doctest in rings.py that you fixed was meant to test the code path resulting in a NotImplementedError.

Of course. I will not create a dummy ring just for checking this code path anyway.

Fair enough. But I was wondering why you didn't just remove the test...

@vbraun
Copy link
Member

vbraun commented Sep 2, 2015

Changed branch from u/vdelecroix/19005 to 8a09308

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants