def test_special_printers(): class IntervalPrinter(LambdaPrinter): """Use ``lambda`` printer but print numbers as ``mpi`` intervals. """ def _print_Integer(self, expr): return "mpi('%s')" % super(IntervalPrinter, self)._print_Integer(expr) def _print_Rational(self, expr): return "mpi('%s')" % super(IntervalPrinter, self)._print_Rational(expr) def intervalrepr(expr): return IntervalPrinter().doprint(expr) expr = diofant.sqrt(diofant.sqrt(2) + diofant.sqrt(3)) + diofant.Rational( 1, 2) 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)
def test_numpy_numexpr(): 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_diofant_lambda(): mpmath.mp.dps = 50 sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020") f = lambdify(x, sin(x), "diofant") 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 pytest.raises(NameError, lambda: lambdify(x, arctan(x), "diofant"))
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_numexpr_userfunctions(): 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_numpy_piecewise(): 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_diofant_lambda(): mpmath.mp.dps = 50 sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020") f = lambdify(x, sin(x), "diofant") 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 pytest.raises(NameError, lambda: lambdify(x, arctan(x), "diofant")) # noqa: F821
def test_bad_args(): # no vargs given pytest.raises(TypeError, lambda: lambdify(1)) # same with vector exprs pytest.raises(TypeError, lambda: lambdify([1, 2])) # reserved name pytest.raises(ValueError, lambda: lambdify((('__flatten_args__',),), 1)) pytest.raises(NameError, lambda: lambdify(x, 1, 'spam'))
def test_numpy_logical_ops(): and_func = lambdify((x, y), And(x, y), modules="numpy") or_func = lambdify((x, y), Or(x, y), modules="numpy") not_func = lambdify(x, Not(x), modules="numpy") arr1 = numpy.array([True, True]) arr2 = numpy.array([False, True]) numpy.testing.assert_array_equal(and_func(arr1, arr2), numpy.array([False, True])) numpy.testing.assert_array_equal(or_func(arr1, arr2), numpy.array([True, True])) numpy.testing.assert_array_equal(not_func(arr2), numpy.array([True, False]))
def test_numpy_logical_ops(): and_func = lambdify((x, y), And(x, y), modules="numpy") or_func = lambdify((x, y), Or(x, y), modules="numpy") not_func = lambdify((x), Not(x), modules="numpy") arr1 = numpy.array([True, True]) arr2 = numpy.array([False, True]) numpy.testing.assert_array_equal(and_func(arr1, arr2), numpy.array([False, True])) numpy.testing.assert_array_equal(or_func(arr1, arr2), numpy.array([True, True])) numpy.testing.assert_array_equal(not_func(arr2), numpy.array([True, False]))
def test_numexpr_userfunctions(): 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_numpy_matmul(): 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_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="diofant") assert f(1, 2, 3) == sol f = lambdify((x, y, z), (A, [A]), modules="diofant") 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='diofant')(1, 2) == sol assert lambdify(v.T, J, modules='diofant')(1, 2) == sol
def test_lambdify_docstring(): func = lambdify((w, x, y, z), w + x + y + z) assert func.__doc__ == ( "Created with lambdify. Signature:\n\n" "func(w, x, y, z)\n\n" "Expression:\n\n" "w + x + y + z") syms = symbols('a1:26') func = lambdify(syms, sum(syms)) assert func.__doc__ == ( "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 +...")
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_diofant_lambda(): mpmath.mp.dps = 50 sin02 = mpmath.mpf('0.19866933079506121545941262711838975037020672954020') f = lambdify(x, sin(x), 'diofant') assert f(x) == sin(x) prec = 1e-15 assert -prec < f(Rational(1, 5)).evalf() - Float(str(sin02)) < prec
def test_own_namespace(): def myfunc(x): return 1 f = lambdify(x, sin(x), {"sin": myfunc}) assert f(0.1) == 1 assert f(100) == 1
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 = diofant.Function('f') g = diofant.Function('g') if1 = lambdify(x, f(x), modules=(n1, "diofant")) assert if1(1) == 'first f' if2 = lambdify(x, g(x), modules=(n2, "diofant")) # previously gave 'second f' assert if1(1) == 'first f'
def test_python_keywords(): # Test for issue sympy/sympy#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(): mpmath.mp.dps = 16 sin02 = mpmath.mpf('0.198669330795061215459412627') f = lambdify(x, sin(x), 'numpy') prec = 1e-15 assert -prec < f(0.2) - sin02 < prec with pytest.raises(TypeError): f(x)
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_numpy_matrix(): 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)
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_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 # if this succeeds, it can't be a python math function pytest.raises(TypeError, lambda: f(x))
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 = diofant.Function('f') g = diofant.Function('g') if1 = lambdify(x, f(x), modules=(n1, "diofant")) assert if1(1) == 'first f' if2 = lambdify(x, g(x), modules=(n2, "diofant")) assert if2(1) == 'function g' # previously gave 'second f' assert if1(1) == 'first f'
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 = diofant.Function('myfunc') assert not hasattr(func, '_imp_') my_f = implemented_function(func, lambda x: 2*x) assert hasattr(func, '_imp_') and hasattr(my_f, '_imp_') # Error for functions with same name and different implementation f2 = implemented_function("f", lambda x: x + 101) pytest.raises(ValueError, lambda: lambdify(x, f(f2(x))))
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 # if this succeeds, it can't be a mpmath function pytest.raises(TypeError, lambda: f(x))
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 = diofant.Function('myfunc') assert not hasattr(func, '_imp_') my_f = implemented_function(func, lambda x: 2*x) assert hasattr(func, '_imp_') # Error for functions with same name and different implementation f2 = implemented_function("f", lambda x: x + 101) pytest.raises(ValueError, lambda: lambdify(x, f(f2(x))))
def test_piecewise_lambdify(): p = Piecewise((x**2, x < 0), (x, Interval(0, 1, False, True).contains(x)), (2 - x, x >= 1), (0, True)) f = lambdify(x, p) assert f(-2.0) == 4.0 assert f(0.0) == 0.0 assert f(0.5) == 0.5 assert f(2.0) == 0.0
def sample_iter_lambdify(expr, condition=None, numsamples=S.Infinity, **kwargs): """ See sample_iter Uses lambdify for computation. This is fast but does not always work. """ if condition: ps = pspace(Tuple(expr, condition)) else: ps = pspace(expr) rvs = list(ps.values) fn = lambdify(rvs, expr, **kwargs) if condition: given_fn = lambdify(rvs, condition, **kwargs) # Check that lambdify can handle the expression # Some operations like Sum can prove difficult try: d = ps.sample() # a dictionary that maps RVs to values args = [d[rv] for rv in rvs] fn(*args) if condition: given_fn(*args) except Exception: raise TypeError("Expr/condition too complex for lambdify") def return_generator(): count = 0 while count < numsamples: d = ps.sample() # a dictionary that maps RVs to values args = [d[rv] for rv in rvs] if condition: # Check that these values satisfy the condition gd = given_fn(*args) if gd not in (True, False): raise ValueError( "Conditions must not contain free symbols") if not gd: # If the values don't satisfy then try again continue yield fn(*args) count += 1 return return_generator()
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_trig(): f = lambdify([x], [cos(x), sin(x)]) 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_lambdify_matrix_multi_input(): M = diofant.Matrix([[x**2, x * y, x * z], [y * x, y**2, y * z], [z * x, z * y, z**2]]) f = lambdify((x, y, z), M, [{'ImmutableMatrix': numpy.array}, "numpy"]) xh, yh, zh = 1.0, 2.0, 3.0 expected = array([[xh**2, xh * yh, xh * zh], [yh * xh, yh**2, yh * zh], [zh * xh, zh * yh, zh**2]]) actual = f(xh, yh, zh) assert numpy.allclose(actual, expected)
def test_lambdify(): mpmath.mp.dps = 16 sin02 = mpmath.mpf("0.198669330795061215459412627") f = lambdify(x, sin(x), "numpy") prec = 1e-15 assert -prec < f(0.2) - sin02 < prec try: f(x) # if this succeeds, it can't be a numpy function assert False except AttributeError: pass
def test_lambdify(): mpmath.mp.dps = 16 sin02 = mpmath.mpf('0.198669330795061215459412627') f = lambdify(x, sin(x), 'numpy') prec = 1e-15 assert -prec < f(0.2) - sin02 < prec if distutils.version.LooseVersion( numpy.__version__) >= distutils.version.LooseVersion('1.17'): with pytest.raises(TypeError): f(x) else: with pytest.raises(AttributeError): f(x)
def test_piecewise_lambdify(): p = Piecewise( (x**2, x < 0), (x, Interval(0, 1, False, True).contains(x)), (2 - x, x >= 1), (0, True) ) f = lambdify(x, p) assert f(-2.0) == 4.0 assert f(0.0) == 0.0 assert f(0.5) == 0.5 assert f(2.0) == 0.0
def test_lambdify_matrix_vec_input(): X = DeferredVector('X') M = Matrix([[X[0]**2, X[0] * X[1], X[0] * X[2]], [X[1] * X[0], X[1]**2, X[1] * X[2]], [X[2] * X[0], X[2] * X[1], X[2]**2]]) f = lambdify(X, M, [{'ImmutableMatrix': numpy.array}, "numpy"]) Xh = numpy.array([1.0, 2.0, 3.0]) expected = numpy.array([[Xh[0]**2, Xh[0] * Xh[1], Xh[0] * Xh[2]], [Xh[1] * Xh[0], Xh[1]**2, Xh[1] * Xh[2]], [Xh[2] * Xh[0], Xh[2] * Xh[1], Xh[2]**2]]) actual = f(Xh) assert numpy.allclose(actual, expected)
def test_special_printers(): class IntervalPrinter(LambdaPrinter): """Use ``lambda`` printer but print numbers as ``mpi`` intervals. """ def _print_Integer(self, expr): return "mpi('%s')" % super()._print_Integer(expr) def _print_Rational(self, expr): return "mpi('%s')" % super()._print_Rational(expr) def intervalrepr(expr): return IntervalPrinter().doprint(expr) expr = diofant.sqrt(diofant.sqrt(2) + diofant.sqrt(3)) + diofant.Rational(1, 2) 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)
def test_numexpr_printer(): # if translation/printing is done incorrectly then evaluating # a lambdified numexpr expression will throw an exception blacklist = ('where', 'complex', 'contains') arg_tuple = (x, y, z) # some functions take more than one argument for sym in NumExprPrinter._numexpr_functions: if sym in blacklist: continue ssym = sympify(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_numexpr_printer(): # if translation/printing is done incorrectly then evaluating # a lambdified numexpr expression will throw an exception blacklist = ('where', 'complex', 'contains') arg_tuple = (x, y, z) # some functions take more than one argument for sym in NumExprPrinter._numexpr_functions: if sym in blacklist: continue ssym = sympify(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_dummification(): 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 pytest.raises(SyntaxError, lambda: lambdify(F(t) * G(t), F(t) * G(t) + 5)) pytest.raises(SyntaxError, lambda: lambdify(2 * F(t), 2 * F(t) + 5)) pytest.raises(SyntaxError, lambda: lambdify(2 * F(t), 4 * F(t) + 5))
def test_Min_Max(): # see sympy/sympy#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_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
def test_bad_args(): # no vargs given pytest.raises(TypeError, lambda: lambdify(1)) # same with vector exprs pytest.raises(TypeError, lambda: lambdify([1, 2]))
def test_own_module(): f = lambdify(x, sin(x), math) assert f(0) == 0.0
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_sympyissue_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_true_false(): # We want exact is comparison here, not just == assert lambdify([], true)() is True assert lambdify([], false)() is False