switching to high quality piper tts and added label translations
This commit is contained in:
@@ -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])]
|
||||
+143
@@ -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
|
||||
+490
@@ -0,0 +1,490 @@
|
||||
"""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.ntheory.generate import nextprime
|
||||
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_issue_26903():
|
||||
p1 = nextprime(10**16) # greater than 10**15
|
||||
p2 = nextprime(p1)
|
||||
assert sqrt(p1**2*p2).is_Pow # square not extracted
|
||||
zero = sqrt(p1**2*p2) - p1*sqrt(p2)
|
||||
assert minimal_polynomial(zero, x) == x
|
||||
assert minimal_polynomial(sqrt(2) - zero, x) == x**2 - 2
|
||||
|
||||
|
||||
def test_issue_8353():
|
||||
assert minimal_polynomial(exp(3*I*pi, evaluate=False), x) == x + 1
|
||||
assert minimal_polynomial(Pow(8, S(1)/3, evaluate=False), x
|
||||
) == x - 2
|
||||
|
||||
|
||||
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))
|
||||
+752
@@ -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))
|
||||
+202
@@ -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)
|
||||
+296
@@ -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)
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
"""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.domains import QQ
|
||||
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]
|
||||
|
||||
|
||||
def test_issue_27798():
|
||||
# https://github.com/sympy/sympy/issues/27798
|
||||
a, b = CRootOf(49*x**3 - 49*x**2 + 14*x - 1, 2), CRootOf(49*x**3 - 49*x**2 + 14*x - 1, 0)
|
||||
assert primitive_element([a, b], polys=True)[0].primitive()[0] == 1
|
||||
assert primitive_element([a, b], polys=True, ex=True)[0].primitive()[0] == 1
|
||||
|
||||
f1, f2 = QQ.algebraic_field(a), QQ.algebraic_field(b)
|
||||
f3 = f1.unify(f2)
|
||||
assert f3.mod.primitive()[0] == 1
|
||||
assert Poly(x, x, domain=f1) + Poly(x, x, domain=f2) == Poly(2*x, x, domain=f3)
|
||||
+113
@@ -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))
|
||||
Reference in New Issue
Block a user