I am done

This commit is contained in:
2024-10-30 22:14:35 +01:00
parent 720dc28c09
commit 40e2a747cf
36901 changed files with 5011519 additions and 0 deletions

View File

@ -0,0 +1,85 @@
from sympy.abc import x
from sympy.core import S
from sympy.core.numbers import AlgebraicNumber
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.polys import Poly, cyclotomic_poly
from sympy.polys.domains import QQ
from sympy.polys.matrices import DomainMatrix, DM
from sympy.polys.numberfields.basis import round_two
from sympy.testing.pytest import raises
def test_round_two():
# Poly must be irreducible, and over ZZ or QQ:
raises(ValueError, lambda: round_two(Poly(x ** 2 - 1)))
raises(ValueError, lambda: round_two(Poly(x ** 2 + sqrt(2))))
# Test on many fields:
cases = (
# A couple of cyclotomic fields:
(cyclotomic_poly(5), DomainMatrix.eye(4, QQ), 125),
(cyclotomic_poly(7), DomainMatrix.eye(6, QQ), -16807),
# A couple of quadratic fields (one 1 mod 4, one 3 mod 4):
(x ** 2 - 5, DM([[1, (1, 2)], [0, (1, 2)]], QQ), 5),
(x ** 2 - 7, DM([[1, 0], [0, 1]], QQ), 28),
# Dedekind's example of a field with 2 as essential disc divisor:
(x ** 3 + x ** 2 - 2 * x + 8, DM([[1, 0, 0], [0, 1, 0], [0, (1, 2), (1, 2)]], QQ).transpose(), -503),
# A bunch of cubics with various forms for F -- all of these require
# second or third enlargements. (Five of them require a third, while the rest require just a second.)
# F = 2^2
(x**3 + 3 * x**2 - 4 * x + 4, DM([((1, 2), (1, 4), (1, 4)), (0, (1, 2), (1, 2)), (0, 0, 1)], QQ).transpose(), -83),
# F = 2^2 * 3
(x**3 + 3 * x**2 + 3 * x - 3, DM([((1, 2), 0, (1, 2)), (0, 1, 0), (0, 0, 1)], QQ).transpose(), -108),
# F = 2^3
(x**3 + 5 * x**2 - x + 3, DM([((1, 4), 0, (3, 4)), (0, (1, 2), (1, 2)), (0, 0, 1)], QQ).transpose(), -31),
# F = 2^2 * 5
(x**3 + 5 * x**2 - 5 * x - 5, DM([((1, 2), 0, (1, 2)), (0, 1, 0), (0, 0, 1)], QQ).transpose(), 1300),
# F = 3^2
(x**3 + 3 * x**2 + 5, DM([((1, 3), (1, 3), (1, 3)), (0, 1, 0), (0, 0, 1)], QQ).transpose(), -135),
# F = 3^3
(x**3 + 6 * x**2 + 3 * x - 1, DM([((1, 3), (1, 3), (1, 3)), (0, 1, 0), (0, 0, 1)], QQ).transpose(), 81),
# F = 2^2 * 3^2
(x**3 + 6 * x**2 + 4, DM([((1, 3), (2, 3), (1, 3)), (0, 1, 0), (0, 0, (1, 2))], QQ).transpose(), -108),
# F = 2^3 * 7
(x**3 + 7 * x**2 + 7 * x - 7, DM([((1, 4), 0, (3, 4)), (0, (1, 2), (1, 2)), (0, 0, 1)], QQ).transpose(), 49),
# F = 2^2 * 13
(x**3 + 7 * x**2 - x + 5, DM([((1, 2), 0, (1, 2)), (0, 1, 0), (0, 0, 1)], QQ).transpose(), -2028),
# F = 2^4
(x**3 + 7 * x**2 - 5 * x + 5, DM([((1, 4), 0, (3, 4)), (0, (1, 2), (1, 2)), (0, 0, 1)], QQ).transpose(), -140),
# F = 5^2
(x**3 + 4 * x**2 - 3 * x + 7, DM([((1, 5), (4, 5), (4, 5)), (0, 1, 0), (0, 0, 1)], QQ).transpose(), -175),
# F = 7^2
(x**3 + 8 * x**2 + 5 * x - 1, DM([((1, 7), (6, 7), (2, 7)), (0, 1, 0), (0, 0, 1)], QQ).transpose(), 49),
# F = 2 * 5 * 7
(x**3 + 8 * x**2 - 2 * x + 6, DM([(1, 0, 0), (0, 1, 0), (0, 0, 1)], QQ).transpose(), -14700),
# F = 2^2 * 3 * 5
(x**3 + 6 * x**2 - 3 * x + 8, DM([(1, 0, 0), (0, (1, 4), (1, 4)), (0, 0, 1)], QQ).transpose(), -675),
# F = 2 * 3^2 * 7
(x**3 + 9 * x**2 + 6 * x - 8, DM([(1, 0, 0), (0, (1, 2), (1, 2)), (0, 0, 1)], QQ).transpose(), 3969),
# F = 2^2 * 3^2 * 7
(x**3 + 15 * x**2 - 9 * x + 13, DM([((1, 6), (1, 3), (1, 6)), (0, 1, 0), (0, 0, 1)], QQ).transpose(), -5292),
# Polynomial need not be monic
(5*x**3 + 5*x**2 - 10 * x + 40, DM([[1, 0, 0], [0, 1, 0], [0, (1, 2), (1, 2)]], QQ).transpose(), -503),
# Polynomial can have non-integer rational coeffs
(QQ(5, 3)*x**3 + QQ(5, 3)*x**2 - QQ(10, 3)*x + QQ(40, 3), DM([[1, 0, 0], [0, 1, 0], [0, (1, 2), (1, 2)]], QQ).transpose(), -503),
)
for f, B_exp, d_exp in cases:
K = QQ.alg_field_from_poly(f)
B = K.maximal_order().QQ_matrix
d = K.discriminant()
assert d == d_exp
# The computed basis need not equal the expected one, but their quotient
# must be unimodular:
assert (B.inv()*B_exp).det()**2 == 1
def test_AlgebraicField_integral_basis():
alpha = AlgebraicNumber(sqrt(5), alias='alpha')
k = QQ.algebraic_field(alpha)
B0 = k.integral_basis()
B1 = k.integral_basis(fmt='sympy')
B2 = k.integral_basis(fmt='alg')
assert B0 == [k([1]), k([S.Half, S.Half])]
assert B1 == [1, S.Half + alpha/2]
assert B2 == [k.ext.field_element([1]),
k.ext.field_element([S.Half, S.Half])]

View File

@ -0,0 +1,143 @@
"""Tests for computing Galois groups. """
from sympy.abc import x
from sympy.combinatorics.galois import (
S1TransitiveSubgroups, S2TransitiveSubgroups, S3TransitiveSubgroups,
S4TransitiveSubgroups, S5TransitiveSubgroups, S6TransitiveSubgroups,
)
from sympy.polys.domains.rationalfield import QQ
from sympy.polys.numberfields.galoisgroups import (
tschirnhausen_transformation,
galois_group,
_galois_group_degree_4_root_approx,
_galois_group_degree_5_hybrid,
)
from sympy.polys.numberfields.subfield import field_isomorphism
from sympy.polys.polytools import Poly
from sympy.testing.pytest import raises
def test_tschirnhausen_transformation():
for T in [
Poly(x**2 - 2),
Poly(x**2 + x + 1),
Poly(x**4 + 1),
Poly(x**4 - x**3 + x**2 - x + 1),
]:
_, U = tschirnhausen_transformation(T)
assert U.degree() == T.degree()
assert U.is_monic
assert U.is_irreducible
K = QQ.alg_field_from_poly(T)
L = QQ.alg_field_from_poly(U)
assert field_isomorphism(K.ext, L.ext) is not None
# Test polys are from:
# Cohen, H. *A Course in Computational Algebraic Number Theory*.
test_polys_by_deg = {
# Degree 1
1: [
(x, S1TransitiveSubgroups.S1, True)
],
# Degree 2
2: [
(x**2 + x + 1, S2TransitiveSubgroups.S2, False)
],
# Degree 3
3: [
(x**3 + x**2 - 2*x - 1, S3TransitiveSubgroups.A3, True),
(x**3 + 2, S3TransitiveSubgroups.S3, False),
],
# Degree 4
4: [
(x**4 + x**3 + x**2 + x + 1, S4TransitiveSubgroups.C4, False),
(x**4 + 1, S4TransitiveSubgroups.V, True),
(x**4 - 2, S4TransitiveSubgroups.D4, False),
(x**4 + 8*x + 12, S4TransitiveSubgroups.A4, True),
(x**4 + x + 1, S4TransitiveSubgroups.S4, False),
],
# Degree 5
5: [
(x**5 + x**4 - 4*x**3 - 3*x**2 + 3*x + 1, S5TransitiveSubgroups.C5, True),
(x**5 - 5*x + 12, S5TransitiveSubgroups.D5, True),
(x**5 + 2, S5TransitiveSubgroups.M20, False),
(x**5 + 20*x + 16, S5TransitiveSubgroups.A5, True),
(x**5 - x + 1, S5TransitiveSubgroups.S5, False),
],
# Degree 6
6: [
(x**6 + x**5 + x**4 + x**3 + x**2 + x + 1, S6TransitiveSubgroups.C6, False),
(x**6 + 108, S6TransitiveSubgroups.S3, False),
(x**6 + 2, S6TransitiveSubgroups.D6, False),
(x**6 - 3*x**2 - 1, S6TransitiveSubgroups.A4, True),
(x**6 + 3*x**3 + 3, S6TransitiveSubgroups.G18, False),
(x**6 - 3*x**2 + 1, S6TransitiveSubgroups.A4xC2, False),
(x**6 - 4*x**2 - 1, S6TransitiveSubgroups.S4p, True),
(x**6 - 3*x**5 + 6*x**4 - 7*x**3 + 2*x**2 + x - 4, S6TransitiveSubgroups.S4m, False),
(x**6 + 2*x**3 - 2, S6TransitiveSubgroups.G36m, False),
(x**6 + 2*x**2 + 2, S6TransitiveSubgroups.S4xC2, False),
(x**6 + 10*x**5 + 55*x**4 + 140*x**3 + 175*x**2 + 170*x + 25, S6TransitiveSubgroups.PSL2F5, True),
(x**6 + 10*x**5 + 55*x**4 + 140*x**3 + 175*x**2 - 3019*x + 25, S6TransitiveSubgroups.PGL2F5, False),
(x**6 + 6*x**4 + 2*x**3 + 9*x**2 + 6*x - 4, S6TransitiveSubgroups.G36p, True),
(x**6 + 2*x**4 + 2*x**3 + x**2 + 2*x + 2, S6TransitiveSubgroups.G72, False),
(x**6 + 24*x - 20, S6TransitiveSubgroups.A6, True),
(x**6 + x + 1, S6TransitiveSubgroups.S6, False),
],
}
def test_galois_group():
"""
Try all the test polys.
"""
for deg in range(1, 7):
polys = test_polys_by_deg[deg]
for T, G, alt in polys:
assert galois_group(T, by_name=True) == (G, alt)
def test_galois_group_degree_out_of_bounds():
raises(ValueError, lambda: galois_group(Poly(0, x)))
raises(ValueError, lambda: galois_group(Poly(1, x)))
raises(ValueError, lambda: galois_group(Poly(x ** 7 + 1)))
def test_galois_group_not_by_name():
"""
Check at least one polynomial of each supported degree, to see that
conversion from name to group works.
"""
for deg in range(1, 7):
T, G_name, _ = test_polys_by_deg[deg][0]
G, _ = galois_group(T)
assert G == G_name.get_perm_group()
def test_galois_group_not_monic_over_ZZ():
"""
Check that we can work with polys that are not monic over ZZ.
"""
for deg in range(1, 7):
T, G, alt = test_polys_by_deg[deg][0]
assert galois_group(T/2, by_name=True) == (G, alt)
def test__galois_group_degree_4_root_approx():
for T, G, alt in test_polys_by_deg[4]:
assert _galois_group_degree_4_root_approx(Poly(T)) == (G, alt)
def test__galois_group_degree_5_hybrid():
for T, G, alt in test_polys_by_deg[5]:
assert _galois_group_degree_5_hybrid(Poly(T)) == (G, alt)
def test_AlgebraicField_galois_group():
k = QQ.alg_field_from_poly(Poly(x**4 + 1))
G, _ = k.galois_group(by_name=True)
assert G == S4TransitiveSubgroups.V
k = QQ.alg_field_from_poly(Poly(x**4 - 2))
G, _ = k.galois_group(by_name=True)
assert G == S4TransitiveSubgroups.D4

View File

