图片解析应用
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.

345 lines
9.3 KiB

  1. from sympy.testing.pytest import raises
  2. from sympy.polys import ZZ, QQ
  3. from sympy.polys.matrices.ddm import DDM
  4. from sympy.polys.matrices.dense import (
  5. ddm_transpose,
  6. ddm_iadd, ddm_isub, ddm_ineg, ddm_imatmul, ddm_imul, ddm_irref,
  7. ddm_idet, ddm_iinv, ddm_ilu, ddm_ilu_split, ddm_ilu_solve, ddm_berk)
  8. from sympy.polys.matrices.exceptions import (
  9. DMShapeError, DMNonInvertibleMatrixError, DMNonSquareMatrixError)
  10. def test_ddm_transpose():
  11. a = [[1, 2], [3, 4]]
  12. assert ddm_transpose(a) == [[1, 3], [2, 4]]
  13. def test_ddm_iadd():
  14. a = [[1, 2], [3, 4]]
  15. b = [[5, 6], [7, 8]]
  16. ddm_iadd(a, b)
  17. assert a == [[6, 8], [10, 12]]
  18. def test_ddm_isub():
  19. a = [[1, 2], [3, 4]]
  20. b = [[5, 6], [7, 8]]
  21. ddm_isub(a, b)
  22. assert a == [[-4, -4], [-4, -4]]
  23. def test_ddm_ineg():
  24. a = [[1, 2], [3, 4]]
  25. ddm_ineg(a)
  26. assert a == [[-1, -2], [-3, -4]]
  27. def test_ddm_matmul():
  28. a = [[1, 2], [3, 4]]
  29. ddm_imul(a, 2)
  30. assert a == [[2, 4], [6, 8]]
  31. a = [[1, 2], [3, 4]]
  32. ddm_imul(a, 0)
  33. assert a == [[0, 0], [0, 0]]
  34. def test_ddm_imatmul():
  35. a = [[1, 2, 3], [4, 5, 6]]
  36. b = [[1, 2], [3, 4], [5, 6]]
  37. c1 = [[0, 0], [0, 0]]
  38. ddm_imatmul(c1, a, b)
  39. assert c1 == [[22, 28], [49, 64]]
  40. c2 = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
  41. ddm_imatmul(c2, b, a)
  42. assert c2 == [[9, 12, 15], [19, 26, 33], [29, 40, 51]]
  43. b3 = [[1], [2], [3]]
  44. c3 = [[0], [0]]
  45. ddm_imatmul(c3, a, b3)
  46. assert c3 == [[14], [32]]
  47. def test_ddm_irref():
  48. # Empty matrix
  49. A = []
  50. Ar = []
  51. pivots = []
  52. assert ddm_irref(A) == pivots
  53. assert A == Ar
  54. # Standard square case
  55. A = [[QQ(0), QQ(1)], [QQ(1), QQ(1)]]
  56. Ar = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]]
  57. pivots = [0, 1]
  58. assert ddm_irref(A) == pivots
  59. assert A == Ar
  60. # m < n case
  61. A = [[QQ(1), QQ(2), QQ(1)], [QQ(3), QQ(4), QQ(1)]]
  62. Ar = [[QQ(1), QQ(0), QQ(-1)], [QQ(0), QQ(1), QQ(1)]]
  63. pivots = [0, 1]
  64. assert ddm_irref(A) == pivots
  65. assert A == Ar
  66. # same m < n but reversed
  67. A = [[QQ(3), QQ(4), QQ(1)], [QQ(1), QQ(2), QQ(1)]]
  68. Ar = [[QQ(1), QQ(0), QQ(-1)], [QQ(0), QQ(1), QQ(1)]]
  69. pivots = [0, 1]
  70. assert ddm_irref(A) == pivots
  71. assert A == Ar
  72. # m > n case
  73. A = [[QQ(1), QQ(0)], [QQ(1), QQ(3)], [QQ(0), QQ(1)]]
  74. Ar = [[QQ(1), QQ(0)], [QQ(0), QQ(1)], [QQ(0), QQ(0)]]
  75. pivots = [0, 1]
  76. assert ddm_irref(A) == pivots
  77. assert A == Ar
  78. # Example with missing pivot
  79. A = [[QQ(1), QQ(0), QQ(1)], [QQ(3), QQ(0), QQ(1)]]
  80. Ar = [[QQ(1), QQ(0), QQ(0)], [QQ(0), QQ(0), QQ(1)]]
  81. pivots = [0, 2]
  82. assert ddm_irref(A) == pivots
  83. assert A == Ar
  84. # Example with missing pivot and no replacement
  85. A = [[QQ(0), QQ(1)], [QQ(0), QQ(2)], [QQ(1), QQ(0)]]
  86. Ar = [[QQ(1), QQ(0)], [QQ(0), QQ(1)], [QQ(0), QQ(0)]]
  87. pivots = [0, 1]
  88. assert ddm_irref(A) == pivots
  89. assert A == Ar
  90. def test_ddm_idet():
  91. A = []
  92. assert ddm_idet(A, ZZ) == ZZ(1)
  93. A = [[ZZ(2)]]
  94. assert ddm_idet(A, ZZ) == ZZ(2)
  95. A = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]]
  96. assert ddm_idet(A, ZZ) == ZZ(-2)
  97. A = [[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(3), ZZ(5)]]
  98. assert ddm_idet(A, ZZ) == ZZ(-1)
  99. A = [[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(2), ZZ(5)]]
  100. assert ddm_idet(A, ZZ) == ZZ(0)
  101. A = [[QQ(1, 2), QQ(1, 2)], [QQ(1, 3), QQ(1, 4)]]
  102. assert ddm_idet(A, QQ) == QQ(-1, 24)
  103. def test_ddm_inv():
  104. A = []
  105. Ainv = []
  106. ddm_iinv(Ainv, A, QQ)
  107. assert Ainv == A
  108. A = []
  109. Ainv = []
  110. raises(ValueError, lambda: ddm_iinv(Ainv, A, ZZ))
  111. A = [[QQ(1), QQ(2)]]
  112. Ainv = [[QQ(0), QQ(0)]]
  113. raises(DMNonSquareMatrixError, lambda: ddm_iinv(Ainv, A, QQ))
  114. A = [[QQ(1, 1), QQ(2, 1)], [QQ(3, 1), QQ(4, 1)]]
  115. Ainv = [[QQ(0), QQ(0)], [QQ(0), QQ(0)]]
  116. Ainv_expected = [[QQ(-2, 1), QQ(1, 1)], [QQ(3, 2), QQ(-1, 2)]]
  117. ddm_iinv(Ainv, A, QQ)
  118. assert Ainv == Ainv_expected
  119. A = [[QQ(1, 1), QQ(2, 1)], [QQ(2, 1), QQ(4, 1)]]
  120. Ainv = [[QQ(0), QQ(0)], [QQ(0), QQ(0)]]
  121. raises(DMNonInvertibleMatrixError, lambda: ddm_iinv(Ainv, A, QQ))
  122. def test_ddm_ilu():
  123. A = []
  124. Alu = []
  125. swaps = ddm_ilu(A)
  126. assert A == Alu
  127. assert swaps == []
  128. A = [[]]
  129. Alu = [[]]
  130. swaps = ddm_ilu(A)
  131. assert A == Alu
  132. assert swaps == []
  133. A = [[QQ(1), QQ(2)], [QQ(3), QQ(4)]]
  134. Alu = [[QQ(1), QQ(2)], [QQ(3), QQ(-2)]]
  135. swaps = ddm_ilu(A)
  136. assert A == Alu
  137. assert swaps == []
  138. A = [[QQ(0), QQ(2)], [QQ(3), QQ(4)]]
  139. Alu = [[QQ(3), QQ(4)], [QQ(0), QQ(2)]]
  140. swaps = ddm_ilu(A)
  141. assert A == Alu
  142. assert swaps == [(0, 1)]
  143. A = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)], [QQ(7), QQ(8), QQ(9)]]
  144. Alu = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(-3), QQ(-6)], [QQ(7), QQ(2), QQ(0)]]
  145. swaps = ddm_ilu(A)
  146. assert A == Alu
  147. assert swaps == []
  148. A = [[QQ(0), QQ(1), QQ(2)], [QQ(0), QQ(1), QQ(3)], [QQ(1), QQ(1), QQ(2)]]
  149. Alu = [[QQ(1), QQ(1), QQ(2)], [QQ(0), QQ(1), QQ(3)], [QQ(0), QQ(1), QQ(-1)]]
  150. swaps = ddm_ilu(A)
  151. assert A == Alu
  152. assert swaps == [(0, 2)]
  153. A = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)]]
  154. Alu = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(-3), QQ(-6)]]
  155. swaps = ddm_ilu(A)
  156. assert A == Alu
  157. assert swaps == []
  158. A = [[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]]
  159. Alu = [[QQ(1), QQ(2)], [QQ(3), QQ(-2)], [QQ(5), QQ(2)]]
  160. swaps = ddm_ilu(A)
  161. assert A == Alu
  162. assert swaps == []
  163. def test_ddm_ilu_split():
  164. U = []
  165. L = []
  166. Uexp = []
  167. Lexp = []
  168. swaps = ddm_ilu_split(L, U, QQ)
  169. assert U == Uexp
  170. assert L == Lexp
  171. assert swaps == []
  172. U = [[]]
  173. L = [[QQ(1)]]
  174. Uexp = [[]]
  175. Lexp = [[QQ(1)]]
  176. swaps = ddm_ilu_split(L, U, QQ)
  177. assert U == Uexp
  178. assert L == Lexp
  179. assert swaps == []
  180. U = [[QQ(1), QQ(2)], [QQ(3), QQ(4)]]
  181. L = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]]
  182. Uexp = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)]]
  183. Lexp = [[QQ(1), QQ(0)], [QQ(3), QQ(1)]]
  184. swaps = ddm_ilu_split(L, U, QQ)
  185. assert U == Uexp
  186. assert L == Lexp
  187. assert swaps == []
  188. U = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)]]
  189. L = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]]
  190. Uexp = [[QQ(1), QQ(2), QQ(3)], [QQ(0), QQ(-3), QQ(-6)]]
  191. Lexp = [[QQ(1), QQ(0)], [QQ(4), QQ(1)]]
  192. swaps = ddm_ilu_split(L, U, QQ)
  193. assert U == Uexp
  194. assert L == Lexp
  195. assert swaps == []
  196. U = [[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]]
  197. L = [[QQ(1), QQ(0), QQ(0)], [QQ(0), QQ(1), QQ(0)], [QQ(0), QQ(0), QQ(1)]]
  198. Uexp = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)], [QQ(0), QQ(0)]]
  199. Lexp = [[QQ(1), QQ(0), QQ(0)], [QQ(3), QQ(1), QQ(0)], [QQ(5), QQ(2), QQ(1)]]
  200. swaps = ddm_ilu_split(L, U, QQ)
  201. assert U == Uexp
  202. assert L == Lexp
  203. assert swaps == []
  204. def test_ddm_ilu_solve():
  205. # Basic example
  206. # A = [[QQ(1), QQ(2)], [QQ(3), QQ(4)]]
  207. U = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)]]
  208. L = [[QQ(1), QQ(0)], [QQ(3), QQ(1)]]
  209. swaps = []
  210. b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ)
  211. x = DDM([[QQ(0)], [QQ(0)]], (2, 1), QQ)
  212. xexp = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ)
  213. ddm_ilu_solve(x, L, U, swaps, b)
  214. assert x == xexp
  215. # Example with swaps
  216. # A = [[QQ(0), QQ(2)], [QQ(3), QQ(4)]]
  217. U = [[QQ(3), QQ(4)], [QQ(0), QQ(2)]]
  218. L = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]]
  219. swaps = [(0, 1)]
  220. b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ)
  221. x = DDM([[QQ(0)], [QQ(0)]], (2, 1), QQ)
  222. xexp = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ)
  223. ddm_ilu_solve(x, L, U, swaps, b)
  224. assert x == xexp
  225. # Overdetermined, consistent
  226. # A = DDM([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ)
  227. U = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)], [QQ(0), QQ(0)]]
  228. L = [[QQ(1), QQ(0), QQ(0)], [QQ(3), QQ(1), QQ(0)], [QQ(5), QQ(2), QQ(1)]]
  229. swaps = []
  230. b = DDM([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ)
  231. x = DDM([[QQ(0)], [QQ(0)]], (2, 1), QQ)
  232. xexp = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ)
  233. ddm_ilu_solve(x, L, U, swaps, b)
  234. assert x == xexp
  235. # Overdetermined, inconsistent
  236. b = DDM([[QQ(1)], [QQ(2)], [QQ(4)]], (3, 1), QQ)
  237. raises(DMNonInvertibleMatrixError, lambda: ddm_ilu_solve(x, L, U, swaps, b))
  238. # Square, noninvertible
  239. # A = DDM([[QQ(1), QQ(2)], [QQ(1), QQ(2)]], (2, 2), QQ)
  240. U = [[QQ(1), QQ(2)], [QQ(0), QQ(0)]]
  241. L = [[QQ(1), QQ(0)], [QQ(1), QQ(1)]]
  242. swaps = []
  243. b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ)
  244. raises(DMNonInvertibleMatrixError, lambda: ddm_ilu_solve(x, L, U, swaps, b))
  245. # Underdetermined
  246. # A = DDM([[QQ(1), QQ(2)]], (1, 2), QQ)
  247. U = [[QQ(1), QQ(2)]]
  248. L = [[QQ(1)]]
  249. swaps = []
  250. b = DDM([[QQ(3)]], (1, 1), QQ)
  251. raises(NotImplementedError, lambda: ddm_ilu_solve(x, L, U, swaps, b))
  252. # Shape mismatch
  253. b3 = DDM([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ)
  254. raises(DMShapeError, lambda: ddm_ilu_solve(x, L, U, swaps, b3))
  255. # Empty shape mismatch
  256. U = [[QQ(1)]]
  257. L = [[QQ(1)]]
  258. swaps = []
  259. x = [[QQ(1)]]
  260. b = []
  261. raises(DMShapeError, lambda: ddm_ilu_solve(x, L, U, swaps, b))
  262. # Empty system
  263. U = []
  264. L = []
  265. swaps = []
  266. b = []
  267. x = []
  268. ddm_ilu_solve(x, L, U, swaps, b)
  269. assert x == []
  270. def test_ddm_charpoly():
  271. A = []
  272. assert ddm_berk(A, ZZ) == [[ZZ(1)]]
  273. A = [[ZZ(1), ZZ(2), ZZ(3)], [ZZ(4), ZZ(5), ZZ(6)], [ZZ(7), ZZ(8), ZZ(9)]]
  274. Avec = [[ZZ(1)], [ZZ(-15)], [ZZ(-18)], [ZZ(0)]]
  275. assert ddm_berk(A, ZZ) == Avec
  276. A = DDM([[ZZ(1), ZZ(2)]], (1, 2), ZZ)
  277. raises(DMShapeError, lambda: ddm_berk(A, ZZ))