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

Total refactor of any_root() to solve issue in characteristic two and clean up the code #37170

Merged
merged 31 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
852944b
Ugly patch for characteristic two in any_root
GiacomoPope Jan 26, 2024
356c881
Simply rewrite any_root, as it's easier than debugging the old code
GiacomoPope Jan 27, 2024
661efd8
handle deprecation properly
GiacomoPope Jan 27, 2024
a8dcf5a
Include any_irreducible_factor and refactor any_root to simply wrap this
GiacomoPope Jan 29, 2024
32066e2
Fix linting issues
GiacomoPope Jan 29, 2024
b810fcc
Small edits to fix review notes
GiacomoPope Jan 29, 2024
b240bcf
Add docstrings to helper functions
GiacomoPope Jan 29, 2024
f26534e
Remove the check for the zero polynomial
GiacomoPope Jan 29, 2024
66e1ae0
Too much whitespace
GiacomoPope Jan 29, 2024
24c2779
Fix refactoring bugs
GiacomoPope Jan 29, 2024
f7e157c
Try and make new function work like th eold one
GiacomoPope Jan 29, 2024
afa5f5f
white space
GiacomoPope Jan 29, 2024
aa5a290
Replace trac with issue throughout polynomial_element.pyx
GiacomoPope Jan 29, 2024
006fbae
Add doctests for new functions
GiacomoPope Jan 29, 2024
f0ba87e
every time, whitespace...
GiacomoPope Jan 29, 2024
c65548f
Ensure that the roots returned are of the expected type and add a not…
GiacomoPope Jan 30, 2024
e488817
Whitespace
GiacomoPope Jan 30, 2024
450b0cd
More comments and refactoring of any_root
GiacomoPope Jan 31, 2024
6b67582
Modify doctests to handle that any_root() is no longer deterministic
GiacomoPope Jan 31, 2024
cd20de4
Reintroduce traceback doctests after getting advice
GiacomoPope Feb 1, 2024
a5b5403
Apply suggestions from code review
GiacomoPope Feb 1, 2024
713ddf0
Add reviewer suggestions
GiacomoPope Feb 1, 2024
51b733c
Reformat INPUT for docstring
GiacomoPope Feb 1, 2024
89b8a4a
Clarify TODO about 37118
GiacomoPope Feb 1, 2024
bc13fa5
Clarify degree=None
GiacomoPope Feb 1, 2024
6b633fc
Clean up examples
GiacomoPope Feb 1, 2024
32baddd
Clarify TODO in CZ function
GiacomoPope Feb 1, 2024
ba8eeef
Fix failing doctests
GiacomoPope Feb 2, 2024
c37baf9
Remove some random tags from doctests and fix reported bug
GiacomoPope Feb 5, 2024
888eb3f
Merge branch 'sagemath:develop' into fix_any_root_even_char
GiacomoPope Feb 5, 2024
490ffcb
More robust doctests
GiacomoPope Feb 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions src/sage/rings/finite_rings/conway_polynomials.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class PseudoConwayLattice(WithEqualityById, SageObject):
sage: # needs sage.rings.finite_rings
sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
sage: PCL = PseudoConwayLattice(2, use_database=False)
sage: PCL.polynomial(3)
sage: PCL.polynomial(3) # random
x^3 + x + 1

TESTS::
Expand Down Expand Up @@ -164,16 +164,16 @@ def __init__(self, p, use_database=True):
sage: # needs sage.rings.finite_rings
sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
sage: PCL = PseudoConwayLattice(3)
sage: PCL.polynomial(3)
sage: PCL.polynomial(3) # random
x^3 + 2*x + 1

