m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

671 lines
20 KiB

7 months ago
  1. from sympy.abc import x, zeta
  2. from sympy.polys import Poly, cyclotomic_poly
  3. from sympy.polys.domains import FF, QQ, ZZ
  4. from sympy.polys.matrices import DomainMatrix, DM
  5. from sympy.polys.numberfields.exceptions import (
  6. ClosureFailure, MissingUnityError
  7. )
  8. from sympy.polys.numberfields.modules import (
  9. Module, ModuleElement, ModuleEndomorphism, PowerBasis, PowerBasisElement,
  10. find_min_poly, is_sq_maxrank_HNF, make_mod_elt, to_col,
  11. )
  12. from sympy.polys.numberfields.utilities import is_int
  13. from sympy.polys.polyerrors import UnificationFailed
  14. from sympy.testing.pytest import raises
  15. def test_to_col():
  16. c = [1, 2, 3, 4]
  17. m = to_col(c)
  18. assert m.domain.is_ZZ
  19. assert m.shape == (4, 1)
  20. assert m.flat() == c
  21. def test_Module_NotImplemented():
  22. M = Module()
  23. raises(NotImplementedError, lambda: M.n)
  24. raises(NotImplementedError, lambda: M.mult_tab())
  25. raises(NotImplementedError, lambda: M.represent(None))
  26. raises(NotImplementedError, lambda: M.starts_with_unity())
  27. raises(NotImplementedError, lambda: M.element_from_rational(QQ(2, 3)))
  28. def test_Module_ancestors():
  29. T = Poly(cyclotomic_poly(5, x))
  30. A = PowerBasis(T)
  31. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  32. C = B.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  33. D = B.submodule_from_matrix(5 * DomainMatrix.eye(4, ZZ))
  34. assert C.ancestors(include_self=True) == [A, B, C]
  35. assert D.ancestors(include_self=True) == [A, B, D]
  36. assert C.power_basis_ancestor() == A
  37. assert C.nearest_common_ancestor(D) == B
  38. M = Module()
  39. assert M.power_basis_ancestor() is None
  40. def test_Module_compat_col():
  41. T = Poly(cyclotomic_poly(5, x))
  42. A = PowerBasis(T)
  43. col = to_col([1, 2, 3, 4])
  44. row = col.transpose()
  45. assert A.is_compat_col(col) is True
  46. assert A.is_compat_col(row) is False
  47. assert A.is_compat_col(1) is False
  48. assert A.is_compat_col(DomainMatrix.eye(3, ZZ)[:, 0]) is False
  49. assert A.is_compat_col(DomainMatrix.eye(4, QQ)[:, 0]) is False
  50. assert A.is_compat_col(DomainMatrix.eye(4, ZZ)[:, 0]) is True
  51. def test_Module_call():
  52. T = Poly(cyclotomic_poly(5, x))
  53. B = PowerBasis(T)
  54. assert B(0).col.flat() == [1, 0, 0, 0]
  55. assert B(1).col.flat() == [0, 1, 0, 0]
  56. col = DomainMatrix.eye(4, ZZ)[:, 2]
  57. assert B(col).col == col
  58. raises(ValueError, lambda: B(-1))
  59. def test_Module_starts_with_unity():
  60. T = Poly(cyclotomic_poly(5, x))
  61. A = PowerBasis(T)
  62. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  63. assert A.starts_with_unity() is True
  64. assert B.starts_with_unity() is False
  65. def test_Module_basis_elements():
  66. T = Poly(cyclotomic_poly(5, x))
  67. A = PowerBasis(T)
  68. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  69. basis = B.basis_elements()
  70. bp = B.basis_element_pullbacks()
  71. for i, (e, p) in enumerate(zip(basis, bp)):
  72. c = [0] * 4
  73. assert e.module == B
  74. assert p.module == A
  75. c[i] = 1
  76. assert e == B(to_col(c))
  77. c[i] = 2
  78. assert p == A(to_col(c))
  79. def test_Module_zero():
  80. T = Poly(cyclotomic_poly(5, x))
  81. A = PowerBasis(T)
  82. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  83. assert A.zero().col.flat() == [0, 0, 0, 0]
  84. assert A.zero().module == A
  85. assert B.zero().col.flat() == [0, 0, 0, 0]
  86. assert B.zero().module == B
  87. def test_Module_one():
  88. T = Poly(cyclotomic_poly(5, x))
  89. A = PowerBasis(T)
  90. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  91. assert A.one().col.flat() == [1, 0, 0, 0]
  92. assert A.one().module == A
  93. assert B.one().col.flat() == [1, 0, 0, 0]
  94. assert B.one().module == A
  95. def test_Module_element_from_rational():
  96. T = Poly(cyclotomic_poly(5, x))
  97. A = PowerBasis(T)
  98. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  99. rA = A.element_from_rational(QQ(22, 7))
  100. rB = B.element_from_rational(QQ(22, 7))
  101. assert rA.coeffs == [22, 0, 0, 0]
  102. assert rA.denom == 7
  103. assert rA.module == A
  104. assert rB.coeffs == [22, 0, 0, 0]
  105. assert rB.denom == 7
  106. assert rB.module == A
  107. def test_Module_submodule_from_gens():
  108. T = Poly(cyclotomic_poly(5, x))
  109. A = PowerBasis(T)
  110. gens = [2*A(0), 2*A(1), 6*A(0), 6*A(1)]
  111. B = A.submodule_from_gens(gens)
  112. # Because the 3rd and 4th generators do not add anything new, we expect
  113. # the cols of the matrix of B to just reproduce the first two gens:
  114. M = gens[0].column().hstack(gens[1].column())
  115. assert B.matrix == M
  116. # At least one generator must be provided:
  117. raises(ValueError, lambda: A.submodule_from_gens([]))
  118. # All generators must belong to A:
  119. raises(ValueError, lambda: A.submodule_from_gens([3*A(0), B(0)]))
  120. def test_Module_submodule_from_matrix():
  121. T = Poly(cyclotomic_poly(5, x))
  122. A = PowerBasis(T)
  123. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  124. e = B(to_col([1, 2, 3, 4]))
  125. f = e.to_parent()
  126. assert f.col.flat() == [2, 4, 6, 8]
  127. # Matrix must be over ZZ:
  128. raises(ValueError, lambda: A.submodule_from_matrix(DomainMatrix.eye(4, QQ)))
  129. # Number of rows of matrix must equal number of generators of module A:
  130. raises(ValueError, lambda: A.submodule_from_matrix(2 * DomainMatrix.eye(5, ZZ)))
  131. def test_Module_whole_submodule():
  132. T = Poly(cyclotomic_poly(5, x))
  133. A = PowerBasis(T)
  134. B = A.whole_submodule()
  135. e = B(to_col([1, 2, 3, 4]))
  136. f = e.to_parent()
  137. assert f.col.flat() == [1, 2, 3, 4]
  138. e0, e1, e2, e3 = B(0), B(1), B(2), B(3)
  139. assert e2 * e3 == e0
  140. assert e3 ** 2 == e1
  141. def test_PowerBasis_repr():
  142. T = Poly(cyclotomic_poly(5, x))
  143. A = PowerBasis(T)
  144. assert repr(A) == 'PowerBasis(x**4 + x**3 + x**2 + x + 1)'
  145. def test_PowerBasis_eq():
  146. T = Poly(cyclotomic_poly(5, x))
  147. A = PowerBasis(T)
  148. B = PowerBasis(T)
  149. assert A == B
  150. def test_PowerBasis_mult_tab():
  151. T = Poly(cyclotomic_poly(5, x))
  152. A = PowerBasis(T)
  153. M = A.mult_tab()
  154. exp = {0: {0: [1, 0, 0, 0], 1: [0, 1, 0, 0], 2: [0, 0, 1, 0], 3: [0, 0, 0, 1]},
  155. 1: {1: [0, 0, 1, 0], 2: [0, 0, 0, 1], 3: [-1, -1, -1, -1]},
  156. 2: {2: [-1, -1, -1, -1], 3: [1, 0, 0, 0]},
  157. 3: {3: [0, 1, 0, 0]}}
  158. # We get the table we expect:
  159. assert M == exp
  160. # And all entries are of expected type:
  161. assert all(is_int(c) for u in M for v in M[u] for c in M[u][v])
  162. def test_PowerBasis_represent():
  163. T = Poly(cyclotomic_poly(5, x))
  164. A = PowerBasis(T)
  165. col = to_col([1, 2, 3, 4])
  166. a = A(col)
  167. assert A.represent(a) == col
  168. b = A(col, denom=2)
  169. raises(ClosureFailure, lambda: A.represent(b))
  170. def test_PowerBasis_element_from_poly():
  171. T = Poly(cyclotomic_poly(5, x))
  172. A = PowerBasis(T)
  173. f = Poly(1 + 2*x)
  174. g = Poly(x**4)
  175. h = Poly(0, x)
  176. assert A.element_from_poly(f).coeffs == [1, 2, 0, 0]
  177. assert A.element_from_poly(g).coeffs == [-1, -1, -1, -1]
  178. assert A.element_from_poly(h).coeffs == [0, 0, 0, 0]
  179. def test_Submodule_repr():
  180. T = Poly(cyclotomic_poly(5, x))
  181. A = PowerBasis(T)
  182. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ), denom=3)
  183. assert repr(B) == 'Submodule[[2, 0, 0, 0], [0, 2, 0, 0], [0, 0, 2, 0], [0, 0, 0, 2]]/3'
  184. def test_Submodule_reduced():
  185. T = Poly(cyclotomic_poly(5, x))
  186. A = PowerBasis(T)
  187. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  188. C = A.submodule_from_matrix(6 * DomainMatrix.eye(4, ZZ), denom=3)
  189. D = C.reduced()
  190. assert D.denom == 1 and D == C == B
  191. def test_Submodule_discard_before():
  192. T = Poly(cyclotomic_poly(5, x))
  193. A = PowerBasis(T)
  194. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  195. B.compute_mult_tab()
  196. C = B.discard_before(2)
  197. assert C.parent == B.parent
  198. assert B.is_sq_maxrank_HNF() and not C.is_sq_maxrank_HNF()
  199. assert C.matrix == B.matrix[:, 2:]
  200. assert C.mult_tab() == {0: {0: [-2, -2], 1: [0, 0]}, 1: {1: [0, 0]}}
  201. def test_Submodule_QQ_matrix():
  202. T = Poly(cyclotomic_poly(5, x))
  203. A = PowerBasis(T)
  204. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  205. C = A.submodule_from_matrix(6 * DomainMatrix.eye(4, ZZ), denom=3)
  206. assert C.QQ_matrix == B.QQ_matrix
  207. def test_Submodule_represent():
  208. T = Poly(cyclotomic_poly(5, x))
  209. A = PowerBasis(T)
  210. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  211. C = B.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  212. a0 = A(to_col([6, 12, 18, 24]))
  213. a1 = A(to_col([2, 4, 6, 8]))
  214. a2 = A(to_col([1, 3, 5, 7]))
  215. b1 = B.represent(a1)
  216. assert b1.flat() == [1, 2, 3, 4]
  217. c0 = C.represent(a0)
  218. assert c0.flat() == [1, 2, 3, 4]
  219. Y = A.submodule_from_matrix(DomainMatrix([
  220. [1, 0, 0, 0],
  221. [0, 1, 0, 0],
  222. [0, 0, 1, 0],
  223. ], (3, 4), ZZ).transpose())
  224. U = Poly(cyclotomic_poly(7, x))
  225. Z = PowerBasis(U)
  226. z0 = Z(to_col([1, 2, 3, 4, 5, 6]))
  227. raises(ClosureFailure, lambda: Y.represent(A(3)))
  228. raises(ClosureFailure, lambda: B.represent(a2))
  229. raises(ClosureFailure, lambda: B.represent(z0))
  230. def test_Submodule_is_compat_submodule():
  231. T = Poly(cyclotomic_poly(5, x))
  232. A = PowerBasis(T)
  233. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  234. C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  235. D = C.submodule_from_matrix(5 * DomainMatrix.eye(4, ZZ))
  236. assert B.is_compat_submodule(C) is True
  237. assert B.is_compat_submodule(A) is False
  238. assert B.is_compat_submodule(D) is False
  239. def test_Submodule_eq():
  240. T = Poly(cyclotomic_poly(5, x))
  241. A = PowerBasis(T)
  242. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  243. C = A.submodule_from_matrix(6 * DomainMatrix.eye(4, ZZ), denom=3)
  244. assert C == B
  245. def test_Submodule_add():
  246. T = Poly(cyclotomic_poly(5, x))
  247. A = PowerBasis(T)
  248. B = A.submodule_from_matrix(DomainMatrix([
  249. [4, 0, 0, 0],
  250. [0, 4, 0, 0],
  251. ], (2, 4), ZZ).transpose(), denom=6)
  252. C = A.submodule_from_matrix(DomainMatrix([
  253. [0, 10, 0, 0],
  254. [0, 0, 7, 0],
  255. ], (2, 4), ZZ).transpose(), denom=15)
  256. D = A.submodule_from_matrix(DomainMatrix([
  257. [20, 0, 0, 0],
  258. [ 0, 20, 0, 0],
  259. [ 0, 0, 14, 0],
  260. ], (3, 4), ZZ).transpose(), denom=30)
  261. assert B + C == D
  262. U = Poly(cyclotomic_poly(7, x))
  263. Z = PowerBasis(U)
  264. Y = Z.submodule_from_gens([Z(0), Z(1)])
  265. raises(TypeError, lambda: B + Y)
  266. def test_Submodule_mul():
  267. T = Poly(cyclotomic_poly(5, x))
  268. A = PowerBasis(T)
  269. C = A.submodule_from_matrix(DomainMatrix([
  270. [0, 10, 0, 0],
  271. [0, 0, 7, 0],
  272. ], (2, 4), ZZ).transpose(), denom=15)
  273. C1 = A.submodule_from_matrix(DomainMatrix([
  274. [0, 20, 0, 0],
  275. [0, 0, 14, 0],
  276. ], (2, 4), ZZ).transpose(), denom=3)
  277. C2 = A.submodule_from_matrix(DomainMatrix([
  278. [0, 0, 10, 0],
  279. [0, 0, 0, 7],
  280. ], (2, 4), ZZ).transpose(), denom=15)
  281. C3_unred = A.submodule_from_matrix(DomainMatrix([
  282. [0, 0, 100, 0],
  283. [0, 0, 0, 70],
  284. [0, 0, 0, 70],
  285. [-49, -49, -49, -49]
  286. ], (4, 4), ZZ).transpose(), denom=225)
  287. C3 = A.submodule_from_matrix(DomainMatrix([
  288. [4900, 4900, 0, 0],
  289. [4410, 4410, 10, 0],
  290. [2107, 2107, 7, 7]
  291. ], (3, 4), ZZ).transpose(), denom=225)
  292. assert C * 1 == C
  293. assert C ** 1 == C
  294. assert C * 10 == C1
  295. assert C * A(1) == C2
  296. assert C.mul(C, hnf=False) == C3_unred
  297. assert C * C == C3
  298. assert C ** 2 == C3
  299. def test_is_HNF():
  300. M = DM([
  301. [3, 2, 1],
  302. [0, 2, 1],
  303. [0, 0, 1]
  304. ], ZZ)
  305. M1 = DM([
  306. [3, 2, 1],
  307. [0, -2, 1],
  308. [0, 0, 1]
  309. ], ZZ)
  310. M2 = DM([
  311. [3, 2, 3],
  312. [0, 2, 1],
  313. [0, 0, 1]
  314. ], ZZ)
  315. assert is_sq_maxrank_HNF(M) is True
  316. assert is_sq_maxrank_HNF(M1) is False
  317. assert is_sq_maxrank_HNF(M2) is False
  318. def test_make_mod_elt():
  319. T = Poly(cyclotomic_poly(5, x))
  320. A = PowerBasis(T)
  321. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  322. col = to_col([1, 2, 3, 4])
  323. eA = make_mod_elt(A, col)
  324. eB = make_mod_elt(B, col)
  325. assert isinstance(eA, PowerBasisElement)
  326. assert not isinstance(eB, PowerBasisElement)
  327. def test_ModuleElement_repr():
  328. T = Poly(cyclotomic_poly(5, x))
  329. A = PowerBasis(T)
  330. e = A(to_col([1, 2, 3, 4]), denom=2)
  331. assert repr(e) == '[1, 2, 3, 4]/2'
  332. def test_ModuleElement_reduced():
  333. T = Poly(cyclotomic_poly(5, x))
  334. A = PowerBasis(T)
  335. e = A(to_col([2, 4, 6, 8]), denom=2)
  336. f = e.reduced()
  337. assert f.denom == 1 and f == e
  338. def test_ModuleElement_reduced_mod_p():
  339. T = Poly(cyclotomic_poly(5, x))
  340. A = PowerBasis(T)
  341. e = A(to_col([20, 40, 60, 80]))
  342. f = e.reduced_mod_p(7)
  343. assert f.coeffs == [-1, -2, -3, 3]
  344. def test_ModuleElement_from_int_list():
  345. T = Poly(cyclotomic_poly(5, x))
  346. A = PowerBasis(T)
  347. c = [1, 2, 3, 4]
  348. assert ModuleElement.from_int_list(A, c).coeffs == c
  349. def test_ModuleElement_len():
  350. T = Poly(cyclotomic_poly(5, x))
  351. A = PowerBasis(T)
  352. e = A(0)
  353. assert len(e) == 4
  354. def test_ModuleElement_column():
  355. T = Poly(cyclotomic_poly(5, x))
  356. A = PowerBasis(T)
  357. e = A(0)
  358. col1 = e.column()
  359. assert col1 == e.col and col1 is not e.col
  360. col2 = e.column(domain=FF(5))
  361. assert col2.domain.is_FF
  362. def test_ModuleElement_QQ_col():
  363. T = Poly(cyclotomic_poly(5, x))
  364. A = PowerBasis(T)
  365. e = A(to_col([1, 2, 3, 4]), denom=1)
  366. f = A(to_col([3, 6, 9, 12]), denom=3)
  367. assert e.QQ_col == f.QQ_col
  368. def test_ModuleElement_to_ancestors():
  369. T = Poly(cyclotomic_poly(5, x))
  370. A = PowerBasis(T)
  371. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  372. C = B.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  373. D = C.submodule_from_matrix(5 * DomainMatrix.eye(4, ZZ))
  374. eD = D(0)
  375. eC = eD.to_parent()
  376. eB = eD.to_ancestor(B)
  377. eA = eD.over_power_basis()
  378. assert eC.module is C and eC.coeffs == [5, 0, 0, 0]
  379. assert eB.module is B and eB.coeffs == [15, 0, 0, 0]
  380. assert eA.module is A and eA.coeffs == [30, 0, 0, 0]
  381. a = A(0)
  382. raises(ValueError, lambda: a.to_parent())
  383. def test_ModuleElement_compatibility():
  384. T = Poly(cyclotomic_poly(5, x))
  385. A = PowerBasis(T)
  386. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  387. C = B.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  388. D = B.submodule_from_matrix(5 * DomainMatrix.eye(4, ZZ))
  389. assert C(0).is_compat(C(1)) is True
  390. assert C(0).is_compat(D(0)) is False
  391. u, v = C(0).unify(D(0))
  392. assert u.module is B and v.module is B
  393. assert C(C.represent(u)) == C(0) and D(D.represent(v)) == D(0)
  394. u, v = C(0).unify(C(1))
  395. assert u == C(0) and v == C(1)
  396. U = Poly(cyclotomic_poly(7, x))
  397. Z = PowerBasis(U)
  398. raises(UnificationFailed, lambda: C(0).unify(Z(1)))
  399. def test_ModuleElement_eq():
  400. T = Poly(cyclotomic_poly(5, x))
  401. A = PowerBasis(T)
  402. e = A(to_col([1, 2, 3, 4]), denom=1)
  403. f = A(to_col([3, 6, 9, 12]), denom=3)
  404. assert e == f
  405. U = Poly(cyclotomic_poly(7, x))
  406. Z = PowerBasis(U)
  407. assert e != Z(0)
  408. assert e != 3.14
  409. def test_ModuleElement_equiv():
  410. T = Poly(cyclotomic_poly(5, x))
  411. A = PowerBasis(T)
  412. e = A(to_col([1, 2, 3, 4]), denom=1)
  413. f = A(to_col([3, 6, 9, 12]), denom=3)
  414. assert e.equiv(f)
  415. C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  416. g = C(to_col([1, 2, 3, 4]), denom=1)
  417. h = A(to_col([3, 6, 9, 12]), denom=1)
  418. assert g.equiv(h)
  419. assert C(to_col([5, 0, 0, 0]), denom=7).equiv(QQ(15, 7))
  420. U = Poly(cyclotomic_poly(7, x))
  421. Z = PowerBasis(U)
  422. raises(UnificationFailed, lambda: e.equiv(Z(0)))
  423. assert e.equiv(3.14) is False
  424. def test_ModuleElement_add():
  425. T = Poly(cyclotomic_poly(5, x))
  426. A = PowerBasis(T)
  427. C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  428. e = A(to_col([1, 2, 3, 4]), denom=6)
  429. f = A(to_col([5, 6, 7, 8]), denom=10)
  430. g = C(to_col([1, 1, 1, 1]), denom=2)
  431. assert e + f == A(to_col([10, 14, 18, 22]), denom=15)
  432. assert e - f == A(to_col([-5, -4, -3, -2]), denom=15)
  433. assert e + g == A(to_col([10, 11, 12, 13]), denom=6)
  434. assert e + QQ(7, 10) == A(to_col([26, 10, 15, 20]), denom=30)
  435. assert g + QQ(7, 10) == A(to_col([22, 15, 15, 15]), denom=10)
  436. U = Poly(cyclotomic_poly(7, x))
  437. Z = PowerBasis(U)
  438. raises(TypeError, lambda: e + Z(0))
  439. raises(TypeError, lambda: e + 3.14)
  440. def test_ModuleElement_mul():
  441. T = Poly(cyclotomic_poly(5, x))
  442. A = PowerBasis(T)
  443. C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  444. e = A(to_col([0, 2, 0, 0]), denom=3)
  445. f = A(to_col([0, 0, 0, 7]), denom=5)
  446. g = C(to_col([0, 0, 0, 1]), denom=2)
  447. h = A(to_col([0, 0, 3, 1]), denom=7)
  448. assert e * f == A(to_col([-14, -14, -14, -14]), denom=15)
  449. assert e * g == A(to_col([-1, -1, -1, -1]))
  450. assert e * h == A(to_col([-2, -2, -2, 4]), denom=21)
  451. assert e * QQ(6, 5) == A(to_col([0, 4, 0, 0]), denom=5)
  452. assert (g * QQ(10, 21)).equiv(A(to_col([0, 0, 0, 5]), denom=7))
  453. assert e // QQ(6, 5) == A(to_col([0, 5, 0, 0]), denom=9)
  454. U = Poly(cyclotomic_poly(7, x))
  455. Z = PowerBasis(U)
  456. raises(TypeError, lambda: e * Z(0))
  457. raises(TypeError, lambda: e * 3.14)
  458. raises(TypeError, lambda: e // 3.14)
  459. raises(ZeroDivisionError, lambda: e // 0)
  460. def test_ModuleElement_div():
  461. T = Poly(cyclotomic_poly(5, x))
  462. A = PowerBasis(T)
  463. C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  464. e = A(to_col([0, 2, 0, 0]), denom=3)
  465. f = A(to_col([0, 0, 0, 7]), denom=5)
  466. g = C(to_col([1, 1, 1, 1]))
  467. assert e // f == 10*A(3)//21
  468. assert e // g == -2*A(2)//9
  469. assert 3 // g == -A(1)
  470. def test_ModuleElement_pow():
  471. T = Poly(cyclotomic_poly(5, x))
  472. A = PowerBasis(T)
  473. C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
  474. e = A(to_col([0, 2, 0, 0]), denom=3)
  475. g = C(to_col([0, 0, 0, 1]), denom=2)
  476. assert e ** 3 == A(to_col([0, 0, 0, 8]), denom=27)
  477. assert g ** 2 == C(to_col([0, 3, 0, 0]), denom=4)
  478. assert e ** 0 == A(to_col([1, 0, 0, 0]))
  479. assert g ** 0 == A(to_col([1, 0, 0, 0]))
  480. assert e ** 1 == e
  481. assert g ** 1 == g
  482. def test_ModuleElement_mod():
  483. T = Poly(cyclotomic_poly(5, x))
  484. A = PowerBasis(T)
  485. e = A(to_col([1, 15, 8, 0]), denom=2)
  486. assert e % 7 == A(to_col([1, 1, 8, 0]), denom=2)
  487. raises(TypeError, lambda: e % QQ(1, 2))
  488. def test_PowerBasisElement_polys():
  489. T = Poly(cyclotomic_poly(5, x))
  490. A = PowerBasis(T)
  491. e = A(to_col([1, 15, 8, 0]), denom=2)
  492. assert e.numerator(x=zeta) == Poly(8 * zeta ** 2 + 15 * zeta + 1, domain=ZZ)
  493. assert e.poly(x=zeta) == Poly(4 * zeta ** 2 + QQ(15, 2) * zeta + QQ(1, 2), domain=QQ)
  494. def test_PowerBasisElement_norm():
  495. T = Poly(cyclotomic_poly(5, x))
  496. A = PowerBasis(T)
  497. lam = A(to_col([1, -1, 0, 0]))
  498. assert lam.norm() == 5
  499. def test_PowerBasisElement_inverse():
  500. T = Poly(cyclotomic_poly(5, x))
  501. A = PowerBasis(T)
  502. e = A(to_col([1, 1, 1, 1]))
  503. assert 2 // e == -2*A(1)
  504. assert e ** -3 == -A(3)
  505. def test_ModuleHomomorphism_matrix():
  506. T = Poly(cyclotomic_poly(5, x))
  507. A = PowerBasis(T)
  508. phi = ModuleEndomorphism(A, lambda a: a ** 2)
  509. M = phi.matrix()
  510. assert M == DomainMatrix([
  511. [1, 0, -1, 0],
  512. [0, 0, -1, 1],
  513. [0, 1, -1, 0],
  514. [0, 0, -1, 0]
  515. ], (4, 4), ZZ)
  516. def test_ModuleHomomorphism_kernel():
  517. T = Poly(cyclotomic_poly(5, x))
  518. A = PowerBasis(T)
  519. phi = ModuleEndomorphism(A, lambda a: a ** 5)
  520. N = phi.kernel()
  521. assert N.n == 3
  522. def test_EndomorphismRing_represent():
  523. T = Poly(cyclotomic_poly(5, x))
  524. A = PowerBasis(T)
  525. R = A.endomorphism_ring()
  526. phi = R.inner_endomorphism(A(1))
  527. col = R.represent(phi)
  528. assert col.transpose() == DomainMatrix([
  529. [0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -1, -1, -1, -1]
  530. ], (1, 16), ZZ)
  531. B = A.submodule_from_matrix(DomainMatrix.zeros((4, 0), ZZ))
  532. S = B.endomorphism_ring()
  533. psi = S.inner_endomorphism(A(1))
  534. col = S.represent(psi)
  535. assert col == DomainMatrix([], (0, 0), ZZ)
  536. raises(NotImplementedError, lambda: R.represent(3.14))
  537. def test_find_min_poly():
  538. T = Poly(cyclotomic_poly(5, x))
  539. A = PowerBasis(T)
  540. powers = []
  541. m = find_min_poly(A(1), QQ, x=x, powers=powers)
  542. assert m == Poly(T, domain=QQ)
  543. assert len(powers) == 5
  544. # powers list need not be passed
  545. m = find_min_poly(A(1), QQ, x=x)
  546. assert m == Poly(T, domain=QQ)
  547. B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
  548. raises(MissingUnityError, lambda: find_min_poly(B(1), QQ))