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
Division in a finite extension #19593
Conversation
✅ Hi, I am the SymPy bot (v160). I'm here to help you write a release notes entry. Please read the guide on how to write release notes. Your release notes are in good order. Here is what the release notes will look like:
This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.7. Note: This comment will be updated with the latest check if you edit the pull request. You need to reload the page to see it. Click here to see the pull request description that was parsed.
Update The release notes on the wiki have been updated. |
Codecov Report
@@ Coverage Diff @@
## master #19593 +/- ##
==============================================
+ Coverage 64.420% 75.839% +11.418%
==============================================
Files 656 657 +1
Lines 170248 173512 +3264
Branches 40154 41820 +1666
==============================================
+ Hits 109674 131590 +21916
+ Misses 54537 36209 -18328
+ Partials 6037 5713 -324 |
I checked this out locally and did a few simple computations in GF(27) and QQ[x]/(x**2-2). Nice work. I see the commit is actually from 2018. Do you intend to follow up on this? |
That is why I didn't push it at the time. There seemed to be some interest in improving the FF class, and I was planning to add this as a part of it. But that interest faded away (and I also seemed to have more urgent tasks :). You are welcome to add tests and documentation. |
Ok, will do. Thanks. |
Tests have failed due to timeout:
https://travis-ci.org/github/sympy/sympy/jobs/700338224#L528 I'll add at least one more commit anyway, so let's see how that one goes. And hopefully Github picks up on the results... |
That's because of #19536 |
26db924
to
4a005cd
Compare
I noticed that a nice exposition had already been contributed by @jksuom. Please review. |
4a005cd
to
28d484f
Compare
===== | ||
|
||
It's not possible to use a ``FiniteExtension`` as ``domain`` for the | ||
:class:`~.Poly` class. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't this be used as a domain?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A more a fitting comment might be that FiniteExtension
is not a subclass of Domain
. However, it should be possible to define a FiniteField
class that would derive from Domain
and FiniteExtension
. It is also possible to define other wrapper subclasses of Domain
for (some types of) FiniteExtension
. (Consider PolynomialRing
vs. PolyRing
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A more a fitting comment might be that
FiniteExtension
is not a subclass ofDomain
. However, it should be possible to define aFiniteField
class that would derive fromDomain
andFiniteExtension
. It is also possible to define other wrapper subclasses ofDomain
for (some types of)FiniteExtension
. (ConsiderPolynomialRing
vs.PolyRing
.)
I'll see what this entails and how this works out and at the very least improve the comment.
Finite fields were the motivation for looking into this, but in the meantime I've also had a closer look at galoistools.py
and it definitely has everything that would be needed for implementing proper non-prime finite fields (including algorithms for determining irreducibility over Z_p and actually finding irreducible polynomials). So maybe that's the better way forward when it comes to implementing GF(p^n) as polys domain. At least it seems to have been the original plan.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to work out a proof-of-concept for GF(p**d) using FiniteExtension, but I must confess that I'm struggling a bit with all the (messy/undocumented/labyrinthine) internals of polys
. In particular:
- what is the
lev
argument ofDMP
?
sympy/sympy/polys/polyclasses.py
Lines 145 to 162 in a69a68c
class DMP(PicklableWithSlots, CantSympify): """Dense Multivariate Polynomials over `K`. """ __slots__ = ('rep', 'lev', 'dom', 'ring') def __init__(self, rep, dom, lev=None, ring=None): if lev is not None: if type(rep) is dict: rep = dmp_from_dict(rep, lev, dom) elif type(rep) is not list: rep = dmp_ground(dom.convert(rep), lev) else: rep, lev = dmp_validate(rep) self.rep = rep self.lev = lev self.dom = dom self.ring = ring - I noticed the following:
In [60]: F = FiniteExtension(poly(x**3+x**2+2, modulus=5))
In [61]: type(F.ring)
Out[61]: sympy.polys.domains.old_polynomialring.GlobalPolynomialRing
Isn't the old_polynomialring
somewhat deprecated? Does it matter for this application?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the lev argument is basically the number of generators:
In [5]: Poly(x, x, domain=ZZ).rep.lev
Out[5]: 0
In [6]: Poly(x, x, y, domain=ZZ).rep.lev
Out[6]: 1
In [7]: Poly(x, x, y, z, domain=ZZ).rep.lev
Out[7]: 2
I think it's called lev
as short for "level" representing the fact that in the dense representation a poly in n
generators is implemented as a poly of polys in n-1
generators. The internal representation is a list of domain elements for an univariate poly and then a list of lists for bivariate etc:
In [9]: Poly(x, x, domain=ZZ).rep.rep
Out[9]: [mpz(1), mpz(0)]
In [10]: Poly(x, x, y, domain=ZZ).rep.rep
Out[10]: [[mpz(1)], []]
In [11]: Poly(x, x, y, z, domain=ZZ).rep.rep
Out[11]: [[[mpz(1)]], [[]]]
The lev
argument basically tells the dmp_*
functions how many levels to recurse.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the lev argument is basically the number of generators [...]
Thanks!
I'm also hitting circular import issues (concerning Poly
) when I try adding a PrimePowerFiniteField
class in domains/finitefield.py
that subclasses FiniteField
and FiniteExtension
. That's probaby not unexpected given that logically the chain is domains -> polynomials -> extensions. Maybe a more direct implementation is less prone to such issues.
Concerning this PR I'll modify the note in the docstring and that's it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the old_polynomialring somewhat deprecated?
It depends on the number of generators. For a small number of generators, say, 1, 2, (3,) and dense polynomials, I think that it is quite efficient. For a large number of generators, the nested list representation becomes very inefficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lev
is the number of generators minus 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'm also hitting circular import issues (concerning Poly) when I try adding a PrimePowerFiniteField class in domains/finitefield.py that subclasses FiniteField and FiniteExtension.
I have suggested another approach: Define a new class, say, FiniteRing
, that would do what FiniteField
does now (or simply rename FiniteField
). Invoking FiniteField
with a non-prime argument would pass the call to FiniteRing
, presumably with a deprecation statement. Then FiniteField
could subclass from FiniteExtension
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
presumably with a deprecation statement
I don't think that's necessary as long as the new FiniteField
also accepts the current parameters for creating a finite field of prime order. There are only some 3 or 4 very minor (and non-sensical) tests in the whole testsuite that actually instantiate a ring of integers modulo a composite. There's no real use anywhere and the current broken behavior is (fortunately) not publicly documented.
I think it's best to take the discussion concerning the implementation to #9544.
The Travis build hit the timeout again... :-/ |
I restarted the timed out tests which have now finished. Unfortunately there are no merge conflicts... |
Strange, locally I could now merge master to the branch without a hitch. Hmm. I'll push that merge commit. That should do. |
And now the timeout hit again. I think this can wait till the slow tests/density split have been sorted out. I'll refrain from restarting the job to leave more Travis capacity for those more urgent issues... |
Tests have now passed successfully. |
Looks good |
Thanks @jksuom and @gschintgen! |
References to other Issues or PRs
Brief description of what is fixed or changed
Define division in a finite extension.
Other comments
Release Notes