sage: # needs sage.rings.finite_rings
sage: PCL = PseudoConwayLattice(5, use_database=False)
sage: PCL.polynomial(12)
sage: PCL.polynomial(12) # random
x^12 + 4*x^11 + 2*x^10 + 4*x^9 + 2*x^8 + 2*x^7 + 4*x^6 + x^5 + 2*x^4 + 2*x^2 + x + 2
sage: PCL.polynomial(6)
sage: PCL.polynomial(6) # random
x^6 + x^5 + 4*x^4 + 3*x^3 + 3*x^2 + 2*x + 2
sage: PCL.polynomial(11)
sage: PCL.polynomial(11) # random
x^11 + x^6 + 3*x^3 + 4*x + 3
"""
self.p = p
Expand Down Expand Up @@ -215,11 +215,11 @@ def polynomial(self, n):
sage: # needs sage.rings.finite_rings
sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
sage: PCL = PseudoConwayLattice(2, use_database=False)
sage: PCL.polynomial(3)
sage: PCL.polynomial(3) # random
x^3 + x + 1
sage: PCL.polynomial(4)
sage: PCL.polynomial(4) # random
x^4 + x^3 + 1
sage: PCL.polynomial(60)
sage: PCL.polynomial(60) # random
x^60 + x^59 + x^58 + x^55 + x^54 + x^53 + x^52 + x^51 + x^48 + x^46 + x^45 + x^42 + x^41 + x^39 + x^38 + x^37 + x^35 + x^32 + x^31 + x^30 + x^28 + x^24 + x^22 + x^21 + x^18 + x^17 + x^16 + x^15 + x^14 + x^10 + x^8 + x^7 + x^5 + x^3 + x^2 + x + 1
"""
if n in self.nodes:
Expand All @@ -239,7 +239,7 @@ def polynomial(self, n):
# TODO: something like the following
# gcds = [n.gcd(d) for d in self.nodes.keys()]
# xi = { m: (...) for m in gcds }
xi = {q: self.polynomial(n//q).any_root(K, -n//q, assume_squarefree=True)
xi = {q: self.polynomial(n//q).any_root(K, n//q, assume_squarefree=True, assume_distinct_deg=True)
for q in n.prime_divisors()}

# The following is needed to ensure that in the concrete instantiation
Expand Down Expand Up @@ -402,9 +402,9 @@ def _frobenius_shift(K, generators, check_only=False):
sage: f20 = x^20 + x^19 + x^15 + x^13 + x^12 + x^11 + x^9 + x^8 + x^7 + x^4 + x^2 + x + 1
sage: f12 = x^12 + x^10 + x^9 + x^8 + x^4 + x^2 + 1
sage: K.<a> = GF(2^60, modulus='first_lexicographic')
sage: x30 = f30.any_root(K)
sage: x20 = f20.any_root(K)
sage: x12 = f12.any_root(K)
sage: x30 = f30.roots(K, multiplicities=False)[0]
sage: x20 = f20.roots(K, multiplicities=False)[0]
sage: x12 = f12.roots(K, multiplicities=False)[0]
sage: generators = {2: x30, 3: x20, 5: x12}
sage: from sage.rings.finite_rings.conway_polynomials import _frobenius_shift, _find_pow_of_frobenius
sage: _frobenius_shift(K, generators)
Expand Down
50 changes: 31 additions & 19 deletions src/sage/rings/finite_rings/hom_finite_field.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,35 @@ Construction of an embedding::

sage: k.<t> = GF(3^7)
sage: K.<T> = GF(3^21)
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K)); f
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K)); f # random
Ring morphism:
From: Finite Field in t of size 3^7
To: Finite Field in T of size 3^21
Defn: t |--> T^20 + 2*T^18 + T^16 + 2*T^13 + T^9 + 2*T^8 + T^7 + T^6 + T^5 + T^3 + 2*T^2 + T

sage: f(t)
sage: f(t) # random
T^20 + 2*T^18 + T^16 + 2*T^13 + T^9 + 2*T^8 + T^7 + T^6 + T^5 + T^3 + 2*T^2 + T
sage: f(t) == f.im_gens()[0]
True

The map `f` has a method ``section`` which returns a partially defined
map which is the inverse of `f` on the image of `f`::

sage: g = f.section(); g
sage: g = f.section(); g # random
Section of Ring morphism:
From: Finite Field in t of size 3^7
To: Finite Field in T of size 3^21
Defn: t |--> T^20 + 2*T^18 + T^16 + 2*T^13 + T^9 + 2*T^8 + T^7 + T^6 + T^5 + T^3 + 2*T^2 + T
sage: g(f(t^3+t^2+1))
t^3 + t^2 + 1
sage: a = k.random_element()
sage: g(f(a)) == a
True
sage: g(T)
Traceback (most recent call last):
...
ValueError: T is not in the image of Ring morphism:
From: Finite Field in t of size 3^7
To: Finite Field in T of size 3^21
Defn: t |--> T^20 + 2*T^18 + T^16 + 2*T^13 + T^9 + 2*T^8 + T^7 + T^6 + T^5 + T^3 + 2*T^2 + T
Defn: ...

There is no embedding of `GF(5^6)` into `GF(5^11)`::

Expand Down Expand Up @@ -130,16 +133,17 @@ cdef class SectionFiniteFieldHomomorphism_generic(Section):
sage: K.<T> = GF(3^21)
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
sage: g = f.section()
sage: g(f(t^3+t^2+1))
t^3 + t^2 + 1
sage: a = k.random_element()
sage: g(f(a)) == a
True

