test_lambdify.py 58 KB

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