@ -0,0 +1,474 @@
"""Tests for minimal polynomials. """
from sympy.core.function import expand
from sympy.core import (GoldenRatio, TribonacciConstant)
from sympy.core.numbers import (AlgebraicNumber, I, Rational, oo, pi)
from sympy.core.power import Pow
from sympy.core.singleton import S
from sympy.functions.elementary.exponential import exp
from sympy.functions.elementary.miscellaneous import (cbrt, sqrt)
from sympy.functions.elementary.trigonometric import (cos, sin, tan)
from sympy.polys.polytools import Poly
from sympy.polys.rootoftools import CRootOf
from sympy.solvers.solveset import nonlinsolve
from sympy.geometry import Circle, intersection
from sympy.testing.pytest import raises, slow
from sympy.sets.sets import FiniteSet
from sympy.geometry.point import Point2D
from sympy.polys.numberfields.minpoly import (
minimal_polynomial,
_choose_factor,
_minpoly_op_algebraic_element,
_separate_sq,
_minpoly_groebner,
)
from sympy.polys.partfrac import apart
from sympy.polys.polyerrors import (
NotAlgebraic,
GeneratorsError,
)
from sympy.polys.domains import QQ
from sympy.polys.rootoftools import rootof
from sympy.polys.polytools import degree
from sympy.abc import x, y, z
Q = Rational
def test_minimal_polynomial():
assert minimal_polynomial(-7, x) == x + 7
assert minimal_polynomial(-1, x) == x + 1
assert minimal_polynomial( 0, x) == x
assert minimal_polynomial( 1, x) == x - 1
assert minimal_polynomial( 7, x) == x - 7
assert minimal_polynomial(sqrt(2), x) == x**2 - 2
assert minimal_polynomial(sqrt(5), x) == x**2 - 5
assert minimal_polynomial(sqrt(6), x) == x**2 - 6
assert minimal_polynomial(2*sqrt(2), x) == x**2 - 8
assert minimal_polynomial(3*sqrt(5), x) == x**2 - 45
assert minimal_polynomial(4*sqrt(6), x) == x**2 - 96
assert minimal_polynomial(2*sqrt(2) + 3, x) == x**2 - 6*x + 1
assert minimal_polynomial(3*sqrt(5) + 6, x) == x**2 - 12*x - 9
assert minimal_polynomial(4*sqrt(6) + 7, x) == x**2 - 14*x - 47
assert minimal_polynomial(2*sqrt(2) - 3, x) == x**2 + 6*x + 1
assert minimal_polynomial(3*sqrt(5) - 6, x) == x**2 + 12*x - 9
assert minimal_polynomial(4*sqrt(6) - 7, x) == x**2 + 14*x - 47
assert minimal_polynomial(sqrt(1 + sqrt(6)), x) == x**4 - 2*x**2 - 5
assert minimal_polynomial(sqrt(I + sqrt(6)), x) == x**8 - 10*x**4 + 49
assert minimal_polynomial(2*I + sqrt(2 + I), x) == x**4 + 4*x**2 + 8*x + 37
assert minimal_polynomial(sqrt(2) + sqrt(3), x) == x**4 - 10*x**2 + 1
assert minimal_polynomial(
sqrt(2) + sqrt(3) + sqrt(6), x) == x**4 - 22*x**2 - 48*x - 23
a = 1 - 9*sqrt(2) + 7*sqrt(3)
assert minimal_polynomial(
1/a, x) == 392*x**4 - 1232*x**3 + 612*x**2 + 4*x - 1
assert minimal_polynomial(
1/sqrt(a), x) == 392*x**8 - 1232*x**6 + 612*x**4 + 4*x**2 - 1
raises(NotAlgebraic, lambda: minimal_polynomial(oo, x))
raises(NotAlgebraic, lambda: minimal_polynomial(2**y, x))
raises(NotAlgebraic, lambda: minimal_polynomial(sin(1), x))
assert minimal_polynomial(sqrt(2)).dummy_eq(x**2 - 2)
assert minimal_polynomial(sqrt(2), x) == x**2 - 2
assert minimal_polynomial(sqrt(2), polys=True) == Poly(x**2 - 2)
assert minimal_polynomial(sqrt(2), x, polys=True) == Poly(x**2 - 2, domain='QQ')
assert minimal_polynomial(sqrt(2), x, polys=True, compose=False) == Poly(x**2 - 2, domain='QQ')
a = AlgebraicNumber(sqrt(2))
b = AlgebraicNumber(sqrt(3))
assert minimal_polynomial(a, x) == x**2 - 2
assert minimal_polynomial(b, x) == x**2 - 3
assert minimal_polynomial(a, x, polys=True) == Poly(x**2 - 2, domain='QQ')
assert minimal_polynomial(b, x, polys=True) == Poly(x**2 - 3, domain='QQ')
assert minimal_polynomial(sqrt(a/2 + 17), x) == 2*x**4 - 68*x**2 + 577
assert minimal_polynomial(sqrt(b/2 + 17), x) == 4*x**4 - 136*x**2 + 1153
a, b = sqrt(2)/3 + 7, AlgebraicNumber(sqrt(2)/3 + 7)
f = 81*x**8 - 2268*x**6 - 4536*x**5 + 22644*x**4 + 63216*x**3 - \
31608*x**2 - 189648*x + 141358
assert minimal_polynomial(sqrt(a) + sqrt(sqrt(a)), x) == f
assert minimal_polynomial(sqrt(b) + sqrt(sqrt(b)), x) == f
assert minimal_polynomial(
a**Q(3, 2), x) == 729*x**4 - 506898*x**2 + 84604519
# issue 5994
eq = S('''
-1/(800*sqrt(-1/240 + 1/(18000*(-1/17280000 +
sqrt(15)*I/28800000)**(1/3)) + 2*(-1/17280000 +
sqrt(15)*I/28800000)**(1/3)))''')
assert minimal_polynomial(eq, x) == 8000*x**2 - 1
ex = (sqrt(5)*sqrt(I)/(5*sqrt(1 + 125*I))
+ 25*sqrt(5)/(I**Q(5,2)*(1 + 125*I)**Q(3,2))
+ 3125*sqrt(5)/(I**Q(11,2)*(1 + 125*I)**Q(3,2))
+ 5*I*sqrt(1 - I/125))
mp = minimal_polynomial(ex, x)
assert mp == 25*x**4 + 5000*x**2 + 250016
ex = 1 + sqrt(2) + sqrt(3)
mp = minimal_polynomial(ex, x)
assert mp == x**4 - 4*x**3 - 4*x**2 + 16*x - 8
ex = 1/(1 + sqrt(2) + sqrt(3))
mp = minimal_polynomial(ex, x)
assert mp == 8*x**4 - 16*x**3 + 4*x**2 + 4*x - 1
p = (expand((1 + sqrt(2) - 2*sqrt(3) + sqrt(7))**3))**Rational(1, 3)
mp = minimal_polynomial(p, x)
assert mp == x**8 - 8*x**7 - 56*x**6 + 448*x**5 + 480*x**4 - 5056*x**3 + 1984*x**2 + 7424*x - 3008
p = expand((1 + sqrt(2) - 2*sqrt(3) + sqrt(7))**3)
mp = minimal_polynomial(p, x)
assert mp == x**8 - 512*x**7 - 118208*x**6 + 31131136*x**5 + 647362560*x**4 - 56026611712*x**3 + 116994310144*x**2 + 404854931456*x - 27216576512
assert minimal_polynomial(S("-sqrt(5)/2 - 1/2 + (-sqrt(5)/2 - 1/2)**2"), x) == x - 1
a = 1 + sqrt(2)
assert minimal_polynomial((a*sqrt(2) + a)**3, x) == x**2 - 198*x + 1
p = 1/(1 + sqrt(2) + sqrt(3))
assert minimal_polynomial(p, x, compose=False) == 8*x**4 - 16*x**3 + 4*x**2 + 4*x - 1
p = 2/(1 + sqrt(2) + sqrt(3))
assert minimal_polynomial(p, x, compose=False) == x**4 - 4*x**3 + 2*x**2 + 4*x - 2
assert minimal_polynomial(1 + sqrt(2)*I, x, compose=False) == x**2 - 2*x + 3
assert minimal_polynomial(1/(1 + sqrt(2)) + 1, x, compose=False) == x**2 - 2
assert minimal_polynomial(sqrt(2)*I + I*(1 + sqrt(2)), x,
compose=False) == x**4 + 18*x**2 + 49
# minimal polynomial of I
assert minimal_polynomial(I, x, domain=QQ.algebraic_field(I)) == x - I
K = QQ.algebraic_field(I*(sqrt(2) + 1))
assert minimal_polynomial(I, x, domain=K) == x - I
assert minimal_polynomial(I, x, domain=QQ) == x**2 + 1
assert minimal_polynomial(I, x, domain='QQ(y)') == x**2 + 1
#issue 11553
assert minimal_polynomial(GoldenRatio, x) == x**2 - x - 1
assert minimal_polynomial(TribonacciConstant + 3, x) == x**3 - 10*x**2 + 32*x - 34
assert minimal_polynomial(GoldenRatio, x, domain=QQ.algebraic_field(sqrt(5))) == \
2*x - sqrt(5) - 1
assert minimal_polynomial(TribonacciConstant, x, domain=QQ.algebraic_field(cbrt(19 - 3*sqrt(33)))) == \
48*x - 19*(19 - 3*sqrt(33))**Rational(2, 3) - 3*sqrt(33)*(19 - 3*sqrt(33))**Rational(2, 3) \
- 16*(19 - 3*sqrt(33))**Rational(1, 3) - 16
# AlgebraicNumber with an alias.
# Wester H24
phi = AlgebraicNumber(S.GoldenRatio.expand(func=True), alias='phi')
assert minimal_polynomial(phi, x) == x**2 - x - 1
def test_minimal_polynomial_issue_19732():
# https://github.com/sympy/sympy/issues/19732
expr = (-280898097948878450887044002323982963174671632174995451265117559518123750720061943079105185551006003416773064305074191140286225850817291393988597615/(-488144716373031204149459129212782509078221364279079444636386844223983756114492222145074506571622290776245390771587888364089507840000000*sqrt(238368341569)*sqrt(S(11918417078450)/63568729
- 24411360*sqrt(238368341569)/63568729) +
238326799225996604451373809274348704114327860564921529846705817404208077866956345381951726531296652901169111729944612727047670549086208000000*sqrt(S(11918417078450)/63568729
- 24411360*sqrt(238368341569)/63568729)) -
180561807339168676696180573852937120123827201075968945871075967679148461189459480842956689723484024031016208588658753107/(-59358007109636562851035004992802812513575019937126272896569856090962677491318275291141463850327474176000000*sqrt(238368341569)*sqrt(S(11918417078450)/63568729
- 24411360*sqrt(238368341569)/63568729) +
28980348180319251787320809875930301310576055074938369007463004788921613896002936637780993064387310446267596800000*sqrt(S(11918417078450)/63568729
- 24411360*sqrt(238368341569)/63568729)))
poly = (2151288870990266634727173620565483054187142169311153766675688628985237817262915166497766867289157986631135400926544697981091151416655364879773546003475813114962656742744975460025956167152918469472166170500512008351638710934022160294849059721218824490226159355197136265032810944357335461128949781377875451881300105989490353140886315677977149440000000000000000000000*x**4
- 5773274155644072033773937864114266313663195672820501581692669271302387257492905909558846459600429795784309388968498783843631580008547382703258503404023153694528041873101120067477617592651525155101107144042679962433039557235772239171616433004024998230222455940044709064078962397144550855715640331680262171410099614469231080995436488414164502751395405398078353242072696360734131090111239998110773292915337556205692674790561090109440000000000000*x**2
+ 211295968822207088328287206509522887719741955693091053353263782924470627623790749534705683380138972642560898936171035770539616881000369889020398551821767092685775598633794696371561234818461806577723412581353857653829324364446419444210520602157621008010129702779407422072249192199762604318993590841636967747488049176548615614290254356975376588506729604345612047361483789518445332415765213187893207704958013682516462853001964919444736320672860140355089)
assert minimal_polynomial(expr, x) == poly
def test_minimal_polynomial_hi_prec():
p = 1/sqrt(1 - 9*sqrt(2) + 7*sqrt(3) + Rational(1, 10)**30)
mp = minimal_polynomial(p, x)
# checked with Wolfram Alpha
assert mp.coeff(x**6) == -1232000000000000000000000000001223999999999999999999999999999987999999999999999999999999999996000000000000000000000000000000
def test_minimal_polynomial_sq():
from sympy.core.add import Add
from sympy.core.function import expand_multinomial
p = expand_multinomial((1 + 5*sqrt(2) + 2*sqrt(3))**3)
mp = minimal_polynomial(p**Rational(1, 3), x)
assert mp == x**4 - 4*x**3 - 118*x**2 + 244*x + 1321
p = expand_multinomial((1 + sqrt(2) - 2*sqrt(3) + sqrt(7))**3)
mp = minimal_polynomial(p**Rational(1, 3), x)
assert mp == x**8 - 8*x**7 - 56*x**6 + 448*x**5 + 480*x**4 - 5056*x**3 + 1984*x**2 + 7424*x - 3008
p = Add(*[sqrt(i) for i in range(1, 12)])
mp = minimal_polynomial(p, x)
assert mp.subs({x: 0}) == -71965773323122507776
def test_minpoly_compose():
# issue 6868
eq = S('''
-1/(800*sqrt(-1/240 + 1/(18000*(-1/17280000 +
sqrt(15)*I/28800000)**(1/3)) + 2*(-1/17280000 +
sqrt(15)*I/28800000)**(1/3)))''')
mp = minimal_polynomial(eq + 3, x)
assert mp == 8000*x**2 - 48000*x + 71999
# issue 5888
assert minimal_polynomial(exp(I*pi/8), x) == x**8 + 1
mp = minimal_polynomial(sin(pi/7) + sqrt(2), x)
assert mp == 4096*x**12 - 63488*x**10 + 351488*x**8 - 826496*x**6 + \
770912*x**4 - 268432*x**2 + 28561
mp = minimal_polynomial(cos(pi/7) + sqrt(2), x)
assert mp == 64*x**6 - 64*x**5 - 432*x**4 + 304*x**3 + 712*x**2 - \
232*x - 239
mp = minimal_polynomial(exp(I*pi/7) + sqrt(2), x)
assert mp == x**12 - 2*x**11 - 9*x**10 + 16*x**9 + 43*x**8 - 70*x**7 - 97*x**6 + 126*x**5 + 211*x**4 - 212*x**3 - 37*x**2 + 142*x + 127
mp = minimal_polynomial(sin(pi/7) + sqrt(2), x)
assert mp == 4096*x**12 - 63488*x**10 + 351488*x**8 - 826496*x**6 + \
770912*x**4 - 268432*x**2 + 28561
mp = minimal_polynomial(cos(pi/7) + sqrt(2), x)
assert mp == 64*x**6 - 64*x**5 - 432*x**4 + 304*x**3 + 712*x**2 - \
232*x - 239
mp = minimal_polynomial(exp(I*pi/7) + sqrt(2), x)
assert mp == x**12 - 2*x**11 - 9*x**10 + 16*x**9 + 43*x**8 - 70*x**7 - 97*x**6 + 126*x**5 + 211*x**4 - 212*x**3 - 37*x**2 + 142*x + 127
mp = minimal_polynomial(exp(I*pi*Rational(2, 7)), x)
assert mp == x**6 + x**5 + x**4 + x**3 + x**2 + x + 1
mp = minimal_polynomial(exp(I*pi*Rational(2, 15)), x)
assert mp == x**8 - x**7 + x**5 - x**4 + x**3 - x + 1
mp = minimal_polynomial(cos(pi*Rational(2, 7)), x)
assert mp == 8*x**3 + 4*x**2 - 4*x - 1
mp = minimal_polynomial(sin(pi*Rational(2, 7)), x)
ex = (5*cos(pi*Rational(2, 7)) - 7)/(9*cos(pi/7) - 5*cos(pi*Rational(3, 7)))
mp = minimal_polynomial(ex, x)
assert mp == x**3 + 2*x**2 - x - 1
assert minimal_polynomial(-1/(2*cos(pi/7)), x) == x**3 + 2*x**2 - x - 1
assert minimal_polynomial(sin(pi*Rational(2, 15)), x) == \
256*x**8 - 448*x**6 + 224*x**4 - 32*x**2 + 1
assert minimal_polynomial(sin(pi*Rational(5, 14)), x) == 8*x**3 - 4*x**2 - 4*x + 1
assert minimal_polynomial(cos(pi/15), x) == 16*x**4 + 8*x**3 - 16*x**2 - 8*x + 1
ex = rootof(x**3 +x*4 + 1, 0)
mp = minimal_polynomial(ex, x)
assert mp == x**3 + 4*x + 1
mp = minimal_polynomial(ex + 1, x)
assert mp == x**3 - 3*x**2 + 7*x - 4
assert minimal_polynomial(exp(I*pi/3), x) == x**2 - x + 1
assert minimal_polynomial(exp(I*pi/4), x) == x**4 + 1
assert minimal_polynomial(exp(I*pi/6), x) == x**4 - x**2 + 1
assert minimal_polynomial(exp(I*pi/9), x) == x**6 - x**3 + 1
assert minimal_polynomial(exp(I*pi/10), x) == x**8 - x**6 + x**4 - x**2 + 1
assert minimal_polynomial(sin(pi/9), x) == 64*x**6 - 96*x**4 + 36*x**2 - 3
assert minimal_polynomial(sin(pi/11), x) == 1024*x**10 - 2816*x**8 + \
2816*x**6 - 1232*x**4 + 220*x**2 - 11
assert minimal_polynomial(sin(pi/21), x) == 4096*x**12 - 11264*x**10 + \
11264*x**8 - 4992*x**6 + 960*x**4 - 64*x**2 + 1
assert minimal_polynomial(cos(pi/9), x) == 8*x**3 - 6*x - 1
ex = 2**Rational(1, 3)*exp(2*I*pi/3)
assert minimal_polynomial(ex, x) == x**3 - 2
raises(NotAlgebraic, lambda: minimal_polynomial(cos(pi*sqrt(2)), x))
raises(NotAlgebraic, lambda: minimal_polynomial(sin(pi*sqrt(2)), x))
raises(NotAlgebraic, lambda: minimal_polynomial(exp(1.618*I*pi), x))
raises(NotAlgebraic, lambda: minimal_polynomial(exp(I*pi*sqrt(2)), x))
# issue 5934
ex = 1/(-36000 - 7200*sqrt(5) + (12*sqrt(10)*sqrt(sqrt(5) + 5) +
24*sqrt(10)*sqrt(-sqrt(5) + 5))**2) + 1
raises(ZeroDivisionError, lambda: minimal_polynomial(ex, x))
ex = sqrt(1 + 2**Rational(1,3)) + sqrt(1 + 2**Rational(1,4)) + sqrt(2)
mp = minimal_polynomial(ex, x)
assert degree(mp) == 48 and mp.subs({x:0}) == -16630256576
ex = tan(pi/5, evaluate=False)
mp = minimal_polynomial(ex, x)
assert mp == x**4 - 10*x**2 + 5
assert mp.subs(x, tan(pi/5)).is_zero
ex = tan(pi/6, evaluate=False)
mp = minimal_polynomial(ex, x)
assert mp == 3*x**2 - 1
assert mp.subs(x, tan(pi/6)).is_zero
ex = tan(pi/10, evaluate=False)
mp = minimal_polynomial(ex, x)
assert mp == 5*x**4 - 10*x**2 + 1
assert mp.subs(x, tan(pi/10)).is_zero
raises(NotAlgebraic, lambda: minimal_polynomial(tan(pi*sqrt(2)), x))
def test_minpoly_issue_7113():
# see discussion in https://github.com/sympy/sympy/pull/2234
from sympy.simplify.simplify import nsimplify
r = nsimplify(pi, tolerance=0.000000001)
mp = minimal_polynomial(r, x)
assert mp == 1768292677839237920489538677417507171630859375*x**109 - \
2734577732179183863586489182929671773182898498218854181690460140337930774573792597743853652058046464
def test_minpoly_issue_23677():
r1 = CRootOf(4000000*x**3 - 239960000*x**2 + 4782399900*x - 31663998001, 0)
r2 = CRootOf(4000000*x**3 - 239960000*x**2 + 4782399900*x - 31663998001, 1)
num = (7680000000000000000*r1**4*r2**4 - 614323200000000000000*r1**4*r2**3
+ 18458112576000000000000*r1**4*r2**2 - 246896663036160000000000*r1**4*r2
+ 1240473830323209600000000*r1**4 - 614323200000000000000*r1**3*r2**4
- 1476464424954240000000000*r1**3*r2**2 - 99225501687553535904000000*r1**3
+ 18458112576000000000000*r1**2*r2**4 - 1476464424954240000000000*r1**2*r2**3
- 593391458458356671712000000*r1**2*r2 + 2981354896834339226880720000*r1**2
- 246896663036160000000000*r1*r2**4 - 593391458458356671712000000*r1*r2**2
- 39878756418031796275267195200*r1 + 1240473830323209600000000*r2**4
- 99225501687553535904000000*r2**3 + 2981354896834339226880720000*r2**2 -
39878756418031796275267195200*r2 + 200361370275616536577343808012)
mp = (x**3 + 59426520028417434406408556687919*x**2 +
1161475464966574421163316896737773190861975156439163671112508400*x +
7467465541178623874454517208254940823818304424383315270991298807299003671748074773558707779600)
assert minimal_polynomial(num, x) == mp
def test_minpoly_issue_7574():
ex = -(-1)**Rational(1, 3) + (-1)**Rational(2,3)
assert minimal_polynomial(ex, x) == x + 1
def test_choose_factor():
# Test that this does not enter an infinite loop:
bad_factors = [Poly(x-2, x), Poly(x+2, x)]
raises(NotImplementedError, lambda: _choose_factor(bad_factors, x, sqrt(3)))
def test_minpoly_fraction_field():
assert minimal_polynomial(1/x, y) == -x*y + 1
assert minimal_polynomial(1 / (x + 1), y) == (x + 1)*y - 1
assert minimal_polynomial(sqrt(x), y) == y**2 - x
assert minimal_polynomial(sqrt(x + 1), y) == y**2 - x - 1
assert minimal_polynomial(sqrt(x) / x, y) == x*y**2 - 1
assert minimal_polynomial(sqrt(2) * sqrt(x), y) == y**2 - 2 * x
assert minimal_polynomial(sqrt(2) + sqrt(x), y) == \
y**4 + (-2*x - 4)*y**2 + x**2 - 4*x + 4
assert minimal_polynomial(x**Rational(1,3), y) == y**3 - x
assert minimal_polynomial(x**Rational(1,3) + sqrt(x), y) == \
y**6 - 3*x*y**4 - 2*x*y**3 + 3*x**2*y**2 - 6*x**2*y - x**3 + x**2
assert minimal_polynomial(sqrt(x) / z, y) == z**2*y**2 - x
assert minimal_polynomial(sqrt(x) / (z + 1), y) == (z**2 + 2*z + 1)*y**2 - x
assert minimal_polynomial(1/x, y, polys=True) == Poly(-x*y + 1, y, domain='ZZ(x)')
assert minimal_polynomial(1 / (x + 1), y, polys=True) == \
Poly((x + 1)*y - 1, y, domain='ZZ(x)')
assert minimal_polynomial(sqrt(x), y, polys=True) == Poly(y**2 - x, y, domain='ZZ(x)')
assert minimal_polynomial(sqrt(x) / z, y, polys=True) == \
Poly(z**2*y**2 - x, y, domain='ZZ(x, z)')
# this is (sqrt(1 + x**3)/x).integrate(x).diff(x) - sqrt(1 + x**3)/x
a = sqrt(x)/sqrt(1 + x**(-3)) - sqrt(x**3 + 1)/x + 1/(x**Rational(5, 2)* \
(1 + x**(-3))**Rational(3, 2)) + 1/(x**Rational(11, 2)*(1 + x**(-3))**Rational(3, 2))
assert minimal_polynomial(a, y) == y
raises(NotAlgebraic, lambda: minimal_polynomial(exp(x), y))
raises(GeneratorsError, lambda: minimal_polynomial(sqrt(x), x))
raises(GeneratorsError, lambda: minimal_polynomial(sqrt(x) - y, x))
raises(NotImplementedError, lambda: minimal_polynomial(sqrt(x), y, compose=False))
@slow
def test_minpoly_fraction_field_slow():
assert minimal_polynomial(minimal_polynomial(sqrt(x**Rational(1,5) - 1),
y).subs(y, sqrt(x**Rational(1,5) - 1)), z) == z
def test_minpoly_domain():
assert minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2))) == \
x - sqrt(2)
assert minimal_polynomial(sqrt(8), x, domain=QQ.algebraic_field(sqrt(2))) == \
x - 2*sqrt(2)
assert minimal_polynomial(sqrt(Rational(3,2)), x,
domain=QQ.algebraic_field(sqrt(2))) == 2*x**2 - 3
raises(NotAlgebraic, lambda: minimal_polynomial(y, x, domain=QQ))
def test_issue_14831():
a = -2*sqrt(2)*sqrt(12*sqrt(2) + 17)
assert minimal_polynomial(a, x) == x**2 + 16*x - 8
e = (-3*sqrt(12*sqrt(2) + 17) + 12*sqrt(2) +
17 - 2*sqrt(2)*sqrt(12*sqrt(2) + 17))
assert minimal_polynomial(e, x) == x
def test_issue_18248():
assert nonlinsolve([x*y**3-sqrt(2)/3, x*y**6-4/(9*(sqrt(3)))],x,y) == \
FiniteSet((sqrt(3)/2, sqrt(6)/3), (sqrt(3)/2, -sqrt(6)/6 - sqrt(2)*I/2),
(sqrt(3)/2, -sqrt(6)/6 + sqrt(2)*I/2))
def test_issue_13230():
c1 = Circle(Point2D(3, sqrt(5)), 5)
c2 = Circle(Point2D(4, sqrt(7)), 6)
assert intersection(c1, c2) == [Point2D(-1 + (-sqrt(7) + sqrt(5))*(-2*sqrt(7)/29
+ 9*sqrt(5)/29 + sqrt(196*sqrt(35) + 1941)/29), -2*sqrt(7)/29 + 9*sqrt(5)/29
+ sqrt(196*sqrt(35) + 1941)/29), Point2D(-1 + (-sqrt(7) + sqrt(5))*(-sqrt(196*sqrt(35)
+ 1941)/29 - 2*sqrt(7)/29 + 9*sqrt(5)/29), -sqrt(196*sqrt(35) + 1941)/29 - 2*sqrt(7)/29 + 9*sqrt(5)/29)]
def test_issue_19760():
e = 1/(sqrt(1 + sqrt(2)) - sqrt(2)*sqrt(1 + sqrt(2))) + 1
mp_expected = x**4 - 4*x**3 + 4*x**2 - 2
for comp in (True, False):
mp = Poly(minimal_polynomial(e, compose=comp))
assert mp(x) == mp_expected, "minimal_polynomial(e, compose=%s) = %s; %s expected" % (comp, mp(x), mp_expected)
def test_issue_20163():
assert apart(1/(x**6+1), extension=[sqrt(3), I]) == \
(sqrt(3) + I)/(2*x + sqrt(3) + I)/6 + \
(sqrt(3) - I)/(2*x + sqrt(3) - I)/6 - \
(sqrt(3) - I)/(2*x - sqrt(3) + I)/6 - \
(sqrt(3) + I)/(2*x - sqrt(3) - I)/6 + \
I/(x + I)/6 - I/(x - I)/6
def test_issue_22559():
alpha = AlgebraicNumber(sqrt(2))
assert minimal_polynomial(alpha**3, x) == x**2 - 8
def test_issue_22561():
a = AlgebraicNumber(sqrt(2) + sqrt(3), [S(1) / 2, 0, S(-9) / 2, 0], gen=x)
assert a.as_expr() == sqrt(2)
assert minimal_polynomial(a, x) == x**2 - 2
assert minimal_polynomial(a**3, x) == x**2 - 8
def test_separate_sq_not_impl():
raises(NotImplementedError, lambda: _separate_sq(x**(S(1)/3) + x))
def test_minpoly_op_algebraic_element_not_impl():
raises(NotImplementedError,
lambda: _minpoly_op_algebraic_element(Pow, sqrt(2), sqrt(3), x, QQ))
def test_minpoly_groebner():
assert _minpoly_groebner(S(2)/3, x, Poly) == 3*x - 2
assert _minpoly_groebner(
(sqrt(2) + 3)*(sqrt(2) + 1), x, Poly) == x**2 - 10*x - 7
assert _minpoly_groebner((sqrt(2) + 3)**(S(1)/3)*(sqrt(2) + 1)**(S(1)/3),
x, Poly) == x**6 - 10*x**3 - 7
assert _minpoly_groebner((sqrt(2) + 3)**(-S(1)/3)*(sqrt(2) + 1)**(S(1)/3),
x, Poly) == 7*x**6 - 2*x**3 - 1
raises(NotAlgebraic, lambda: _minpoly_groebner(pi**2, x, Poly))

