| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263 |
- from itertools import product
- import math
- import inspect
- import linecache
- import gc
- import mpmath
- import cmath
- from sympy.testing.pytest import raises, warns_deprecated_sympy
- from sympy.concrete.summations import Sum
- from sympy.core.function import (Function, Lambda, diff)
- from sympy.core.numbers import (E, Float, I, Rational, all_close, oo, pi)
- from sympy.core.relational import Eq
- from sympy.core.singleton import S
- from sympy.core.symbol import (Dummy, symbols)
- from sympy.functions.combinatorial.factorials import (RisingFactorial, factorial)
- from sympy.functions.combinatorial.numbers import bernoulli, harmonic
- from sympy.functions.elementary.complexes import Abs, sign
- from sympy.functions.elementary.exponential import exp, log
- from sympy.functions.elementary.hyperbolic import asinh,acosh,atanh
- from sympy.functions.elementary.integers import floor
- from sympy.functions.elementary.miscellaneous import (Max, Min, sqrt)
- from sympy.functions.elementary.piecewise import Piecewise
- from sympy.functions.elementary.trigonometric import (asin, acos, atan, cos, cot, sin,
- sinc, tan)
- from sympy.functions import sinh,cosh,tanh
- from sympy.functions.special.bessel import (besseli, besselj, besselk, bessely, jn, yn)
- from sympy.functions.special.beta_functions import (beta, betainc, betainc_regularized)
- from sympy.functions.special.delta_functions import (Heaviside)
- from sympy.functions.special.error_functions import (Ei, erf, erfc, fresnelc, fresnels, Si, Ci)
- from sympy.functions.special.gamma_functions import (digamma, gamma, loggamma, polygamma)
- from sympy.functions.special.zeta_functions import zeta
- from sympy.integrals.integrals import Integral
- from sympy.logic.boolalg import (And, false, ITE, Not, Or, true)
- from sympy.matrices.expressions.dotproduct import DotProduct
- from sympy.simplify.cse_main import cse
- from sympy.tensor.array import derive_by_array, Array
- from sympy.tensor.array.expressions import ArraySymbol
- from sympy.tensor.indexed import IndexedBase, Idx
- from sympy.utilities.lambdify import lambdify
- from sympy.utilities.iterables import numbered_symbols
- from sympy.vector import CoordSys3D
- from sympy.core.expr import UnevaluatedExpr
- from sympy.codegen.cfunctions import expm1, log1p, exp2, log2, log10, hypot, isnan, isinf
- from sympy.codegen.numpy_nodes import logaddexp, logaddexp2, amin, amax, minimum, maximum
- from sympy.codegen.scipy_nodes import cosm1, powm1
- from sympy.functions.elementary.complexes import re, im, arg
- from sympy.functions.special.polynomials import \
- chebyshevt, chebyshevu, legendre, hermite, laguerre, gegenbauer, \
- assoc_legendre, assoc_laguerre, jacobi
- from sympy.matrices import Matrix, MatrixSymbol, SparseMatrix
- from sympy.printing.codeprinter import PrintMethodNotImplementedError
- from sympy.printing.lambdarepr import LambdaPrinter
- from sympy.printing.numpy import NumPyPrinter
- from sympy.utilities.lambdify import implemented_function, lambdastr
- from sympy.testing.pytest import skip
- from sympy.utilities.decorator import conserve_mpmath_dps
- from sympy.utilities.exceptions import ignore_warnings
- from sympy.external import import_module
- from sympy.functions.special.gamma_functions import uppergamma, lowergamma
- import sympy
- MutableDenseMatrix = Matrix
- numpy = import_module('numpy')
- scipy = import_module('scipy', import_kwargs={'fromlist': ['sparse']})
- numexpr = import_module('numexpr')
- tensorflow = import_module('tensorflow')
- cupy = import_module('cupy')
- jax = import_module('jax')
- numba = import_module('numba')
- if tensorflow:
- # Hide Tensorflow warnings
- import os
- os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
- w, x, y, z = symbols('w,x,y,z')
- #================== Test different arguments =======================
- def test_no_args():
- f = lambdify([], 1)
- raises(TypeError, lambda: f(-1))
- assert f() == 1
- def test_single_arg():
- f = lambdify(x, 2*x)
- assert f(1) == 2
- def test_list_args():
- f = lambdify([x, y], x + y)
- assert f(1, 2) == 3
- def test_nested_args():
- f1 = lambdify([[w, x]], [w, x])
- assert f1([91, 2]) == [91, 2]
- raises(TypeError, lambda: f1(1, 2))
- f2 = lambdify([(w, x), (y, z)], [w, x, y, z])
- assert f2((18, 12), (73, 4)) == [18, 12, 73, 4]
- raises(TypeError, lambda: f2(3, 4))
- f3 = lambdify([w, [[[x]], y], z], [w, x, y, z])
- assert f3(10, [[[52]], 31], 44) == [10, 52, 31, 44]
- def test_str_args():
- f = lambdify('x,y,z', 'z,y,x')
- assert f(3, 2, 1) == (1, 2, 3)
- assert f(1.0, 2.0, 3.0) == (3.0, 2.0, 1.0)
- # make sure correct number of args required
- raises(TypeError, lambda: f(0))
- def test_own_namespace_1():
- myfunc = lambda x: 1
- f = lambdify(x, sin(x), {"sin": myfunc})
- assert f(0.1) == 1
- assert f(100) == 1
- def test_own_namespace_2():
- def myfunc(x):
- return 1
- f = lambdify(x, sin(x), {'sin': myfunc})
- assert f(0.1) == 1
- assert f(100) == 1
- def test_own_module():
- f = lambdify(x, sin(x), math)
- assert f(0) == 0.0
- p, q, r = symbols("p q r", real=True)
- ae = abs(exp(p+UnevaluatedExpr(q+r)))
- f = lambdify([p, q, r], [ae, ae], modules=math)
- results = f(1.0, 1e18, -1e18)
- refvals = [math.exp(1.0)]*2
- for res, ref in zip(results, refvals):
- assert abs((res-ref)/ref) < 1e-15
- def test_bad_args():
- # no vargs given
- raises(TypeError, lambda: lambdify(1))
- # same with vector exprs
- raises(TypeError, lambda: lambdify([1, 2]))
- def test_atoms():
- # Non-Symbol atoms should not be pulled out from the expression namespace
- f = lambdify(x, pi + x, {"pi": 3.14})
- assert f(0) == 3.14
- f = lambdify(x, I + x, {"I": 1j})
- assert f(1) == 1 + 1j
- #================== Test different modules =========================
- # high precision output of sin(0.2*pi) is used to detect if precision is lost unwanted
- @conserve_mpmath_dps
- def test_sympy_lambda():
- mpmath.mp.dps = 50
- sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020")
- f = lambdify(x, sin(x), "sympy")
- assert f(x) == sin(x)
- prec = 1e-15
- assert -prec < f(Rational(1, 5)).evalf() - Float(str(sin02)) < prec
- # arctan is in numpy module and should not be available
- # The arctan below gives NameError. What is this supposed to test?
- # raises(NameError, lambda: lambdify(x, arctan(x), "sympy"))
- @conserve_mpmath_dps
- def test_math_lambda():
- mpmath.mp.dps = 50
- sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020")
- f = lambdify(x, sin(x), "math")
- prec = 1e-15
- assert -prec < f(0.2) - sin02 < prec
- raises(TypeError, lambda: f(x))
- # if this succeeds, it can't be a Python math function
- @conserve_mpmath_dps
- def test_mpmath_lambda():
- mpmath.mp.dps = 50
- sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020")
- f = lambdify(x, sin(x), "mpmath")
- prec = 1e-49 # mpmath precision is around 50 decimal places
- assert -prec < f(mpmath.mpf("0.2")) - sin02 < prec
- raises(TypeError, lambda: f(x))
- # if this succeeds, it can't be a mpmath function
- ref2 = (mpmath.mpf("1e-30")
- - mpmath.mpf("1e-45")/2
- + 5*mpmath.mpf("1e-60")/6
- - 3*mpmath.mpf("1e-75")/4
- + 33*mpmath.mpf("1e-90")/40
- )
- f2a = lambdify((x, y), x**y - 1, "mpmath")
- f2b = lambdify((x, y), powm1(x, y), "mpmath")
- f2c = lambdify((x,), expm1(x*log1p(x)), "mpmath")
- ans2a = f2a(mpmath.mpf("1")+mpmath.mpf("1e-15"), mpmath.mpf("1e-15"))
- ans2b = f2b(mpmath.mpf("1")+mpmath.mpf("1e-15"), mpmath.mpf("1e-15"))
- ans2c = f2c(mpmath.mpf("1e-15"))
- assert abs(ans2a - ref2) < 1e-51
- assert abs(ans2b - ref2) < 1e-67
- assert abs(ans2c - ref2) < 1e-80
- @conserve_mpmath_dps
- def test_number_precision():
- mpmath.mp.dps = 50
- sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020")
- f = lambdify(x, sin02, "mpmath")
- prec = 1e-49 # mpmath precision is around 50 decimal places
- assert -prec < f(0) - sin02 < prec
- @conserve_mpmath_dps
- def test_mpmath_precision():
- mpmath.mp.dps = 100
- assert str(lambdify((), pi.evalf(100), 'mpmath')()) == str(pi.evalf(100))
- #================== Test Translations ==============================
- # We can only check if all translated functions are valid. It has to be checked
- # by hand if they are complete.
- def test_math_transl():
- from sympy.utilities.lambdify import MATH_TRANSLATIONS
- for sym, mat in MATH_TRANSLATIONS.items():
- assert sym in sympy.__dict__
- assert mat in math.__dict__
- def test_mpmath_transl():
- from sympy.utilities.lambdify import MPMATH_TRANSLATIONS
- for sym, mat in MPMATH_TRANSLATIONS.items():
- assert sym in sympy.__dict__ or sym == 'Matrix'
- assert mat in mpmath.__dict__
- def test_numpy_transl():
- if not numpy:
- skip("numpy not installed.")
- from sympy.utilities.lambdify import NUMPY_TRANSLATIONS
- for sym, nump in NUMPY_TRANSLATIONS.items():
- assert sym in sympy.__dict__
- assert nump in numpy.__dict__
- def test_scipy_transl():
- if not scipy:
- skip("scipy not installed.")
- from sympy.utilities.lambdify import SCIPY_TRANSLATIONS
- for sym, scip in SCIPY_TRANSLATIONS.items():
- assert sym in sympy.__dict__
- assert scip in scipy.__dict__ or scip in scipy.special.__dict__
- def test_numpy_translation_abs():
- if not numpy:
- skip("numpy not installed.")
- f = lambdify(x, Abs(x), "numpy")
- assert f(-1) == 1
- assert f(1) == 1
- def test_numexpr_printer():
- if not numexpr:
- skip("numexpr not installed.")
- # if translation/printing is done incorrectly then evaluating
- # a lambdified numexpr expression will throw an exception
- from sympy.printing.lambdarepr import NumExprPrinter
- blacklist = ('where', 'complex', 'contains')
- arg_tuple = (x, y, z) # some functions take more than one argument
- for sym in NumExprPrinter._numexpr_functions.keys():
- if sym in blacklist:
- continue
- ssym = S(sym)
- if hasattr(ssym, '_nargs'):
- nargs = ssym._nargs[0]
- else:
- nargs = 1
- args = arg_tuple[:nargs]
- f = lambdify(args, ssym(*args), modules='numexpr')
- assert f(*(1, )*nargs) is not None
- def test_cmath_sqrt():
- f = lambdify(x, sqrt(x), "cmath")
- assert f(0) == 0
- assert f(1) == 1
- assert f(4) == 2
- assert abs(f(2) - 1.414) < 0.001
- assert f(-1) == 1j
- assert f(-4) == 2j
- def test_cmath_log():
- f = lambdify(x, log(x), "cmath")
- assert abs(f(1) - 0) < 1e-15
- assert abs(f(cmath.e) - 1) < 1e-15
- assert abs(f(-1) - cmath.log(-1)) < 1e-15
- def test_cmath_sinh():
- f = lambdify(x, sinh(x), "cmath")
- assert abs(f(0) - cmath.sinh(0)) < 1e-15
- assert abs(f(pi) - cmath.sinh(pi)) < 1e-15
- assert abs(f(-pi) - cmath.sinh(-pi)) < 1e-15
- assert abs(f(1j) - cmath.sinh(1j)) < 1e-15
- def test_cmath_cosh():
- f = lambdify(x, cosh(x), "cmath")
- assert abs(f(0) - cmath.cosh(0)) < 1e-15
- assert abs(f(pi) - cmath.cosh(pi)) < 1e-15
- assert abs(f(-pi) - cmath.cosh(-pi)) < 1e-15
- assert abs(f(1j) - cmath.cosh(1j)) < 1e-15
- def test_cmath_tanh():
- f = lambdify(x, tanh(x), "cmath")
- assert abs(f(0) - cmath.tanh(0)) < 1e-15
- assert abs(f(pi) - cmath.tanh(pi)) < 1e-15
- assert abs(f(-pi) - cmath.tanh(-pi)) < 1e-15
- assert abs(f(1j) - cmath.tanh(1j)) < 1e-15
- def test_cmath_sin():
- f = lambdify(x, sin(x), "cmath")
- assert abs(f(0) - cmath.sin(0)) < 1e-15
- assert abs(f(pi) - cmath.sin(pi)) < 1e-15
- assert abs(f(-pi) - cmath.sin(-pi)) < 1e-15
- assert abs(f(1j) - cmath.sin(1j)) < 1e-15
- def test_cmath_cos():
- f = lambdify(x, cos(x), "cmath")
- assert abs(f(0) - cmath.cos(0)) < 1e-15
- assert abs(f(pi) - cmath.cos(pi)) < 1e-15
- assert abs(f(-pi) - cmath.cos(-pi)) < 1e-15
- assert abs(f(1j) - cmath.cos(1j)) < 1e-15
- def test_cmath_tan():
- f = lambdify(x, tan(x), "cmath")
- assert abs(f(0) - cmath.tan(0)) < 1e-15
- assert abs(f(1j) - cmath.tan(1j)) < 1e-15
- def test_cmath_asin():
- f = lambdify(x, asin(x), "cmath")
- assert abs(f(0) - cmath.asin(0)) < 1e-15
- assert abs(f(1) - cmath.asin(1)) < 1e-15
- assert abs(f(-1) - cmath.asin(-1)) < 1e-15
- assert abs(f(2) - cmath.asin(2)) < 1e-15
- assert abs(f(1j) - cmath.asin(1j)) < 1e-15
- def test_cmath_acos():
- f = lambdify(x, acos(x), "cmath")
- assert abs(f(1) - cmath.acos(1)) < 1e-15
- assert abs(f(-1) - cmath.acos(-1)) < 1e-15
- assert abs(f(2) - cmath.acos(2)) < 1e-15
- assert abs(f(1j) - cmath.acos(1j)) < 1e-15
- def test_cmath_atan():
- f = lambdify(x, atan(x), "cmath")
- assert abs(f(0) - cmath.atan(0)) < 1e-15
- assert abs(f(1) - cmath.atan(1)) < 1e-15
- assert abs(f(-1) - cmath.atan(-1)) < 1e-15
- assert abs(f(2) - cmath.atan(2)) < 1e-15
- assert abs(f(2j) - cmath.atan(2j)) < 1e-15
- def test_cmath_asinh():
- f = lambdify(x, asinh(x), "cmath")
- assert abs(f(0) - cmath.asinh(0)) < 1e-15
- assert abs(f(1) - cmath.asinh(1)) < 1e-15
- assert abs(f(-1) - cmath.asinh(-1)) < 1e-15
- assert abs(f(2) - cmath.asinh(2)) < 1e-15
- assert abs(f(2j) - cmath.asinh(2j)) < 1e-15
- def test_cmath_acosh():
- f = lambdify(x, acosh(x), "cmath")
- assert abs(f(1) - cmath.acosh(1)) < 1e-15
- assert abs(f(2) - cmath.acosh(2)) < 1e-15
- assert abs(f(-1) - cmath.acosh(-1)) < 1e-15
- assert abs(f(2j) - cmath.acosh(2j)) < 1e-15
- def test_cmath_atanh():
- f = lambdify(x, atanh(x), "cmath")
- assert abs(f(0) - cmath.atanh(0)) < 1e-15
- assert abs(f(0.5) - cmath.atanh(0.5)) < 1e-15
- assert abs(f(-0.5) - cmath.atanh(-0.5)) < 1e-15
- assert abs(f(2) - cmath.atanh(2)) < 1e-15
- assert abs(f(-2) - cmath.atanh(-2)) < 1e-15
- assert abs(f(2j) - cmath.atanh(2j)) < 1e-15
- def test_cmath_complex_identities():
- # Define symbol
- z = symbols('z')
- # Trigonometric identity using re(z) and im(z)
- expr = cos(z) - cos(re(z)) * cosh(im(z)) + I * sin(re(z)) * sinh(im(z))
- func = lambdify([z], expr, modules=["cmath", "math"])
- hpi = math.pi / 2
- assert abs(func(hpi + 1j * hpi)) < 4e-16
- # Euler's Formula: e^(i*z) = cos(z) + i*sin(z)
- func = lambdify([z], exp(I * z) - (cos(z) + I * sin(z)), modules=["cmath", "math"])
- assert abs(func(hpi)) < 4e-16
- # Exponential Identity: e^z = e^(Re(z)) * (cos(Im(z)) + i*sin(Im(z)))
- func_exp = lambdify([z], exp(z) - exp(re(z)) * (cos(im(z)) + I * sin(im(z))),
- modules=["cmath", "math"])
- assert abs(func_exp(hpi + 1j * hpi)) < 4e-16
- # Complex Cosine Identity: cos(z) = cos(Re(z)) * cosh(Im(z)) - i*sin(Re(z)) * sinh(Im(z))
- func_cos = lambdify([z], cos(z) - (cos(re(z)) * cosh(im(z)) - I * sin(re(z)) * sinh(im(z))),
- modules=["cmath", "math"])
- assert abs(func_cos(hpi + 1j * hpi)) < 4e-16
- # Complex Sine Identity: sin(z) = sin(Re(z)) * cosh(Im(z)) + i*cos(Re(z)) * sinh(Im(z))
- func_sin = lambdify([z], sin(z) - (sin(re(z)) * cosh(im(z)) + I * cos(re(z)) * sinh(im(z))),
- modules=["cmath", "math"])
- assert abs(func_sin(hpi + 1j * hpi)) < 4e-16
- # Complex Hyperbolic Cosine Identity: cosh(z) = cosh(Re(z)) * cos(Im(z)) + i*sinh(Re(z)) * sin(Im(z))
- func_cosh_1 = lambdify([z], cosh(z) - (cosh(re(z)) * cos(im(z)) + I * sinh(re(z)) * sin(im(z))),
- modules=["cmath", "math"])
- assert abs(func_cosh_1(hpi + 1j * hpi)) < 4e-16
- # Complex Hyperbolic Sine Identity: sinh(z) = sinh(Re(z)) * cos(Im(z)) + i*cosh(Re(z)) * sin(Im(z))
- func_sinh = lambdify([z], sinh(z) - (sinh(re(z)) * cos(im(z)) + I * cosh(re(z)) * sin(im(z))),
- modules=["cmath", "math"])
- assert abs(func_sinh(hpi + 1j * hpi)) < 4e-16
- # cosh(z) = (e^z + e^(-z)) / 2
- func_cosh_2 = lambdify([z], cosh(z) - (exp(z) + exp(-z)) / 2, modules=["cmath", "math"])
- assert abs(func_cosh_2(hpi)) < 4e-16
- # Additional expressions testing log and exp with real and imaginary parts
- expr1 = log(re(z)) + log(im(z)) - log(re(z) * im(z))
- expr2 = exp(re(z)) * exp(im(z) * I) - exp(z)
- expr3 = log(exp(re(z))) - re(z)
- expr4 = exp(log(re(z))) - re(z)
- expr5 = log(exp(re(z) + im(z))) - (re(z) + im(z))
- expr6 = exp(log(re(z) + im(z))) - (re(z) + im(z))
- func1 = lambdify([z], expr1, modules=["cmath", "math"])
- func2 = lambdify([z], expr2, modules=["cmath", "math"])
- func3 = lambdify([z], expr3, modules=["cmath", "math"])
- func4 = lambdify([z], expr4, modules=["cmath", "math"])
- func5 = lambdify([z], expr5, modules=["cmath", "math"])
- func6 = lambdify([z], expr6, modules=["cmath", "math"])
- test_value = 3 + 4j
- assert abs(func1(test_value)) < 4e-16
- assert abs(func2(test_value)) < 4e-16
- assert abs(func3(test_value)) < 4e-16
- assert abs(func4(test_value)) < 4e-16
- assert abs(func5(test_value)) < 4e-16
- assert abs(func6(test_value)) < 4e-16
- def test_issue_9334():
- if not numexpr:
- skip("numexpr not installed.")
- if not numpy:
- skip("numpy not installed.")
- expr = S('b*a - sqrt(a**2)')
- a, b = sorted(expr.free_symbols, key=lambda s: s.name)
- func_numexpr = lambdify((a,b), expr, modules=[numexpr], dummify=False)
- foo, bar = numpy.random.random((2, 4))
- func_numexpr(foo, bar)
- def test_issue_12984():
- if not numexpr:
- skip("numexpr not installed.")
- func_numexpr = lambdify((x,y,z), Piecewise((y, x >= 0), (z, x > -1)), numexpr)
- with ignore_warnings(RuntimeWarning):
- assert func_numexpr(1, 24, 42) == 24
- assert str(func_numexpr(-1, 24, 42)) == 'nan'
- def test_empty_modules():
- x, y = symbols('x y')
- expr = -(x % y)
- no_modules = lambdify([x, y], expr)
- empty_modules = lambdify([x, y], expr, modules=[])
- assert no_modules(3, 7) == empty_modules(3, 7)
- assert no_modules(3, 7) == -3
- def test_exponentiation():
- f = lambdify(x, x**2)
- assert f(-1) == 1
- assert f(0) == 0
- assert f(1) == 1
- assert f(-2) == 4
- assert f(2) == 4
- assert f(2.5) == 6.25
- def test_sqrt():
- f = lambdify(x, sqrt(x))
- assert f(0) == 0.0
- assert f(1) == 1.0
- assert f(4) == 2.0
- assert abs(f(2) - 1.414) < 0.001
- assert f(6.25) == 2.5
- def test_trig():
- f = lambdify([x], [cos(x), sin(x)], 'math')
- d = f(pi)
- prec = 1e-11
- assert -prec < d[0] + 1 < prec
- assert -prec < d[1] < prec
- d = f(3.14159)
- prec = 1e-5
- assert -prec < d[0] + 1 < prec
- assert -prec < d[1] < prec
- def test_integral():
- if numpy and not scipy:
- skip("scipy not installed.")
- f = Lambda(x, exp(-x**2))
- l = lambdify(y, Integral(f(x), (x, y, oo)))
- d = l(-oo)
- assert 1.77245385 < d < 1.772453851
- def test_double_integral():
- if numpy and not scipy:
- skip("scipy not installed.")
- # example from http://mpmath.org/doc/current/calculus/integration.html
- i = Integral(1/(1 - x**2*y**2), (x, 0, 1), (y, 0, z))
- l = lambdify([z], i)
- d = l(1)
- assert 1.23370055 < d < 1.233700551
- def test_spherical_bessel():
- if numpy and not scipy:
- skip("scipy not installed.")
- test_point = 4.2 #randomly selected
- x = symbols("x")
- jtest = jn(2, x)
- assert abs(lambdify(x,jtest)(test_point) -
- jtest.subs(x,test_point).evalf()) < 1e-8
- ytest = yn(2, x)
- assert abs(lambdify(x,ytest)(test_point) -
- ytest.subs(x,test_point).evalf()) < 1e-8
- #================== Test vectors ===================================
- def test_vector_simple():
- f = lambdify((x, y, z), (z, y, x))
- assert f(3, 2, 1) == (1, 2, 3)
- assert f(1.0, 2.0, 3.0) == (3.0, 2.0, 1.0)
- # make sure correct number of args required
- raises(TypeError, lambda: f(0))
- def test_vector_discontinuous():
- f = lambdify(x, (-1/x, 1/x))
- raises(ZeroDivisionError, lambda: f(0))
- assert f(1) == (-1.0, 1.0)
- assert f(2) == (-0.5, 0.5)
- assert f(-2) == (0.5, -0.5)
- def test_trig_symbolic():
- f = lambdify([x], [cos(x), sin(x)], 'math')
- d = f(pi)
- assert abs(d[0] + 1) < 0.0001
- assert abs(d[1] - 0) < 0.0001
- def test_trig_float():
- f = lambdify([x], [cos(x), sin(x)])
- d = f(3.14159)
- assert abs(d[0] + 1) < 0.0001
- assert abs(d[1] - 0) < 0.0001
- def test_docs():
- f = lambdify(x, x**2)
- assert f(2) == 4
- f = lambdify([x, y, z], [z, y, x])
- assert f(1, 2, 3) == [3, 2, 1]
- f = lambdify(x, sqrt(x))
- assert f(4) == 2.0
- f = lambdify((x, y), sin(x*y)**2)
- assert f(0, 5) == 0
- def test_math():
- f = lambdify((x, y), sin(x), modules="math")
- assert f(0, 5) == 0
- def test_sin():
- f = lambdify(x, sin(x)**2)
- assert isinstance(f(2), float)
- f = lambdify(x, sin(x)**2, modules="math")
- assert isinstance(f(2), float)
- def test_matrix():
- A = Matrix([[x, x*y], [sin(z) + 4, x**z]])
- sol = Matrix([[1, 2], [sin(3) + 4, 1]])
- f = lambdify((x, y, z), A, modules="sympy")
- assert f(1, 2, 3) == sol
- f = lambdify((x, y, z), (A, [A]), modules="sympy")
- assert f(1, 2, 3) == (sol, [sol])
- J = Matrix((x, x + y)).jacobian((x, y))
- v = Matrix((x, y))
- sol = Matrix([[1, 0], [1, 1]])
- assert lambdify(v, J, modules='sympy')(1, 2) == sol
- assert lambdify(v.T, J, modules='sympy')(1, 2) == sol
- def test_numpy_matrix():
- if not numpy:
- skip("numpy not installed.")
- A = Matrix([[x, x*y], [sin(z) + 4, x**z]])
- sol_arr = numpy.array([[1, 2], [numpy.sin(3) + 4, 1]])
- #Lambdify array first, to ensure return to array as default
- f = lambdify((x, y, z), A, ['numpy'])
- numpy.testing.assert_allclose(f(1, 2, 3), sol_arr)
- #Check that the types are arrays and matrices
- assert isinstance(f(1, 2, 3), numpy.ndarray)
- # gh-15071
- class dot(Function):
- pass
- x_dot_mtx = dot(x, Matrix([[2], [1], [0]]))
- f_dot1 = lambdify(x, x_dot_mtx)
- inp = numpy.zeros((17, 3))
- assert numpy.all(f_dot1(inp) == 0)
- strict_kw = {"allow_unknown_functions": False, "inline": True, "fully_qualified_modules": False}
- p2 = NumPyPrinter(dict(user_functions={'dot': 'dot'}, **strict_kw))
- f_dot2 = lambdify(x, x_dot_mtx, printer=p2)
- assert numpy.all(f_dot2(inp) == 0)
- p3 = NumPyPrinter(strict_kw)
- # The line below should probably fail upon construction (before calling with "(inp)"):
- raises(Exception, lambda: lambdify(x, x_dot_mtx, printer=p3)(inp))
- def test_numpy_transpose():
- if not numpy:
- skip("numpy not installed.")
- A = Matrix([[1, x], [0, 1]])
- f = lambdify((x), A.T, modules="numpy")
- numpy.testing.assert_array_equal(f(2), numpy.array([[1, 0], [2, 1]]))
- def test_numpy_dotproduct():
- if not numpy:
- skip("numpy not installed")
- A = Matrix([x, y, z])
- f1 = lambdify([x, y, z], DotProduct(A, A), modules='numpy')
- f2 = lambdify([x, y, z], DotProduct(A, A.T), modules='numpy')
- f3 = lambdify([x, y, z], DotProduct(A.T, A), modules='numpy')
- f4 = lambdify([x, y, z], DotProduct(A, A.T), modules='numpy')
- assert f1(1, 2, 3) == \
- f2(1, 2, 3) == \
- f3(1, 2, 3) == \
- f4(1, 2, 3) == \
- numpy.array([14])
- def test_numpy_inverse():
- if not numpy:
- skip("numpy not installed.")
- A = Matrix([[1, x], [0, 1]])
- f = lambdify((x), A**-1, modules="numpy")
- numpy.testing.assert_array_equal(f(2), numpy.array([[1, -2], [0, 1]]))
- def test_numpy_old_matrix():
- if not numpy:
- skip("numpy not installed.")
- A = Matrix([[x, x*y], [sin(z) + 4, x**z]])
- sol_arr = numpy.array([[1, 2], [numpy.sin(3) + 4, 1]])
- f = lambdify((x, y, z), A, [{'ImmutableDenseMatrix': numpy.matrix}, 'numpy'])
- with ignore_warnings(PendingDeprecationWarning):
- numpy.testing.assert_allclose(f(1, 2, 3), sol_arr)
- assert isinstance(f(1, 2, 3), numpy.matrix)
- def test_scipy_sparse_matrix():
- if not scipy:
- skip("scipy not installed.")
- A = SparseMatrix([[x, 0], [0, y]])
- f = lambdify((x, y), A, modules="scipy")
- B = f(1, 2)
- assert isinstance(B, scipy.sparse.coo_matrix)
- def test_python_div_zero_issue_11306():
- if not numpy:
- skip("numpy not installed.")
- p = Piecewise((1 / x, y < -1), (x, y < 1), (1 / x, True))
- f = lambdify([x, y], p, modules='numpy')
- with numpy.errstate(divide='ignore'):
- assert float(f(numpy.array(0), numpy.array(0.5))) == 0
- assert float(f(numpy.array(0), numpy.array(1))) == float('inf')
- def test_issue9474():
- mods = [None, 'math']
- if numpy:
- mods.append('numpy')
- if mpmath:
- mods.append('mpmath')
- for mod in mods:
- f = lambdify(x, S.One/x, modules=mod)
- assert f(2) == 0.5
- f = lambdify(x, floor(S.One/x), modules=mod)
- assert f(2) == 0
- for absfunc, modules in product([Abs, abs], mods):
- f = lambdify(x, absfunc(x), modules=modules)
- assert f(-1) == 1
- assert f(1) == 1
- assert f(3+4j) == 5
- def test_issue_9871():
- if not numexpr:
- skip("numexpr not installed.")
- if not numpy:
- skip("numpy not installed.")
- r = sqrt(x**2 + y**2)
- expr = diff(1/r, x)
- xn = yn = numpy.linspace(1, 10, 16)
- # expr(xn, xn) = -xn/(sqrt(2)*xn)^3
- fv_exact = -numpy.sqrt(2.)**-3 * xn**-2
- fv_numpy = lambdify((x, y), expr, modules='numpy')(xn, yn)
- fv_numexpr = lambdify((x, y), expr, modules='numexpr')(xn, yn)
- numpy.testing.assert_allclose(fv_numpy, fv_exact, rtol=1e-10)
- numpy.testing.assert_allclose(fv_numexpr, fv_exact, rtol=1e-10)
- def test_numpy_piecewise():
- if not numpy:
- skip("numpy not installed.")
- pieces = Piecewise((x, x < 3), (x**2, x > 5), (0, True))
- f = lambdify(x, pieces, modules="numpy")
- numpy.testing.assert_array_equal(f(numpy.arange(10)),
- numpy.array([0, 1, 2, 0, 0, 0, 36, 49, 64, 81]))
- # If we evaluate somewhere all conditions are False, we should get back NaN
- nodef_func = lambdify(x, Piecewise((x, x > 0), (-x, x < 0)))
- numpy.testing.assert_array_equal(nodef_func(numpy.array([-1, 0, 1])),
- numpy.array([1, numpy.nan, 1]))
- def test_numpy_logical_ops():
- if not numpy:
- skip("numpy not installed.")
- and_func = lambdify((x, y), And(x, y), modules="numpy")
- and_func_3 = lambdify((x, y, z), And(x, y, z), modules="numpy")
- or_func = lambdify((x, y), Or(x, y), modules="numpy")
- or_func_3 = lambdify((x, y, z), Or(x, y, z), modules="numpy")
- not_func = lambdify((x), Not(x), modules="numpy")
- arr1 = numpy.array([True, True])
- arr2 = numpy.array([False, True])
- arr3 = numpy.array([True, False])
- numpy.testing.assert_array_equal(and_func(arr1, arr2), numpy.array([False, True]))
- numpy.testing.assert_array_equal(and_func_3(arr1, arr2, arr3), numpy.array([False, False]))
- numpy.testing.assert_array_equal(or_func(arr1, arr2), numpy.array([True, True]))
- numpy.testing.assert_array_equal(or_func_3(arr1, arr2, arr3), numpy.array([True, True]))
- numpy.testing.assert_array_equal(not_func(arr2), numpy.array([True, False]))
- def test_numpy_matmul():
- if not numpy:
- skip("numpy not installed.")
- xmat = Matrix([[x, y], [z, 1+z]])
- ymat = Matrix([[x**2], [Abs(x)]])
- mat_func = lambdify((x, y, z), xmat*ymat, modules="numpy")
- numpy.testing.assert_array_equal(mat_func(0.5, 3, 4), numpy.array([[1.625], [3.5]]))
- numpy.testing.assert_array_equal(mat_func(-0.5, 3, 4), numpy.array([[1.375], [3.5]]))
- # Multiple matrices chained together in multiplication
- f = lambdify((x, y, z), xmat*xmat*xmat, modules="numpy")
- numpy.testing.assert_array_equal(f(0.5, 3, 4), numpy.array([[72.125, 119.25],
- [159, 251]]))
- def test_numpy_numexpr():
- if not numpy:
- skip("numpy not installed.")
- if not numexpr:
- skip("numexpr not installed.")
- a, b, c = numpy.random.randn(3, 128, 128)
- # ensure that numpy and numexpr return same value for complicated expression
- expr = sin(x) + cos(y) + tan(z)**2 + Abs(z-y)*acos(sin(y*z)) + \
- Abs(y-z)*acosh(2+exp(y-x))- sqrt(x**2+I*y**2)
- npfunc = lambdify((x, y, z), expr, modules='numpy')
- nefunc = lambdify((x, y, z), expr, modules='numexpr')
- assert numpy.allclose(npfunc(a, b, c), nefunc(a, b, c))
- def test_numexpr_userfunctions():
- if not numpy:
- skip("numpy not installed.")
- if not numexpr:
- skip("numexpr not installed.")
- a, b = numpy.random.randn(2, 10)
- uf = type('uf', (Function, ),
- {'eval' : classmethod(lambda x, y : y**2+1)})
- func = lambdify(x, 1-uf(x), modules='numexpr')
- assert numpy.allclose(func(a), -(a**2))
- uf = implemented_function(Function('uf'), lambda x, y : 2*x*y+1)
- func = lambdify((x, y), uf(x, y), modules='numexpr')
- assert numpy.allclose(func(a, b), 2*a*b+1)
- def test_tensorflow_basic_math():
- if not tensorflow:
- skip("tensorflow not installed.")
- expr = Max(sin(x), Abs(1/(x+2)))
- func = lambdify(x, expr, modules="tensorflow")
- with tensorflow.compat.v1.Session() as s:
- a = tensorflow.constant(0, dtype=tensorflow.float32)
- assert func(a).eval(session=s) == 0.5
- def test_tensorflow_placeholders():
- if not tensorflow:
- skip("tensorflow not installed.")
- expr = Max(sin(x), Abs(1/(x+2)))
- func = lambdify(x, expr, modules="tensorflow")
- with tensorflow.compat.v1.Session() as s:
- a = tensorflow.compat.v1.placeholder(dtype=tensorflow.float32)
- assert func(a).eval(session=s, feed_dict={a: 0}) == 0.5
- def test_tensorflow_variables():
- if not tensorflow:
- skip("tensorflow not installed.")
- expr = Max(sin(x), Abs(1/(x+2)))
- func = lambdify(x, expr, modules="tensorflow")
- with tensorflow.compat.v1.Session() as s:
- a = tensorflow.Variable(0, dtype=tensorflow.float32)
- s.run(a.initializer)
- assert func(a).eval(session=s, feed_dict={a: 0}) == 0.5
- def test_tensorflow_logical_operations():
- if not tensorflow:
- skip("tensorflow not installed.")
- expr = Not(And(Or(x, y), y))
- func = lambdify([x, y], expr, modules="tensorflow")
- with tensorflow.compat.v1.Session() as s:
- assert func(False, True).eval(session=s) == False
- def test_tensorflow_piecewise():
- if not tensorflow:
- skip("tensorflow not installed.")
- expr = Piecewise((0, Eq(x,0)), (-1, x < 0), (1, x > 0))
- func = lambdify(x, expr, modules="tensorflow")
- with tensorflow.compat.v1.Session() as s:
- assert func(-1).eval(session=s) == -1
- assert func(0).eval(session=s) == 0
- assert func(1).eval(session=s) == 1
- def test_tensorflow_multi_max():
- if not tensorflow:
- skip("tensorflow not installed.")
- expr = Max(x, -x, x**2)
- func = lambdify(x, expr, modules="tensorflow")
- with tensorflow.compat.v1.Session() as s:
- assert func(-2).eval(session=s) == 4
- def test_tensorflow_multi_min():
- if not tensorflow:
- skip("tensorflow not installed.")
- expr = Min(x, -x, x**2)
- func = lambdify(x, expr, modules="tensorflow")
- with tensorflow.compat.v1.Session() as s:
- assert func(-2).eval(session=s) == -2
- def test_tensorflow_relational():
- if not tensorflow:
- skip("tensorflow not installed.")
- expr = x >= 0
- func = lambdify(x, expr, modules="tensorflow")
- with tensorflow.compat.v1.Session() as s:
- assert func(1).eval(session=s) == True
- def test_tensorflow_complexes():
- if not tensorflow:
- skip("tensorflow not installed")
- func1 = lambdify(x, re(x), modules="tensorflow")
- func2 = lambdify(x, im(x), modules="tensorflow")
- func3 = lambdify(x, Abs(x), modules="tensorflow")
- func4 = lambdify(x, arg(x), modules="tensorflow")
- with tensorflow.compat.v1.Session() as s:
- # For versions before
- # https://github.com/tensorflow/tensorflow/issues/30029
- # resolved, using Python numeric types may not work
- a = tensorflow.constant(1+2j)
- assert func1(a).eval(session=s) == 1
- assert func2(a).eval(session=s) == 2
- tensorflow_result = func3(a).eval(session=s)
- sympy_result = Abs(1 + 2j).evalf()
- assert abs(tensorflow_result-sympy_result) < 10**-6
- tensorflow_result = func4(a).eval(session=s)
- sympy_result = arg(1 + 2j).evalf()
- assert abs(tensorflow_result-sympy_result) < 10**-6
- def test_tensorflow_array_arg():
- # Test for issue 14655 (tensorflow part)
- if not tensorflow:
- skip("tensorflow not installed.")
- f = lambdify([[x, y]], x*x + y, 'tensorflow')
- with tensorflow.compat.v1.Session() as s:
- fcall = f(tensorflow.constant([2.0, 1.0]))
- assert fcall.eval(session=s) == 5.0
- #================== Test symbolic ==================================
- def test_sym_single_arg():
- f = lambdify(x, x * y)
- assert f(z) == z * y
- def test_sym_list_args():
- f = lambdify([x, y], x + y + z)
- assert f(1, 2) == 3 + z
- def test_sym_integral():
- f = Lambda(x, exp(-x**2))
- l = lambdify(x, Integral(f(x), (x, -oo, oo)), modules="sympy")
- assert l(y) == Integral(exp(-y**2), (y, -oo, oo))
- assert l(y).doit() == sqrt(pi)
- def test_namespace_order():
- # lambdify had a bug, such that module dictionaries or cached module
- # dictionaries would pull earlier namespaces into themselves.
- # Because the module dictionaries form the namespace of the
- # generated lambda, this meant that the behavior of a previously
- # generated lambda function could change as a result of later calls
- # to lambdify.
- n1 = {'f': lambda x: 'first f'}
- n2 = {'f': lambda x: 'second f',
- 'g': lambda x: 'function g'}
- f = sympy.Function('f')
- g = sympy.Function('g')
- if1 = lambdify(x, f(x), modules=(n1, "sympy"))
- assert if1(1) == 'first f'
- if2 = lambdify(x, g(x), modules=(n2, "sympy"))
- # previously gave 'second f'
- assert if1(1) == 'first f'
- assert if2(1) == 'function g'
- def test_imps():
- # Here we check if the default returned functions are anonymous - in
- # the sense that we can have more than one function with the same name
- f = implemented_function('f', lambda x: 2*x)
- g = implemented_function('f', lambda x: math.sqrt(x))
- l1 = lambdify(x, f(x))
- l2 = lambdify(x, g(x))
- assert str(f(x)) == str(g(x))
- assert l1(3) == 6
- assert l2(3) == math.sqrt(3)
- # check that we can pass in a Function as input
- func = sympy.Function('myfunc')
- assert not hasattr(func, '_imp_')
- my_f = implemented_function(func, lambda x: 2*x)
- assert hasattr(my_f, '_imp_')
- # Error for functions with same name and different implementation
- f2 = implemented_function("f", lambda x: x + 101)
- raises(ValueError, lambda: lambdify(x, f(f2(x))))
- def test_imps_errors():
- # Test errors that implemented functions can return, and still be able to
- # form expressions.
- # See: https://github.com/sympy/sympy/issues/10810
- #
- # XXX: Removed AttributeError here. This test was added due to issue 10810
- # but that issue was about ValueError. It doesn't seem reasonable to
- # "support" catching AttributeError in the same context...
- for val, error_class in product((0, 0., 2, 2.0), (TypeError, ValueError)):
- def myfunc(a):
- if a == 0:
- raise error_class
- return 1
- f = implemented_function('f', myfunc)
- expr = f(val)
- assert expr == f(val)
- def test_imps_wrong_args():
- raises(ValueError, lambda: implemented_function(sin, lambda x: x))
- def test_lambdify_imps():
- # Test lambdify with implemented functions
- # first test basic (sympy) lambdify
- f = sympy.cos
- assert lambdify(x, f(x))(0) == 1
- assert lambdify(x, 1 + f(x))(0) == 2
- assert lambdify((x, y), y + f(x))(0, 1) == 2
- # make an implemented function and test
- f = implemented_function("f", lambda x: x + 100)
- assert lambdify(x, f(x))(0) == 100
- assert lambdify(x, 1 + f(x))(0) == 101
- assert lambdify((x, y), y + f(x))(0, 1) == 101
- # Can also handle tuples, lists, dicts as expressions
- lam = lambdify(x, (f(x), x))
- assert lam(3) == (103, 3)
- lam = lambdify(x, [f(x), x])
- assert lam(3) == [103, 3]
- lam = lambdify(x, [f(x), (f(x), x)])
- assert lam(3) == [103, (103, 3)]
- lam = lambdify(x, {f(x): x})
- assert lam(3) == {103: 3}
- lam = lambdify(x, {f(x): x})
- assert lam(3) == {103: 3}
- lam = lambdify(x, {x: f(x)})
- assert lam(3) == {3: 103}
- # Check that imp preferred to other namespaces by default
- d = {'f': lambda x: x + 99}
- lam = lambdify(x, f(x), d)
- assert lam(3) == 103
- # Unless flag passed
- lam = lambdify(x, f(x), d, use_imps=False)
- assert lam(3) == 102
- def test_dummification():
- t = symbols('t')
- F = Function('F')
- G = Function('G')
- #"\alpha" is not a valid Python variable name
- #lambdify should sub in a dummy for it, and return
- #without a syntax error
- alpha = symbols(r'\alpha')
- some_expr = 2 * F(t)**2 / G(t)
- lam = lambdify((F(t), G(t)), some_expr)
- assert lam(3, 9) == 2
- lam = lambdify(sin(t), 2 * sin(t)**2)
- assert lam(F(t)) == 2 * F(t)**2
- #Test that \alpha was properly dummified
- lam = lambdify((alpha, t), 2*alpha + t)
- assert lam(2, 1) == 5
- raises(SyntaxError, lambda: lambdify(F(t) * G(t), F(t) * G(t) + 5))
- raises(SyntaxError, lambda: lambdify(2 * F(t), 2 * F(t) + 5))
- raises(SyntaxError, lambda: lambdify(2 * F(t), 4 * F(t) + 5))
- def test_lambdify__arguments_with_invalid_python_identifiers():
- # see sympy/sympy#26690
- N = CoordSys3D('N')
- xn, yn, zn = N.base_scalars()
- expr = xn + yn
- f = lambdify([xn, yn], expr)
- res = f(0.2, 0.3)
- ref = 0.2 + 0.3
- assert abs(res-ref) < 1e-15
- def test_curly_matrix_symbol():
- # Issue #15009
- curlyv = sympy.MatrixSymbol("{v}", 2, 1)
- lam = lambdify(curlyv, curlyv)
- assert lam(1)==1
- lam = lambdify(curlyv, curlyv, dummify=True)
- assert lam(1)==1
- def test_python_keywords():
- # Test for issue 7452. The automatic dummification should ensure use of
- # Python reserved keywords as symbol names will create valid lambda
- # functions. This is an additional regression test.
- python_if = symbols('if')
- expr = python_if / 2
- f = lambdify(python_if, expr)
- assert f(4.0) == 2.0
- def test_lambdify_docstring():
- func = lambdify((w, x, y, z), w + x + y + z)
- ref = (
- "Created with lambdify. Signature:\n\n"
- "func(w, x, y, z)\n\n"
- "Expression:\n\n"
- "w + x + y + z"
- ).splitlines()
- assert func.__doc__.splitlines()[:len(ref)] == ref
- syms = symbols('a1:26')
- func = lambdify(syms, sum(syms))
- ref = (
- "Created with lambdify. Signature:\n\n"
- "func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,\n"
- " a16, a17, a18, a19, a20, a21, a22, a23, a24, a25)\n\n"
- "Expression:\n\n"
- "a1 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a2 + a20 +..."
- ).splitlines()
- assert func.__doc__.splitlines()[:len(ref)] == ref
- def test_lambdify_linecache():
- func = lambdify(x, x + 1)
- source = 'def _lambdifygenerated(x):\n return x + 1\n'
- assert inspect.getsource(func) == source
- filename = inspect.getsourcefile(func)
- assert filename.startswith('<lambdifygenerated-')
- assert filename in linecache.cache
- assert linecache.cache[filename] == (len(source), None, source.splitlines(True), filename)
- del func
- gc.collect()
- assert filename not in linecache.cache
- #================== Test special printers ==========================
- def test_special_printers():
- from sympy.printing.lambdarepr import IntervalPrinter
- def intervalrepr(expr):
- return IntervalPrinter().doprint(expr)
- expr = sqrt(sqrt(2) + sqrt(3)) + S.Half
- func0 = lambdify((), expr, modules="mpmath", printer=intervalrepr)
- func1 = lambdify((), expr, modules="mpmath", printer=IntervalPrinter)
- func2 = lambdify((), expr, modules="mpmath", printer=IntervalPrinter())
- mpi = type(mpmath.mpi(1, 2))
- assert isinstance(func0(), mpi)
- assert isinstance(func1(), mpi)
- assert isinstance(func2(), mpi)
- # To check Is lambdify loggamma works for mpmath or not
- exp1 = lambdify(x, loggamma(x), 'mpmath')(5)
- exp2 = lambdify(x, loggamma(x), 'mpmath')(1.8)
- exp3 = lambdify(x, loggamma(x), 'mpmath')(15)
- exp_ls = [exp1, exp2, exp3]
- sol1 = mpmath.loggamma(5)
- sol2 = mpmath.loggamma(1.8)
- sol3 = mpmath.loggamma(15)
- sol_ls = [sol1, sol2, sol3]
- assert exp_ls == sol_ls
- def test_true_false():
- # We want exact is comparison here, not just ==
- assert lambdify([], true)() is True
- assert lambdify([], false)() is False
- def test_issue_2790():
- assert lambdify((x, (y, z)), x + y)(1, (2, 4)) == 3
- assert lambdify((x, (y, (w, z))), w + x + y + z)(1, (2, (3, 4))) == 10
- assert lambdify(x, x + 1, dummify=False)(1) == 2
- def test_issue_12092():
- f = implemented_function('f', lambda x: x**2)
- assert f(f(2)).evalf() == Float(16)
- def test_issue_14911():
- class Variable(sympy.Symbol):
- def _sympystr(self, printer):
- return printer.doprint(self.name)
- _lambdacode = _sympystr
- _numpycode = _sympystr
- x = Variable('x')
- y = 2 * x
- code = LambdaPrinter().doprint(y)
- assert code.replace(' ', '') == '2*x'
- def test_ITE():
- assert lambdify((x, y, z), ITE(x, y, z))(True, 5, 3) == 5
- assert lambdify((x, y, z), ITE(x, y, z))(False, 5, 3) == 3
- def test_Min_Max():
- # see gh-10375
- assert lambdify((x, y, z), Min(x, y, z))(1, 2, 3) == 1
- assert lambdify((x, y, z), Max(x, y, z))(1, 2, 3) == 3
- def test_amin_amax_minimum_maximum():
- if not numpy:
- skip("numpy not installed")
- a234 = numpy.array([2, 3, 4])
- a152 = numpy.array([1, 5, 2])
- a254 = numpy.array([2, 5, 4])
- a132 = numpy.array([1, 3, 2])
- # 2 args
- assert numpy.all(lambdify((x, y), maximum(x, y))(a234, a152) == a254)
- assert numpy.all(lambdify((x, y), minimum(x, y))(a234, a152) == a132)
- # 3 args
- assert numpy.all(lambdify((x, y, z), maximum(x, y, z))(a234, a152, a234) == a254)
- assert numpy.all(lambdify((x, y, z), minimum(x, y, z))(a234, a152, a234) == a132)
- # 1 arg
- assert numpy.all(lambdify((x,), maximum(x))(a234) == a234)
- assert numpy.all(lambdify((x,), minimum(x))(a234) == a234)
- # 4 args, mixed length
- assert numpy.all(lambdify((x, y, z, w), maximum(x, y, z, w))(a234, a152, a234, 3) == [3, 5, 4])
- assert numpy.all(lambdify((x, y, z, w), minimum(x, y, z, w))(a234, a152, a234, 2) == [1, 2, 2])
- # amin & amax
- assert lambdify((x, y), [amin(x), amax(y)])(a234, a152) == [2, 5]
- A = numpy.array([
- [0, 4, 8],
- [1, 5, 9],
- [2, 6, 10],
- ])
- min_, max_ = lambdify((x,), [amin(x, axis=0), amax(x, axis=1)])(A)
- assert numpy.all(min_ == numpy.amin(A, axis=0))
- assert numpy.all(max_ == numpy.amax(A, axis=1))
- # see gh-25659
- assert numpy.all(lambdify((x, y), Max(x, y))([1, 2, 3], [3, 2, 1]) == [3, 2, 3])
- assert numpy.all(lambdify((x), Min(2, x))([1, 2, 3]) == [1, 2, 2])
- def test_Indexed():
- # Issue #10934
- if not numpy:
- skip("numpy not installed")
- a = IndexedBase('a')
- i, j = symbols('i j')
- b = numpy.array([[1, 2], [3, 4]])
- assert lambdify(a, Sum(a[x, y], (x, 0, 1), (y, 0, 1)))(b) == 10
- def test_Sum():
- e = Sum(z, (y, 0, x), (x, 0, 10))
- ref = 66*z
- assert e.doit() == ref
- assert lambdify([z], e)(7) == ref.subs(z, 7)
- def test_Idx():
- # Issue 26888
- a = IndexedBase('a')
- i = Idx('i')
- b = [1,2,3]
- assert lambdify([a, i], a[i])(b, 2) == 3
- def test_issue_12173():
- #test for issue 12173
- expr1 = lambdify((x, y), uppergamma(x, y),"mpmath")(1, 2)
- expr2 = lambdify((x, y), lowergamma(x, y),"mpmath")(1, 2)
- assert expr1 == uppergamma(1, 2).evalf()
- assert expr2 == lowergamma(1, 2).evalf()
- def test_issue_13642():
- if not numpy:
- skip("numpy not installed")
- f = lambdify(x, sinc(x))
- assert Abs(f(1) - sinc(1)).n() < 1e-15
- def test_sinc_mpmath():
- f = lambdify(x, sinc(x), "mpmath")
- assert Abs(f(1) - sinc(1)).n() < 1e-15
- def test_lambdify_dummy_arg():
- d1 = Dummy()
- f1 = lambdify(d1, d1 + 1, dummify=False)
- assert f1(2) == 3
- f1b = lambdify(d1, d1 + 1)
- assert f1b(2) == 3
- d2 = Dummy('x')
- f2 = lambdify(d2, d2 + 1)
- assert f2(2) == 3
- f3 = lambdify([[d2]], d2 + 1)
- assert f3([2]) == 3
- def test_lambdify_mixed_symbol_dummy_args():
- d = Dummy()
- # Contrived example of name clash
- dsym = symbols(str(d))
- f = lambdify([d, dsym], d - dsym)
- assert f(4, 1) == 3
- def test_numpy_array_arg():
- # Test for issue 14655 (numpy part)
- if not numpy:
- skip("numpy not installed")
- f = lambdify([[x, y]], x*x + y, 'numpy')
- assert f(numpy.array([2.0, 1.0])) == 5
- def test_scipy_fns():
- if not scipy:
- skip("scipy not installed")
- single_arg_sympy_fns = [Ei, erf, erfc, factorial, gamma, loggamma, digamma, Si, Ci]
- single_arg_scipy_fns = [scipy.special.expi, scipy.special.erf, scipy.special.erfc,
- scipy.special.factorial, scipy.special.gamma, scipy.special.gammaln,
- scipy.special.psi, scipy.special.sici, scipy.special.sici]
- numpy.random.seed(0)
- for (sympy_fn, scipy_fn) in zip(single_arg_sympy_fns, single_arg_scipy_fns):
- f = lambdify(x, sympy_fn(x), modules="scipy")
- for i in range(20):
- tv = numpy.random.uniform(-10, 10) + 1j*numpy.random.uniform(-5, 5)
- # SciPy thinks that factorial(z) is 0 when re(z) < 0 and
- # does not support complex numbers.
- # SymPy does not think so.
- if sympy_fn == factorial:
- tv = numpy.abs(tv)
- # SciPy supports gammaln for real arguments only,
- # and there is also a branch cut along the negative real axis
- if sympy_fn == loggamma:
- tv = numpy.abs(tv)
- # SymPy's digamma evaluates as polygamma(0, z)
- # which SciPy supports for real arguments only
- if sympy_fn == digamma:
- tv = numpy.real(tv)
- sympy_result = sympy_fn(tv).evalf()
- scipy_result = scipy_fn(tv)
- # SciPy's sici returns a tuple with both Si and Ci present in it
- # which needs to be unpacked
- if sympy_fn == Si:
- scipy_result = scipy_fn(tv)[0]
- if sympy_fn == Ci:
- scipy_result = scipy_fn(tv)[1]
- assert abs(f(tv) - sympy_result) < 1e-13*(1 + abs(sympy_result))
- assert abs(f(tv) - scipy_result) < 1e-13*(1 + abs(sympy_result))
- double_arg_sympy_fns = [RisingFactorial, besselj, bessely, besseli,
- besselk, polygamma]
- double_arg_scipy_fns = [scipy.special.poch, scipy.special.jv,
- scipy.special.yv, scipy.special.iv, scipy.special.kv, scipy.special.polygamma]
- for (sympy_fn, scipy_fn) in zip(double_arg_sympy_fns, double_arg_scipy_fns):
- f = lambdify((x, y), sympy_fn(x, y), modules="scipy")
- for i in range(20):
- # SciPy supports only real orders of Bessel functions
- tv1 = numpy.random.uniform(-10, 10)
- tv2 = numpy.random.uniform(-10, 10) + 1j*numpy.random.uniform(-5, 5)
- # SciPy requires a real valued 2nd argument for: poch, polygamma
- if sympy_fn in (RisingFactorial, polygamma):
- tv2 = numpy.real(tv2)
- if sympy_fn == polygamma:
- tv1 = abs(int(tv1)) # first argument to polygamma must be a non-negative integer.
- sympy_result = sympy_fn(tv1, tv2).evalf()
- assert abs(f(tv1, tv2) - sympy_result) < 1e-13*(1 + abs(sympy_result))
- assert abs(f(tv1, tv2) - scipy_fn(tv1, tv2)) < 1e-13*(1 + abs(sympy_result))
- def test_scipy_polys():
- if not scipy:
- skip("scipy not installed")
- numpy.random.seed(0)
- params = symbols('n k a b')
- # list polynomials with the number of parameters
- polys = [
- (chebyshevt, 1),
- (chebyshevu, 1),
- (legendre, 1),
- (hermite, 1),
- (laguerre, 1),
- (gegenbauer, 2),
- (assoc_legendre, 2),
- (assoc_laguerre, 2),
- (jacobi, 3)
- ]
- msg = \
- "The random test of the function {func} with the arguments " \
- "{args} had failed because the SymPy result {sympy_result} " \
- "and SciPy result {scipy_result} had failed to converge " \
- "within the tolerance {tol} " \
- "(Actual absolute difference : {diff})"
- for sympy_fn, num_params in polys:
- args = params[:num_params] + (x,)
- f = lambdify(args, sympy_fn(*args))
- for _ in range(10):
- tn = numpy.random.randint(3, 10)
- tparams = tuple(numpy.random.uniform(0, 5, size=num_params-1))
- tv = numpy.random.uniform(-10, 10) + 1j*numpy.random.uniform(-5, 5)
- # SciPy supports hermite for real arguments only
- if sympy_fn == hermite:
- tv = numpy.real(tv)
- # assoc_legendre needs x in (-1, 1) and integer param at most n
- if sympy_fn == assoc_legendre:
- tv = numpy.random.uniform(-1, 1)
- tparams = tuple(numpy.random.randint(1, tn, size=1))
- vals = (tn,) + tparams + (tv,)
- scipy_result = f(*vals)
- sympy_result = sympy_fn(*vals).evalf()
- atol = 1e-9*(1 + abs(sympy_result))
- diff = abs(scipy_result - sympy_result)
- try:
- assert diff < atol
- except TypeError:
- raise AssertionError(
- msg.format(
- func=repr(sympy_fn),
- args=repr(vals),
- sympy_result=repr(sympy_result),
- scipy_result=repr(scipy_result),
- diff=diff,
- tol=atol)
- )
- def test_lambdify_inspect():
- f = lambdify(x, x**2)
- # Test that inspect.getsource works but don't hard-code implementation
- # details
- assert 'x**2' in inspect.getsource(f)
- def test_issue_14941():
- x, y = Dummy(), Dummy()
- # test dict
- f1 = lambdify([x, y], {x: 3, y: 3}, 'sympy')
- assert f1(2, 3) == {2: 3, 3: 3}
- # test tuple
- f2 = lambdify([x, y], (y, x), 'sympy')
- assert f2(2, 3) == (3, 2)
- f2b = lambdify([], (1,)) # gh-23224
- assert f2b() == (1,)
- # test list
- f3 = lambdify([x, y], [y, x], 'sympy')
- assert f3(2, 3) == [3, 2]
- def test_lambdify_Derivative_arg_issue_16468():
- f = Function('f')(x)
- fx = f.diff()
- assert lambdify((f, fx), f + fx)(10, 5) == 15
- assert eval(lambdastr((f, fx), f/fx))(10, 5) == 2
- raises(Exception, lambda:
- eval(lambdastr((f, fx), f/fx, dummify=False)))
- assert eval(lambdastr((f, fx), f/fx, dummify=True))(10, 5) == 2
- assert eval(lambdastr((fx, f), f/fx, dummify=True))(S(10), 5) == S.Half
- assert lambdify(fx, 1 + fx)(41) == 42
- assert eval(lambdastr(fx, 1 + fx, dummify=True))(41) == 42
- def test_lambdify_Derivative_zeta():
- # This is related to gh-11802 (and to lesser extent gh-26663)
- expr1 = zeta(x).diff(x, evaluate=False)
- f1 = lambdify(x, expr1, modules=['mpmath'])
- ans1 = f1(2)
- ref1 = (zeta(2+1e-8).evalf()-zeta(2).evalf())/1e-8
- assert abs(ans1 - ref1)/abs(ref1) < 1e-7
- expr2 = zeta(x**2).diff(x)
- f2 = lambdify(x, expr2, modules=['mpmath'])
- ans2 = f2(2**0.5)
- ref2 = 2*2**0.5*ref1
- assert abs(ans2-ref2)/abs(ref2) < 1e-7
- def test_lambdify_Derivative_custom_printer():
- func1 = Function('func1')
- func2 = Function('func2')
- class MyPrinter(NumPyPrinter):
- def _print_Derivative_func1(self, args, seq_orders):
- arg, = args
- order, = seq_orders
- return '42'
- expr1 = func1(x).diff(x)
- raises(PrintMethodNotImplementedError, lambda: lambdify([x], expr1))
- f1 = lambdify([x], expr1, printer=MyPrinter)
- assert f1(7) == 42
- expr2 = func2(x).diff(x)
- raises(PrintMethodNotImplementedError, lambda: lambdify([x], expr2, printer=MyPrinter))
- def test_lambdify_derivative_and_functions_as_arguments():
- # see: https://github.com/sympy/sympy/issues/26663#issuecomment-2157179517
- t, a, b = symbols('t, a, b')
- f = Function('f')(t)
- args = f.diff(t, 2), f.diff(t), f, a, b
- expr1 = a*f.diff(t, 2) + b*f.diff(t) + a*b*f + a**2
- num_args = 2.0, 3.0, 4.0, 5.0, 6.0
- ref1 = 5*2 + 6*3 + 5*6*4 + 5**2
- expr2 = a*f.diff(t, 2) + b*f.diff(t) - a*b*f + b**2 - a**2
- ref2 = 5*2 + 6*3 - 5*6*4 + 6**2 - 5**2
- for dummify, _cse in product([False, None, True], [False, True]):
- func1 = lambdify(args, expr1, cse=_cse, dummify=dummify)
- res1 = func1(*num_args)
- assert abs(res1 - ref1) < 1e-12
- func12 = lambdify(args, [expr1, expr2], cse=_cse, dummify=dummify)
- res12 = func12(*num_args)
- assert len(res12) == 2
- assert abs(res12[0] - ref1) < 1e-12
- assert abs(res12[1] - ref2) < 1e-12
- def test_imag_real():
- f_re = lambdify([z], sympy.re(z))
- val = 3+2j
- assert f_re(val) == val.real
- f_im = lambdify([z], sympy.im(z)) # see #15400
- assert f_im(val) == val.imag
- def test_MatrixSymbol_issue_15578():
- if not numpy:
- skip("numpy not installed")
- A = MatrixSymbol('A', 2, 2)
- A0 = numpy.array([[1, 2], [3, 4]])
- f = lambdify(A, A**(-1))
- assert numpy.allclose(f(A0), numpy.array([[-2., 1.], [1.5, -0.5]]))
- g = lambdify(A, A**3)
- assert numpy.allclose(g(A0), numpy.array([[37, 54], [81, 118]]))
- def test_issue_15654():
- if not scipy:
- skip("scipy not installed")
- from sympy.abc import n, l, r, Z
- from sympy.physics import hydrogen
- nv, lv, rv, Zv = 1, 0, 3, 1
- sympy_value = hydrogen.R_nl(nv, lv, rv, Zv).evalf()
- f = lambdify((n, l, r, Z), hydrogen.R_nl(n, l, r, Z))
- scipy_value = f(nv, lv, rv, Zv)
- assert abs(sympy_value - scipy_value) < 1e-15
- def test_issue_15827():
- if not numpy:
- skip("numpy not installed")
- A = MatrixSymbol("A", 3, 3)
- B = MatrixSymbol("B", 2, 3)
- C = MatrixSymbol("C", 3, 4)
- D = MatrixSymbol("D", 4, 5)
- k=symbols("k")
- f = lambdify(A, (2*k)*A)
- g = lambdify(A, (2+k)*A)
- h = lambdify(A, 2*A)
- i = lambdify((B, C, D), 2*B*C*D)
- assert numpy.array_equal(f(numpy.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])), \
- numpy.array([[2*k, 4*k, 6*k], [2*k, 4*k, 6*k], [2*k, 4*k, 6*k]], dtype=object))
- assert numpy.array_equal(g(numpy.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])), \
- numpy.array([[k + 2, 2*k + 4, 3*k + 6], [k + 2, 2*k + 4, 3*k + 6], \
- [k + 2, 2*k + 4, 3*k + 6]], dtype=object))
- assert numpy.array_equal(h(numpy.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])), \
- numpy.array([[2, 4, 6], [2, 4, 6], [2, 4, 6]]))
- 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]]), \
- 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], \
- [ 120, 240, 360, 480, 600]]))
- def test_issue_16930():
- if not scipy:
- skip("scipy not installed")
- x = symbols("x")
- f = lambda x: S.GoldenRatio * x**2
- f_ = lambdify(x, f(x), modules='scipy')
- assert f_(1) == scipy.constants.golden_ratio
- def test_issue_17898():
- if not scipy:
- skip("scipy not installed")
- x = symbols("x")
- f_ = lambdify([x], sympy.LambertW(x,-1), modules='scipy')
- assert f_(0.1) == mpmath.lambertw(0.1, -1)
- def test_issue_13167_21411():
- if not numpy:
- skip("numpy not installed")
- f1 = lambdify(x, sympy.Heaviside(x))
- f2 = lambdify(x, sympy.Heaviside(x, 1))
- res1 = f1([-1, 0, 1])
- res2 = f2([-1, 0, 1])
- assert Abs(res1[0]).n() < 1e-15 # First functionality: only one argument passed
- assert Abs(res1[1] - 1/2).n() < 1e-15
- assert Abs(res1[2] - 1).n() < 1e-15
- assert Abs(res2[0]).n() < 1e-15 # Second functionality: two arguments passed
- assert Abs(res2[1] - 1).n() < 1e-15
- assert Abs(res2[2] - 1).n() < 1e-15
- def test_single_e():
- f = lambdify(x, E)
- assert f(23) == exp(1.0)
- def test_issue_16536():
- if not scipy:
- skip("scipy not installed")
- a = symbols('a')
- f1 = lowergamma(a, x)
- F = lambdify((a, x), f1, modules='scipy')
- assert abs(lowergamma(1, 3) - F(1, 3)) <= 1e-10
- f2 = uppergamma(a, x)
- F = lambdify((a, x), f2, modules='scipy')
- assert abs(uppergamma(1, 3) - F(1, 3)) <= 1e-10
- def test_issue_22726():
- if not numpy:
- skip("numpy not installed")
- x1, x2 = symbols('x1 x2')
- f = Max(S.Zero, Min(x1, x2))
- g = derive_by_array(f, (x1, x2))
- G = lambdify((x1, x2), g, modules='numpy')
- point = {x1: 1, x2: 2}
- assert (abs(g.subs(point) - G(*point.values())) <= 1e-10).all()
- def test_issue_22739():
- if not numpy:
- skip("numpy not installed")
- x1, x2 = symbols('x1 x2')
- f = Heaviside(Min(x1, x2))
- F = lambdify((x1, x2), f, modules='numpy')
- point = {x1: 1, x2: 2}
- assert abs(f.subs(point) - F(*point.values())) <= 1e-10
- def test_issue_22992():
- if not numpy:
- skip("numpy not installed")
- a, t = symbols('a t')
- expr = a*(log(cot(t/2)) - cos(t))
- F = lambdify([a, t], expr, 'numpy')
- point = {a: 10, t: 2}
- assert abs(expr.subs(point) - F(*point.values())) <= 1e-10
- # Standard math
- F = lambdify([a, t], expr)
- assert abs(expr.subs(point) - F(*point.values())) <= 1e-10
- def test_issue_19764():
- if not numpy:
- skip("numpy not installed")
- expr = Array([x, x**2])
- f = lambdify(x, expr, 'numpy')
- assert f(1).__class__ == numpy.ndarray
- def test_issue_20070():
- if not numba:
- skip("numba not installed")
- f = lambdify(x, sin(x), 'numpy')
- assert numba.jit(f, nopython=True)(1)==0.8414709848078965
- def test_fresnel_integrals_scipy():
- if not scipy:
- skip("scipy not installed")
- f1 = fresnelc(x)
- f2 = fresnels(x)
- F1 = lambdify(x, f1, modules='scipy')
- F2 = lambdify(x, f2, modules='scipy')
- assert abs(fresnelc(1.3) - F1(1.3)) <= 1e-10
- assert abs(fresnels(1.3) - F2(1.3)) <= 1e-10
- def test_beta_scipy():
- if not scipy:
- skip("scipy not installed")
- f = beta(x, y)
- F = lambdify((x, y), f, modules='scipy')
- assert abs(beta(1.3, 2.3) - F(1.3, 2.3)) <= 1e-10
- def test_beta_math():
- f = beta(x, y)
- F = lambdify((x, y), f, modules='math')
- assert abs(beta(1.3, 2.3) - F(1.3, 2.3)) <= 1e-10
- def test_betainc_scipy():
- if not scipy:
- skip("scipy not installed")
- f = betainc(w, x, y, z)
- F = lambdify((w, x, y, z), f, modules='scipy')
- assert abs(betainc(1.4, 3.1, 0.1, 0.5) - F(1.4, 3.1, 0.1, 0.5)) <= 1e-10
- def test_betainc_regularized_scipy():
- if not scipy:
- skip("scipy not installed")
- f = betainc_regularized(w, x, y, z)
- F = lambdify((w, x, y, z), f, modules='scipy')
- assert abs(betainc_regularized(0.2, 3.5, 0.1, 1) - F(0.2, 3.5, 0.1, 1)) <= 1e-10
- def test_numpy_special_math():
- if not numpy:
- skip("numpy not installed")
- funcs = [expm1, log1p, exp2, log2, log10, hypot, logaddexp, logaddexp2]
- for func in funcs:
- if 2 in func.nargs:
- expr = func(x, y)
- args = (x, y)
- num_args = (0.3, 0.4)
- elif 1 in func.nargs:
- expr = func(x)
- args = (x,)
- num_args = (0.3,)
- else:
- raise NotImplementedError("Need to handle other than unary & binary functions in test")
- f = lambdify(args, expr)
- result = f(*num_args)
- reference = expr.subs(dict(zip(args, num_args))).evalf()
- assert numpy.allclose(result, float(reference))
- lae2 = lambdify((x, y), logaddexp2(log2(x), log2(y)))
- assert abs(2.0**lae2(1e-50, 2.5e-50) - 3.5e-50) < 1e-62 # from NumPy's docstring
- def test_scipy_special_math():
- if not scipy:
- skip("scipy not installed")
- cm1 = lambdify((x,), cosm1(x), modules='scipy')
- assert abs(cm1(1e-20) + 5e-41) < 1e-200
- have_scipy_1_10plus = tuple(map(int, scipy.version.version.split('.')[:2])) >= (1, 10)
- if have_scipy_1_10plus:
- cm2 = lambdify((x, y), powm1(x, y), modules='scipy')
- assert abs(cm2(1.2, 1e-9) - 1.82321557e-10) < 1e-17
- def test_scipy_bernoulli():
- if not scipy:
- skip("scipy not installed")
- bern = lambdify((x,), bernoulli(x), modules='scipy')
- assert bern(1) == 0.5
- def test_scipy_harmonic():
- if not scipy:
- skip("scipy not installed")
- hn = lambdify((x,), harmonic(x), modules='scipy')
- assert hn(2) == 1.5
- hnm = lambdify((x, y), harmonic(x, y), modules='scipy')
- assert hnm(2, 2) == 1.25
- def test_cupy_array_arg():
- if not cupy:
- skip("CuPy not installed")
- f = lambdify([[x, y]], x*x + y, 'cupy')
- result = f(cupy.array([2.0, 1.0]))
- assert result == 5
- assert "cupy" in str(type(result))
- def test_cupy_array_arg_using_numpy():
- # numpy functions can be run on cupy arrays
- # unclear if we can "officially" support this,
- # depends on numpy __array_function__ support
- if not cupy:
- skip("CuPy not installed")
- f = lambdify([[x, y]], x*x + y, 'numpy')
- result = f(cupy.array([2.0, 1.0]))
- assert result == 5
- assert "cupy" in str(type(result))
- def test_cupy_dotproduct():
- if not cupy:
- skip("CuPy not installed")
- A = Matrix([x, y, z])
- f1 = lambdify([x, y, z], DotProduct(A, A), modules='cupy')
- f2 = lambdify([x, y, z], DotProduct(A, A.T), modules='cupy')
- f3 = lambdify([x, y, z], DotProduct(A.T, A), modules='cupy')
- f4 = lambdify([x, y, z], DotProduct(A, A.T), modules='cupy')
- assert f1(1, 2, 3) == \
- f2(1, 2, 3) == \
- f3(1, 2, 3) == \
- f4(1, 2, 3) == \
- cupy.array([14])
- def test_jax_array_arg():
- if not jax:
- skip("JAX not installed")
- f = lambdify([[x, y]], x*x + y, 'jax')
- result = f(jax.numpy.array([2.0, 1.0]))
- assert result == 5
- assert "jax" in str(type(result))
- def test_jax_array_arg_using_numpy():
- if not jax:
- skip("JAX not installed")
- f = lambdify([[x, y]], x*x + y, 'numpy')
- result = f(jax.numpy.array([2.0, 1.0]))
- assert result == 5
- assert "jax" in str(type(result))
- def test_jax_dotproduct():
- if not jax:
- skip("JAX not installed")
- A = Matrix([x, y, z])
- f1 = lambdify([x, y, z], DotProduct(A, A), modules='jax')
- f2 = lambdify([x, y, z], DotProduct(A, A.T), modules='jax')
- f3 = lambdify([x, y, z], DotProduct(A.T, A), modules='jax')
- f4 = lambdify([x, y, z], DotProduct(A, A.T), modules='jax')
- assert f1(1, 2, 3) == \
- f2(1, 2, 3) == \
- f3(1, 2, 3) == \
- f4(1, 2, 3) == \
- jax.numpy.array([14])
- def test_lambdify_cse():
- def no_op_cse(exprs):
- return (), exprs
- def dummy_cse(exprs):
- from sympy.simplify.cse_main import cse
- return cse(exprs, symbols=numbered_symbols(cls=Dummy))
- def minmem(exprs):
- from sympy.simplify.cse_main import cse_release_variables, cse
- return cse(exprs, postprocess=cse_release_variables)
- class Case:
- def __init__(self, *, args, exprs, num_args, requires_numpy=False):
- self.args = args
- self.exprs = exprs
- self.num_args = num_args
- subs_dict = dict(zip(self.args, self.num_args))
- self.ref = [e.subs(subs_dict).evalf() for e in exprs]
- self.requires_numpy = requires_numpy
- def lambdify(self, *, cse):
- return lambdify(self.args, self.exprs, cse=cse)
- def assertAllClose(self, result, *, abstol=1e-15, reltol=1e-15):
- if self.requires_numpy:
- assert all(numpy.allclose(result[i], numpy.asarray(r, dtype=float),
- rtol=reltol, atol=abstol)
- for i, r in enumerate(self.ref))
- return
- for i, r in enumerate(self.ref):
- abs_err = abs(result[i] - r)
- if r == 0:
- assert abs_err < abstol
- else:
- assert abs_err/abs(r) < reltol
- cases = [
- Case(
- args=(x, y, z),
- exprs=[
- x + y + z,
- x + y - z,
- 2*x + 2*y - z,
- (x+y)**2 + (y+z)**2,
- ],
- num_args=(2., 3., 4.)
- ),
- Case(
- args=(x, y, z),
- exprs=[
- x + sympy.Heaviside(x),
- y + sympy.Heaviside(x),
- z + sympy.Heaviside(x, 1),
- z/sympy.Heaviside(x, 1)
- ],
- num_args=(0., 3., 4.)
- ),
- Case(
- args=(x, y, z),
- exprs=[
- x + sinc(y),
- y + sinc(y),
- z - sinc(y)
- ],
- num_args=(0.1, 0.2, 0.3)
- ),
- Case(
- args=(x, y, z),
- exprs=[
- Matrix([[x, x*y], [sin(z) + 4, x**z]]),
- x*y+sin(z)-x**z,
- Matrix([x*x, sin(z), x**z])
- ],
- num_args=(1.,2.,3.),
- requires_numpy=True
- ),
- Case(
- args=(x, y),
- exprs=[(x + y - 1)**2, x, x + y,
- (x + y)/(2*x + 1) + (x + y - 1)**2, (2*x + 1)**(x + y)],
- num_args=(1,2)
- )
- ]
- for case in cases:
- if not numpy and case.requires_numpy:
- continue
- for _cse in [False, True, minmem, no_op_cse, dummy_cse]:
- f = case.lambdify(cse=_cse)
- result = f(*case.num_args)
- case.assertAllClose(result)
- def test_issue_25288():
- syms = numbered_symbols(cls=Dummy)
- ok = lambdify(x, [x**2, sin(x**2)], cse=lambda e: cse(e, symbols=syms))(2)
- assert ok
- def test_deprecated_set():
- with warns_deprecated_sympy():
- lambdify({x, y}, x + y)
- def test_issue_13881():
- if not numpy:
- skip("numpy not installed.")
- X = MatrixSymbol('X', 3, 1)
- f = lambdify(X, X.T*X, 'numpy')
- assert f(numpy.array([1, 2, 3])) == 14
- assert f(numpy.array([3, 2, 1])) == 14
- f = lambdify(X, X*X.T, 'numpy')
- assert f(numpy.array([1, 2, 3])) == 14
- assert f(numpy.array([3, 2, 1])) == 14
- f = lambdify(X, (X*X.T)*X, 'numpy')
- arr1 = numpy.array([[1], [2], [3]])
- arr2 = numpy.array([[14],[28],[42]])
- assert numpy.array_equal(f(arr1), arr2)
- def test_23536_lambdify_cse_dummy():
- f = Function('x')(y)
- g = Function('w')(y)
- expr = z + (f**4 + g**5)*(f**3 + (g*f)**3)
- expr = expr.expand()
- eval_expr = lambdify(((f, g), z), expr, cse=True)
- ans = eval_expr((1.0, 2.0), 3.0) # shouldn't raise NameError
- assert ans == 300.0 # not a list and value is 300
- class LambdifyDocstringTestCase:
- SIGNATURE = None
- EXPR = None
- SRC = None
- def __init__(self, docstring_limit, expected_redacted):
- self.docstring_limit = docstring_limit
- self.expected_redacted = expected_redacted
- @property
- def expected_expr(self):
- expr_redacted_msg = "EXPRESSION REDACTED DUE TO LENGTH, (see lambdify's `docstring_limit`)"
- return self.EXPR if not self.expected_redacted else expr_redacted_msg
- @property
- def expected_src(self):
- src_redacted_msg = "SOURCE CODE REDACTED DUE TO LENGTH, (see lambdify's `docstring_limit`)"
- return self.SRC if not self.expected_redacted else src_redacted_msg
- @property
- def expected_docstring(self):
- expected_docstring = (
- f'Created with lambdify. Signature:\n\n'
- f'func({self.SIGNATURE})\n\n'
- f'Expression:\n\n'
- f'{self.expected_expr}\n\n'
- f'Source code:\n\n'
- f'{self.expected_src}\n\n'
- f'Imported modules:\n\n'
- )
- return expected_docstring
- def __len__(self):
- return len(self.expected_docstring)
- def __repr__(self):
- return (
- f'{self.__class__.__name__}('
- f'docstring_limit={self.docstring_limit}, '
- f'expected_redacted={self.expected_redacted})'
- )
- def test_lambdify_docstring_size_limit_simple_symbol():
- class SimpleSymbolTestCase(LambdifyDocstringTestCase):
- SIGNATURE = 'x'
- EXPR = 'x'
- SRC = (
- 'def _lambdifygenerated(x):\n'
- ' return x\n'
- )
- x = symbols('x')
- test_cases = (
- SimpleSymbolTestCase(docstring_limit=None, expected_redacted=False),
- SimpleSymbolTestCase(docstring_limit=100, expected_redacted=False),
- SimpleSymbolTestCase(docstring_limit=1, expected_redacted=False),
- SimpleSymbolTestCase(docstring_limit=0, expected_redacted=True),
- SimpleSymbolTestCase(docstring_limit=-1, expected_redacted=True),
- )
- for test_case in test_cases:
- lambdified_expr = lambdify(
- [x],
- x,
- 'sympy',
- docstring_limit=test_case.docstring_limit,
- )
- assert lambdified_expr.__doc__ == test_case.expected_docstring
- def test_lambdify_docstring_size_limit_nested_expr():
- class ExprListTestCase(LambdifyDocstringTestCase):
- SIGNATURE = 'x, y, z'
- EXPR = (
- '[x, [y], z, x**3 + 3*x**2*y + 3*x**2*z + 3*x*y**2 + 6*x*y*z '
- '+ 3*x*z**2 +...'
- )
- SRC = (
- 'def _lambdifygenerated(x, y, z):\n'
- ' return [x, [y], z, x**3 + 3*x**2*y + 3*x**2*z + 3*x*y**2 '
- '+ 6*x*y*z + 3*x*z**2 + y**3 + 3*y**2*z + 3*y*z**2 + z**3]\n'
- )
- x, y, z = symbols('x, y, z')
- expr = [x, [y], z, ((x + y + z)**3).expand()]
- test_cases = (
- ExprListTestCase(docstring_limit=None, expected_redacted=False),
- ExprListTestCase(docstring_limit=200, expected_redacted=False),
- ExprListTestCase(docstring_limit=50, expected_redacted=True),
- ExprListTestCase(docstring_limit=0, expected_redacted=True),
- ExprListTestCase(docstring_limit=-1, expected_redacted=True),
- )
- for test_case in test_cases:
- lambdified_expr = lambdify(
- [x, y, z],
- expr,
- 'sympy',
- docstring_limit=test_case.docstring_limit,
- )
- assert lambdified_expr.__doc__ == test_case.expected_docstring
- def test_lambdify_docstring_size_limit_matrix():
- class MatrixTestCase(LambdifyDocstringTestCase):
- SIGNATURE = 'x, y, z'
- EXPR = (
- 'Matrix([[0, x], [x + y + z, x**3 + 3*x**2*y + 3*x**2*z + 3*x*y**2 '
- '+ 6*x*y*z...'
- )
- SRC = (
- 'def _lambdifygenerated(x, y, z):\n'
- ' return ImmutableDenseMatrix([[0, x], [x + y + z, x**3 '
- '+ 3*x**2*y + 3*x**2*z + 3*x*y**2 + 6*x*y*z + 3*x*z**2 + y**3 '
- '+ 3*y**2*z + 3*y*z**2 + z**3]])\n'
- )
- x, y, z = symbols('x, y, z')
- expr = Matrix([[S.Zero, x], [x + y + z, ((x + y + z)**3).expand()]])
- test_cases = (
- MatrixTestCase(docstring_limit=None, expected_redacted=False),
- MatrixTestCase(docstring_limit=200, expected_redacted=False),
- MatrixTestCase(docstring_limit=50, expected_redacted=True),
- MatrixTestCase(docstring_limit=0, expected_redacted=True),
- MatrixTestCase(docstring_limit=-1, expected_redacted=True),
- )
- for test_case in test_cases:
- lambdified_expr = lambdify(
- [x, y, z],
- expr,
- 'sympy',
- docstring_limit=test_case.docstring_limit,
- )
- assert lambdified_expr.__doc__ == test_case.expected_docstring
- def test_lambdify_empty_tuple():
- a = symbols("a")
- expr = ((), (a,))
- f = lambdify(a, expr)
- result = f(1)
- assert result == ((), (1,)), "Lambdify did not handle the empty tuple correctly."
- def test_assoc_legendre_numerical_evaluation():
- tol = 1e-10
- sympy_result_integer = assoc_legendre(1, 1/2, 0.1).evalf()
- sympy_result_complex = assoc_legendre(2, 1, 3).evalf()
- mpmath_result_integer = -0.474572528387641
- mpmath_result_complex = -25.45584412271571*I
- assert all_close(sympy_result_integer, mpmath_result_integer, tol)
- assert all_close(sympy_result_complex, mpmath_result_complex, tol)
- def test_Piecewise():
- modules = [math]
- if numpy:
- modules.append('numpy')
- for mod in modules:
- # test isinf
- f = lambdify(x, Piecewise((7.0, isinf(x)), (3.0, True)), mod)
- assert f(+float('inf')) == +7.0
- assert f(-float('inf')) == +7.0
- assert f(42.) == 3.0
- f2 = lambdify(x, Piecewise((7.0*sign(x), isinf(x)), (3.0, True)), mod)
- assert f2(+float('inf')) == +7.0
- assert f2(-float('inf')) == -7.0
- assert f2(42.) == 3.0
- # test isnan (gh-26784)
- g = lambdify(x, Piecewise((7.0, isnan(x)), (3.0, True)), mod)
- assert g(float('nan')) == 7.0
- assert g(42.) == 3.0
- def test_array_symbol():
- if not numpy:
- skip("numpy not installed.")
- a = ArraySymbol('a', (3,))
- f = lambdify((a), a)
- assert numpy.all(f(numpy.array([1,2,3])) == numpy.array([1,2,3]))
|