Opened 7 years ago
Closed 6 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 )
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:
Attachments (2)
Change History (6)
Changed 7 years ago by
comment:1 Changed 7 years ago by
- Cc mvngu added
- Status changed from new to needs_review
Changed 7 years ago by
comment:2 Changed 7 years ago by
- 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 7 years ago by
- 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 6 years ago by
- Merged in set to sage-4.6.1.alpha3
- Resolution set to fixed
- Status changed from positive_review to closed
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:previous_row
fromNone
to[]
. I doubt this would break anything, but it is a slight change in the function signature.[]
or[0]
. The former is more consistent with theprevious_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?