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.

1576 lines
49 KiB

6 months ago
  1. from itertools import product
  2. import math
  3. import inspect
  4. import mpmath
  5. from sympy.testing.pytest import raises, warns_deprecated_sympy
  6. from sympy.concrete.summations import Sum
  7. from sympy.core.function import (Function, Lambda, diff)
  8. from sympy.core.numbers import (E, Float, I, Rational, oo, pi)
  9. from sympy.core.relational import Eq
  10. from sympy.core.singleton import S
  11. from sympy.core.symbol import (Dummy, symbols)
  12. from sympy.functions.combinatorial.factorials import (RisingFactorial, factorial)
  13. from sympy.functions.elementary.complexes import Abs
  14. from sympy.functions.elementary.exponential import exp
  15. from sympy.functions.elementary.hyperbolic import acosh
  16. from sympy.functions.elementary.integers import floor
  17. from sympy.functions.elementary.miscellaneous import (Max, Min, sqrt)
  18. from sympy.functions.elementary.piecewise import Piecewise
  19. from sympy.functions.elementary.trigonometric import (acos, cos, sin, sinc, tan)
  20. from sympy.functions.special.bessel import (besseli, besselj, besselk, bessely)
  21. from sympy.functions.special.beta_functions import (beta, betainc, betainc_regularized)
  22. from sympy.functions.special.delta_functions import (Heaviside)
  23. from sympy.functions.special.error_functions import (erf, erfc, fresnelc, fresnels)
  24. from sympy.functions.special.gamma_functions import (digamma, gamma, loggamma)
  25. from sympy.integrals.integrals import Integral
  26. from sympy.logic.boolalg import (And, false, ITE, Not, Or, true)
  27. from sympy.matrices.expressions.dotproduct import DotProduct
  28. from sympy.tensor.array import derive_by_array, Array
  29. from sympy.tensor.indexed import IndexedBase
  30. from sympy.utilities.lambdify import lambdify
  31. from sympy.core.expr import UnevaluatedExpr
  32. from sympy.codegen.cfunctions import expm1, log1p, exp2, log2, log10, hypot
  33. from sympy.codegen.numpy_nodes import logaddexp, logaddexp2
  34. from sympy.codegen.scipy_nodes import cosm1
  35. from sympy.functions.elementary.complexes import re, im, arg
  36. from sympy.functions.special.polynomials import \
  37. chebyshevt, chebyshevu, legendre, hermite, laguerre, gegenbauer, \
  38. assoc_legendre, assoc_laguerre, jacobi
  39. from sympy.matrices import Matrix, MatrixSymbol, SparseMatrix
  40. from sympy.printing.lambdarepr import LambdaPrinter
  41. from sympy.printing.numpy import NumPyPrinter
  42. from sympy.utilities.lambdify import implemented_function, lambdastr
  43. from sympy.testing.pytest import skip
  44. from sympy.utilities.decorator import conserve_mpmath_dps
  45. from sympy.external import import_module
  46. from sympy.functions.special.gamma_functions import uppergamma, lowergamma
  47. import sympy
  48. MutableDenseMatrix = Matrix
  49. numpy = import_module('numpy')
  50. scipy = import_module('scipy', import_kwargs={'fromlist': ['sparse']})
  51. numexpr = import_module('numexpr')
  52. tensorflow = import_module('tensorflow')
  53. cupy = import_module('cupy')
  54. if tensorflow:
  55. # Hide Tensorflow warnings
  56. import os
  57. os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
  58. w, x, y, z = symbols('w,x,y,z')
  59. #================== Test different arguments =======================
  60. def test_no_args():
  61. f = lambdify([], 1)
  62. raises(TypeError, lambda: f(-1))
  63. assert f() == 1
  64. def test_single_arg():
  65. f = lambdify(x, 2*x)
  66. assert f(1) == 2
  67. def test_list_args():
  68. f = lambdify([x, y], x + y)
  69. assert f(1, 2) == 3
  70. def test_nested_args():
  71. f1 = lambdify([[w, x]], [w, x])
  72. assert f1([91, 2]) == [91, 2]
  73. raises(TypeError, lambda: f1(1, 2))
  74. f2 = lambdify([(w, x), (y, z)], [w, x, y, z])
  75. assert f2((18, 12), (73, 4)) == [18, 12, 73, 4]
  76. raises(TypeError, lambda: f2(3, 4))
  77. f3 = lambdify([w, [[[x]], y], z], [w, x, y, z])
  78. assert f3(10, [[[52]], 31], 44) == [10, 52, 31, 44]
  79. def test_str_args():
  80. f = lambdify('x,y,z', 'z,y,x')
  81. assert f(3, 2, 1) == (1, 2, 3)
  82. assert f(1.0, 2.0, 3.0) == (3.0, 2.0, 1.0)
  83. # make sure correct number of args required
  84. raises(TypeError, lambda: f(0))
  85. def test_own_namespace_1():
  86. myfunc = lambda x: 1
  87. f = lambdify(x, sin(x), {"sin": myfunc})
  88. assert f(0.1) == 1
  89. assert f(100) == 1
  90. def test_own_namespace_2():
  91. def myfunc(x):
  92. return 1
  93. f = lambdify(x, sin(x), {'sin': myfunc})
  94. assert f(0.1) == 1
  95. assert f(100) == 1
  96. def test_own_module():
  97. f = lambdify(x, sin(x), math)
  98. assert f(0) == 0.0
  99. p, q, r = symbols("p q r", real=True)
  100. ae = abs(exp(p+UnevaluatedExpr(q+r)))
  101. f = lambdify([p, q, r], [ae, ae], modules=math)
  102. results = f(1.0, 1e18, -1e18)
  103. refvals = [math.exp(1.0)]*2
  104. for res, ref in zip(results, refvals):
  105. assert abs((res-ref)/ref) < 1e-15
  106. def test_bad_args():
  107. # no vargs given
  108. raises(TypeError, lambda: lambdify(1))
  109. # same with vector exprs
  110. raises(TypeError, lambda: lambdify([1, 2]))
  111. def test_atoms():
  112. # Non-Symbol atoms should not be pulled out from the expression namespace
  113. f = lambdify(x, pi + x, {"pi": 3.14})
  114. assert f(0) == 3.14
  115. f = lambdify(x, I + x, {"I": 1j})
  116. assert f(1) == 1 + 1j
  117. #================== Test different modules =========================
  118. # high precision output of sin(0.2*pi) is used to detect if precision is lost unwanted
  119. @conserve_mpmath_dps
  120. def test_sympy_lambda():
  121. mpmath.mp.dps = 50
  122. sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020")
  123. f = lambdify(x, sin(x), "sympy")
  124. assert f(x) == sin(x)
  125. prec = 1e-15
  126. assert -prec < f(Rational(1, 5)).evalf() - Float(str(sin02)) < prec
  127. # arctan is in numpy module and should not be available
  128. # The arctan below gives NameError. What is this supposed to test?
  129. # raises(NameError, lambda: lambdify(x, arctan(x), "sympy"))
  130. @conserve_mpmath_dps
  131. def test_math_lambda():
  132. mpmath.mp.dps = 50
  133. sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020")
  134. f = lambdify(x, sin(x), "math")
  135. prec = 1e-15
  136. assert -prec < f(0.2) - sin02 < prec
  137. raises(TypeError, lambda: f(x))
  138. # if this succeeds, it can't be a Python math function
  139. @conserve_mpmath_dps
  140. def test_mpmath_lambda():
  141. mpmath.mp.dps = 50
  142. sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020")
  143. f = lambdify(x, sin(x), "mpmath")
  144. prec = 1e-49 # mpmath precision is around 50 decimal places
  145. assert -prec < f(mpmath.mpf("0.2")) - sin02 < prec
  146. raises(TypeError, lambda: f(x))
  147. # if this succeeds, it can't be a mpmath function
  148. @conserve_mpmath_dps
  149. def test_number_precision():
  150. mpmath.mp.dps = 50
  151. sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020")
  152. f = lambdify(x, sin02, "mpmath")
  153. prec = 1e-49 # mpmath precision is around 50 decimal places
  154. assert -prec < f(0) - sin02 < prec
  155. @conserve_mpmath_dps
  156. def test_mpmath_precision():
  157. mpmath.mp.dps = 100
  158. assert str(lambdify((), pi.evalf(100), 'mpmath')()) == str(pi.evalf(100))
  159. #================== Test Translations ==============================
  160. # We can only check if all translated functions are valid. It has to be checked
  161. # by hand if they are complete.
  162. def test_math_transl():
  163. from sympy.utilities.lambdify import MATH_TRANSLATIONS
  164. for sym, mat in MATH_TRANSLATIONS.items():
  165. assert sym in sympy.__dict__
  166. assert mat in math.__dict__
  167. def test_mpmath_transl():
  168. from sympy.utilities.lambdify import MPMATH_TRANSLATIONS
  169. for sym, mat in MPMATH_TRANSLATIONS.items():
  170. assert sym in sympy.__dict__ or sym == 'Matrix'
  171. assert mat in mpmath.__dict__
  172. def test_numpy_transl():
  173. if not numpy:
  174. skip("numpy not installed.")
  175. from sympy.utilities.lambdify import NUMPY_TRANSLATIONS
  176. for sym, nump in NUMPY_TRANSLATIONS.items():
  177. assert sym in sympy.__dict__
  178. assert nump in numpy.__dict__
  179. def test_scipy_transl():
  180. if not scipy:
  181. skip("scipy not installed.")
  182. from sympy.utilities.lambdify import SCIPY_TRANSLATIONS
  183. for sym, scip in SCIPY_TRANSLATIONS.items():
  184. assert sym in sympy.__dict__
  185. assert scip in scipy.__dict__ or scip in scipy.special.__dict__
  186. def test_numpy_translation_abs():
  187. if not numpy:
  188. skip("numpy not installed.")
  189. f = lambdify(x, Abs(x), "numpy")
  190. assert f(-1) == 1
  191. assert f(1) == 1
  192. def test_numexpr_printer():
  193. if not numexpr:
  194. skip("numexpr not installed.")
  195. # if translation/printing is done incorrectly then evaluating
  196. # a lambdified numexpr expression will throw an exception
  197. from sympy.printing.lambdarepr import NumExprPrinter
  198. blacklist = ('where', 'complex', 'contains')
  199. arg_tuple = (x, y, z) # some functions take more than one argument
  200. for sym in NumExprPrinter._numexpr_functions.keys():
  201. if sym in blacklist:
  202. continue
  203. ssym = S(sym)
  204. if hasattr(ssym, '_nargs'):
  205. nargs = ssym._nargs[0]
  206. else:
  207. nargs = 1
  208. args = arg_tuple[:nargs]
  209. f = lambdify(args, ssym(*args), modules='numexpr')
  210. assert f(*(1, )*nargs) is not None
  211. def test_issue_9334():
  212. if not numexpr:
  213. skip("numexpr not installed.")
  214. if not numpy:
  215. skip("numpy not installed.")
  216. expr = S('b*a - sqrt(a**2)')
  217. a, b = sorted(expr.free_symbols, key=lambda s: s.name)
  218. func_numexpr = lambdify((a,b), expr, modules=[numexpr], dummify=False)
  219. foo, bar = numpy.random.random((2, 4))
  220. func_numexpr(foo, bar)
  221. def test_issue_12984():
  222. import warnings
  223. if not numexpr:
  224. skip("numexpr not installed.")
  225. func_numexpr = lambdify((x,y,z), Piecewise((y, x >= 0), (z, x > -1)), numexpr)
  226. assert func_numexpr(1, 24, 42) == 24
  227. with warnings.catch_warnings():
  228. warnings.simplefilter("ignore", RuntimeWarning)
  229. assert str(func_numexpr(-1, 24, 42)) == 'nan'
  230. def test_empty_modules():
  231. x, y = symbols('x y')
  232. expr = -(x % y)
  233. no_modules = lambdify([x, y], expr)
  234. empty_modules = lambdify([x, y], expr, modules=[])
  235. assert no_modules(3, 7) == empty_modules(3, 7)
  236. assert no_modules(3, 7) == -3
  237. def test_exponentiation():
  238. f = lambdify(x, x**2)
  239. assert f(-1) == 1
  240. assert f(0) == 0
  241. assert f(1) == 1
  242. assert f(-2) == 4
  243. assert f(2) == 4
  244. assert f(2.5) == 6.25
  245. def test_sqrt():
  246. f = lambdify(x, sqrt(x))
  247. assert f(0) == 0.0
  248. assert f(1) == 1.0
  249. assert f(4) == 2.0
  250. assert abs(f(2) - 1.414) < 0.001
  251. assert f(6.25) == 2.5
  252. def test_trig():
  253. f = lambdify([x], [cos(x), sin(x)], 'math')
  254. d = f(pi)
  255. prec = 1e-11
  256. assert -prec < d[0] + 1 < prec
  257. assert -prec < d[1] < prec
  258. d = f(3.14159)
  259. prec = 1e-5
  260. assert -prec < d[0] + 1 < prec
  261. assert -prec < d[1] < prec
  262. def test_integral():
  263. # XXX: This fails if numpy is installed but scipy isn't. Since it works
  264. # without numpy it should be able to work whe numpy is installed as well.
  265. # https://github.com/sympy/sympy/issues/23133
  266. if numpy and not scipy:
  267. skip("scipy not installed.")
  268. f = Lambda(x, exp(-x**2))
  269. l = lambdify(y, Integral(f(x), (x, y, oo)))
  270. d = l(-oo)
  271. assert 1.77245385 < d < 1.772453851
  272. def test_double_integral():
  273. # XXX: This fails if numpy is installed but scipy isn't. Since it works
  274. # without numpy it should be able to work whe numpy is installed as well.
  275. # https://github.com/sympy/sympy/issues/23133
  276. if numpy and not scipy:
  277. skip("scipy not installed.")
  278. # example from http://mpmath.org/doc/current/calculus/integration.html
  279. i = Integral(1/(1 - x**2*y**2), (x, 0, 1), (y, 0, z))
  280. l = lambdify([z], i)
  281. d = l(1)
  282. assert 1.23370055 < d < 1.233700551
  283. #================== Test vectors ===================================
  284. def test_vector_simple():
  285. f = lambdify((x, y, z), (z, y, x))
  286. assert f(3, 2, 1) == (1, 2, 3)
  287. assert f(1.0, 2.0, 3.0) == (3.0, 2.0, 1.0)
  288. # make sure correct number of args required
  289. raises(TypeError, lambda: f(0))
  290. def test_vector_discontinuous():
  291. f = lambdify(x, (-1/x, 1/x))
  292. raises(ZeroDivisionError, lambda: f(0))
  293. assert f(1) == (-1.0, 1.0)
  294. assert f(2) == (-0.5, 0.5)
  295. assert f(-2) == (0.5, -0.5)
  296. def test_trig_symbolic():
  297. f = lambdify([x], [cos(x), sin(x)], 'math')
  298. d = f(pi)
  299. assert abs(d[0] + 1) < 0.0001
  300. assert abs(d[1] - 0) < 0.0001
  301. def test_trig_float():
  302. f = lambdify([x], [cos(x), sin(x)])
  303. d = f(3.14159)
  304. assert abs(d[0] + 1) < 0.0001
  305. assert abs(d[1] - 0) < 0.0001
  306. def test_docs():
  307. f = lambdify(x, x**2)
  308. assert f(2) == 4
  309. f = lambdify([x, y, z], [z, y, x])
  310. assert f(1, 2, 3) == [3, 2, 1]
  311. f = lambdify(x, sqrt(x))
  312. assert f(4) == 2.0
  313. f = lambdify((x, y), sin(x*y)**2)
  314. assert f(0, 5) == 0
  315. def test_math():
  316. f = lambdify((x, y), sin(x), modules="math")
  317. assert f(0, 5) == 0
  318. def test_sin():
  319. f = lambdify(x, sin(x)**2)
  320. assert isinstance(f(2), float)
  321. f = lambdify(x, sin(x)**2, modules="math")
  322. assert isinstance(f(2), float)
  323. def test_matrix():
  324. A = Matrix([[x, x*y], [sin(z) + 4, x**z]])
  325. sol = Matrix([[1, 2], [sin(3) + 4, 1]])
  326. f = lambdify((x, y, z), A, modules="sympy")
  327. assert f(1, 2, 3) == sol
  328. f = lambdify((x, y, z), (A, [A]), modules="sympy")
  329. assert f(1, 2, 3) == (sol, [sol])
  330. J = Matrix((x, x + y)).jacobian((x, y))
  331. v = Matrix((x, y))
  332. sol = Matrix([[1, 0], [1, 1]])
  333. assert lambdify(v, J, modules='sympy')(1, 2) == sol
  334. assert lambdify(v.T, J, modules='sympy')(1, 2) == sol
  335. def test_numpy_matrix():
  336. if not numpy:
  337. skip("numpy not installed.")
  338. A = Matrix([[x, x*y], [sin(z) + 4, x**z]])
  339. sol_arr = numpy.array([[1, 2], [numpy.sin(3) + 4, 1]])
  340. #Lambdify array first, to ensure return to array as default
  341. f = lambdify((x, y, z), A, ['numpy'])
  342. numpy.testing.assert_allclose(f(1, 2, 3), sol_arr)
  343. #Check that the types are arrays and matrices
  344. assert isinstance(f(1, 2, 3), numpy.ndarray)
  345. # gh-15071
  346. class dot(Function):
  347. pass
  348. x_dot_mtx = dot(x, Matrix([[2], [1], [0]]))
  349. f_dot1 = lambdify(x, x_dot_mtx)
  350. inp = numpy.zeros((17, 3))
  351. assert numpy.all(f_dot1(inp) == 0)
  352. strict_kw = dict(allow_unknown_functions=False, inline=True, fully_qualified_modules=False)
  353. p2 = NumPyPrinter(dict(user_functions={'dot': 'dot'}, **strict_kw))
  354. f_dot2 = lambdify(x, x_dot_mtx, printer=p2)
  355. assert numpy.all(f_dot2(inp) == 0)
  356. p3 = NumPyPrinter(strict_kw)
  357. # The line below should probably fail upon construction (before calling with "(inp)"):
  358. raises(Exception, lambda: lambdify(x, x_dot_mtx, printer=p3)(inp))
  359. def test_numpy_transpose():
  360. if not numpy:
  361. skip("numpy not installed.")
  362. A = Matrix([[1, x], [0, 1]])
  363. f = lambdify((x), A.T, modules="numpy")
  364. numpy.testing.assert_array_equal(f(2), numpy.array([[1, 0], [2, 1]]))
  365. def test_numpy_dotproduct():
  366. if not numpy:
  367. skip("numpy not installed")
  368. A = Matrix([x, y, z])
  369. f1 = lambdify([x, y, z], DotProduct(A, A), modules='numpy')
  370. f2 = lambdify([x, y, z], DotProduct(A, A.T), modules='numpy')
  371. f3 = lambdify([x, y, z], DotProduct(A.T, A), modules='numpy')
  372. f4 = lambdify([x, y, z], DotProduct(A, A.T), modules='numpy')
  373. assert f1(1, 2, 3) == \
  374. f2(1, 2, 3) == \
  375. f3(1, 2, 3) == \
  376. f4(1, 2, 3) == \
  377. numpy.array([14])
  378. def test_numpy_inverse():
  379. if not numpy:
  380. skip("numpy not installed.")
  381. A = Matrix([[1, x], [0, 1]])
  382. f = lambdify((x), A**-1, modules="numpy")
  383. numpy.testing.assert_array_equal(f(2), numpy.array([[1, -2], [0, 1]]))
  384. def test_numpy_old_matrix():
  385. if not numpy:
  386. skip("numpy not installed.")
  387. A = Matrix([[x, x*y], [sin(z) + 4, x**z]])
  388. sol_arr = numpy.array([[1, 2], [numpy.sin(3) + 4, 1]])
  389. f = lambdify((x, y, z), A, [{'ImmutableDenseMatrix': numpy.matrix}, 'numpy'])
  390. numpy.testing.assert_allclose(f(1, 2, 3), sol_arr)
  391. assert isinstance(f(1, 2, 3), numpy.matrix)
  392. def test_scipy_sparse_matrix():
  393. if not scipy:
  394. skip("scipy not installed.")
  395. A = SparseMatrix([[x, 0], [0, y]])
  396. f = lambdify((x, y), A, modules="scipy")
  397. B = f(1, 2)
  398. assert isinstance(B, scipy.sparse.coo_matrix)
  399. def test_python_div_zero_issue_11306():
  400. if not numpy:
  401. skip("numpy not installed.")
  402. p = Piecewise((1 / x, y < -1), (x, y < 1), (1 / x, True))
  403. f = lambdify([x, y], p, modules='numpy')
  404. numpy.seterr(divide='ignore')
  405. assert float(f(numpy.array([0]),numpy.array([0.5]))) == 0
  406. assert str(float(f(numpy.array([0]),numpy.array([1])))) == 'inf'
  407. numpy.seterr(divide='warn')
  408. def test_issue9474():
  409. mods = [None, 'math']
  410. if numpy:
  411. mods.append('numpy')
  412. if mpmath:
  413. mods.append('mpmath')
  414. for mod in mods:
  415. f = lambdify(x, S.One/x, modules=mod)
  416. assert f(2) == 0.5
  417. f = lambdify(x, floor(S.One/x), modules=mod)
  418. assert f(2) == 0
  419. for absfunc, modules in product([Abs, abs], mods):
  420. f = lambdify(x, absfunc(x), modules=modules)
  421. assert f(-1) == 1
  422. assert f(1) == 1
  423. assert f(3+4j) == 5
  424. def test_issue_9871():
  425. if not numexpr:
  426. skip("numexpr not installed.")
  427. if not numpy:
  428. skip("numpy not installed.")
  429. r = sqrt(x**2 + y**2)
  430. expr = diff(1/r, x)
  431. xn = yn = numpy.linspace(1, 10, 16)
  432. # expr(xn, xn) = -xn/(sqrt(2)*xn)^3
  433. fv_exact = -numpy.sqrt(2.)**-3 * xn**-2
  434. fv_numpy = lambdify((x, y), expr, modules='numpy')(xn, yn)
  435. fv_numexpr = lambdify((x, y), expr, modules='numexpr')(xn, yn)
  436. numpy.testing.assert_allclose(fv_numpy, fv_exact, rtol=1e-10)
  437. numpy.testing.assert_allclose(fv_numexpr, fv_exact, rtol=1e-10)
  438. def test_numpy_piecewise():
  439. if not numpy:
  440. skip("numpy not installed.")
  441. pieces = Piecewise((x, x < 3), (x**2, x > 5), (0, True))
  442. f = lambdify(x, pieces, modules="numpy")
  443. numpy.testing.assert_array_equal(f(numpy.arange(10)),
  444. numpy.array([0, 1, 2, 0, 0, 0, 36, 49, 64, 81]))
  445. # If we evaluate somewhere all conditions are False, we should get back NaN
  446. nodef_func = lambdify(x, Piecewise((x, x > 0), (-x, x < 0)))
  447. numpy.testing.assert_array_equal(nodef_func(numpy.array([-1, 0, 1])),
  448. numpy.array([1, numpy.nan, 1]))
  449. def test_numpy_logical_ops():
  450. if not numpy:
  451. skip("numpy not installed.")
  452. and_func = lambdify((x, y), And(x, y), modules="numpy")
  453. and_func_3 = lambdify((x, y, z), And(x, y, z), modules="numpy")
  454. or_func = lambdify((x, y), Or(x, y), modules="numpy")
  455. or_func_3 = lambdify((x, y, z), Or(x, y, z), modules="numpy")
  456. not_func = lambdify((x), Not(x), modules="numpy")
  457. arr1 = numpy.array([True, True])
  458. arr2 = numpy.array([False, True])
  459. arr3 = numpy.array([True, False])
  460. numpy.testing.assert_array_equal(and_func(arr1, arr2), numpy.array([False, True]))
  461. numpy.testing.assert_array_equal(and_func_3(arr1, arr2, arr3), numpy.array([False, False]))
  462. numpy.testing.assert_array_equal(or_func(arr1, arr2), numpy.array([True, True]))
  463. numpy.testing.assert_array_equal(or_func_3(arr1, arr2, arr3), numpy.array([True, True]))
  464. numpy.testing.assert_array_equal(not_func(arr2), numpy.array([True, False]))
  465. def test_numpy_matmul():
  466. if not numpy:
  467. skip("numpy not installed.")
  468. xmat = Matrix([[x, y], [z, 1+z]])
  469. ymat = Matrix([[x**2], [Abs(x)]])
  470. mat_func = lambdify((x, y, z), xmat*ymat, modules="numpy")
  471. numpy.testing.assert_array_equal(mat_func(0.5, 3, 4), numpy.array([[1.625], [3.5]]))
  472. numpy.testing.assert_array_equal(mat_func(-0.5, 3, 4), numpy.array([[1.375], [3.5]]))
  473. # Multiple matrices chained together in multiplication
  474. f = lambdify((x, y, z), xmat*xmat*xmat, modules="numpy")
  475. numpy.testing.assert_array_equal(f(0.5, 3, 4), numpy.array([[72.125, 119.25],
  476. [159, 251]]))
  477. def test_numpy_numexpr():
  478. if not numpy:
  479. skip("numpy not installed.")
  480. if not numexpr:
  481. skip("numexpr not installed.")
  482. a, b, c = numpy.random.randn(3, 128, 128)
  483. # ensure that numpy and numexpr return same value for complicated expression
  484. expr = sin(x) + cos(y) + tan(z)**2 + Abs(z-y)*acos(sin(y*z)) + \
  485. Abs(y-z)*acosh(2+exp(y-x))- sqrt(x**2+I*y**2)
  486. npfunc = lambdify((x, y, z), expr, modules='numpy')
  487. nefunc = lambdify((x, y, z), expr, modules='numexpr')
  488. assert numpy.allclose(npfunc(a, b, c), nefunc(a, b, c))
  489. def test_numexpr_userfunctions():
  490. if not numpy:
  491. skip("numpy not installed.")
  492. if not numexpr:
  493. skip("numexpr not installed.")
  494. a, b = numpy.random.randn(2, 10)
  495. uf = type('uf', (Function, ),
  496. {'eval' : classmethod(lambda x, y : y**2+1)})
  497. func = lambdify(x, 1-uf(x), modules='numexpr')
  498. assert numpy.allclose(func(a), -(a**2))
  499. uf = implemented_function(Function('uf'), lambda x, y : 2*x*y+1)
  500. func = lambdify((x, y), uf(x, y), modules='numexpr')
  501. assert numpy.allclose(func(a, b), 2*a*b+1)
  502. def test_tensorflow_basic_math():
  503. if not tensorflow:
  504. skip("tensorflow not installed.")
  505. expr = Max(sin(x), Abs(1/(x+2)))
  506. func = lambdify(x, expr, modules="tensorflow")
  507. with tensorflow.compat.v1.Session() as s:
  508. a = tensorflow.constant(0, dtype=tensorflow.float32)
  509. assert func(a).eval(session=s) == 0.5
  510. def test_tensorflow_placeholders():
  511. if not tensorflow:
  512. skip("tensorflow not installed.")
  513. expr = Max(sin(x), Abs(1/(x+2)))
  514. func = lambdify(x, expr, modules="tensorflow")
  515. with tensorflow.compat.v1.Session() as s:
  516. a = tensorflow.compat.v1.placeholder(dtype=tensorflow.float32)
  517. assert func(a).eval(session=s, feed_dict={a: 0}) == 0.5
  518. def test_tensorflow_variables():
  519. if not tensorflow:
  520. skip("tensorflow not installed.")
  521. expr = Max(sin(x), Abs(1/(x+2)))
  522. func = lambdify(x, expr, modules="tensorflow")
  523. with tensorflow.compat.v1.Session() as s:
  524. a = tensorflow.Variable(0, dtype=tensorflow.float32)
  525. s.run(a.initializer)
  526. assert func(a).eval(session=s, feed_dict={a: 0}) == 0.5
  527. def test_tensorflow_logical_operations():
  528. if not tensorflow:
  529. skip("tensorflow not installed.")
  530. expr = Not(And(Or(x, y), y))
  531. func = lambdify([x, y], expr, modules="tensorflow")
  532. with tensorflow.compat.v1.Session() as s:
  533. assert func(False, True).eval(session=s) == False
  534. def test_tensorflow_piecewise():
  535. if not tensorflow:
  536. skip("tensorflow not installed.")
  537. expr = Piecewise((0, Eq(x,0)), (-1, x < 0), (1, x > 0))
  538. func = lambdify(x, expr, modules="tensorflow")
  539. with tensorflow.compat.v1.Session() as s:
  540. assert func(-1).eval(session=s) == -1
  541. assert func(0).eval(session=s) == 0
  542. assert func(1).eval(session=s) == 1
  543. def test_tensorflow_multi_max():
  544. if not tensorflow:
  545. skip("tensorflow not installed.")
  546. expr = Max(x, -x, x**2)
  547. func = lambdify(x, expr, modules="tensorflow")
  548. with tensorflow.compat.v1.Session() as s:
  549. assert func(-2).eval(session=s) == 4
  550. def test_tensorflow_multi_min():
  551. if not tensorflow:
  552. skip("tensorflow not installed.")
  553. expr = Min(x, -x, x**2)
  554. func = lambdify(x, expr, modules="tensorflow")
  555. with tensorflow.compat.v1.Session() as s:
  556. assert func(-2).eval(session=s) == -2
  557. def test_tensorflow_relational():
  558. if not tensorflow:
  559. skip("tensorflow not installed.")
  560. expr = x >= 0
  561. func = lambdify(x, expr, modules="tensorflow")
  562. with tensorflow.compat.v1.Session() as s:
  563. assert func(1).eval(session=s) == True
  564. def test_tensorflow_complexes():
  565. if not tensorflow:
  566. skip("tensorflow not installed")
  567. func1 = lambdify(x, re(x), modules="tensorflow")
  568. func2 = lambdify(x, im(x), modules="tensorflow")
  569. func3 = lambdify(x, Abs(x), modules="tensorflow")
  570. func4 = lambdify(x, arg(x), modules="tensorflow")
  571. with tensorflow.compat.v1.Session() as s:
  572. # For versions before
  573. # https://github.com/tensorflow/tensorflow/issues/30029
  574. # resolved, using Python numeric types may not work
  575. a = tensorflow.constant(1+2j)
  576. assert func1(a).eval(session=s) == 1
  577. assert func2(a).eval(session=s) == 2
  578. tensorflow_result = func3(a).eval(session=s)
  579. sympy_result = Abs(1 + 2j).evalf()
  580. assert abs(tensorflow_result-sympy_result) < 10**-6
  581. tensorflow_result = func4(a).eval(session=s)
  582. sympy_result = arg(1 + 2j).evalf()
  583. assert abs(tensorflow_result-sympy_result) < 10**-6
  584. def test_tensorflow_array_arg():
  585. # Test for issue 14655 (tensorflow part)
  586. if not tensorflow:
  587. skip("tensorflow not installed.")
  588. f = lambdify([[x, y]], x*x + y, 'tensorflow')
  589. with tensorflow.compat.v1.Session() as s:
  590. fcall = f(tensorflow.constant([2.0, 1.0]))
  591. assert fcall.eval(session=s) == 5.0
  592. #================== Test symbolic ==================================
  593. def test_sym_single_arg():
  594. f = lambdify(x, x * y)
  595. assert f(z) == z * y
  596. def test_sym_list_args():
  597. f = lambdify([x, y], x + y + z)
  598. assert f(1, 2) == 3 + z
  599. def test_sym_integral():
  600. f = Lambda(x, exp(-x**2))
  601. l = lambdify(x, Integral(f(x), (x, -oo, oo)), modules="sympy")
  602. assert l(y) == Integral(exp(-y**2), (y, -oo, oo))
  603. assert l(y).doit() == sqrt(pi)
  604. def test_namespace_order():
  605. # lambdify had a bug, such that module dictionaries or cached module
  606. # dictionaries would pull earlier namespaces into themselves.
  607. # Because the module dictionaries form the namespace of the
  608. # generated lambda, this meant that the behavior of a previously
  609. # generated lambda function could change as a result of later calls
  610. # to lambdify.
  611. n1 = {'f': lambda x: 'first f'}
  612. n2 = {'f': lambda x: 'second f',
  613. 'g': lambda x: 'function g'}
  614. f = sympy.Function('f')
  615. g = sympy.Function('g')
  616. if1 = lambdify(x, f(x), modules=(n1, "sympy"))
  617. assert if1(1) == 'first f'
  618. if2 = lambdify(x, g(x), modules=(n2, "sympy"))
  619. # previously gave 'second f'
  620. assert if1(1) == 'first f'
  621. assert if2(1) == 'function g'
  622. def test_imps():
  623. # Here we check if the default returned functions are anonymous - in
  624. # the sense that we can have more than one function with the same name
  625. f = implemented_function('f', lambda x: 2*x)
  626. g = implemented_function('f', lambda x: math.sqrt(x))
  627. l1 = lambdify(x, f(x))
  628. l2 = lambdify(x, g(x))
  629. assert str(f(x)) == str(g(x))
  630. assert l1(3) == 6
  631. assert l2(3) == math.sqrt(3)
  632. # check that we can pass in a Function as input
  633. func = sympy.Function('myfunc')
  634. assert not hasattr(func, '_imp_')
  635. my_f = implemented_function(func, lambda x: 2*x)
  636. assert hasattr(my_f, '_imp_')
  637. # Error for functions with same name and different implementation
  638. f2 = implemented_function("f", lambda x: x + 101)
  639. raises(ValueError, lambda: lambdify(x, f(f2(x))))
  640. def test_imps_errors():
  641. # Test errors that implemented functions can return, and still be able to
  642. # form expressions.
  643. # See: https://github.com/sympy/sympy/issues/10810
  644. #
  645. # XXX: Removed AttributeError here. This test was added due to issue 10810
  646. # but that issue was about ValueError. It doesn't seem reasonable to
  647. # "support" catching AttributeError in the same context...
  648. for val, error_class in product((0, 0., 2, 2.0), (TypeError, ValueError)):
  649. def myfunc(a):
  650. if a == 0:
  651. raise error_class
  652. return 1
  653. f = implemented_function('f', myfunc)
  654. expr = f(val)
  655. assert expr == f(val)
  656. def test_imps_wrong_args():
  657. raises(ValueError, lambda: implemented_function(sin, lambda x: x))
  658. def test_lambdify_imps():
  659. # Test lambdify with implemented functions
  660. # first test basic (sympy) lambdify
  661. f = sympy.cos
  662. assert lambdify(x, f(x))(0) == 1
  663. assert lambdify(x, 1 + f(x))(0) == 2
  664. assert lambdify((x, y), y + f(x))(0, 1) == 2
  665. # make an implemented function and test
  666. f = implemented_function("f", lambda x: x + 100)
  667. assert lambdify(x, f(x))(0) == 100
  668. assert lambdify(x, 1 + f(x))(0) == 101
  669. assert lambdify((x, y), y + f(x))(0, 1) == 101
  670. # Can also handle tuples, lists, dicts as expressions
  671. lam = lambdify(x, (f(x), x))
  672. assert lam(3) == (103, 3)
  673. lam = lambdify(x, [f(x), x])
  674. assert lam(3) == [103, 3]
  675. lam = lambdify(x, [f(x), (f(x), x)])
  676. assert lam(3) == [103, (103, 3)]
  677. lam = lambdify(x, {f(x): x})
  678. assert lam(3) == {103: 3}
  679. lam = lambdify(x, {f(x): x})
  680. assert lam(3) == {103: 3}
  681. lam = lambdify(x, {x: f(x)})
  682. assert lam(3) == {3: 103}
  683. # Check that imp preferred to other namespaces by default
  684. d = {'f': lambda x: x + 99}
  685. lam = lambdify(x, f(x), d)
  686. assert lam(3) == 103
  687. # Unless flag passed
  688. lam = lambdify(x, f(x), d, use_imps=False)
  689. assert lam(3) == 102
  690. def test_dummification():
  691. t = symbols('t')
  692. F = Function('F')
  693. G = Function('G')
  694. #"\alpha" is not a valid Python variable name
  695. #lambdify should sub in a dummy for it, and return
  696. #without a syntax error
  697. alpha = symbols(r'\alpha')
  698. some_expr = 2 * F(t)**2 / G(t)
  699. lam = lambdify((F(t), G(t)), some_expr)
  700. assert lam(3, 9) == 2
  701. lam = lambdify(sin(t), 2 * sin(t)**2)
  702. assert lam(F(t)) == 2 * F(t)**2
  703. #Test that \alpha was properly dummified
  704. lam = lambdify((alpha, t), 2*alpha + t)
  705. assert lam(2, 1) == 5
  706. raises(SyntaxError, lambda: lambdify(F(t) * G(t), F(t) * G(t) + 5))
  707. raises(SyntaxError, lambda: lambdify(2 * F(t), 2 * F(t) + 5))
  708. raises(SyntaxError, lambda: lambdify(2 * F(t), 4 * F(t) + 5))
  709. def test_curly_matrix_symbol():
  710. # Issue #15009
  711. curlyv = sympy.MatrixSymbol("{v}", 2, 1)
  712. lam = lambdify(curlyv, curlyv)
  713. assert lam(1)==1
  714. lam = lambdify(curlyv, curlyv, dummify=True)
  715. assert lam(1)==1
  716. def test_python_keywords():
  717. # Test for issue 7452. The automatic dummification should ensure use of
  718. # Python reserved keywords as symbol names will create valid lambda
  719. # functions. This is an additional regression test.
  720. python_if = symbols('if')
  721. expr = python_if / 2
  722. f = lambdify(python_if, expr)
  723. assert f(4.0) == 2.0
  724. def test_lambdify_docstring():
  725. func = lambdify((w, x, y, z), w + x + y + z)
  726. ref = (
  727. "Created with lambdify. Signature:\n\n"
  728. "func(w, x, y, z)\n\n"
  729. "Expression:\n\n"
  730. "w + x + y + z"
  731. ).splitlines()
  732. assert func.__doc__.splitlines()[:len(ref)] == ref
  733. syms = symbols('a1:26')
  734. func = lambdify(syms, sum(syms))
  735. ref = (
  736. "Created with lambdify. Signature:\n\n"
  737. "func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,\n"
  738. " a16, a17, a18, a19, a20, a21, a22, a23, a24, a25)\n\n"
  739. "Expression:\n\n"
  740. "a1 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a2 + a20 +..."
  741. ).splitlines()
  742. assert func.__doc__.splitlines()[:len(ref)] == ref
  743. #================== Test special printers ==========================
  744. def test_special_printers():
  745. from sympy.printing.lambdarepr import IntervalPrinter
  746. def intervalrepr(expr):
  747. return IntervalPrinter().doprint(expr)
  748. expr = sqrt(sqrt(2) + sqrt(3)) + S.Half
  749. func0 = lambdify((), expr, modules="mpmath", printer=intervalrepr)
  750. func1 = lambdify((), expr, modules="mpmath", printer=IntervalPrinter)
  751. func2 = lambdify((), expr, modules="mpmath", printer=IntervalPrinter())
  752. mpi = type(mpmath.mpi(1, 2))
  753. assert isinstance(func0(), mpi)
  754. assert isinstance(func1(), mpi)
  755. assert isinstance(func2(), mpi)
  756. # To check Is lambdify loggamma works for mpmath or not
  757. exp1 = lambdify(x, loggamma(x), 'mpmath')(5)
  758. exp2 = lambdify(x, loggamma(x), 'mpmath')(1.8)
  759. exp3 = lambdify(x, loggamma(x), 'mpmath')(15)
  760. exp_ls = [exp1, exp2, exp3]
  761. sol1 = mpmath.loggamma(5)
  762. sol2 = mpmath.loggamma(1.8)
  763. sol3 = mpmath.loggamma(15)
  764. sol_ls = [sol1, sol2, sol3]
  765. assert exp_ls == sol_ls
  766. def test_true_false():
  767. # We want exact is comparison here, not just ==
  768. assert lambdify([], true)() is True
  769. assert lambdify([], false)() is False
  770. def test_issue_2790():
  771. assert lambdify((x, (y, z)), x + y)(1, (2, 4)) == 3
  772. assert lambdify((x, (y, (w, z))), w + x + y + z)(1, (2, (3, 4))) == 10
  773. assert lambdify(x, x + 1, dummify=False)(1) == 2
  774. def test_issue_12092():
  775. f = implemented_function('f', lambda x: x**2)
  776. assert f(f(2)).evalf() == Float(16)
  777. def test_issue_14911():
  778. class Variable(sympy.Symbol):
  779. def _sympystr(self, printer):
  780. return printer.doprint(self.name)
  781. _lambdacode = _sympystr
  782. _numpycode = _sympystr
  783. x = Variable('x')
  784. y = 2 * x
  785. code = LambdaPrinter().doprint(y)
  786. assert code.replace(' ', '') == '2*x'
  787. def test_ITE():
  788. assert lambdify((x, y, z), ITE(x, y, z))(True, 5, 3) == 5
  789. assert lambdify((x, y, z), ITE(x, y, z))(False, 5, 3) == 3
  790. def test_Min_Max():
  791. # see gh-10375
  792. assert lambdify((x, y, z), Min(x, y, z))(1, 2, 3) == 1
  793. assert lambdify((x, y, z), Max(x, y, z))(1, 2, 3) == 3
  794. def test_Indexed():
  795. # Issue #10934
  796. if not numpy:
  797. skip("numpy not installed")
  798. a = IndexedBase('a')
  799. i, j = symbols('i j')
  800. b = numpy.array([[1, 2], [3, 4]])
  801. assert lambdify(a, Sum(a[x, y], (x, 0, 1), (y, 0, 1)))(b) == 10
  802. def test_issue_12173():
  803. #test for issue 12173
  804. expr1 = lambdify((x, y), uppergamma(x, y),"mpmath")(1, 2)
  805. expr2 = lambdify((x, y), lowergamma(x, y),"mpmath")(1, 2)
  806. assert expr1 == uppergamma(1, 2).evalf()
  807. assert expr2 == lowergamma(1, 2).evalf()
  808. def test_issue_13642():
  809. if not numpy:
  810. skip("numpy not installed")
  811. f = lambdify(x, sinc(x))
  812. assert Abs(f(1) - sinc(1)).n() < 1e-15
  813. def test_sinc_mpmath():
  814. f = lambdify(x, sinc(x), "mpmath")
  815. assert Abs(f(1) - sinc(1)).n() < 1e-15
  816. def test_lambdify_dummy_arg():
  817. d1 = Dummy()
  818. f1 = lambdify(d1, d1 + 1, dummify=False)
  819. assert f1(2) == 3
  820. f1b = lambdify(d1, d1 + 1)
  821. assert f1b(2) == 3
  822. d2 = Dummy('x')
  823. f2 = lambdify(d2, d2 + 1)
  824. assert f2(2) == 3
  825. f3 = lambdify([[d2]], d2 + 1)
  826. assert f3([2]) == 3
  827. def test_lambdify_mixed_symbol_dummy_args():
  828. d = Dummy()
  829. # Contrived example of name clash
  830. dsym = symbols(str(d))
  831. f = lambdify([d, dsym], d - dsym)
  832. assert f(4, 1) == 3
  833. def test_numpy_array_arg():
  834. # Test for issue 14655 (numpy part)
  835. if not numpy:
  836. skip("numpy not installed")
  837. f = lambdify([[x, y]], x*x + y, 'numpy')
  838. assert f(numpy.array([2.0, 1.0])) == 5
  839. def test_scipy_fns():
  840. if not scipy:
  841. skip("scipy not installed")
  842. single_arg_sympy_fns = [erf, erfc, factorial, gamma, loggamma, digamma]
  843. single_arg_scipy_fns = [scipy.special.erf, scipy.special.erfc,
  844. scipy.special.factorial, scipy.special.gamma, scipy.special.gammaln,
  845. scipy.special.psi]
  846. numpy.random.seed(0)
  847. for (sympy_fn, scipy_fn) in zip(single_arg_sympy_fns, single_arg_scipy_fns):
  848. f = lambdify(x, sympy_fn(x), modules="scipy")
  849. for i in range(20):
  850. tv = numpy.random.uniform(-10, 10) + 1j*numpy.random.uniform(-5, 5)
  851. # SciPy thinks that factorial(z) is 0 when re(z) < 0 and
  852. # does not support complex numbers.
  853. # SymPy does not think so.
  854. if sympy_fn == factorial:
  855. tv = numpy.abs(tv)
  856. # SciPy supports gammaln for real arguments only,
  857. # and there is also a branch cut along the negative real axis
  858. if sympy_fn == loggamma:
  859. tv = numpy.abs(tv)
  860. # SymPy's digamma evaluates as polygamma(0, z)
  861. # which SciPy supports for real arguments only
  862. if sympy_fn == digamma:
  863. tv = numpy.real(tv)
  864. sympy_result = sympy_fn(tv).evalf()
  865. assert abs(f(tv) - sympy_result) < 1e-13*(1 + abs(sympy_result))
  866. assert abs(f(tv) - scipy_fn(tv)) < 1e-13*(1 + abs(sympy_result))
  867. double_arg_sympy_fns = [RisingFactorial, besselj, bessely, besseli,
  868. besselk]
  869. double_arg_scipy_fns = [scipy.special.poch, scipy.special.jv,
  870. scipy.special.yv, scipy.special.iv, scipy.special.kv]
  871. for (sympy_fn, scipy_fn) in zip(double_arg_sympy_fns, double_arg_scipy_fns):
  872. f = lambdify((x, y), sympy_fn(x, y), modules="scipy")
  873. for i in range(20):
  874. # SciPy supports only real orders of Bessel functions
  875. tv1 = numpy.random.uniform(-10, 10)
  876. tv2 = numpy.random.uniform(-10, 10) + 1j*numpy.random.uniform(-5, 5)
  877. # SciPy supports poch for real arguments only
  878. if sympy_fn == RisingFactorial:
  879. tv2 = numpy.real(tv2)
  880. sympy_result = sympy_fn(tv1, tv2).evalf()
  881. assert abs(f(tv1, tv2) - sympy_result) < 1e-13*(1 + abs(sympy_result))
  882. assert abs(f(tv1, tv2) - scipy_fn(tv1, tv2)) < 1e-13*(1 + abs(sympy_result))
  883. def test_scipy_polys():
  884. if not scipy:
  885. skip("scipy not installed")
  886. numpy.random.seed(0)
  887. params = symbols('n k a b')
  888. # list polynomials with the number of parameters
  889. polys = [
  890. (chebyshevt, 1),
  891. (chebyshevu, 1),
  892. (legendre, 1),
  893. (hermite, 1),
  894. (laguerre, 1),
  895. (gegenbauer, 2),
  896. (assoc_legendre, 2),
  897. (assoc_laguerre, 2),
  898. (jacobi, 3)
  899. ]
  900. msg = \
  901. "The random test of the function {func} with the arguments " \
  902. "{args} had failed because the SymPy result {sympy_result} " \
  903. "and SciPy result {scipy_result} had failed to converge " \
  904. "within the tolerance {tol} " \
  905. "(Actual absolute difference : {diff})"
  906. for sympy_fn, num_params in polys:
  907. args = params[:num_params] + (x,)
  908. f = lambdify(args, sympy_fn(*args))
  909. for _ in range(10):
  910. tn = numpy.random.randint(3, 10)
  911. tparams = tuple(numpy.random.uniform(0, 5, size=num_params-1))
  912. tv = numpy.random.uniform(-10, 10) + 1j*numpy.random.uniform(-5, 5)
  913. # SciPy supports hermite for real arguments only
  914. if sympy_fn == hermite:
  915. tv = numpy.real(tv)
  916. # assoc_legendre needs x in (-1, 1) and integer param at most n
  917. if sympy_fn == assoc_legendre:
  918. tv = numpy.random.uniform(-1, 1)
  919. tparams = tuple(numpy.random.randint(1, tn, size=1))
  920. vals = (tn,) + tparams + (tv,)
  921. scipy_result = f(*vals)
  922. sympy_result = sympy_fn(*vals).evalf()
  923. atol = 1e-9*(1 + abs(sympy_result))
  924. diff = abs(scipy_result - sympy_result)
  925. try:
  926. assert diff < atol
  927. except TypeError:
  928. raise AssertionError(
  929. msg.format(
  930. func=repr(sympy_fn),
  931. args=repr(vals),
  932. sympy_result=repr(sympy_result),
  933. scipy_result=repr(scipy_result),
  934. diff=diff,
  935. tol=atol)
  936. )
  937. def test_lambdify_inspect():
  938. f = lambdify(x, x**2)
  939. # Test that inspect.getsource works but don't hard-code implementation
  940. # details
  941. assert 'x**2' in inspect.getsource(f)
  942. def test_issue_14941():
  943. x, y = Dummy(), Dummy()
  944. # test dict
  945. f1 = lambdify([x, y], {x: 3, y: 3}, 'sympy')
  946. assert f1(2, 3) == {2: 3, 3: 3}
  947. # test tuple
  948. f2 = lambdify([x, y], (y, x), 'sympy')
  949. assert f2(2, 3) == (3, 2)
  950. # test list
  951. f3 = lambdify([x, y], [y, x], 'sympy')
  952. assert f3(2, 3) == [3, 2]
  953. def test_lambdify_Derivative_arg_issue_16468():
  954. f = Function('f')(x)
  955. fx = f.diff()
  956. assert lambdify((f, fx), f + fx)(10, 5) == 15
  957. assert eval(lambdastr((f, fx), f/fx))(10, 5) == 2
  958. raises(SyntaxError, lambda:
  959. eval(lambdastr((f, fx), f/fx, dummify=False)))
  960. assert eval(lambdastr((f, fx), f/fx, dummify=True))(10, 5) == 2
  961. assert eval(lambdastr((fx, f), f/fx, dummify=True))(S(10), 5) == S.Half
  962. assert lambdify(fx, 1 + fx)(41) == 42
  963. assert eval(lambdastr(fx, 1 + fx, dummify=True))(41) == 42
  964. def test_imag_real():
  965. f_re = lambdify([z], sympy.re(z))
  966. val = 3+2j
  967. assert f_re(val) == val.real
  968. f_im = lambdify([z], sympy.im(z)) # see #15400
  969. assert f_im(val) == val.imag
  970. def test_MatrixSymbol_issue_15578():
  971. if not numpy:
  972. skip("numpy not installed")
  973. A = MatrixSymbol('A', 2, 2)
  974. A0 = numpy.array([[1, 2], [3, 4]])
  975. f = lambdify(A, A**(-1))
  976. assert numpy.allclose(f(A0), numpy.array([[-2., 1.], [1.5, -0.5]]))
  977. g = lambdify(A, A**3)
  978. assert numpy.allclose(g(A0), numpy.array([[37, 54], [81, 118]]))
  979. def test_issue_15654():
  980. if not scipy:
  981. skip("scipy not installed")
  982. from sympy.abc import n, l, r, Z
  983. from sympy.physics import hydrogen
  984. nv, lv, rv, Zv = 1, 0, 3, 1
  985. sympy_value = hydrogen.R_nl(nv, lv, rv, Zv).evalf()
  986. f = lambdify((n, l, r, Z), hydrogen.R_nl(n, l, r, Z))
  987. scipy_value = f(nv, lv, rv, Zv)
  988. assert abs(sympy_value - scipy_value) < 1e-15
  989. def test_issue_15827():
  990. if not numpy:
  991. skip("numpy not installed")
  992. A = MatrixSymbol("A", 3, 3)
  993. B = MatrixSymbol("B", 2, 3)
  994. C = MatrixSymbol("C", 3, 4)
  995. D = MatrixSymbol("D", 4, 5)
  996. k=symbols("k")
  997. f = lambdify(A, (2*k)*A)
  998. g = lambdify(A, (2+k)*A)
  999. h = lambdify(A, 2*A)
  1000. i = lambdify((B, C, D), 2*B*C*D)
  1001. assert numpy.array_equal(f(numpy.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])), \
  1002. numpy.array([[2*k, 4*k, 6*k], [2*k, 4*k, 6*k], [2*k, 4*k, 6*k]], dtype=object))
  1003. assert numpy.array_equal(g(numpy.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])), \
  1004. numpy.array([[k + 2, 2*k + 4, 3*k + 6], [k + 2, 2*k + 4, 3*k + 6], \
  1005. [k + 2, 2*k + 4, 3*k + 6]], dtype=object))
  1006. assert numpy.array_equal(h(numpy.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])), \
  1007. numpy.array([[2, 4, 6], [2, 4, 6], [2, 4, 6]]))
  1008. assert numpy.array_equal(i(numpy.array([[1, 2, 3], [1, 2, 3]]), numpy.array([[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]), \
  1009. numpy.array([[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]])), numpy.array([[ 120, 240, 360, 480, 600], \
  1010. [ 120, 240, 360, 480, 600]]))
  1011. def test_issue_16930():
  1012. if not scipy:
  1013. skip("scipy not installed")
  1014. x = symbols("x")
  1015. f = lambda x: S.GoldenRatio * x**2
  1016. f_ = lambdify(x, f(x), modules='scipy')
  1017. assert f_(1) == scipy.constants.golden_ratio
  1018. def test_issue_17898():
  1019. if not scipy:
  1020. skip("scipy not installed")
  1021. x = symbols("x")
  1022. f_ = lambdify([x], sympy.LambertW(x,-1), modules='scipy')
  1023. assert f_(0.1) == mpmath.lambertw(0.1, -1)
  1024. def test_issue_13167_21411():
  1025. if not numpy:
  1026. skip("numpy not installed")
  1027. f1 = lambdify(x, sympy.Heaviside(x))
  1028. f2 = lambdify(x, sympy.Heaviside(x, 1))
  1029. res1 = f1([-1, 0, 1])
  1030. res2 = f2([-1, 0, 1])
  1031. assert Abs(res1[0]).n() < 1e-15 # First functionality: only one argument passed
  1032. assert Abs(res1[1] - 1/2).n() < 1e-15
  1033. assert Abs(res1[2] - 1).n() < 1e-15
  1034. assert Abs(res2[0]).n() < 1e-15 # Second functionality: two arguments passed
  1035. assert Abs(res2[1] - 1).n() < 1e-15
  1036. assert Abs(res2[2] - 1).n() < 1e-15
  1037. def test_single_e():
  1038. f = lambdify(x, E)
  1039. assert f(23) == exp(1.0)
  1040. def test_issue_16536():
  1041. if not scipy:
  1042. skip("scipy not installed")
  1043. a = symbols('a')
  1044. f1 = lowergamma(a, x)
  1045. F = lambdify((a, x), f1, modules='scipy')
  1046. assert abs(lowergamma(1, 3) - F(1, 3)) <= 1e-10
  1047. f2 = uppergamma(a, x)
  1048. F = lambdify((a, x), f2, modules='scipy')
  1049. assert abs(uppergamma(1, 3) - F(1, 3)) <= 1e-10
  1050. def test_issue_22726():
  1051. if not numpy:
  1052. skip("numpy not installed")
  1053. x1, x2 = symbols('x1 x2')
  1054. f = Max(S.Zero, Min(x1, x2))
  1055. g = derive_by_array(f, (x1, x2))
  1056. G = lambdify((x1, x2), g, modules='numpy')
  1057. point = {x1: 1, x2: 2}
  1058. assert (abs(g.subs(point) - G(*point.values())) <= 1e-10).all()
  1059. def test_issue_22739():
  1060. if not numpy:
  1061. skip("numpy not installed")
  1062. x1, x2 = symbols('x1 x2')
  1063. f = Heaviside(Min(x1, x2))
  1064. F = lambdify((x1, x2), f, modules='numpy')
  1065. point = {x1: 1, x2: 2}
  1066. assert abs(f.subs(point) - F(*point.values())) <= 1e-10
  1067. def test_issue_19764():
  1068. if not numpy:
  1069. skip("numpy not installed")
  1070. expr = Array([x, x**2])
  1071. f = lambdify(x, expr, 'numpy')
  1072. assert f(1).__class__ == numpy.ndarray
  1073. def test_fresnel_integrals_scipy():
  1074. if not scipy:
  1075. skip("scipy not installed")
  1076. f1 = fresnelc(x)
  1077. f2 = fresnels(x)
  1078. F1 = lambdify(x, f1, modules='scipy')
  1079. F2 = lambdify(x, f2, modules='scipy')
  1080. assert abs(fresnelc(1.3) - F1(1.3)) <= 1e-10
  1081. assert abs(fresnels(1.3) - F2(1.3)) <= 1e-10
  1082. def test_beta_scipy():
  1083. if not scipy:
  1084. skip("scipy not installed")
  1085. f = beta(x, y)
  1086. F = lambdify((x, y), f, modules='scipy')
  1087. assert abs(beta(1.3, 2.3) - F(1.3, 2.3)) <= 1e-10
  1088. def test_beta_math():
  1089. f = beta(x, y)
  1090. F = lambdify((x, y), f, modules='math')
  1091. assert abs(beta(1.3, 2.3) - F(1.3, 2.3)) <= 1e-10
  1092. def test_betainc_scipy():
  1093. if not scipy:
  1094. skip("scipy not installed")
  1095. f = betainc(w, x, y, z)
  1096. F = lambdify((w, x, y, z), f, modules='scipy')
  1097. assert abs(betainc(1.4, 3.1, 0.1, 0.5) - F(1.4, 3.1, 0.1, 0.5)) <= 1e-10
  1098. def test_betainc_regularized_scipy():
  1099. if not scipy:
  1100. skip("scipy not installed")
  1101. f = betainc_regularized(w, x, y, z)
  1102. F = lambdify((w, x, y, z), f, modules='scipy')
  1103. assert abs(betainc_regularized(0.2, 3.5, 0.1, 1) - F(0.2, 3.5, 0.1, 1)) <= 1e-10
  1104. def test_numpy_special_math():
  1105. if not numpy:
  1106. skip("numpy not installed")
  1107. funcs = [expm1, log1p, exp2, log2, log10, hypot, logaddexp, logaddexp2]
  1108. for func in funcs:
  1109. if 2 in func.nargs:
  1110. expr = func(x, y)
  1111. args = (x, y)
  1112. num_args = (0.3, 0.4)
  1113. elif 1 in func.nargs:
  1114. expr = func(x)
  1115. args = (x,)
  1116. num_args = (0.3,)
  1117. else:
  1118. raise NotImplementedError("Need to handle other than unary & binary functions in test")
  1119. f = lambdify(args, expr)
  1120. result = f(*num_args)
  1121. reference = expr.subs(dict(zip(args, num_args))).evalf()
  1122. assert numpy.allclose(result, float(reference))
  1123. lae2 = lambdify((x, y), logaddexp2(log2(x), log2(y)))
  1124. assert abs(2.0**lae2(1e-50, 2.5e-50) - 3.5e-50) < 1e-62 # from NumPy's docstring
  1125. def test_scipy_special_math():
  1126. if not scipy:
  1127. skip("scipy not installed")
  1128. cm1 = lambdify((x,), cosm1(x), modules='scipy')
  1129. assert abs(cm1(1e-20) + 5e-41) < 1e-200
  1130. def test_cupy_array_arg():
  1131. if not cupy:
  1132. skip("CuPy not installed")
  1133. f = lambdify([[x, y]], x*x + y, 'cupy')
  1134. result = f(cupy.array([2.0, 1.0]))
  1135. assert result == 5
  1136. assert "cupy" in str(type(result))
  1137. def test_cupy_array_arg_using_numpy():
  1138. # numpy functions can be run on cupy arrays
  1139. # unclear if we can "officialy" support this,
  1140. # depends on numpy __array_function__ support
  1141. if not cupy:
  1142. skip("CuPy not installed")
  1143. f = lambdify([[x, y]], x*x + y, 'numpy')
  1144. result = f(cupy.array([2.0, 1.0]))
  1145. assert result == 5
  1146. assert "cupy" in str(type(result))
  1147. def test_cupy_dotproduct():
  1148. if not cupy:
  1149. skip("CuPy not installed")
  1150. A = Matrix([x, y, z])
  1151. f1 = lambdify([x, y, z], DotProduct(A, A), modules='cupy')
  1152. f2 = lambdify([x, y, z], DotProduct(A, A.T), modules='cupy')
  1153. f3 = lambdify([x, y, z], DotProduct(A.T, A), modules='cupy')
  1154. f4 = lambdify([x, y, z], DotProduct(A, A.T), modules='cupy')
  1155. assert f1(1, 2, 3) == \
  1156. f2(1, 2, 3) == \
  1157. f3(1, 2, 3) == \
  1158. f4(1, 2, 3) == \
  1159. cupy.array([14])
  1160. def test_lambdify_cse():
  1161. def dummy_cse(exprs):
  1162. return (), exprs
  1163. def minmem(exprs):
  1164. from sympy.simplify.cse_main import cse_release_variables, cse
  1165. return cse(exprs, postprocess=cse_release_variables)
  1166. class Case:
  1167. def __init__(self, *, args, exprs, num_args, requires_numpy=False):
  1168. self.args = args
  1169. self.exprs = exprs
  1170. self.num_args = num_args
  1171. subs_dict = dict(zip(self.args, self.num_args))
  1172. self.ref = [e.subs(subs_dict).evalf() for e in exprs]
  1173. self.requires_numpy = requires_numpy
  1174. def lambdify(self, *, cse):
  1175. return lambdify(self.args, self.exprs, cse=cse)
  1176. def assertAllClose(self, result, *, abstol=1e-15, reltol=1e-15):
  1177. if self.requires_numpy:
  1178. assert all(numpy.allclose(result[i], numpy.asarray(r, dtype=float),
  1179. rtol=reltol, atol=abstol)
  1180. for i, r in enumerate(self.ref))
  1181. return
  1182. for i, r in enumerate(self.ref):
  1183. abs_err = abs(result[i] - r)
  1184. if r == 0:
  1185. assert abs_err < abstol
  1186. else:
  1187. assert abs_err/abs(r) < reltol
  1188. cases = [
  1189. Case(
  1190. args=(x, y, z),
  1191. exprs=[
  1192. x + y + z,
  1193. x + y - z,
  1194. 2*x + 2*y - z,
  1195. (x+y)**2 + (y+z)**2,
  1196. ],
  1197. num_args=(2., 3., 4.)
  1198. ),
  1199. Case(
  1200. args=(x, y, z),
  1201. exprs=[
  1202. x + sympy.Heaviside(x),
  1203. y + sympy.Heaviside(x),
  1204. z + sympy.Heaviside(x, 1),
  1205. z/sympy.Heaviside(x, 1)
  1206. ],
  1207. num_args=(0., 3., 4.)
  1208. ),
  1209. Case(
  1210. args=(x, y, z),
  1211. exprs=[
  1212. x + sinc(y),
  1213. y + sinc(y),
  1214. z - sinc(y)
  1215. ],
  1216. num_args=(0.1, 0.2, 0.3)
  1217. ),
  1218. Case(
  1219. args=(x, y, z),
  1220. exprs=[
  1221. Matrix([[x, x*y], [sin(z) + 4, x**z]]),
  1222. x*y+sin(z)-x**z,
  1223. Matrix([x*x, sin(z), x**z])
  1224. ],
  1225. num_args=(1.,2.,3.),
  1226. requires_numpy=True
  1227. ),
  1228. Case(
  1229. args=(x, y),
  1230. exprs=[(x + y - 1)**2, x, x + y,
  1231. (x + y)/(2*x + 1) + (x + y - 1)**2, (2*x + 1)**(x + y)],
  1232. num_args=(1,2)
  1233. )
  1234. ]
  1235. for case in cases:
  1236. if not numpy and case.requires_numpy:
  1237. continue
  1238. for cse in [False, True, minmem, dummy_cse]:
  1239. f = case.lambdify(cse=cse)
  1240. result = f(*case.num_args)
  1241. case.assertAllClose(result)
  1242. def test_deprecated_set():
  1243. with warns_deprecated_sympy():
  1244. lambdify({x, y}, x + y)