sage: g(T)
Traceback (most recent call last):
...
ValueError: T is not in the image of Ring morphism:
From: Finite Field in t of size 3^7
To: Finite Field in T of size 3^21
Defn: t |--> T^20 + 2*T^18 + T^16 + 2*T^13 + T^9 + 2*T^8 + T^7 + T^6 + T^5 + T^3 + 2*T^2 + T
Defn: t |--> ...
"""
for root, _ in x.minimal_polynomial().roots(ring=self.codomain()):
if self._inverse(root) == x:
Expand All @@ -158,7 +162,7 @@ cdef class SectionFiniteFieldHomomorphism_generic(Section):
sage: K.<T> = GF(3^21)
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
sage: g = f.section()
sage: g._repr_()
sage: g._repr_() # random
'Section of Ring morphism:\n From: Finite Field in t of size 3^7\n To: Finite Field in T of size 3^21\n Defn: t |--> T^20 + 2*T^18 + T^16 + 2*T^13 + T^9 + 2*T^8 + T^7 + T^6 + T^5 + T^3 + 2*T^2 + T'
"""
return "Section of %s" % self._inverse
Expand Down Expand Up @@ -202,11 +206,15 @@ cdef class FiniteFieldHomomorphism_generic(RingHomomorphism_im_gens):
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
sage: k.<t> = GF(3^7)
sage: K.<T> = GF(3^21)
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K)); f
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K)); f # random
Ring morphism:
From: Finite Field in t of size 3^7
To: Finite Field in T of size 3^21
Defn: t |--> T^20 + 2*T^18 + T^16 + 2*T^13 + T^9 + 2*T^8 + T^7 + T^6 + T^5 + T^3 + 2*T^2 + T
sage: a = k.random_element()
sage: b = k.random_element()
sage: f(a) + f(b) == f(a + b)
True

sage: k.<t> = GF(3^6)
sage: K.<t> = GF(3^9)
Expand Down Expand Up @@ -299,7 +307,7 @@ cdef class FiniteFieldHomomorphism_generic(RingHomomorphism_im_gens):
sage: k.<t> = GF(3^3)
sage: K.<T> = GF(3^9)
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
sage: f(t)
sage: f(t) # random
2*T^6 + 2*T^4 + T^2 + T

sage: a = k.random_element()
Expand Down Expand Up @@ -368,20 +376,22 @@ cdef class FiniteFieldHomomorphism_generic(RingHomomorphism_im_gens):
sage: k.<t> = GF(3^7)
sage: K.<T> = GF(3^21)
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
sage: g = f.section(); g
sage: g = f.section(); g # random
Section of Ring morphism:
From: Finite Field in t of size 3^7
To: Finite Field in T of size 3^21
Defn: t |--> T^20 + 2*T^18 + T^16 + 2*T^13 + T^9 + 2*T^8 + T^7 + T^6 + T^5 + T^3 + 2*T^2 + T
sage: g(f(t^3+t^2+1))
t^3 + t^2 + 1
sage: a = k.random_element()
sage: b = k.random_element()
sage: g(f(a) + f(b)) == a + b
True
sage: g(T)
Traceback (most recent call last):
...
ValueError: T is not in the image of Ring morphism:
From: Finite Field in t of size 3^7
To: Finite Field in T of size 3^21
Defn: t |--> T^20 + 2*T^18 + T^16 + 2*T^13 + T^9 + 2*T^8 + T^7 + T^6 + T^5 + T^3 + 2*T^2 + T
Defn: ...
"""
if self.base_map() is not None:
raise NotImplementedError
Expand Down Expand Up @@ -421,7 +431,7 @@ cdef class FiniteFieldHomomorphism_generic(RingHomomorphism_im_gens):
sage: k.<t> = GF(5^3)
sage: Frob = k.frobenius_endomorphism()
sage: embed = Frob.fixed_field()[1]
sage: hash(embed) # random
sage: hash(embed) # random
-2441354824160407762
"""
return Morphism.__hash__(self)
Expand Down Expand Up @@ -751,15 +761,17 @@ cdef class FrobeniusEndomorphism_finite_field(FrobeniusEndomorphism_generic):
sage: kfixed, embed = f.fixed_field()
sage: kfixed
Finite Field in t_fixed of size 5^2
sage: embed
sage: embed # random
Ring morphism:
From: Finite Field in t_fixed of size 5^2
To: Finite Field in t of size 5^6
Defn: t_fixed |--> 4*t^5 + 2*t^4 + 4*t^2 + t

