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

Add a method divides to Polynomial #19171

Closed
bgrenet opened this issue Sep 9, 2015 · 59 comments
Closed

Add a method divides to Polynomial #19171

bgrenet opened this issue Sep 9, 2015 · 59 comments

Comments

@bgrenet
Copy link
Contributor

bgrenet commented Sep 9, 2015

The generic method divides that can be found in src/sage/structure/element.pyx uses quo_rem (via %) to test if an element divides another one: return (x % self) == 0.

For polynomials, depending on the implementations, the method quo_rem may raise an error if the divisor is not monic (see #16649 for more on this).

This ticket aims at implementing a method divides for the class Polynomial, so that it catches the errors in quo_rem to return False when it is needed.

Example of a problematic behavior:

sage: R.<x> = PolynomialRing(ZZ, implementation="FLINT")
sage: p = 2*x + 1
sage: q = R.random_element(10)
sage: p.divides(q)
False
sage: R.<x> = PolynomialRing(ZZ, implementation="NTL")
sage: p = R(p)
sage: q = R(q)
sage: p.divides(q)
Traceback (most recent call last):
...
ArithmeticError: division not exact in Z[x] (consider coercing to Q[x] first)

Depends on #16649
Depends on #25277

Component: commutative algebra

Keywords: polynomial, division

Author: Bruno Grenet

Branch/Commit: 94c0390

Reviewer: Vincent Delecroix

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

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

bgrenet commented Sep 9, 2015

Dependencies: 16649

@bgrenet
Copy link
Contributor Author

bgrenet commented Sep 9, 2015

Changed dependencies from 16649 to #16649

@bgrenet
Copy link
Contributor Author

bgrenet commented Sep 9, 2015

Branch: u/bruno/t19171_divides_poly

@bgrenet
Copy link
Contributor Author

bgrenet commented Sep 9, 2015

New commits:

98b7ca1Rebased on 6.9beta1
6d0da24One last zero_element removed + correct one doctest
dbfb518Remove useless colons
331c713#19171: New method divides

@bgrenet
Copy link
Contributor Author

bgrenet commented Sep 9, 2015

Commit: 331c713

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented May 22, 2016

Changed commit from 331c713 to 27040e0

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented May 22, 2016

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

27040e0#19171: New method divides

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented May 23, 2016

Changed commit from 27040e0 to 9a189c7

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented May 23, 2016

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

9a189c7#19171: New method divides

@bgrenet
Copy link
Contributor Author

bgrenet commented May 23, 2016

comment:8

I added some noise with two forced pushes (due to some mistake I made), but there is really only one commit! Now the ticket passes the tests (as far as I can tell) and is very ready for review!

@videlec
Copy link
Contributor

videlec commented Jul 11, 2016

comment:9

You would better use coerce_binop from sage.structure.element rather than a manually handled coercion.

Why is this code specific to polynomials?

@videlec
Copy link
Contributor

videlec commented Jul 11, 2016

Reviewer: Vincent Delecroix

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jul 18, 2016

Changed commit from 9a189c7 to ac43c02

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jul 18, 2016

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

d03a75e#19171: New method divides
ac43c0219171: Use coerce_binop

@bgrenet
Copy link
Contributor Author

bgrenet commented Jul 18, 2016

comment:12

Replying to @videlec:

You would better use coerce_binop from sage.structure.element rather than a manually handled coercion.

Done.

Why is this code specific to polynomials?

I tried to explain the reasons in the description: For polynomials over (say) ZZ, the euclidean division is not well defined. The problem occurs when the leading coefficient is not invertible. There are several ways to deal with this problem, and different implementations in Sage use different conventions (see #16649 for pointers on this). As a result, testing divisibility by invoking self % p == 0 can lead to ArithmeticError for polynomials: But when this exception is raised, we know that self does not divide p.¹ That's why I decided to add this new method which only differs from the generic one by the fact it catches the exception.

I could have changed the generic method instead to catch an ArithmeticError and return False in such case, but though I am pretty confident that it makes sense for polynomials, I am much less confident concerning other rings.

¹ "We know" is maybe a too strong assumption. In #16649, I did changes that ensure that the assumption holds for all current implementations of polynomials in Sage. (This was not the case before.) Yet, future implementations may break this rule. This may imply that we shouldn't simply rely on quo_rem to test divisibility.

@videlec videlec modified the milestones: sage-8.0, sage-8.3 May 12, 2018
@bgrenet
Copy link
Contributor Author

bgrenet commented Jun 12, 2018

comment:37

The difficulties with rings such as Zmod(6) let me think that we should indeed restrict to polynomials over integral domains. The problem being that I actually do not know for instance how to test divisibility over Zmod(6).

If we decide this, the problem with PolynomialRing(ZZ, 'x', implementation="NTL") remains since quo_rem cannot be used there without catching an exception, which is not very appealing... Should we convert first the polynomial to polynomials over the fraction field of the base ring?

@videlec
Copy link
Contributor

videlec commented Jun 16, 2018

comment:38

Replying to @bgrenet:

The difficulties with rings such as Zmod(6) let me think that we should indeed restrict to polynomials over integral domains. The problem being that I actually do not know for instance how to test divisibility over Zmod(6).

There is #25277 for that (it is merged in beta3 already). So you can test for division... but you can not divide yet.

If we decide this, the problem with PolynomialRing(ZZ, 'x', implementation="NTL") remains since quo_rem cannot be used there without catching an exception, which is not very appealing... Should we convert first the polynomial to polynomials over the fraction field of the base ring?

It is fine to catch an exception, but it should be clear what it means.

@bgrenet
Copy link
Contributor Author

bgrenet commented Jun 18, 2018

comment:39

Replying to @videlec:

Replying to @bgrenet:

The difficulties with rings such as Zmod(6) let me think that we should indeed restrict to polynomials over integral domains. The problem being that I actually do not know for instance how to test divisibility over Zmod(6).

There is #25277 for that (it is merged in beta3 already). So you can test for division... but you can not divide yet.

I meant testing divisibility of polynomials over Zmod(6). I am not sure that it can be reduced to simply testing divisibility of elements of Zmod(6), I think you need to perform some divisions.

@videlec
Copy link
Contributor

videlec commented Jun 18, 2018

comment:40

Replying to @bgrenet:

Replying to @videlec:

Replying to @bgrenet:

The difficulties with rings such as Zmod(6) let me think that we should indeed restrict to polynomials over integral domains. The problem being that I actually do not know for instance how to test divisibility over Zmod(6).

There is #25277 for that (it is merged in beta3 already). So you can test for division... but you can not divide yet.

I meant testing divisibility of polynomials over Zmod(6). I am not sure that it can be reduced to simply testing divisibility of elements of Zmod(6), I think you need to perform some divisions.

A far from efficient method consist in

  1. testing divisibility of leading coefficients b_m | a_n
  2. if yes, test all possible quotients q so that a_n = q b_m

But for that, you need a method that return all quotients. Hence my remark.

@bgrenet
Copy link
Contributor Author

bgrenet commented Jun 19, 2018

comment:41

So do you agree with me that we should better abandon non-integral rings (at least for now)?

@videlec
Copy link
Contributor

videlec commented Jun 19, 2018

comment:42

Replying to @bgrenet:

So do you agree with me that we should better abandon non-integral rings (at least for now)?

yes

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jun 19, 2018

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

fbc129cMerge branch 'u/bruno/t19171_divides_poly' of git://trac.sagemath.org/sage into ticket/19171
213ccd8Add degree test and lc test

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jun 19, 2018

Changed commit from 5bac984 to 213ccd8

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jun 19, 2018

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

235735f19171: only for integral domains

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jun 19, 2018

Changed commit from 213ccd8 to 235735f

@bgrenet
Copy link
Contributor Author

bgrenet commented Jun 19, 2018

comment:45

Is the proposed solution ok for you?

@videlec
Copy link
Contributor

videlec commented Jun 19, 2018

comment:46

You are not doing the right thing on non-integral domains. You should test is_integral_domain much earlier. With the ticket applied

sage: R.<x> = Zmod(6)[]
sage: (2*x +1).divides(3)
False
sage: (2*x + 1) * 3 == 3
True

(testing divisibility of leading coefficient is not even valid... I was wrong)

You need a line break after TESTS::

It should be documented that this method only works for integral domains. And the examples with Zmod(6) (raising error) should be in the EXAMPLES block rather than TESTS.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jul 4, 2018

Changed commit from 235735f to 94c0390

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Jul 4, 2018

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

94c039019171: Divides implemented only for integral domains

@bgrenet
Copy link
Contributor Author

bgrenet commented Jul 4, 2018

comment:48

I've followed your advice, and changed my mind: My idea was to give an answer (for non-integral domains) as long as I am able to do so. The problem with the divisibility of leading coefficients made me adopt the opposite viewpoint: Divisibility is not implemented for non-integral domains, that's it. I am not sure that an implementation which only works in some uninteresting cases would be helpful to anyone!

@videlec
Copy link
Contributor

videlec commented Aug 3, 2018

comment:49

update milestone 8.3 -> 8.4

@videlec videlec modified the milestones: sage-8.3, sage-8.4 Aug 3, 2018
@videlec
Copy link
Contributor

videlec commented Aug 23, 2018

comment:50

ok

@vbraun
Copy link
Member

vbraun commented Aug 26, 2018

Changed branch from u/bruno/t19171_divides_poly to 94c0390

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

6 participants