test_numpy.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. from sympy.concrete.summations import Sum
  2. from sympy.core.mod import Mod
  3. from sympy.core.relational import (Equality, Unequality)
  4. from sympy.core.symbol import Symbol
  5. from sympy.functions.elementary.miscellaneous import sqrt
  6. from sympy.functions.elementary.piecewise import Piecewise
  7. from sympy.functions.special.gamma_functions import polygamma
  8. from sympy.functions.special.error_functions import (Si, Ci)
  9. from sympy.matrices import Matrix
  10. from sympy.matrices.expressions.blockmatrix import BlockMatrix
  11. from sympy.matrices.expressions.matexpr import MatrixSymbol
  12. from sympy.matrices.expressions.special import Identity
  13. from sympy.utilities.lambdify import lambdify
  14. from sympy import symbols, Min, Max
  15. from sympy.abc import x, i, j, a, b, c, d
  16. from sympy.core import Pow
  17. from sympy.codegen.matrix_nodes import MatrixSolve
  18. from sympy.codegen.numpy_nodes import logaddexp, logaddexp2
  19. from sympy.codegen.cfunctions import log1p, expm1, hypot, log10, exp2, log2, Sqrt
  20. from sympy.tensor.array import Array
  21. from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct, ArrayAdd, \
  22. PermuteDims, ArrayDiagonal
  23. from sympy.printing.numpy import NumPyPrinter, SciPyPrinter, _numpy_known_constants, \
  24. _numpy_known_functions, _scipy_known_constants, _scipy_known_functions
  25. from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array
  26. from sympy.testing.pytest import skip, raises
  27. from sympy.external import import_module
  28. np = import_module('numpy')
  29. jax = import_module('jax')
  30. if np:
  31. deafult_float_info = np.finfo(np.array([]).dtype)
  32. NUMPY_DEFAULT_EPSILON = deafult_float_info.eps
  33. def test_numpy_piecewise_regression():
  34. """
  35. NumPyPrinter needs to print Piecewise()'s choicelist as a list to avoid
  36. breaking compatibility with numpy 1.8. This is not necessary in numpy 1.9+.
  37. See gh-9747 and gh-9749 for details.
  38. """
  39. printer = NumPyPrinter()
  40. p = Piecewise((1, x < 0), (0, True))
  41. assert printer.doprint(p) == \
  42. 'numpy.select([numpy.less(x, 0),True], [1,0], default=numpy.nan)'
  43. assert printer.module_imports == {'numpy': {'select', 'less', 'nan'}}
  44. def test_numpy_logaddexp():
  45. lae = logaddexp(a, b)
  46. assert NumPyPrinter().doprint(lae) == 'numpy.logaddexp(a, b)'
  47. lae2 = logaddexp2(a, b)
  48. assert NumPyPrinter().doprint(lae2) == 'numpy.logaddexp2(a, b)'
  49. def test_sum():
  50. if not np:
  51. skip("NumPy not installed")
  52. s = Sum(x ** i, (i, a, b))
  53. f = lambdify((a, b, x), s, 'numpy')
  54. a_, b_ = 0, 10
  55. x_ = np.linspace(-1, +1, 10)
  56. assert np.allclose(f(a_, b_, x_), sum(x_ ** i_ for i_ in range(a_, b_ + 1)))
  57. s = Sum(i * x, (i, a, b))
  58. f = lambdify((a, b, x), s, 'numpy')
  59. a_, b_ = 0, 10
  60. x_ = np.linspace(-1, +1, 10)
  61. assert np.allclose(f(a_, b_, x_), sum(i_ * x_ for i_ in range(a_, b_ + 1)))
  62. def test_multiple_sums():
  63. if not np:
  64. skip("NumPy not installed")
  65. s = Sum((x + j) * i, (i, a, b), (j, c, d))
  66. f = lambdify((a, b, c, d, x), s, 'numpy')
  67. a_, b_ = 0, 10
  68. c_, d_ = 11, 21
  69. x_ = np.linspace(-1, +1, 10)
  70. assert np.allclose(f(a_, b_, c_, d_, x_),
  71. sum((x_ + j_) * i_ for i_ in range(a_, b_ + 1) for j_ in range(c_, d_ + 1)))
  72. def test_codegen_einsum():
  73. if not np:
  74. skip("NumPy not installed")
  75. M = MatrixSymbol("M", 2, 2)
  76. N = MatrixSymbol("N", 2, 2)
  77. cg = convert_matrix_to_array(M * N)
  78. f = lambdify((M, N), cg, 'numpy')
  79. ma = np.array([[1, 2], [3, 4]])
  80. mb = np.array([[1,-2], [-1, 3]])
  81. assert (f(ma, mb) == np.matmul(ma, mb)).all()
  82. def test_codegen_extra():
  83. if not np:
  84. skip("NumPy not installed")
  85. M = MatrixSymbol("M", 2, 2)
  86. N = MatrixSymbol("N", 2, 2)
  87. P = MatrixSymbol("P", 2, 2)
  88. Q = MatrixSymbol("Q", 2, 2)
  89. ma = np.array([[1, 2], [3, 4]])
  90. mb = np.array([[1,-2], [-1, 3]])
  91. mc = np.array([[2, 0], [1, 2]])
  92. md = np.array([[1,-1], [4, 7]])
  93. cg = ArrayTensorProduct(M, N)
  94. f = lambdify((M, N), cg, 'numpy')
  95. assert (f(ma, mb) == np.einsum(ma, [0, 1], mb, [2, 3])).all()
  96. cg = ArrayAdd(M, N)
  97. f = lambdify((M, N), cg, 'numpy')
  98. assert (f(ma, mb) == ma+mb).all()
  99. cg = ArrayAdd(M, N, P)
  100. f = lambdify((M, N, P), cg, 'numpy')
  101. assert (f(ma, mb, mc) == ma+mb+mc).all()
  102. cg = ArrayAdd(M, N, P, Q)
  103. f = lambdify((M, N, P, Q), cg, 'numpy')
  104. assert (f(ma, mb, mc, md) == ma+mb+mc+md).all()
  105. cg = PermuteDims(M, [1, 0])
  106. f = lambdify((M,), cg, 'numpy')
  107. assert (f(ma) == ma.T).all()
  108. cg = PermuteDims(ArrayTensorProduct(M, N), [1, 2, 3, 0])
  109. f = lambdify((M, N), cg, 'numpy')
  110. assert (f(ma, mb) == np.transpose(np.einsum(ma, [0, 1], mb, [2, 3]), (1, 2, 3, 0))).all()
  111. cg = ArrayDiagonal(ArrayTensorProduct(M, N), (1, 2))
  112. f = lambdify((M, N), cg, 'numpy')
  113. assert (f(ma, mb) == np.diagonal(np.einsum(ma, [0, 1], mb, [2, 3]), axis1=1, axis2=2)).all()
  114. def test_relational():
  115. if not np:
  116. skip("NumPy not installed")
  117. e = Equality(x, 1)
  118. f = lambdify((x,), e)
  119. x_ = np.array([0, 1, 2])
  120. assert np.array_equal(f(x_), [False, True, False])
  121. e = Unequality(x, 1)
  122. f = lambdify((x,), e)
  123. x_ = np.array([0, 1, 2])
  124. assert np.array_equal(f(x_), [True, False, True])
  125. e = (x < 1)
  126. f = lambdify((x,), e)
  127. x_ = np.array([0, 1, 2])
  128. assert np.array_equal(f(x_), [True, False, False])
  129. e = (x <= 1)
  130. f = lambdify((x,), e)
  131. x_ = np.array([0, 1, 2])
  132. assert np.array_equal(f(x_), [True, True, False])
  133. e = (x > 1)
  134. f = lambdify((x,), e)
  135. x_ = np.array([0, 1, 2])
  136. assert np.array_equal(f(x_), [False, False, True])
  137. e = (x >= 1)
  138. f = lambdify((x,), e)
  139. x_ = np.array([0, 1, 2])
  140. assert np.array_equal(f(x_), [False, True, True])
  141. def test_mod():
  142. if not np:
  143. skip("NumPy not installed")
  144. e = Mod(a, b)
  145. f = lambdify((a, b), e)
  146. a_ = np.array([0, 1, 2, 3])
  147. b_ = 2
  148. assert np.array_equal(f(a_, b_), [0, 1, 0, 1])
  149. a_ = np.array([0, 1, 2, 3])
  150. b_ = np.array([2, 2, 2, 2])
  151. assert np.array_equal(f(a_, b_), [0, 1, 0, 1])
  152. a_ = np.array([2, 3, 4, 5])
  153. b_ = np.array([2, 3, 4, 5])
  154. assert np.array_equal(f(a_, b_), [0, 0, 0, 0])
  155. def test_pow():
  156. if not np:
  157. skip('NumPy not installed')
  158. expr = Pow(2, -1, evaluate=False)
  159. f = lambdify([], expr, 'numpy')
  160. assert f() == 0.5
  161. def test_expm1():
  162. if not np:
  163. skip("NumPy not installed")
  164. f = lambdify((a,), expm1(a), 'numpy')
  165. assert abs(f(1e-10) - 1e-10 - 5e-21) <= 1e-10 * NUMPY_DEFAULT_EPSILON
  166. def test_log1p():
  167. if not np:
  168. skip("NumPy not installed")
  169. f = lambdify((a,), log1p(a), 'numpy')
  170. assert abs(f(1e-99) - 1e-99) <= 1e-99 * NUMPY_DEFAULT_EPSILON
  171. def test_hypot():
  172. if not np:
  173. skip("NumPy not installed")
  174. assert abs(lambdify((a, b), hypot(a, b), 'numpy')(3, 4) - 5) <= NUMPY_DEFAULT_EPSILON
  175. def test_log10():
  176. if not np:
  177. skip("NumPy not installed")
  178. assert abs(lambdify((a,), log10(a), 'numpy')(100) - 2) <= NUMPY_DEFAULT_EPSILON
  179. def test_exp2():
  180. if not np:
  181. skip("NumPy not installed")
  182. assert abs(lambdify((a,), exp2(a), 'numpy')(5) - 32) <= NUMPY_DEFAULT_EPSILON
  183. def test_log2():
  184. if not np:
  185. skip("NumPy not installed")
  186. assert abs(lambdify((a,), log2(a), 'numpy')(256) - 8) <= NUMPY_DEFAULT_EPSILON
  187. def test_Sqrt():
  188. if not np:
  189. skip("NumPy not installed")
  190. assert abs(lambdify((a,), Sqrt(a), 'numpy')(4) - 2) <= NUMPY_DEFAULT_EPSILON
  191. def test_sqrt():
  192. if not np:
  193. skip("NumPy not installed")
  194. assert abs(lambdify((a,), sqrt(a), 'numpy')(4) - 2) <= NUMPY_DEFAULT_EPSILON
  195. def test_matsolve():
  196. if not np:
  197. skip("NumPy not installed")
  198. M = MatrixSymbol("M", 3, 3)
  199. x = MatrixSymbol("x", 3, 1)
  200. expr = M**(-1) * x + x
  201. matsolve_expr = MatrixSolve(M, x) + x
  202. f = lambdify((M, x), expr)
  203. f_matsolve = lambdify((M, x), matsolve_expr)
  204. m0 = np.array([[1, 2, 3], [3, 2, 5], [5, 6, 7]])
  205. assert np.linalg.matrix_rank(m0) == 3
  206. x0 = np.array([3, 4, 5])
  207. assert np.allclose(f_matsolve(m0, x0), f(m0, x0))
  208. def test_16857():
  209. if not np:
  210. skip("NumPy not installed")
  211. a_1 = MatrixSymbol('a_1', 10, 3)
  212. a_2 = MatrixSymbol('a_2', 10, 3)
  213. a_3 = MatrixSymbol('a_3', 10, 3)
  214. a_4 = MatrixSymbol('a_4', 10, 3)
  215. A = BlockMatrix([[a_1, a_2], [a_3, a_4]])
  216. assert A.shape == (20, 6)
  217. printer = NumPyPrinter()
  218. assert printer.doprint(A) == 'numpy.block([[a_1, a_2], [a_3, a_4]])'
  219. def test_issue_17006():
  220. if not np:
  221. skip("NumPy not installed")
  222. M = MatrixSymbol("M", 2, 2)
  223. f = lambdify(M, M + Identity(2))
  224. ma = np.array([[1, 2], [3, 4]])
  225. mr = np.array([[2, 2], [3, 5]])
  226. assert (f(ma) == mr).all()
  227. from sympy.core.symbol import symbols
  228. n = symbols('n', integer=True)
  229. N = MatrixSymbol("M", n, n)
  230. raises(NotImplementedError, lambda: lambdify(N, N + Identity(n)))
  231. def test_jax_tuple_compatibility():
  232. if not jax:
  233. skip("Jax not installed")
  234. x, y, z = symbols('x y z')
  235. expr = Max(x, y, z) + Min(x, y, z)
  236. func = lambdify((x, y, z), expr, 'jax')
  237. input_tuple1, input_tuple2 = (1, 2, 3), (4, 5, 6)
  238. input_array1, input_array2 = jax.numpy.asarray(input_tuple1), jax.numpy.asarray(input_tuple2)
  239. assert np.allclose(func(*input_tuple1), func(*input_array1))
  240. assert np.allclose(func(*input_tuple2), func(*input_array2))
  241. def test_numpy_array():
  242. p = NumPyPrinter()
  243. assert p.doprint(Array([[1, 2], [3, 5]])) == 'numpy.array([[1, 2], [3, 5]])'
  244. assert p.doprint(Array([1, 2])) == 'numpy.array([1, 2])'
  245. assert p.doprint(Array([[[1, 2, 3]]])) == 'numpy.array([[[1, 2, 3]]])'
  246. assert p.doprint(Array([], (0,))) == 'numpy.zeros((0,))'
  247. assert p.doprint(Array([], (0, 0))) == 'numpy.zeros((0, 0))'
  248. assert p.doprint(Array([], (0, 1))) == 'numpy.zeros((0, 1))'
  249. assert p.doprint(Array([], (1, 0))) == 'numpy.zeros((1, 0))'
  250. assert p.doprint(Array([1], ())) == 'numpy.array(1)'
  251. def test_numpy_matrix():
  252. p = NumPyPrinter()
  253. assert p.doprint(Matrix([[1, 2], [3, 5]])) == 'numpy.array([[1, 2], [3, 5]])'
  254. assert p.doprint(Matrix([1, 2])) == 'numpy.array([[1], [2]])'
  255. assert p.doprint(Matrix(0, 0, [])) == 'numpy.zeros((0, 0))'
  256. assert p.doprint(Matrix(0, 1, [])) == 'numpy.zeros((0, 1))'
  257. assert p.doprint(Matrix(1, 0, [])) == 'numpy.zeros((1, 0))'
  258. def test_numpy_known_funcs_consts():
  259. assert _numpy_known_constants['NaN'] == 'numpy.nan'
  260. assert _numpy_known_constants['EulerGamma'] == 'numpy.euler_gamma'
  261. assert _numpy_known_functions['acos'] == 'numpy.arccos'
  262. assert _numpy_known_functions['log'] == 'numpy.log'
  263. def test_scipy_known_funcs_consts():
  264. assert _scipy_known_constants['GoldenRatio'] == 'scipy.constants.golden_ratio'
  265. assert _scipy_known_constants['Pi'] == 'scipy.constants.pi'
  266. assert _scipy_known_functions['erf'] == 'scipy.special.erf'
  267. assert _scipy_known_functions['factorial'] == 'scipy.special.factorial'
  268. def test_numpy_print_methods():
  269. prntr = NumPyPrinter()
  270. assert hasattr(prntr, '_print_acos')
  271. assert hasattr(prntr, '_print_log')
  272. def test_scipy_print_methods():
  273. prntr = SciPyPrinter()
  274. assert hasattr(prntr, '_print_acos')
  275. assert hasattr(prntr, '_print_log')
  276. assert hasattr(prntr, '_print_erf')
  277. assert hasattr(prntr, '_print_factorial')
  278. assert hasattr(prntr, '_print_chebyshevt')
  279. k = Symbol('k', integer=True, nonnegative=True)
  280. x = Symbol('x', real=True)
  281. assert prntr.doprint(polygamma(k, x)) == "scipy.special.polygamma(k, x)"
  282. assert prntr.doprint(Si(x)) == "scipy.special.sici(x)[0]"
  283. assert prntr.doprint(Ci(x)) == "scipy.special.sici(x)[1]"