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

Division in a finite extension #19593

Merged
merged 7 commits into from Jun 25, 2020

Conversation

jksuom
Copy link
Member

@jksuom jksuom commented Jun 19, 2020

References to other Issues or PRs

Brief description of what is fixed or changed

Define division in a finite extension.

Other comments

Release Notes

  • polys
    • Add division to finite extensions.

@sympy-bot
Copy link

sympy-bot commented Jun 19, 2020

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.

<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### References to other Issues or PRs
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g. "Fixes #1234" (see
https://tinyurl.com/auto-closing for more information). Also, please
write a comment on that issue linking back to this pull request once it is
open. -->


#### Brief description of what is fixed or changed

Define division in a finite extension.
#### Other comments


#### Release Notes

<!-- Write the release notes for this release below. See
https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more information
on how to write release notes. The bot will check your release notes
automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
* polys
    * Add division to finite extensions.    
<!-- END RELEASE NOTES -->

Update

The release notes on the wiki have been updated.

@codecov
Copy link

codecov bot commented Jun 19, 2020

Codecov Report

Merging #19593 into master will increase coverage by 11.419%.
The diff coverage is 61.290%.

@@              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     

@gschintgen
Copy link
Contributor

I checked this out locally and did a few simple computations in GF(27) and QQ[x]/(x**2-2). Nice work.
So I suppose this only needs a few tests? (And ideally a minimum of public documentation.)

I see the commit is actually from 2018. Do you intend to follow up on this?

@jksuom
Copy link
Member Author

jksuom commented Jun 20, 2020

this only needs a few tests

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.

@gschintgen
Copy link
Contributor

You are welcome to add tests and documentation.

Ok, will do. Thanks.

@gschintgen
Copy link
Contributor

Tests have failed due to timeout:

sympy/solvers/ode/tests/test_single.py[17] ..www.........

The job exceeded the maximum time limit for jobs, and has been terminated.

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...

@oscarbenjamin
Copy link
Contributor

Tests have failed due to timeout:

That's because of #19536

@gschintgen
Copy link
Contributor

I noticed that a nice exposition had already been contributed by @jksuom. Please review.
Here's how the docs will look:

Screenshot_2020-06-21 AGCA - Algebraic Geometry and Commutative Algebra Module — SymPy 1 7 dev documentation(4)

The main exposition in agca.rst is the commit message
of 077a9da (by @jksuom).
=====

It's not possible to use a ``FiniteExtension`` as ``domain`` for the
:class:`~.Poly` class.
Copy link
Contributor

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?

Copy link
Member Author

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.)

Copy link
Contributor

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.)

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.

Copy link
Contributor

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 of DMP?
    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?

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Member Author

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.

Copy link
Member Author

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.

Copy link
Contributor

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.

@gschintgen
Copy link
Contributor

The Travis build hit the timeout again... :-/

@gschintgen gschintgen mentioned this pull request Jun 22, 2020
@oscarbenjamin
Copy link
Contributor

I restarted the timed out tests which have now finished. Unfortunately there are no merge conflicts...

@gschintgen
Copy link
Contributor

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.

@gschintgen
Copy link
Contributor

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...

@gschintgen
Copy link
Contributor

Tests have now passed successfully.

@oscarbenjamin
Copy link
Contributor

Looks good

@oscarbenjamin oscarbenjamin merged commit 9e8bd21 into sympy:master Jun 25, 2020
@oscarbenjamin
Copy link
Contributor

Thanks @jksuom and @gschintgen!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants