test_extensions.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. from sympy.core.symbol import symbols
  2. from sympy.functions.elementary.trigonometric import (cos, sin)
  3. from sympy.polys import QQ, ZZ
  4. from sympy.polys.polytools import Poly
  5. from sympy.polys.polyerrors import NotInvertible
  6. from sympy.polys.agca.extensions import FiniteExtension
  7. from sympy.polys.domainmatrix import DomainMatrix
  8. from sympy.testing.pytest import raises
  9. from sympy.abc import x, y, t
  10. def test_FiniteExtension():
  11. # Gaussian integers
  12. A = FiniteExtension(Poly(x**2 + 1, x))
  13. assert A.rank == 2
  14. assert str(A) == 'ZZ[x]/(x**2 + 1)'
  15. i = A.generator
  16. assert i.parent() is A
  17. assert i*i == A(-1)
  18. raises(TypeError, lambda: i*())
  19. assert A.basis == (A.one, i)
  20. assert A(1) == A.one
  21. assert i**2 == A(-1)
  22. assert i**2 != -1 # no coercion
  23. assert (2 + i)*(1 - i) == 3 - i
  24. assert (1 + i)**8 == A(16)
  25. assert A(1).inverse() == A(1)
  26. raises(NotImplementedError, lambda: A(2).inverse())
  27. # Finite field of order 27
  28. F = FiniteExtension(Poly(x**3 - x + 1, x, modulus=3))
  29. assert F.rank == 3
  30. a = F.generator # also generates the cyclic group F - {0}
  31. assert F.basis == (F(1), a, a**2)
  32. assert a**27 == a
  33. assert a**26 == F(1)
  34. assert a**13 == F(-1)
  35. assert a**9 == a + 1
  36. assert a**3 == a - 1
  37. assert a**6 == a**2 + a + 1
  38. assert F(x**2 + x).inverse() == 1 - a
  39. assert F(x + 2)**(-1) == F(x + 2).inverse()
  40. assert a**19 * a**(-19) == F(1)
  41. assert (a - 1) / (2*a**2 - 1) == a**2 + 1
  42. assert (a - 1) // (2*a**2 - 1) == a**2 + 1
  43. assert 2/(a**2 + 1) == a**2 - a + 1
  44. assert (a**2 + 1)/2 == -a**2 - 1
  45. raises(NotInvertible, lambda: F(0).inverse())
  46. # Function field of an elliptic curve
  47. K = FiniteExtension(Poly(t**2 - x**3 - x + 1, t, field=True))
  48. assert K.rank == 2
  49. assert str(K) == 'ZZ(x)[t]/(t**2 - x**3 - x + 1)'
  50. y = K.generator
  51. c = 1/(x**3 - x**2 + x - 1)
  52. assert ((y + x)*(y - x)).inverse() == K(c)
  53. assert (y + x)*(y - x)*c == K(1) # explicit inverse of y + x
  54. def test_FiniteExtension_eq_hash():
  55. # Test eq and hash
  56. p1 = Poly(x**2 - 2, x, domain=ZZ)
  57. p2 = Poly(x**2 - 2, x, domain=QQ)
  58. K1 = FiniteExtension(p1)
  59. K2 = FiniteExtension(p2)
  60. assert K1 == FiniteExtension(Poly(x**2 - 2))
  61. assert K2 != FiniteExtension(Poly(x**2 - 2))
  62. assert len({K1, K2, FiniteExtension(p1)}) == 2
  63. def test_FiniteExtension_mod():
  64. # Test mod
  65. K = FiniteExtension(Poly(x**3 + 1, x, domain=QQ))
  66. xf = K(x)
  67. assert (xf**2 - 1) % 1 == K.zero
  68. assert 1 % (xf**2 - 1) == K.zero
  69. assert (xf**2 - 1) / (xf - 1) == xf + 1
  70. assert (xf**2 - 1) // (xf - 1) == xf + 1
  71. assert (xf**2 - 1) % (xf - 1) == K.zero
  72. raises(ZeroDivisionError, lambda: (xf**2 - 1) % 0)
  73. raises(TypeError, lambda: xf % [])
  74. raises(TypeError, lambda: [] % xf)
  75. # Test mod over ring
  76. K = FiniteExtension(Poly(x**3 + 1, x, domain=ZZ))
  77. xf = K(x)
  78. assert (xf**2 - 1) % 1 == K.zero
  79. raises(NotImplementedError, lambda: (xf**2 - 1) % (xf - 1))
  80. def test_FiniteExtension_from_sympy():
  81. # Test to_sympy/from_sympy
  82. K = FiniteExtension(Poly(x**3 + 1, x, domain=ZZ))
  83. xf = K(x)
  84. assert K.from_sympy(x) == xf
  85. assert K.to_sympy(xf) == x
  86. def test_FiniteExtension_set_domain():
  87. KZ = FiniteExtension(Poly(x**2 + 1, x, domain='ZZ'))
  88. KQ = FiniteExtension(Poly(x**2 + 1, x, domain='QQ'))
  89. assert KZ.set_domain(QQ) == KQ
  90. def test_FiniteExtension_exquo():
  91. # Test exquo
  92. K = FiniteExtension(Poly(x**4 + 1))
  93. xf = K(x)
  94. assert K.exquo(xf**2 - 1, xf - 1) == xf + 1
  95. def test_FiniteExtension_convert():
  96. # Test from_MonogenicFiniteExtension
  97. K1 = FiniteExtension(Poly(x**2 + 1))
  98. K2 = QQ[x]
  99. x1, x2 = K1(x), K2(x)
  100. assert K1.convert(x2) == x1
  101. assert K2.convert(x1) == x2
  102. K = FiniteExtension(Poly(x**2 - 1, domain=QQ))
  103. assert K.convert_from(QQ(1, 2), QQ) == K.one/2
  104. def test_FiniteExtension_division_ring():
  105. # Test division in FiniteExtension over a ring
  106. KQ = FiniteExtension(Poly(x**2 - 1, x, domain=QQ))
  107. KZ = FiniteExtension(Poly(x**2 - 1, x, domain=ZZ))
  108. KQt = FiniteExtension(Poly(x**2 - 1, x, domain=QQ[t]))
  109. KQtf = FiniteExtension(Poly(x**2 - 1, x, domain=QQ.frac_field(t)))
  110. assert KQ.is_Field is True
  111. assert KZ.is_Field is False
  112. assert KQt.is_Field is False
  113. assert KQtf.is_Field is True
  114. for K in KQ, KZ, KQt, KQtf:
  115. xK = K.convert(x)
  116. assert xK / K.one == xK
  117. assert xK // K.one == xK
  118. assert xK % K.one == K.zero
  119. raises(ZeroDivisionError, lambda: xK / K.zero)
  120. raises(ZeroDivisionError, lambda: xK // K.zero)
  121. raises(ZeroDivisionError, lambda: xK % K.zero)
  122. if K.is_Field:
  123. assert xK / xK == K.one
  124. assert xK // xK == K.one
  125. assert xK % xK == K.zero
  126. else:
  127. raises(NotImplementedError, lambda: xK / xK)
  128. raises(NotImplementedError, lambda: xK // xK)
  129. raises(NotImplementedError, lambda: xK % xK)
  130. def test_FiniteExtension_Poly():
  131. K = FiniteExtension(Poly(x**2 - 2))
  132. p = Poly(x, y, domain=K)
  133. assert p.domain == K
  134. assert p.as_expr() == x
  135. assert (p**2).as_expr() == 2
  136. K = FiniteExtension(Poly(x**2 - 2, x, domain=QQ))
  137. K2 = FiniteExtension(Poly(t**2 - 2, t, domain=K))
  138. assert str(K2) == 'QQ[x]/(x**2 - 2)[t]/(t**2 - 2)'
  139. eK = K2.convert(x + t)
  140. assert K2.to_sympy(eK) == x + t
  141. assert K2.to_sympy(eK ** 2) == 4 + 2*x*t
  142. p = Poly(x + t, y, domain=K2)
  143. assert p**2 == Poly(4 + 2*x*t, y, domain=K2)
  144. def test_FiniteExtension_sincos_jacobian():
  145. # Use FiniteExtensino to compute the Jacobian of a matrix involving sin
  146. # and cos of different symbols.
  147. r, p, t = symbols('rho, phi, theta')
  148. elements = [
  149. [sin(p)*cos(t), r*cos(p)*cos(t), -r*sin(p)*sin(t)],
  150. [sin(p)*sin(t), r*cos(p)*sin(t), r*sin(p)*cos(t)],
  151. [ cos(p), -r*sin(p), 0],
  152. ]
  153. def make_extension(K):
  154. K = FiniteExtension(Poly(sin(p)**2+cos(p)**2-1, sin(p), domain=K[cos(p)]))
  155. K = FiniteExtension(Poly(sin(t)**2+cos(t)**2-1, sin(t), domain=K[cos(t)]))
  156. return K
  157. Ksc1 = make_extension(ZZ[r])
  158. Ksc2 = make_extension(ZZ)[r]
  159. for K in [Ksc1, Ksc2]:
  160. elements_K = [[K.convert(e) for e in row] for row in elements]
  161. J = DomainMatrix(elements_K, (3, 3), K)
  162. det = J.charpoly()[-1] * (-K.one)**3
  163. assert det == K.convert(r**2*sin(p))