View File

@ -0,0 +1,752 @@
from sympy.abc import x, zeta
from sympy.polys import Poly, cyclotomic_poly
from sympy.polys.domains import FF, QQ, ZZ
from sympy.polys.matrices import DomainMatrix, DM
from sympy.polys.numberfields.exceptions import (
ClosureFailure, MissingUnityError, StructureError
)
from sympy.polys.numberfields.modules import (
Module, ModuleElement, ModuleEndomorphism, PowerBasis, PowerBasisElement,
find_min_poly, is_sq_maxrank_HNF, make_mod_elt, to_col,
)
from sympy.polys.numberfields.utilities import is_int
from sympy.polys.polyerrors import UnificationFailed
from sympy.testing.pytest import raises
def test_to_col():
c = [1, 2, 3, 4]
m = to_col(c)
assert m.domain.is_ZZ
assert m.shape == (4, 1)
assert m.flat() == c
def test_Module_NotImplemented():
M = Module()
raises(NotImplementedError, lambda: M.n)
raises(NotImplementedError, lambda: M.mult_tab())
raises(NotImplementedError, lambda: M.represent(None))
raises(NotImplementedError, lambda: M.starts_with_unity())
raises(NotImplementedError, lambda: M.element_from_rational(QQ(2, 3)))
def test_Module_ancestors():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
C = B.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
D = B.submodule_from_matrix(5 * DomainMatrix.eye(4, ZZ))
assert C.ancestors(include_self=True) == [A, B, C]
assert D.ancestors(include_self=True) == [A, B, D]
assert C.power_basis_ancestor() == A
assert C.nearest_common_ancestor(D) == B
M = Module()
assert M.power_basis_ancestor() is None
def test_Module_compat_col():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
col = to_col([1, 2, 3, 4])
row = col.transpose()
assert A.is_compat_col(col) is True
assert A.is_compat_col(row) is False
assert A.is_compat_col(1) is False
assert A.is_compat_col(DomainMatrix.eye(3, ZZ)[:, 0]) is False
assert A.is_compat_col(DomainMatrix.eye(4, QQ)[:, 0]) is False
assert A.is_compat_col(DomainMatrix.eye(4, ZZ)[:, 0]) is True
def test_Module_call():
T = Poly(cyclotomic_poly(5, x))
B = PowerBasis(T)
assert B(0).col.flat() == [1, 0, 0, 0]
assert B(1).col.flat() == [0, 1, 0, 0]
col = DomainMatrix.eye(4, ZZ)[:, 2]
assert B(col).col == col
raises(ValueError, lambda: B(-1))
def test_Module_starts_with_unity():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
assert A.starts_with_unity() is True
assert B.starts_with_unity() is False
def test_Module_basis_elements():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
basis = B.basis_elements()
bp = B.basis_element_pullbacks()
for i, (e, p) in enumerate(zip(basis, bp)):
c = [0] * 4
assert e.module == B
assert p.module == A
c[i] = 1
assert e == B(to_col(c))
c[i] = 2
assert p == A(to_col(c))
def test_Module_zero():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
assert A.zero().col.flat() == [0, 0, 0, 0]
assert A.zero().module == A
assert B.zero().col.flat() == [0, 0, 0, 0]
assert B.zero().module == B
def test_Module_one():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
assert A.one().col.flat() == [1, 0, 0, 0]
assert A.one().module == A
assert B.one().col.flat() == [1, 0, 0, 0]
assert B.one().module == A
def test_Module_element_from_rational():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
rA = A.element_from_rational(QQ(22, 7))
rB = B.element_from_rational(QQ(22, 7))
assert rA.coeffs == [22, 0, 0, 0]
assert rA.denom == 7
assert rA.module == A
assert rB.coeffs == [22, 0, 0, 0]
assert rB.denom == 7
assert rB.module == A
def test_Module_submodule_from_gens():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
gens = [2*A(0), 2*A(1), 6*A(0), 6*A(1)]
B = A.submodule_from_gens(gens)
# Because the 3rd and 4th generators do not add anything new, we expect
# the cols of the matrix of B to just reproduce the first two gens:
M = gens[0].column().hstack(gens[1].column())
assert B.matrix == M
# At least one generator must be provided:
raises(ValueError, lambda: A.submodule_from_gens([]))
# All generators must belong to A:
raises(ValueError, lambda: A.submodule_from_gens([3*A(0), B(0)]))
def test_Module_submodule_from_matrix():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
e = B(to_col([1, 2, 3, 4]))
f = e.to_parent()
assert f.col.flat() == [2, 4, 6, 8]
# Matrix must be over ZZ:
raises(ValueError, lambda: A.submodule_from_matrix(DomainMatrix.eye(4, QQ)))
# Number of rows of matrix must equal number of generators of module A:
raises(ValueError, lambda: A.submodule_from_matrix(2 * DomainMatrix.eye(5, ZZ)))
def test_Module_whole_submodule():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.whole_submodule()
e = B(to_col([1, 2, 3, 4]))
f = e.to_parent()
assert f.col.flat() == [1, 2, 3, 4]
e0, e1, e2, e3 = B(0), B(1), B(2), B(3)
assert e2 * e3 == e0
assert e3 ** 2 == e1
def test_PowerBasis_repr():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
assert repr(A) == 'PowerBasis(x**4 + x**3 + x**2 + x + 1)'
def test_PowerBasis_eq():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = PowerBasis(T)
assert A == B
def test_PowerBasis_mult_tab():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
M = A.mult_tab()
exp = {0: {0: [1, 0, 0, 0], 1: [0, 1, 0, 0], 2: [0, 0, 1, 0], 3: [0, 0, 0, 1]},
1: {1: [0, 0, 1, 0], 2: [0, 0, 0, 1], 3: [-1, -1, -1, -1]},
2: {2: [-1, -1, -1, -1], 3: [1, 0, 0, 0]},
3: {3: [0, 1, 0, 0]}}
# We get the table we expect:
assert M == exp
# And all entries are of expected type:
assert all(is_int(c) for u in M for v in M[u] for c in M[u][v])
def test_PowerBasis_represent():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
col = to_col([1, 2, 3, 4])
a = A(col)
assert A.represent(a) == col
b = A(col, denom=2)
raises(ClosureFailure, lambda: A.represent(b))
def test_PowerBasis_element_from_poly():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
f = Poly(1 + 2*x)
g = Poly(x**4)
h = Poly(0, x)
assert A.element_from_poly(f).coeffs == [1, 2, 0, 0]
assert A.element_from_poly(g).coeffs == [-1, -1, -1, -1]
assert A.element_from_poly(h).coeffs == [0, 0, 0, 0]
def test_PowerBasis_element__conversions():
k = QQ.cyclotomic_field(5)
L = QQ.cyclotomic_field(7)
B = PowerBasis(k)
# ANP --> PowerBasisElement
a = k([QQ(1, 2), QQ(1, 3), 5, 7])
e = B.element_from_ANP(a)
assert e.coeffs == [42, 30, 2, 3]
assert e.denom == 6
# PowerBasisElement --> ANP
assert e.to_ANP() == a
# Cannot convert ANP from different field
d = L([QQ(1, 2), QQ(1, 3), 5, 7])
raises(UnificationFailed, lambda: B.element_from_ANP(d))
# AlgebraicNumber --> PowerBasisElement
alpha = k.to_alg_num(a)
eps = B.element_from_alg_num(alpha)
assert eps.coeffs == [42, 30, 2, 3]
assert eps.denom == 6
# PowerBasisElement --> AlgebraicNumber
assert eps.to_alg_num() == alpha
# Cannot convert AlgebraicNumber from different field
delta = L.to_alg_num(d)
raises(UnificationFailed, lambda: B.element_from_alg_num(delta))
# When we don't know the field:
C = PowerBasis(k.ext.minpoly)
# Can convert from AlgebraicNumber:
eps = C.element_from_alg_num(alpha)
assert eps.coeffs == [42, 30, 2, 3]
assert eps.denom == 6
# But can't convert back:
raises(StructureError, lambda: eps.to_alg_num())
def test_Submodule_repr():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ), denom=3)
assert repr(B) == 'Submodule[[2, 0, 0, 0], [0, 2, 0, 0], [0, 0, 2, 0], [0, 0, 0, 2]]/3'
def test_Submodule_reduced():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
C = A.submodule_from_matrix(6 * DomainMatrix.eye(4, ZZ), denom=3)
D = C.reduced()
assert D.denom == 1 and D == C == B
def test_Submodule_discard_before():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
B.compute_mult_tab()
C = B.discard_before(2)
assert C.parent == B.parent
assert B.is_sq_maxrank_HNF() and not C.is_sq_maxrank_HNF()
assert C.matrix == B.matrix[:, 2:]
assert C.mult_tab() == {0: {0: [-2, -2], 1: [0, 0]}, 1: {1: [0, 0]}}
def test_Submodule_QQ_matrix():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
C = A.submodule_from_matrix(6 * DomainMatrix.eye(4, ZZ), denom=3)
assert C.QQ_matrix == B.QQ_matrix
def test_Submodule_represent():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
C = B.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
a0 = A(to_col([6, 12, 18, 24]))
a1 = A(to_col([2, 4, 6, 8]))
a2 = A(to_col([1, 3, 5, 7]))
b1 = B.represent(a1)
assert b1.flat() == [1, 2, 3, 4]
c0 = C.represent(a0)
assert c0.flat() == [1, 2, 3, 4]
Y = A.submodule_from_matrix(DomainMatrix([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
], (3, 4), ZZ).transpose())
U = Poly(cyclotomic_poly(7, x))
Z = PowerBasis(U)
z0 = Z(to_col([1, 2, 3, 4, 5, 6]))
raises(ClosureFailure, lambda: Y.represent(A(3)))
raises(ClosureFailure, lambda: B.represent(a2))
raises(ClosureFailure, lambda: B.represent(z0))
def test_Submodule_is_compat_submodule():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
D = C.submodule_from_matrix(5 * DomainMatrix.eye(4, ZZ))
assert B.is_compat_submodule(C) is True
assert B.is_compat_submodule(A) is False
assert B.is_compat_submodule(D) is False
def test_Submodule_eq():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
C = A.submodule_from_matrix(6 * DomainMatrix.eye(4, ZZ), denom=3)
assert C == B
def test_Submodule_add():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(DomainMatrix([
[4, 0, 0, 0],
[0, 4, 0, 0],
], (2, 4), ZZ).transpose(), denom=6)
C = A.submodule_from_matrix(DomainMatrix([
[0, 10, 0, 0],
[0, 0, 7, 0],
], (2, 4), ZZ).transpose(), denom=15)
D = A.submodule_from_matrix(DomainMatrix([
[20, 0, 0, 0],
[ 0, 20, 0, 0],
[ 0, 0, 14, 0],
], (3, 4), ZZ).transpose(), denom=30)
assert B + C == D
U = Poly(cyclotomic_poly(7, x))
Z = PowerBasis(U)
Y = Z.submodule_from_gens([Z(0), Z(1)])
raises(TypeError, lambda: B + Y)
def test_Submodule_mul():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
C = A.submodule_from_matrix(DomainMatrix([
[0, 10, 0, 0],
[0, 0, 7, 0],
], (2, 4), ZZ).transpose(), denom=15)
C1 = A.submodule_from_matrix(DomainMatrix([
[0, 20, 0, 0],
[0, 0, 14, 0],
], (2, 4), ZZ).transpose(), denom=3)
C2 = A.submodule_from_matrix(DomainMatrix([
[0, 0, 10, 0],
[0, 0, 0, 7],
], (2, 4), ZZ).transpose(), denom=15)
C3_unred = A.submodule_from_matrix(DomainMatrix([
[0, 0, 100, 0],
[0, 0, 0, 70],
[0, 0, 0, 70],
[-49, -49, -49, -49]
], (4, 4), ZZ).transpose(), denom=225)
C3 = A.submodule_from_matrix(DomainMatrix([
[4900, 4900, 0, 0],
[4410, 4410, 10, 0],
[2107, 2107, 7, 7]
], (3, 4), ZZ).transpose(), denom=225)
assert C * 1 == C
assert C ** 1 == C
assert C * 10 == C1
assert C * A(1) == C2
assert C.mul(C, hnf=False) == C3_unred
assert C * C == C3
assert C ** 2 == C3
def test_Submodule_reduce_element():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.whole_submodule()
b = B(to_col([90, 84, 80, 75]), denom=120)
C = B.submodule_from_matrix(DomainMatrix.eye(4, ZZ), denom=2)
b_bar_expected = B(to_col([30, 24, 20, 15]), denom=120)
b_bar = C.reduce_element(b)
assert b_bar == b_bar_expected
C = B.submodule_from_matrix(DomainMatrix.eye(4, ZZ), denom=4)
b_bar_expected = B(to_col([0, 24, 20, 15]), denom=120)
b_bar = C.reduce_element(b)
assert b_bar == b_bar_expected
C = B.submodule_from_matrix(DomainMatrix.eye(4, ZZ), denom=8)
b_bar_expected = B(to_col([0, 9, 5, 0]), denom=120)
b_bar = C.reduce_element(b)
assert b_bar == b_bar_expected
a = A(to_col([1, 2, 3, 4]))
raises(NotImplementedError, lambda: C.reduce_element(a))
C = B.submodule_from_matrix(DomainMatrix([
[5, 4, 3, 2],
[0, 8, 7, 6],
[0, 0,11,12],
[0, 0, 0, 1]
], (4, 4), ZZ).transpose())
raises(StructureError, lambda: C.reduce_element(b))
def test_is_HNF():
M = DM([
[3, 2, 1],
[0, 2, 1],
[0, 0, 1]
], ZZ)
M1 = DM([
[3, 2, 1],
[0, -2, 1],
[0, 0, 1]
], ZZ)
M2 = DM([
[3, 2, 3],
[0, 2, 1],
[0, 0, 1]
], ZZ)
assert is_sq_maxrank_HNF(M) is True
assert is_sq_maxrank_HNF(M1) is False
assert is_sq_maxrank_HNF(M2) is False
def test_make_mod_elt():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
col = to_col([1, 2, 3, 4])
eA = make_mod_elt(A, col)
eB = make_mod_elt(B, col)
assert isinstance(eA, PowerBasisElement)
assert not isinstance(eB, PowerBasisElement)
def test_ModuleElement_repr():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(to_col([1, 2, 3, 4]), denom=2)
assert repr(e) == '[1, 2, 3, 4]/2'
def test_ModuleElement_reduced():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(to_col([2, 4, 6, 8]), denom=2)
f = e.reduced()
assert f.denom == 1 and f == e
def test_ModuleElement_reduced_mod_p():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(to_col([20, 40, 60, 80]))
f = e.reduced_mod_p(7)
assert f.coeffs == [-1, -2, -3, 3]
def test_ModuleElement_from_int_list():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
c = [1, 2, 3, 4]
assert ModuleElement.from_int_list(A, c).coeffs == c
def test_ModuleElement_len():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(0)
assert len(e) == 4
def test_ModuleElement_column():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(0)
col1 = e.column()
assert col1 == e.col and col1 is not e.col
col2 = e.column(domain=FF(5))
assert col2.domain.is_FF
def test_ModuleElement_QQ_col():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(to_col([1, 2, 3, 4]), denom=1)
f = A(to_col([3, 6, 9, 12]), denom=3)
assert e.QQ_col == f.QQ_col
def test_ModuleElement_to_ancestors():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
C = B.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
D = C.submodule_from_matrix(5 * DomainMatrix.eye(4, ZZ))
eD = D(0)
eC = eD.to_parent()
eB = eD.to_ancestor(B)
eA = eD.over_power_basis()
assert eC.module is C and eC.coeffs == [5, 0, 0, 0]
assert eB.module is B and eB.coeffs == [15, 0, 0, 0]
assert eA.module is A and eA.coeffs == [30, 0, 0, 0]
a = A(0)
raises(ValueError, lambda: a.to_parent())
def test_ModuleElement_compatibility():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
C = B.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
D = B.submodule_from_matrix(5 * DomainMatrix.eye(4, ZZ))
assert C(0).is_compat(C(1)) is True
assert C(0).is_compat(D(0)) is False
u, v = C(0).unify(D(0))
assert u.module is B and v.module is B
assert C(C.represent(u)) == C(0) and D(D.represent(v)) == D(0)
u, v = C(0).unify(C(1))
assert u == C(0) and v == C(1)
U = Poly(cyclotomic_poly(7, x))
Z = PowerBasis(U)
raises(UnificationFailed, lambda: C(0).unify(Z(1)))
def test_ModuleElement_eq():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(to_col([1, 2, 3, 4]), denom=1)
f = A(to_col([3, 6, 9, 12]), denom=3)
assert e == f
U = Poly(cyclotomic_poly(7, x))
Z = PowerBasis(U)
assert e != Z(0)
assert e != 3.14
def test_ModuleElement_equiv():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(to_col([1, 2, 3, 4]), denom=1)
f = A(to_col([3, 6, 9, 12]), denom=3)
assert e.equiv(f)
C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
g = C(to_col([1, 2, 3, 4]), denom=1)
h = A(to_col([3, 6, 9, 12]), denom=1)
assert g.equiv(h)
assert C(to_col([5, 0, 0, 0]), denom=7).equiv(QQ(15, 7))
U = Poly(cyclotomic_poly(7, x))
Z = PowerBasis(U)
raises(UnificationFailed, lambda: e.equiv(Z(0)))
assert e.equiv(3.14) is False
def test_ModuleElement_add():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
e = A(to_col([1, 2, 3, 4]), denom=6)
f = A(to_col([5, 6, 7, 8]), denom=10)
g = C(to_col([1, 1, 1, 1]), denom=2)
assert e + f == A(to_col([10, 14, 18, 22]), denom=15)
assert e - f == A(to_col([-5, -4, -3, -2]), denom=15)
assert e + g == A(to_col([10, 11, 12, 13]), denom=6)
assert e + QQ(7, 10) == A(to_col([26, 10, 15, 20]), denom=30)
assert g + QQ(7, 10) == A(to_col([22, 15, 15, 15]), denom=10)
U = Poly(cyclotomic_poly(7, x))
Z = PowerBasis(U)
raises(TypeError, lambda: e + Z(0))
raises(TypeError, lambda: e + 3.14)
def test_ModuleElement_mul():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
e = A(to_col([0, 2, 0, 0]), denom=3)
f = A(to_col([0, 0, 0, 7]), denom=5)
g = C(to_col([0, 0, 0, 1]), denom=2)
h = A(to_col([0, 0, 3, 1]), denom=7)
assert e * f == A(to_col([-14, -14, -14, -14]), denom=15)
assert e * g == A(to_col([-1, -1, -1, -1]))
assert e * h == A(to_col([-2, -2, -2, 4]), denom=21)
assert e * QQ(6, 5) == A(to_col([0, 4, 0, 0]), denom=5)
assert (g * QQ(10, 21)).equiv(A(to_col([0, 0, 0, 5]), denom=7))
assert e // QQ(6, 5) == A(to_col([0, 5, 0, 0]), denom=9)
U = Poly(cyclotomic_poly(7, x))
Z = PowerBasis(U)
raises(TypeError, lambda: e * Z(0))
raises(TypeError, lambda: e * 3.14)
raises(TypeError, lambda: e // 3.14)
raises(ZeroDivisionError, lambda: e // 0)
def test_ModuleElement_div():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
e = A(to_col([0, 2, 0, 0]), denom=3)
f = A(to_col([0, 0, 0, 7]), denom=5)
g = C(to_col([1, 1, 1, 1]))
assert e // f == 10*A(3)//21
assert e // g == -2*A(2)//9
assert 3 // g == -A(1)
def test_ModuleElement_pow():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
e = A(to_col([0, 2, 0, 0]), denom=3)
g = C(to_col([0, 0, 0, 1]), denom=2)
assert e ** 3 == A(to_col([0, 0, 0, 8]), denom=27)
assert g ** 2 == C(to_col([0, 3, 0, 0]), denom=4)
assert e ** 0 == A(to_col([1, 0, 0, 0]))
assert g ** 0 == A(to_col([1, 0, 0, 0]))
assert e ** 1 == e
assert g ** 1 == g
def test_ModuleElement_mod():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(to_col([1, 15, 8, 0]), denom=2)
assert e % 7 == A(to_col([1, 1, 8, 0]), denom=2)
assert e % QQ(1, 2) == A.zero()
assert e % QQ(1, 3) == A(to_col([1, 1, 0, 0]), denom=6)
B = A.submodule_from_gens([A(0), 5*A(1), 3*A(2), A(3)])
assert e % B == A(to_col([1, 5, 2, 0]), denom=2)
C = B.whole_submodule()
raises(TypeError, lambda: e % C)
def test_PowerBasisElement_polys():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(to_col([1, 15, 8, 0]), denom=2)
assert e.numerator(x=zeta) == Poly(8 * zeta ** 2 + 15 * zeta + 1, domain=ZZ)
assert e.poly(x=zeta) == Poly(4 * zeta ** 2 + QQ(15, 2) * zeta + QQ(1, 2), domain=QQ)
def test_PowerBasisElement_norm():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
lam = A(to_col([1, -1, 0, 0]))
assert lam.norm() == 5
def test_PowerBasisElement_inverse():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
e = A(to_col([1, 1, 1, 1]))
assert 2 // e == -2*A(1)
assert e ** -3 == -A(3)
def test_ModuleHomomorphism_matrix():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
phi = ModuleEndomorphism(A, lambda a: a ** 2)
M = phi.matrix()
assert M == DomainMatrix([
[1, 0, -1, 0],
[0, 0, -1, 1],
[0, 1, -1, 0],
[0, 0, -1, 0]
], (4, 4), ZZ)
def test_ModuleHomomorphism_kernel():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
phi = ModuleEndomorphism(A, lambda a: a ** 5)
N = phi.kernel()
assert N.n == 3
def test_EndomorphismRing_represent():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
R = A.endomorphism_ring()
phi = R.inner_endomorphism(A(1))
col = R.represent(phi)
assert col.transpose() == DomainMatrix([
[0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -1, -1, -1, -1]
], (1, 16), ZZ)
B = A.submodule_from_matrix(DomainMatrix.zeros((4, 0), ZZ))
S = B.endomorphism_ring()
psi = S.inner_endomorphism(A(1))
col = S.represent(psi)
assert col == DomainMatrix([], (0, 0), ZZ)
raises(NotImplementedError, lambda: R.represent(3.14))
def test_find_min_poly():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
powers = []
m = find_min_poly(A(1), QQ, x=x, powers=powers)
assert m == Poly(T, domain=QQ)
assert len(powers) == 5
# powers list need not be passed
m = find_min_poly(A(1), QQ, x=x)
assert m == Poly(T, domain=QQ)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
raises(MissingUnityError, lambda: find_min_poly(B(1), QQ))

View File

@ -0,0 +1,202 @@
"""Tests on algebraic numbers. """
from sympy.core.containers import Tuple
from sympy.core.numbers import (AlgebraicNumber, I, Rational)
from sympy.core.singleton import S
from sympy.core.symbol import Symbol
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.polys.polytools import Poly
from sympy.polys.numberfields.subfield import to_number_field
from sympy.polys.polyclasses import DMP
from sympy.polys.domains import QQ
from sympy.polys.rootoftools import CRootOf
from sympy.abc import x, y
def test_AlgebraicNumber():
minpoly, root = x**2 - 2, sqrt(2)
a = AlgebraicNumber(root, gen=x)
assert a.rep == DMP([QQ(1), QQ(0)], QQ)
assert a.root == root
assert a.alias is None
assert a.minpoly == minpoly
assert a.is_number
assert a.is_aliased is False
assert a.coeffs() == [S.One, S.Zero]
assert a.native_coeffs() == [QQ(1), QQ(0)]
a = AlgebraicNumber(root, gen=x, alias='y')
assert a.rep == DMP([QQ(1), QQ(0)], QQ)
assert a.root == root
assert a.alias == Symbol('y')
assert a.minpoly == minpoly
assert a.is_number
assert a.is_aliased is True
a = AlgebraicNumber(root, gen=x, alias=Symbol('y'))
assert a.rep == DMP([QQ(1), QQ(0)], QQ)
assert a.root == root
assert a.alias == Symbol('y')
assert a.minpoly == minpoly
assert a.is_number
assert a.is_aliased is True
assert AlgebraicNumber(sqrt(2), []).rep == DMP([], QQ)
assert AlgebraicNumber(sqrt(2), ()).rep == DMP([], QQ)
assert AlgebraicNumber(sqrt(2), (0, 0)).rep == DMP([], QQ)
assert AlgebraicNumber(sqrt(2), [8]).rep == DMP([QQ(8)], QQ)
assert AlgebraicNumber(sqrt(2), [Rational(8, 3)]).rep == DMP([QQ(8, 3)], QQ)
assert AlgebraicNumber(sqrt(2), [7, 3]).rep == DMP([QQ(7), QQ(3)], QQ)
assert AlgebraicNumber(
sqrt(2), [Rational(7, 9), Rational(3, 2)]).rep == DMP([QQ(7, 9), QQ(3, 2)], QQ)
assert AlgebraicNumber(sqrt(2), [1, 2, 3]).rep == DMP([QQ(2), QQ(5)], QQ)
a = AlgebraicNumber(AlgebraicNumber(root, gen=x), [1, 2])
assert a.rep == DMP([QQ(1), QQ(2)], QQ)
assert a.root == root
assert a.alias is None
assert a.minpoly == minpoly
assert a.is_number
assert a.is_aliased is False
assert a.coeffs() == [S.One, S(2)]
assert a.native_coeffs() == [QQ(1), QQ(2)]
a = AlgebraicNumber((minpoly, root), [1, 2])
assert a.rep == DMP([QQ(1), QQ(2)], QQ)
assert a.root == root
assert a.alias is None
assert a.minpoly == minpoly
assert a.is_number
assert a.is_aliased is False
a = AlgebraicNumber((Poly(minpoly), root), [1, 2])
assert a.rep == DMP([QQ(1), QQ(2)], QQ)
assert a.root == root
assert a.alias is None
assert a.minpoly == minpoly
assert a.is_number
assert a.is_aliased is False
assert AlgebraicNumber( sqrt(3)).rep == DMP([ QQ(1), QQ(0)], QQ)
assert AlgebraicNumber(-sqrt(3)).rep == DMP([ QQ(1), QQ(0)], QQ)
a = AlgebraicNumber(sqrt(2))
b = AlgebraicNumber(sqrt(2))
assert a == b
c = AlgebraicNumber(sqrt(2), gen=x)
assert a == b
assert a == c
a = AlgebraicNumber(sqrt(2), [1, 2])
b = AlgebraicNumber(sqrt(2), [1, 3])
assert a != b and a != sqrt(2) + 3
assert (a == x) is False and (a != x) is True
a = AlgebraicNumber(sqrt(2), [1, 0])
b = AlgebraicNumber(sqrt(2), [1, 0], alias=y)
assert a.as_poly(x) == Poly(x, domain='QQ')
assert b.as_poly() == Poly(y, domain='QQ')
assert a.as_expr() == sqrt(2)
assert a.as_expr(x) == x
assert b.as_expr() == sqrt(2)
assert b.as_expr(x) == x
a = AlgebraicNumber(sqrt(2), [2, 3])
b = AlgebraicNumber(sqrt(2), [2, 3], alias=y)
p = a.as_poly()
assert p == Poly(2*p.gen + 3)
assert a.as_poly(x) == Poly(2*x + 3, domain='QQ')
assert b.as_poly() == Poly(2*y + 3, domain='QQ')
assert a.as_expr() == 2*sqrt(2) + 3
assert a.as_expr(x) == 2*x + 3
assert b.as_expr() == 2*sqrt(2) + 3
assert b.as_expr(x) == 2*x + 3
a = AlgebraicNumber(sqrt(2))
b = to_number_field(sqrt(2))
assert a.args == b.args == (sqrt(2), Tuple(1, 0))
b = AlgebraicNumber(sqrt(2), alias='alpha')
assert b.args == (sqrt(2), Tuple(1, 0), Symbol('alpha'))
a = AlgebraicNumber(sqrt(2), [1, 2, 3])
assert a.args == (sqrt(2), Tuple(1, 2, 3))
a = AlgebraicNumber(sqrt(2), [1, 2], "alpha")
b = AlgebraicNumber(a)
c = AlgebraicNumber(a, alias="gamma")
assert a == b
assert c.alias.name == "gamma"
a = AlgebraicNumber(sqrt(2) + sqrt(3), [S(1)/2, 0, S(-9)/2, 0])
b = AlgebraicNumber(a, [1, 0, 0])
assert b.root == a.root
assert a.to_root() == sqrt(2)
assert b.to_root() == 2
a = AlgebraicNumber(2)
assert a.is_primitive_element is True
def test_to_algebraic_integer():
a = AlgebraicNumber(sqrt(3), gen=x).to_algebraic_integer()
assert a.minpoly == x**2 - 3
assert a.root == sqrt(3)
assert a.rep == DMP([QQ(1), QQ(0)], QQ)
a = AlgebraicNumber(2*sqrt(3), gen=x).to_algebraic_integer()
assert a.minpoly == x**2 - 12
assert a.root == 2*sqrt(3)
assert a.rep == DMP([QQ(1), QQ(0)], QQ)
a = AlgebraicNumber(sqrt(3)/2, gen=x).to_algebraic_integer()
assert a.minpoly == x**2 - 12
assert a.root == 2*sqrt(3)
assert a.rep == DMP([QQ(1), QQ(0)], QQ)
a = AlgebraicNumber(sqrt(3)/2, [Rational(7, 19), 3], gen=x).to_algebraic_integer()
assert a.minpoly == x**2 - 12
assert a.root == 2*sqrt(3)
assert a.rep == DMP([QQ(7, 19), QQ(3)], QQ)
def test_AlgebraicNumber_to_root():
assert AlgebraicNumber(sqrt(2)).to_root() == sqrt(2)
zeta5_squared = AlgebraicNumber(CRootOf(x**5 - 1, 4), coeffs=[1, 0, 0])
assert zeta5_squared.to_root() == CRootOf(x**4 + x**3 + x**2 + x + 1, 1)
zeta3_squared = AlgebraicNumber(CRootOf(x**3 - 1, 2), coeffs=[1, 0, 0])
assert zeta3_squared.to_root() == -S(1)/2 - sqrt(3)*I/2
assert zeta3_squared.to_root(radicals=False) == CRootOf(x**2 + x + 1, 0)

View File

@ -0,0 +1,296 @@
from math import prod
from sympy import QQ, ZZ
from sympy.abc import x, theta
from sympy.ntheory import factorint
from sympy.ntheory.residue_ntheory import n_order
from sympy.polys import Poly, cyclotomic_poly
from sympy.polys.matrices import DomainMatrix
from sympy.polys.numberfields.basis import round_two
from sympy.polys.numberfields.exceptions import StructureError
from sympy.polys.numberfields.modules import PowerBasis, to_col
from sympy.polys.numberfields.primes import (
prime_decomp, _two_elt_rep,
_check_formal_conditions_for_maximal_order,
)
from sympy.testing.pytest import raises
def test_check_formal_conditions_for_maximal_order():
T = Poly(cyclotomic_poly(5, x))
A = PowerBasis(T)
B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
C = B.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
D = A.submodule_from_matrix(DomainMatrix.eye(4, ZZ)[:, :-1])
# Is a direct submodule of a power basis, but lacks 1 as first generator:
raises(StructureError, lambda: _check_formal_conditions_for_maximal_order(B))
# Is not a direct submodule of a power basis:
raises(StructureError, lambda: _check_formal_conditions_for_maximal_order(C))
# Is direct submod of pow basis, and starts with 1, but not sq/max rank/HNF:
raises(StructureError, lambda: _check_formal_conditions_for_maximal_order(D))
def test_two_elt_rep():
ell = 7
T = Poly(cyclotomic_poly(ell))
ZK, dK = round_two(T)
for p in [29, 13, 11, 5]:
P = prime_decomp(p, T)
for Pi in P:
# We have Pi in two-element representation, and, because we are
# looking at a cyclotomic field, this was computed by the "easy"
# method that just factors T mod p. We will now convert this to
# a set of Z-generators, then convert that back into a two-element
# rep. The latter need not be identical to the two-elt rep we
# already have, but it must have the same HNF.
H = p*ZK + Pi.alpha*ZK
gens = H.basis_element_pullbacks()
# Note: we could supply f = Pi.f, but prefer to test behavior without it.
b = _two_elt_rep(gens, ZK, p)
if b != Pi.alpha:
H2 = p*ZK + b*ZK
assert H2 == H
def test_valuation_at_prime_ideal():
p = 7
T = Poly(cyclotomic_poly(p))
ZK, dK = round_two(T)
P = prime_decomp(p, T, dK=dK, ZK=ZK)
assert len(P) == 1
P0 = P[0]
v = P0.valuation(p*ZK)
assert v == P0.e
# Test easy 0 case:
assert P0.valuation(5*ZK) == 0
def test_decomp_1():
# All prime decompositions in cyclotomic fields are in the "easy case,"
# since the index is unity.
# Here we check the ramified prime.
T = Poly(cyclotomic_poly(7))
raises(ValueError, lambda: prime_decomp(7))
P = prime_decomp(7, T)
assert len(P) == 1
P0 = P[0]
assert P0.e == 6
assert P0.f == 1
# Test powers:
assert P0**0 == P0.ZK
assert P0**1 == P0
assert P0**6 == 7 * P0.ZK
def test_decomp_2():
# More easy cyclotomic cases, but here we check unramified primes.
ell = 7
T = Poly(cyclotomic_poly(ell))
for p in [29, 13, 11, 5]:
f_exp = n_order(p, ell)
g_exp = (ell - 1) // f_exp
P = prime_decomp(p, T)
assert len(P) == g_exp
for Pi in P:
assert Pi.e == 1
assert Pi.f == f_exp
def test_decomp_3():
T = Poly(x ** 2 - 35)
rad = {}
ZK, dK = round_two(T, radicals=rad)
# 35 is 3 mod 4, so field disc is 4*5*7, and theory says each of the
# rational primes 2, 5, 7 should be the square of a prime ideal.
for p in [2, 5, 7]:
P = prime_decomp(p, T, dK=dK, ZK=ZK, radical=rad.get(p))
assert len(P) == 1
assert P[0].e == 2
assert P[0]**2 == p*ZK
def test_decomp_4():
T = Poly(x ** 2 - 21)
rad = {}
ZK, dK = round_two(T, radicals=rad)
# 21 is 1 mod 4, so field disc is 3*7, and theory says the
# rational primes 3, 7 should be the square of a prime ideal.
for p in [3, 7]:
P = prime_decomp(p, T, dK=dK, ZK=ZK, radical=rad.get(p))
assert len(P) == 1
assert P[0].e == 2
assert P[0]**2 == p*ZK
def test_decomp_5():
# Here is our first test of the "hard case" of prime decomposition.
# We work in a quadratic extension Q(sqrt(d)) where d is 1 mod 4, and
# we consider the factorization of the rational prime 2, which divides
# the index.
# Theory says the form of p's factorization depends on the residue of
# d mod 8, so we consider both cases, d = 1 mod 8 and d = 5 mod 8.
for d in [-7, -3]:
T = Poly(x ** 2 - d)
rad = {}
ZK, dK = round_two(T, radicals=rad)
p = 2
P = prime_decomp(p, T, dK=dK, ZK=ZK, radical=rad.get(p))
if d % 8 == 1:
assert len(P) == 2
assert all(P[i].e == 1 and P[i].f == 1 for i in range(2))
assert prod(Pi**Pi.e for Pi in P) == p * ZK
else:
assert d % 8 == 5
assert len(P) == 1
assert P[0].e == 1
assert P[0].f == 2
assert P[0].as_submodule() == p * ZK
def test_decomp_6():
# Another case where 2 divides the index. This is Dedekind's example of
# an essential discriminant divisor. (See Cohen, Exercise 6.10.)
T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
rad = {}
ZK, dK = round_two(T, radicals=rad)
p = 2
P = prime_decomp(p, T, dK=dK, ZK=ZK, radical=rad.get(p))
assert len(P) == 3
assert all(Pi.e == Pi.f == 1 for Pi in P)
assert prod(Pi**Pi.e for Pi in P) == p*ZK
def test_decomp_7():
# Try working through an AlgebraicField
T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
K = QQ.alg_field_from_poly(T)
p = 2
P = K.primes_above(p)
ZK = K.maximal_order()
assert len(P) == 3
assert all(Pi.e == Pi.f == 1 for Pi in P)
assert prod(Pi**Pi.e for Pi in P) == p*ZK
def test_decomp_8():
# This time we consider various cubics, and try factoring all primes
# dividing the index.
cases = (
x ** 3 + 3 * x ** 2 - 4 * x + 4,
x ** 3 + 3 * x ** 2 + 3 * x - 3,
x ** 3 + 5 * x ** 2 - x + 3,
x ** 3 + 5 * x ** 2 - 5 * x - 5,
x ** 3 + 3 * x ** 2 + 5,
x ** 3 + 6 * x ** 2 + 3 * x - 1,
x ** 3 + 6 * x ** 2 + 4,
x ** 3 + 7 * x ** 2 + 7 * x - 7,
x ** 3 + 7 * x ** 2 - x + 5,
x ** 3 + 7 * x ** 2 - 5 * x + 5,
x ** 3 + 4 * x ** 2 - 3 * x + 7,
x ** 3 + 8 * x ** 2 + 5 * x - 1,
x ** 3 + 8 * x ** 2 - 2 * x + 6,
x ** 3 + 6 * x ** 2 - 3 * x + 8,
x ** 3 + 9 * x ** 2 + 6 * x - 8,
x ** 3 + 15 * x ** 2 - 9 * x + 13,
)
def display(T, p, radical, P, I, J):
"""Useful for inspection, when running test manually."""
print('=' * 20)
print(T, p, radical)
for Pi in P:
print(f' ({Pi!r})')
print("I: ", I)
print("J: ", J)
print(f'Equal: {I == J}')
inspect = False
for g in cases:
T = Poly(g)
rad = {}
ZK, dK = round_two(T, radicals=rad)
dT = T.discriminant()
f_squared = dT // dK
F = factorint(f_squared)
for p in F:
radical = rad.get(p)
P = prime_decomp(p, T, dK=dK, ZK=ZK, radical=radical)
I = prod(Pi**Pi.e for Pi in P)
J = p * ZK
if inspect:
display(T, p, radical, P, I, J)
assert I == J
def test_PrimeIdeal_eq():
# `==` should fail on objects of different types, so even a completely
# inert PrimeIdeal should test unequal to the rational prime it divides.
T = Poly(cyclotomic_poly(7))
P0 = prime_decomp(5, T)[0]
assert P0.f == 6
assert P0.as_submodule() == 5 * P0.ZK
assert P0 != 5
def test_PrimeIdeal_add():
T = Poly(cyclotomic_poly(7))
P0 = prime_decomp(7, T)[0]
# Adding ideals computes their GCD, so adding the ramified prime dividing
# 7 to 7 itself should reproduce this prime (as a submodule).
assert P0 + 7 * P0.ZK == P0.as_submodule()
def test_str():
# Without alias:
k = QQ.alg_field_from_poly(Poly(x**2 + 7))
frp = k.primes_above(2)[0]
assert str(frp) == '(2, 3*_x/2 + 1/2)'
frp = k.primes_above(3)[0]
assert str(frp) == '(3)'
# With alias:
k = QQ.alg_field_from_poly(Poly(x ** 2 + 7), alias='alpha')
frp = k.primes_above(2)[0]
assert str(frp) == '(2, 3*alpha/2 + 1/2)'
frp = k.primes_above(3)[0]
assert str(frp) == '(3)'
def test_repr():
T = Poly(x**2 + 7)
ZK, dK = round_two(T)
P = prime_decomp(2, T, dK=dK, ZK=ZK)
assert repr(P[0]) == '[ (2, (3*x + 1)/2) e=1, f=1 ]'
assert P[0].repr(field_gen=theta) == '[ (2, (3*theta + 1)/2) e=1, f=1 ]'
assert P[0].repr(field_gen=theta, just_gens=True) == '(2, (3*theta + 1)/2)'
def test_PrimeIdeal_reduce():
k = QQ.alg_field_from_poly(Poly(x ** 3 + x ** 2 - 2 * x + 8))
Zk = k.maximal_order()
P = k.primes_above(2)
frp = P[2]
# reduce_element
a = Zk.parent(to_col([23, 20, 11]), denom=6)
a_bar_expected = Zk.parent(to_col([11, 5, 2]), denom=6)
a_bar = frp.reduce_element(a)
assert a_bar == a_bar_expected
# reduce_ANP
a = k([QQ(11, 6), QQ(20, 6), QQ(23, 6)])
a_bar_expected = k([QQ(2, 6), QQ(5, 6), QQ(11, 6)])
a_bar = frp.reduce_ANP(a)
assert a_bar == a_bar_expected
# reduce_alg_num
a = k.to_alg_num(a)
a_bar_expected = k.to_alg_num(a_bar_expected)
a_bar = frp.reduce_alg_num(a)
assert a_bar == a_bar_expected
def test_issue_23402():
k = QQ.alg_field_from_poly(Poly(x ** 3 + x ** 2 - 2 * x + 8))
P = k.primes_above(3)
assert P[0].alpha.equiv(0)

View File

@ -0,0 +1,304 @@
"""Tests for the subfield problem and allied problems. """
from sympy.core.numbers import (AlgebraicNumber, I, pi, Rational)
from sympy.core.singleton import S
from sympy.functions.elementary.exponential import exp
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.external.gmpy import MPQ
from sympy.polys.numberfields.subfield import (
is_isomorphism_possible,
field_isomorphism_pslq,
field_isomorphism,
primitive_element,
to_number_field,
)
from sympy.polys.polyerrors import IsomorphismFailed
from sympy.polys.polytools import Poly
from sympy.polys.rootoftools import CRootOf
from sympy.testing.pytest import raises
from sympy.abc import x
Q = Rational
def test_field_isomorphism_pslq():
a = AlgebraicNumber(I)
b = AlgebraicNumber(I*sqrt(3))
raises(NotImplementedError, lambda: field_isomorphism_pslq(a, b))
a = AlgebraicNumber(sqrt(2))
b = AlgebraicNumber(sqrt(3))
c = AlgebraicNumber(sqrt(7))
d = AlgebraicNumber(sqrt(2) + sqrt(3))
e = AlgebraicNumber(sqrt(2) + sqrt(3) + sqrt(7))
assert field_isomorphism_pslq(a, a) == [1, 0]
assert field_isomorphism_pslq(a, b) is None
assert field_isomorphism_pslq(a, c) is None
assert field_isomorphism_pslq(a, d) == [Q(1, 2), 0, -Q(9, 2), 0]
assert field_isomorphism_pslq(
a, e) == [Q(1, 80), 0, -Q(1, 2), 0, Q(59, 20), 0]
assert field_isomorphism_pslq(b, a) is None
assert field_isomorphism_pslq(b, b) == [1, 0]
assert field_isomorphism_pslq(b, c) is None
assert field_isomorphism_pslq(b, d) == [-Q(1, 2), 0, Q(11, 2), 0]
assert field_isomorphism_pslq(b, e) == [-Q(
3, 640), 0, Q(67, 320), 0, -Q(297, 160), 0, Q(313, 80), 0]
assert field_isomorphism_pslq(c, a) is None
assert field_isomorphism_pslq(c, b) is None
assert field_isomorphism_pslq(c, c) == [1, 0]
assert field_isomorphism_pslq(c, d) is None
assert field_isomorphism_pslq(c, e) == [Q(
3, 640), 0, -Q(71, 320), 0, Q(377, 160), 0, -Q(469, 80), 0]
assert field_isomorphism_pslq(d, a) is None
assert field_isomorphism_pslq(d, b) is None
assert field_isomorphism_pslq(d, c) is None
assert field_isomorphism_pslq(d, d) == [1, 0]
assert field_isomorphism_pslq(d, e) == [-Q(
3, 640), 0, Q(71, 320), 0, -Q(377, 160), 0, Q(549, 80), 0]
assert field_isomorphism_pslq(e, a) is None
assert field_isomorphism_pslq(e, b) is None
assert field_isomorphism_pslq(e, c) is None
assert field_isomorphism_pslq(e, d) is None
assert field_isomorphism_pslq(e, e) == [1, 0]
f = AlgebraicNumber(3*sqrt(2) + 8*sqrt(7) - 5)
assert field_isomorphism_pslq(
f, e) == [Q(3, 80), 0, -Q(139, 80), 0, Q(347, 20), 0, -Q(761, 20), -5]
def test_field_isomorphism():
assert field_isomorphism(3, sqrt(2)) == [3]
assert field_isomorphism( I*sqrt(3), I*sqrt(3)/2) == [ 2, 0]
assert field_isomorphism(-I*sqrt(3), I*sqrt(3)/2) == [-2, 0]
assert field_isomorphism( I*sqrt(3), -I*sqrt(3)/2) == [-2, 0]
assert field_isomorphism(-I*sqrt(3), -I*sqrt(3)/2) == [ 2, 0]
assert field_isomorphism( 2*I*sqrt(3)/7, 5*I*sqrt(3)/3) == [ Rational(6, 35), 0]
assert field_isomorphism(-2*I*sqrt(3)/7, 5*I*sqrt(3)/3) == [Rational(-6, 35), 0]
assert field_isomorphism( 2*I*sqrt(3)/7, -5*I*sqrt(3)/3) == [Rational(-6, 35), 0]
assert field_isomorphism(-2*I*sqrt(3)/7, -5*I*sqrt(3)/3) == [ Rational(6, 35), 0]
assert field_isomorphism(
2*I*sqrt(3)/7 + 27, 5*I*sqrt(3)/3) == [ Rational(6, 35), 27]
assert field_isomorphism(
-2*I*sqrt(3)/7 + 27, 5*I*sqrt(3)/3) == [Rational(-6, 35), 27]
assert field_isomorphism(
2*I*sqrt(3)/7 + 27, -5*I*sqrt(3)/3) == [Rational(-6, 35), 27]
assert field_isomorphism(
-2*I*sqrt(3)/7 + 27, -5*I*sqrt(3)/3) == [ Rational(6, 35), 27]
p = AlgebraicNumber( sqrt(2) + sqrt(3))
q = AlgebraicNumber(-sqrt(2) + sqrt(3))
r = AlgebraicNumber( sqrt(2) - sqrt(3))
s = AlgebraicNumber(-sqrt(2) - sqrt(3))
pos_coeffs = [ S.Half, S.Zero, Rational(-9, 2), S.Zero]
neg_coeffs = [Rational(-1, 2), S.Zero, Rational(9, 2), S.Zero]
a = AlgebraicNumber(sqrt(2))
assert is_isomorphism_possible(a, p) is True
assert is_isomorphism_possible(a, q) is True
assert is_isomorphism_possible(a, r) is True
assert is_isomorphism_possible(a, s) is True
assert field_isomorphism(a, p, fast=True) == pos_coeffs
assert field_isomorphism(a, q, fast=True) == neg_coeffs
assert field_isomorphism(a, r, fast=True) == pos_coeffs
assert field_isomorphism(a, s, fast=True) == neg_coeffs
assert field_isomorphism(a, p, fast=False) == pos_coeffs
assert field_isomorphism(a, q, fast=False) == neg_coeffs
assert field_isomorphism(a, r, fast=False) == pos_coeffs
assert field_isomorphism(a, s, fast=False) == neg_coeffs
a = AlgebraicNumber(-sqrt(2))
assert is_isomorphism_possible(a, p) is True
assert is_isomorphism_possible(a, q) is True
assert is_isomorphism_possible(a, r) is True
assert is_isomorphism_possible(a, s) is True
assert field_isomorphism(a, p, fast=True) == neg_coeffs
assert field_isomorphism(a, q, fast=True) == pos_coeffs
assert field_isomorphism(a, r, fast=True) == neg_coeffs
assert field_isomorphism(a, s, fast=True) == pos_coeffs
assert field_isomorphism(a, p, fast=False) == neg_coeffs
assert field_isomorphism(a, q, fast=False) == pos_coeffs
assert field_isomorphism(a, r, fast=False) == neg_coeffs
assert field_isomorphism(a, s, fast=False) == pos_coeffs
pos_coeffs = [ S.Half, S.Zero, Rational(-11, 2), S.Zero]
neg_coeffs = [Rational(-1, 2), S.Zero, Rational(11, 2), S.Zero]
a = AlgebraicNumber(sqrt(3))
assert is_isomorphism_possible(a, p) is True
assert is_isomorphism_possible(a, q) is True
assert is_isomorphism_possible(a, r) is True
assert is_isomorphism_possible(a, s) is True
assert field_isomorphism(a, p, fast=True) == neg_coeffs
assert field_isomorphism(a, q, fast=True) == neg_coeffs
assert field_isomorphism(a, r, fast=True) == pos_coeffs
assert field_isomorphism(a, s, fast=True) == pos_coeffs
assert field_isomorphism(a, p, fast=False) == neg_coeffs
assert field_isomorphism(a, q, fast=False) == neg_coeffs
assert field_isomorphism(a, r, fast=False) == pos_coeffs
assert field_isomorphism(a, s, fast=False) == pos_coeffs
a = AlgebraicNumber(-sqrt(3))
assert is_isomorphism_possible(a, p) is True
assert is_isomorphism_possible(a, q) is True
assert is_isomorphism_possible(a, r) is True
assert is_isomorphism_possible(a, s) is True
assert field_isomorphism(a, p, fast=True) == pos_coeffs
assert field_isomorphism(a, q, fast=True) == pos_coeffs
assert field_isomorphism(a, r, fast=True) == neg_coeffs
assert field_isomorphism(a, s, fast=True) == neg_coeffs
assert field_isomorphism(a, p, fast=False) == pos_coeffs
assert field_isomorphism(a, q, fast=False) == pos_coeffs
assert field_isomorphism(a, r, fast=False) == neg_coeffs
assert field_isomorphism(a, s, fast=False) == neg_coeffs
pos_coeffs = [ Rational(3, 2), S.Zero, Rational(-33, 2), -S(8)]
neg_coeffs = [Rational(-3, 2), S.Zero, Rational(33, 2), -S(8)]
a = AlgebraicNumber(3*sqrt(3) - 8)
assert is_isomorphism_possible(a, p) is True
assert is_isomorphism_possible(a, q) is True
assert is_isomorphism_possible(a, r) is True
assert is_isomorphism_possible(a, s) is True
assert field_isomorphism(a, p, fast=True) == neg_coeffs
assert field_isomorphism(a, q, fast=True) == neg_coeffs
assert field_isomorphism(a, r, fast=True) == pos_coeffs
assert field_isomorphism(a, s, fast=True) == pos_coeffs
assert field_isomorphism(a, p, fast=False) == neg_coeffs
assert field_isomorphism(a, q, fast=False) == neg_coeffs
assert field_isomorphism(a, r, fast=False) == pos_coeffs
assert field_isomorphism(a, s, fast=False) == pos_coeffs
a = AlgebraicNumber(3*sqrt(2) + 2*sqrt(3) + 1)
pos_1_coeffs = [ S.Half, S.Zero, Rational(-5, 2), S.One]
neg_5_coeffs = [Rational(-5, 2), S.Zero, Rational(49, 2), S.One]
pos_5_coeffs = [ Rational(5, 2), S.Zero, Rational(-49, 2), S.One]
neg_1_coeffs = [Rational(-1, 2), S.Zero, Rational(5, 2), S.One]
assert is_isomorphism_possible(a, p) is True
assert is_isomorphism_possible(a, q) is True
assert is_isomorphism_possible(a, r) is True
assert is_isomorphism_possible(a, s) is True
assert field_isomorphism(a, p, fast=True) == pos_1_coeffs
assert field_isomorphism(a, q, fast=True) == neg_5_coeffs
assert field_isomorphism(a, r, fast=True) == pos_5_coeffs
assert field_isomorphism(a, s, fast=True) == neg_1_coeffs
assert field_isomorphism(a, p, fast=False) == pos_1_coeffs
assert field_isomorphism(a, q, fast=False) == neg_5_coeffs
assert field_isomorphism(a, r, fast=False) == pos_5_coeffs
assert field_isomorphism(a, s, fast=False) == neg_1_coeffs
a = AlgebraicNumber(sqrt(2))
b = AlgebraicNumber(sqrt(3))
c = AlgebraicNumber(sqrt(7))
assert is_isomorphism_possible(a, b) is True
assert is_isomorphism_possible(b, a) is True
assert is_isomorphism_possible(c, p) is False
assert field_isomorphism(sqrt(2), sqrt(3), fast=True) is None
assert field_isomorphism(sqrt(3), sqrt(2), fast=True) is None
assert field_isomorphism(sqrt(2), sqrt(3), fast=False) is None
assert field_isomorphism(sqrt(3), sqrt(2), fast=False) is None
a = AlgebraicNumber(sqrt(2))
b = AlgebraicNumber(2 ** (S(1) / 3))
assert is_isomorphism_possible(a, b) is False
assert field_isomorphism(a, b) is None
def test_primitive_element():
assert primitive_element([sqrt(2)], x) == (x**2 - 2, [1])
assert primitive_element(
[sqrt(2), sqrt(3)], x) == (x**4 - 10*x**2 + 1, [1, 1])
assert primitive_element([sqrt(2)], x, polys=True) == (Poly(x**2 - 2, domain='QQ'), [1])
assert primitive_element([sqrt(
2), sqrt(3)], x, polys=True) == (Poly(x**4 - 10*x**2 + 1, domain='QQ'), [1, 1])
assert primitive_element(
[sqrt(2)], x, ex=True) == (x**2 - 2, [1], [[1, 0]])
assert primitive_element([sqrt(2), sqrt(3)], x, ex=True) == \
(x**4 - 10*x**2 + 1, [1, 1], [[Q(1, 2), 0, -Q(9, 2), 0], [-
Q(1, 2), 0, Q(11, 2), 0]])
assert primitive_element(
[sqrt(2)], x, ex=True, polys=True) == (Poly(x**2 - 2, domain='QQ'), [1], [[1, 0]])
assert primitive_element([sqrt(2), sqrt(3)], x, ex=True, polys=True) == \
(Poly(x**4 - 10*x**2 + 1, domain='QQ'), [1, 1], [[Q(1, 2), 0, -Q(9, 2),
0], [-Q(1, 2), 0, Q(11, 2), 0]])
assert primitive_element([sqrt(2)], polys=True) == (Poly(x**2 - 2), [1])
raises(ValueError, lambda: primitive_element([], x, ex=False))
raises(ValueError, lambda: primitive_element([], x, ex=True))
# Issue 14117
a, b = I*sqrt(2*sqrt(2) + 3), I*sqrt(-2*sqrt(2) + 3)
assert primitive_element([a, b, I], x) == (x**4 + 6*x**2 + 1, [1, 0, 0])
assert primitive_element([sqrt(2), 0], x) == (x**2 - 2, [1, 0])
assert primitive_element([0, sqrt(2)], x) == (x**2 - 2, [1, 1])
assert primitive_element([sqrt(2), 0], x, ex=True) == (x**2 - 2, [1, 0], [[MPQ(1,1), MPQ(0,1)], []])
assert primitive_element([0, sqrt(2)], x, ex=True) == (x**2 - 2, [1, 1], [[], [MPQ(1,1), MPQ(0,1)]])
def test_to_number_field():
assert to_number_field(sqrt(2)) == AlgebraicNumber(sqrt(2))
assert to_number_field(
[sqrt(2), sqrt(3)]) == AlgebraicNumber(sqrt(2) + sqrt(3))
a = AlgebraicNumber(sqrt(2) + sqrt(3), [S.Half, S.Zero, Rational(-9, 2), S.Zero])
assert to_number_field(sqrt(2), sqrt(2) + sqrt(3)) == a
assert to_number_field(sqrt(2), AlgebraicNumber(sqrt(2) + sqrt(3))) == a
raises(IsomorphismFailed, lambda: to_number_field(sqrt(2), sqrt(3)))
def test_issue_22561():
a = to_number_field(sqrt(2), sqrt(2) + sqrt(3))
b = to_number_field(sqrt(2), sqrt(2) + sqrt(5))
assert field_isomorphism(a, b) == [1, 0]
def test_issue_22736():
a = CRootOf(x**4 + x**3 + x**2 + x + 1, -1)
a._reset()
b = exp(2*I*pi/5)
assert field_isomorphism(a, b) == [1, 0]

View File

@ -0,0 +1,113 @@
from sympy.abc import x
from sympy.core.numbers import (I, Rational)
from sympy.core.singleton import S
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.polys import Poly, cyclotomic_poly
from sympy.polys.domains import FF, QQ
from sympy.polys.matrices import DomainMatrix, DM
from sympy.polys.matrices.exceptions import DMRankError
from sympy.polys.numberfields.utilities import (
AlgIntPowers, coeff_search, extract_fundamental_discriminant,
isolate, supplement_a_subspace,
)
from sympy.printing.lambdarepr import IntervalPrinter
from sympy.testing.pytest import raises
def test_AlgIntPowers_01():
T = Poly(cyclotomic_poly(5))
zeta_pow = AlgIntPowers(T)
raises(ValueError, lambda: zeta_pow[-1])
for e in range(10):
a = e % 5
if a < 4:
c = zeta_pow[e]
assert c[a] == 1 and all(c[i] == 0 for i in range(4) if i != a)
else:
assert zeta_pow[e] == [-1] * 4
def test_AlgIntPowers_02():
T = Poly(x**3 + 2*x**2 + 3*x + 4)
m = 7
theta_pow = AlgIntPowers(T, m)
for e in range(10):
computed = theta_pow[e]
coeffs = (Poly(x)**e % T + Poly(x**3)).rep.to_list()[1:]
expected = [c % m for c in reversed(coeffs)]
assert computed == expected
def test_coeff_search():
C = []
search = coeff_search(2, 1)
for i, c in enumerate(search):
C.append(c)
if i == 12:
break
assert C == [[1, 1], [1, 0], [1, -1], [0, 1], [2, 2], [2, 1], [2, 0], [2, -1], [2, -2], [1, 2], [1, -2], [0, 2], [3, 3]]
def test_extract_fundamental_discriminant():
# To extract, integer must be 0 or 1 mod 4.
raises(ValueError, lambda: extract_fundamental_discriminant(2))
raises(ValueError, lambda: extract_fundamental_discriminant(3))
# Try many cases, of different forms:
cases = (
(0, {}, {0: 1}),
(1, {}, {}),
(8, {2: 3}, {}),
(-8, {2: 3, -1: 1}, {}),
(12, {2: 2, 3: 1}, {}),
(36, {}, {2: 1, 3: 1}),
(45, {5: 1}, {3: 1}),
(48, {2: 2, 3: 1}, {2: 1}),
(1125, {5: 1}, {3: 1, 5: 1}),
)
for a, D_expected, F_expected in cases:
D, F = extract_fundamental_discriminant(a)
assert D == D_expected
assert F == F_expected
def test_supplement_a_subspace_1():
M = DM([[1, 7, 0], [2, 3, 4]], QQ).transpose()
# First supplement over QQ:
B = supplement_a_subspace(M)
assert B[:, :2] == M
assert B[:, 2] == DomainMatrix.eye(3, QQ).to_dense()[:, 0]
# Now supplement over FF(7):
M = M.convert_to(FF(7))
B = supplement_a_subspace(M)
assert B[:, :2] == M
# When we work mod 7, first col of M goes to [1, 0, 0],
# so the supplementary vector cannot equal this, as it did
# when we worked over QQ. Instead, we get the second std basis vector:
assert B[:, 2] == DomainMatrix.eye(3, FF(7)).to_dense()[:, 1]
def test_supplement_a_subspace_2():
M = DM([[1, 0, 0], [2, 0, 0]], QQ).transpose()
with raises(DMRankError):
supplement_a_subspace(M)
def test_IntervalPrinter():
ip = IntervalPrinter()
assert ip.doprint(x**Rational(1, 3)) == "x**(mpi('1/3'))"
assert ip.doprint(sqrt(x)) == "x**(mpi('1/2'))"
def test_isolate():
assert isolate(1) == (1, 1)
assert isolate(S.Half) == (S.Half, S.Half)
assert isolate(sqrt(2)) == (1, 2)
assert isolate(-sqrt(2)) == (-2, -1)
assert isolate(sqrt(2), eps=Rational(1, 100)) == (Rational(24, 17), Rational(17, 12))
assert isolate(-sqrt(2), eps=Rational(1, 100)) == (Rational(-17, 12), Rational(-24, 17))
raises(NotImplementedError, lambda: isolate(I))