Opened 4 years ago

Closed 4 years ago

#10304 closed defect (fixed)

PolynomialRing_field.lagrange_polynomial doesn't always return a polynomial

Reported by: mguaypaq Owned by: mguaypaq
Priority: major Milestone: sage-4.6.1
Component: algebra Keywords: polynomial ring, lagrange polynomial
Cc: mvngu Merged in: sage-4.6.1.alpha3
Authors: Mathieu Guay-Paquet Reviewers: Minh Van Nguyen
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: Stopgaps:

Description (last modified by mvngu)

The function PolynomialRing_field.lagrange_polynomial sometimes returns an element of the coefficient ring or even a python int instead of an element of the polynomial ring. This can lead to problems if the caller was expecting a polynomial.

sage: R, t = FractionField(QQ['t']).objgen(); R.rename('R')
sage: S, x = R['x'].objgen(); S.rename('S')
sage: S.lagrange_polynomial([(2, 3 * t), (4, t + 1)]).parent()
S
sage: S.lagrange_polynomial([(2, 3 * t)]).parent()
R
sage: type(S.lagrange_polynomial([]))
<type 'int'>

The return value is a python int if the list of points was empty, an element of the base ring if the list of points had one point, and an element of the polynomial ring if the list of points had more than one point.

There are similar problems with the base case for the algorithm='neville' version:

sage: S.lagrange_polynomial([(2, 3 * t), (4, t + 1)], algorithm='neville')
[t + 1, (-t + 1/2)*x + 5*t - 1]
sage: [poly.parent() for poly in _]
[R, S]
sage: S.lagrange_polynomial([(2, 3 * t)], algorithm='neville')
[3*t]
sage: [poly.parent() for poly in _]
[R]
sage: S.lagrange_polynomial([], algorithm='neville')
0
sage: type(_)
<type 'int'>

Note that in this case, the return value is not even a list when the list of points was empty.

Apply:

  1. trac_10304_lagrange_poly_in_self.patch
  2. trac-10304_reviewer.patch

Attachments (2)

trac_10304_lagrange_poly_in_self.patch (5.6 KB) - added by mguaypaq 4 years ago.
trac-10304_reviewer.patch (2.6 KB) - added by mvngu 4 years ago.

Download all attachments as: .zip

Change History (6)

Changed 4 years ago by mguaypaq

comment:1 Changed 4 years ago by mguaypaq

  • Authors set to Mathieu Guay-Paquet
  • Cc mvngu added
  • Status changed from new to needs_review

I've put up a patch that should fix the problem, at least in the case of algorithm='divided_difference', and includes a new doctest to verify this.

For the algorithm='neville' case, I've taken the liberty of rewriting the code, to clean it up and unify it a bit in addition to fixing the original problem. However:

  • This changes the default value of previous_row from None to []. I doubt this would break anything, but it is a slight change in the function signature.
  • In the case of an empty list of points, I wasn't sure whether to return [] or [0]. The former is more consistent with the previous_row option, but the latter preserves the property that the last element of the returned list is the interpolating polynomial (as opposed to non-existent). I opted for the first one, but there's definitely a choice to be made here. (I'll note that neither choice is really backwards-incompatible, since the method used to fail in this case.)

Minh, I've put you on CC, since (I think) you wrote the original code for the algorithm='neville' part. Do you approve of the changes?

Changed 4 years ago by mvngu

comment:2 Changed 4 years ago by mvngu

  • Description modified (diff)
  • Reviewers set to Minh Van Nguyen

I'm happy with most of trac_10304_lagrange_poly_in_self.patch, but here are some problems with that patch:

  • A standard idiom in Python is to avoid using a mutable object for a default value. Using a mutable object (such as a list) as a default value can introduce subtle and difficult to track bugs. See this blog post for an explanation of why one should avoid using mutable values for default arguments. See this section in the Python Language Reference for an official explanation about avoiding the use of mutable objects for default values.


  • When you provide doctests that purports to illustrate that a bug has been fixed, you need to provide the corresponding ticket number in the documentation of the doctests.


  • The docstring you introduce doesn't use proper ReST syntax.

The reviewer patch trac-10304_reviewer.patch fixes all of the above issues. If you're OK with my patch, then set the ticket to positive review. See the ticket description for instructions on which patches to apply and in which order.

comment:3 Changed 4 years ago by mguaypaq

  • Status changed from needs_review to positive_review

I thought the use of a mutable default was safe, since it is always copied, never modified. But since there's an idiom against this, I'm happy to comply! And thanks for fixing the documentation issues.

Positive review for the reviewer patch.

comment:4 Changed 4 years ago by jdemeyer

  • Merged in set to sage-4.6.1.alpha3
  • Resolution set to fixed
  • Status changed from positive_review to closed
Note: See TracTickets for help on using tickets.