Lambdify¶
This module provides convenient functions to transform sympy expressions to lambda functions which can be used to calculate numerical values very fast.
-
sympy.utilities.lambdify.
implemented_function
(symfunc, implementation)[source]¶ Add numerical
implementation
to functionsymfunc
.symfunc
can be anUndefinedFunction
instance, or a name string. In the latter case we create anUndefinedFunction
instance with that name.Be aware that this is a quick workaround, not a general method to create special symbolic functions. If you want to create a symbolic function to be used by all the machinery of SymPy you should subclass the
Function
class.- Parameters
symfunc :
str
orUndefinedFunction
instanceIf
str
, then create newUndefinedFunction
with this as name. If \(symfunc\) is an Undefined function, create a new function with the same name and the implemented function attached.implementation : callable
numerical implementation to be called by
evalf()
orlambdify
- Returns
afunc : sympy.FunctionClass instance
function with attached implementation
Examples
>>> from sympy.abc import x >>> from sympy.utilities.lambdify import lambdify, implemented_function >>> from sympy import Function >>> f = implemented_function('f', lambda x: x+1) >>> lam_f = lambdify(x, f(x)) >>> lam_f(4) 5
-
sympy.utilities.lambdify.
lambdastr
(args, expr, printer=None, dummify=False)[source]¶ Returns a string that can be evaluated to a lambda function.
Examples
>>> from sympy.abc import x, y, z >>> from sympy.utilities.lambdify import lambdastr >>> lambdastr(x, x**2) 'lambda x: (x**2)' >>> lambdastr((x,y,z), [z,y,x]) 'lambda x,y,z: ([z, y, x])'
Although tuples may not appear as arguments to lambda in Python 3, lambdastr will create a lambda function that will unpack the original arguments so that nested arguments can be handled:
>>> lambdastr((x, (y, z)), x + y) 'lambda _0,_1: (lambda x,y,z: (x + y))(_0,_1[0],_1[1])'
-
sympy.utilities.lambdify.
lambdify
(args, expr, modules=None, printer=None, use_imps=True, dummify=False)[source]¶ Returns an anonymous function for fast calculation of numerical values.
If not specified differently by the user,
modules
defaults to["numpy"]
if NumPy is installed, and["math", "mpmath", "sympy"]
if it isn’t, that is, SymPy functions are replaced as far as possible by eithernumpy
functions if available, and Python’s standard librarymath
, ormpmath
functions otherwise. To change this behavior, the “modules” argument can be used. It accepts:the strings “math”, “mpmath”, “numpy”, “numexpr”, “sympy”, “tensorflow”
any modules (e.g. math)
dictionaries that map names of sympy functions to arbitrary functions
lists that contain a mix of the arguments above, with higher priority given to entries appearing first.
Warning
Note that this function uses
eval
, and thus shouldn’t be used on unsanitized input.Arguments in the provided expression that are not valid Python identifiers are substitued with dummy symbols. This allows for applied functions (e.g. f(t)) to be supplied as arguments. Call the function with dummify=True to replace all arguments with dummy symbols (if \(args\) is not a string) - for example, to ensure that the arguments do not redefine any built-in names.
For functions involving large array calculations, numexpr can provide a significant speedup over numpy. Please note that the available functions for numexpr are more limited than numpy but can be expanded with implemented_function and user defined subclasses of Function. If specified, numexpr may be the only option in modules. The official list of numexpr functions can be found at: https://github.com/pydata/numexpr#supported-functions
In previous releases
lambdify
replacedMatrix
withnumpy.matrix
by default. As of release 1.0numpy.array
is the default. To get the old default behavior you must pass in[{'ImmutableDenseMatrix': numpy.matrix}, 'numpy']
to themodules
kwarg.>>> from sympy import lambdify, Matrix >>> from sympy.abc import x, y >>> import numpy >>> array2mat = [{'ImmutableDenseMatrix': numpy.matrix}, 'numpy'] >>> f = lambdify((x, y), Matrix([x, y]), modules=array2mat) >>> f(1, 2) matrix([[1], [2]])
Examples
>>> from sympy.utilities.lambdify import implemented_function >>> from sympy import sqrt, sin, Matrix >>> from sympy import Function >>> from sympy.abc import w, x, y, z
>>> f = lambdify(x, x**2) >>> f(2) 4 >>> f = lambdify((x, y, z), [z, y, x]) >>> f(1,2,3) [3, 2, 1] >>> f = lambdify(x, sqrt(x)) >>> f(4) 2.0 >>> f = lambdify((x, y), sin(x*y)**2) >>> f(0, 5) 0.0 >>> row = lambdify((x, y), Matrix((x, x + y)).T, modules='sympy') >>> row(1, 2) Matrix([[1, 3]])
Tuple arguments are handled and the lambdified function should be called with the same type of arguments as were used to create the function.:
>>> f = lambdify((x, (y, z)), x + y) >>> f(1, (2, 4)) 3
A more robust way of handling this is to always work with flattened arguments:
>>> from sympy.utilities.iterables import flatten >>> args = w, (x, (y, z)) >>> vals = 1, (2, (3, 4)) >>> f = lambdify(flatten(args), w + x + y + z) >>> f(*flatten(vals)) 10
Functions present in \(expr\) can also carry their own numerical implementations, in a callable attached to the
_imp_
attribute. Usually you attach this using theimplemented_function
factory:>>> f = implemented_function(Function('f'), lambda x: x+1) >>> func = lambdify(x, f(x)) >>> func(4) 5
lambdify
always prefers_imp_
implementations to implementations in other namespaces, unless theuse_imps
input parameter is False.Usage with Tensorflow module:
>>> import tensorflow as tf >>> f = Max(x, sin(x)) >>> func = lambdify(x, f, 'tensorflow') >>> result = func(tf.constant(1.0)) >>> result # a tf.Tensor representing the result of the calculation <tf.Tensor 'Maximum:0' shape=() dtype=float32> >>> sess = tf.Session() >>> sess.run(result) # compute result 1.0 >>> var = tf.Variable(1.0) >>> sess.run(tf.global_variables_initializer()) >>> sess.run(func(var)) # also works for tf.Variable and tf.Placeholder 1.0 >>> tensor = tf.constant([[1.0, 2.0], [3.0, 4.0]]) # works with any shape tensor >>> sess.run(func(tensor)) array([[ 1., 2.], [ 3., 4.]], dtype=float32)
Usage
Use one of the provided modules:
>>> from sympy import sin, tan, gamma >>> from sympy.abc import x, y >>> f = lambdify(x, sin(x), "math")
- Attention: Functions that are not in the math module will throw a name
error when the function definition is evaluated! So this would be better:
>>> f = lambdify(x, sin(x)*gamma(x), ("math", "mpmath", "sympy"))
Use some other module:
>>> import numpy >>> f = lambdify((x,y), tan(x*y), numpy)
- Attention: There are naming differences between numpy and sympy. So if
you simply take the numpy module, e.g. sympy.atan will not be translated to numpy.arctan. Use the modified module instead by passing the string “numpy”:
>>> f = lambdify((x,y), tan(x*y), "numpy") >>> f(1, 2) -2.18503986326 >>> from numpy import array >>> f(array([1, 2, 3]), array([2, 3, 5])) [-2.18503986 -0.29100619 -0.8559934 ]
In the above examples, the generated functions can accept scalar values or numpy arrays as arguments. However, in some cases the generated function relies on the input being a numpy array:
>>> from sympy import Piecewise >>> f = lambdify(x, Piecewise((x, x <= 1), (1/x, x > 1)), "numpy") >>> f(array([-1, 0, 1, 2])) [-1. 0. 1. 0.5] >>> f(0) Traceback (most recent call last): ... ZeroDivisionError: division by zero
In such cases, the input should be wrapped in a numpy array: >>> float(f(array([0]))) 0.0
Or if numpy functionality is not required another module can be used: >>> f = lambdify(x, Piecewise((x, x <= 1), (1/x, x > 1)), “math”) >>> f(0) 0
Use a dictionary defining custom functions:
>>> def my_cool_function(x): return 'sin(%s) is cool' % x >>> myfuncs = {"sin" : my_cool_function} >>> f = lambdify(x, sin(x), myfuncs); f(1) 'sin(1) is cool'