add read me
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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])]
|
||||
@@ -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
|
||||
@@ -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))
|
||||
@@ -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))
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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