sage: tfixed = kfixed.gen()
sage: embed(tfixed)
sage: embed(tfixed) # random
4*t^5 + 2*t^4 + 4*t^2 + t
sage: embed(tfixed) == embed.im_gens()[0]
True
"""
if self._degree_fixed == 1:
k = FiniteField(self.domain().characteristic())
Expand Down
22 changes: 16 additions & 6 deletions src/sage/rings/finite_rings/hom_finite_field_givaro.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ cdef class SectionFiniteFieldHomomorphism_givaro(SectionFiniteFieldHomomorphism_
sage: k.<t> = GF(3^2)
sage: K.<T> = GF(3^4)
sage: f = FiniteFieldHomomorphism_givaro(Hom(k, K))
sage: g = f.section(); g
sage: g = f.section(); g # random
Section of Ring morphism:
From: Finite Field in t of size 3^2
To: Finite Field in T of size 3^4
Defn: t |--> 2*T^3 + 2*T^2 + 1
sage: a = k.random_element()
sage: b = k.random_element()
sage: g(f(a) + f(b)) == g(f(a)) + g(f(b)) == a + b
True
"""
if not isinstance(inverse, FiniteFieldHomomorphism_givaro):
raise TypeError("The given map is not an instance of FiniteFieldHomomorphism_givaro")
Expand Down Expand Up @@ -114,7 +118,7 @@ cdef class SectionFiniteFieldHomomorphism_givaro(SectionFiniteFieldHomomorphism_
ValueError: T is not in the image of Ring morphism:
From: Finite Field in t of size 3^2
To: Finite Field in T of size 3^4
Defn: t |--> 2*T^3 + 2*T^2 + 1
Defn: t |--> ...
"""
if x.parent() != self.domain():
raise TypeError("%s is not in %s" % (x, self.domain()))
Expand All @@ -140,11 +144,15 @@ cdef class FiniteFieldHomomorphism_givaro(FiniteFieldHomomorphism_generic):
sage: from sage.rings.finite_rings.hom_finite_field_givaro import FiniteFieldHomomorphism_givaro
sage: k.<t> = GF(3^2)
sage: K.<T> = GF(3^4)
sage: f = FiniteFieldHomomorphism_givaro(Hom(k, K)); f
sage: f = FiniteFieldHomomorphism_givaro(Hom(k, K)); f # random
Ring morphism:
From: Finite Field in t of size 3^2
To: Finite Field in T of size 3^4
Defn: t |--> 2*T^3 + 2*T^2 + 1
sage: a = k.random_element()
sage: b = k.random_element()
sage: f(a) + f(b) == f(a + b)
True

sage: k.<t> = GF(3^10)
sage: K.<T> = GF(3^20)
Expand Down Expand Up @@ -182,8 +190,10 @@ cdef class FiniteFieldHomomorphism_givaro(FiniteFieldHomomorphism_generic):
sage: k.<t> = GF(3^2)
sage: K.<T> = GF(3^4)
sage: f = FiniteFieldHomomorphism_givaro(Hom(k, K))
sage: f(t)
sage: f(t) # random
2*T^3 + 2*T^2 + 1
sage: f(t) == f.im_gens()[0]
True
"""
if x.parent() != self.domain():
raise TypeError("%s is not in %s" % (x, self.domain()))
Expand Down Expand Up @@ -242,14 +252,14 @@ cdef class FrobeniusEndomorphism_givaro(FrobeniusEndomorphism_finite_field):
sage: kfixed, embed = f.fixed_field()
sage: kfixed
Finite Field in t_fixed of size 5^2
sage: embed
sage: embed # random
Ring morphism:
From: Finite Field in t_fixed of size 5^2
To: Finite Field in t of size 5^6
Defn: t_fixed |--> 4*t^5 + 2*t^4 + 4*t^2 + t

sage: tfixed = kfixed.gen()
sage: embed(tfixed)
sage: embed(tfixed) # random
4*t^5 + 2*t^4 + 4*t^2 + t
"""
if self._degree_fixed == 1:
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/finite_rings/homset.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ def _an_element_(self):

TESTS::

sage: Hom(GF(3^3, 'a'), GF(3^6, 'b')).an_element()
sage: Hom(GF(3^3, 'a'), GF(3^6, 'b')).an_element() # random
Ring morphism:
From: Finite Field in a of size 3^3
To: Finite Field in b of size 3^6
Expand Down
Loading
Loading