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

Fix squarefree_decomposition failure over GF(2) #35323

Merged
merged 1 commit into from
Apr 6, 2023

Conversation

remyoudompheng
Copy link
Contributor

📚 Description

Currently the behaviour is strangely inconsistent:

sage: x = GF(4)["x"].gen()
sage: (x^2+1).squarefree_decomposition()
(x + 1)^2
sage: x = GF(3)["x"].gen()
sage: (x^3+1).squarefree_decomposition()
(x + 1)^3
sage: x = GF(2)["x"].gen()
sage: (x^2+1).squarefree_decomposition()
...
AttributeError: 'sage.rings.finite_rings.integer_mod.IntegerMod_int' object has no attribute 'pth_root'

An alternative fix is to introduce a pth_root() API on prime finite fields.

📝 Checklist

  • I have made sure that the title is self-explanatory and the description concisely explains the PR.
  • I have linked an issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation accordingly.

Copy link
Collaborator

@tscrim tscrim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know entirely about the math, but this fix doesn't feel like it is the correct one. Having an extra (Python!) function to special case when self.degree() == 1, not depending on the input x, seems like you are working around the lack of compatibility between implementations. I think you need to add pth_power() and pth_root() to the corresponding implementations. Or there is another (better) special case of this algorithm to implement for the degree 1 case.

src/sage/rings/finite_rings/finite_field_base.pyx Outdated Show resolved Hide resolved
@remyoudompheng
Copy link
Contributor Author

Thanks for the review.
I applied the suggestion and added another test for another failure in Sage 9.8:

sage: R.<x> = PolynomialRing(GF(65537), sparse=True)
sage: (x^65537 + 1).squarefree_decomposition()

The pth_root is now self.frobenius_endomorphism(-1).
I agree that something should be done in the element class, but currently it is the same class as elements of Zmod(n) where pth_power and pth_root do not really make sense, so I expect that adding new methods will require more discussion.

@github-actions
Copy link

Documentation preview for this PR is ready! 🎉
Built with commit: ef1fa37

@codecov-commenter
Copy link

Codecov Report

Patch coverage has no change and project coverage change: -0.01 ⚠️

Comparison is base (c00e6c2) 88.62% compared to head (ef1fa37) 88.61%.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #35323      +/-   ##
===========================================
- Coverage    88.62%   88.61%   -0.01%     
===========================================
  Files         2148     2148              
  Lines       398855   398855              
===========================================
- Hits        353480   353454      -26     
- Misses       45375    45401      +26     

see 28 files with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

Copy link
Collaborator

@tscrim tscrim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. From one simple test for timings, we get

sage: x = GF(4)["x"].gen()
sage: p = x^2 + 1
sage: %timeit p.squarefree_decomposition()
168 µs ± 5.28 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
sage: x = GF(3)["x"].gen()
sage: p = x^3 + 1
sage: %timeit p.squarefree_decomposition()
10.5 µs ± 305 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

versus before

sage: %timeit p.squarefree_decomposition()
158 µs ± 6.74 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
sage: %timeit p.squarefree_decomposition()  # respectively
11.2 µs ± 84.7 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

So there is a bit of a slowdown between 5-10% on the char 2 example but a speedup on the char 3. Hence, at best it is a mixed bag depending on the case, plus now it works with a uniform implementation.

Going forward, I think a pth_* should be implemented for Zmod(n) and raise an error when n is not a prime analogous to frobenius_endomorphism. I don't think this needs a discussion; it is a clear inconsistency. However, that can wait for a followup ticket (in principle, that should be faster than calling going through a morphism).

@vbraun vbraun merged commit ea73835 into sagemath:develop Apr 6, 2023
vbraun pushed a commit that referenced this pull request Apr 6, 2023
    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes #1234" use "Introduce new method to
calculate 1+1"
-->
### 📚 Description

We make some optimizations to the computation of
`squarefree_decomposition()` for polynomials over finite fields. This is
a followup to #35323.

We make improvements by only getting the parent of `T0` once and
manually keep track of its degree.

The current branch
```python
sage: x = GF(4)["x"].gen()
sage: p = x^2 + 1
sage: %timeit p.squarefree_decomposition()
140 µs ± 22.1 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops
each)
```
versus with #35323:
```python
168 µs ± 5.28 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops
each)
```
versus 10.0.beta5:
```python
158 µs ± 6.74 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops
each)
```

<!-- Describe your changes here in detail -->
<!-- Why is this change required? What problem does it solve? -->
<!-- If it resolves an open issue, please link to the issue here. For
example "Closes #1337" -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->

- [x] I have made sure that the title is self-explanatory and the
description concisely explains the PR.
- [x] I have linked an issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation accordingly.

### ⌛ Dependencies

- #35323 Based on this change and needs to avoid conflicts.
    
URL: #35334
Reported by: Travis Scrimshaw
Reviewer(s): Rémy Oudompheng
@mkoeppe mkoeppe added this to the sage-10.0 milestone Apr 7, 2023
@remyoudompheng remyoudompheng deleted the fix-squarefree branch April 14, 2023 05:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants