B
    }[                 @   s  d Z ddlmZmZ ddlmZ ddlZddlZddlZddl	Z	ddl
Z
ddlmZmZmZmZmZmZmZmZmZ ddlmZ i Zi Zi Zi Zi Zi Zi Zi Zi ZddiZ ddiZ!i Z"i Z#i Z$d	d
ddZ%dddddd	ddd
ddddddddddddddd d!Z&i Z'i Z(d"d	d#dd$dd%d&Z)i Z*eee%d'feee&d(fee e'd)fee!e(d*fee"e)d+fee#i d,fee$e*d-fd.Z+dGd0d1Z,d2a-ed3d4dHd7d8Z.d9d: Z/d;d< Z0dId=d>Z1G d?d@ d@e2Z3G dAdB dBe3Z4dJdCdDZ5dEdF Z6dS )Kz
This module provides convenient functions to transform sympy expressions to
lambda functions which can be used to calculate numerical values very fast.
    )print_functiondivision)wrapsN)	exec_is_sequenceiterableNotIterablestring_typesrangebuiltinsinteger_typesPY3)doctest_depends_onIy              ?Zceilelog)ceilingElnZfabsZellipkZellipfZellipeZellippiZchebytZchebyujinfZlambertwZmatrixZconjZaltzetaZeiZshiZchiZsiZciZrfZff)AbsZ
elliptic_kZ
elliptic_fZ
elliptic_eZelliptic_pir   Z
chebyshevtZ
chebyshevur   r   r   ZooZLambertWZMutableDenseMatrixZImmutableDenseMatrix	conjugateZdirichlet_etaZEiZShiZChiZSiZCiZRisingFactorialZFallingFactorialabsimagmodreal)r   r   Zimr   ZModr   re)zfrom math import *)zfrom mpmath import *)z!import numpy; from numpy import *)zLimport numpy; import scipy; from scipy import *; from scipy.special import *)zimport_module('tensorflow'))zfrom sympy.functions import *zfrom sympy.matrices import *z2from sympy import Integral, pi, oo, nan, zoo, E, I)zimport_module('numexpr'))mathmpmathnumpyscipy
tensorflowsympynumexprFalsec       
   	   C   s  ddl m} yt|  \}}}}W n  tk
r@   td|  Y nX ||krf|rb|  || ndS xn|D ]f}|drt|} | dk	r|| j	 qln(yt
|i | wlW n tk
r   Y nX td| |f qlW x | D ]\}}	||	 ||< qW d|kr
t|d< dS )a  
    Creates a global translation dictionary for module.

    The argument module has to be one of the following strings: "math",
    "mpmath", "numpy", "sympy", "tensorflow".
    These dictionaries map names of python functions to their equivalent in
    other modules.
    r   )import_modulez,'%s' module can't be used for lambdificationNr&   z#can't import '%s' with '%s' commandr   )Zsympy.externalr&   MODULESKeyError	NameErrorclearupdate
startswitheval__dict__r   ImportErroritemsr   )
modulereloadr&   	namespaceZnamespace_defaultZtranslationsZimport_commandsZimport_commandZ	sympynameZtranslation r4   7lib/python3.7/site-packages/sympy/utilities/lambdify.py_importk   s:    	

	
r6      r    )modulesTFc       #         sb  ddl m} ddlm} d}|dkrd}ytd W nF tk
rz   ytd W n tk
rn   d	d
dg}Y nX dg}Y n
X ddg}g }	|r|	t| t|t	t
fst|ds|	| n*td|rt|dkrtd|	t|7 }	i }
x(|	ddd D ]}t|}|
| qW t|drN||}x |D ]}|
t
||i q2W |dkrTtd
|	rrddlm} ntd|	rddlm} nttd|	rddlm} nZtd|	rddlm} n@td|	rddlm} n&td|	rddlm} nddlm} i }x<|	ddd D ]*}t|t	rx|D ]}|||< q*W qW |ddd|d}t| sd| f} g }t jj ! }xrt"| D ]f\} t dr| j# nB fdd|D }t|dkr||d  n|dt
|  qW g }xPt$|ddpi ! D ]6\}}x*|D ]"}||
kr|d ||f  qW qW x|D ]}t%|i |
 qHW |
t&t'd! d"}td|	rt(||}n
t)||}|*|| |}i }d#t+ }t+d7 a+t,||d$}t%||
| t|d|-d|ft.j/|< || } d%0d&1d'd( |D }!t2j3|!d)d*}!t
|}"t|"d+krDt24|"d,d d- }"d.j0|!|"|d/1|d0| _5| S )1a  
    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
    either ``numpy`` functions if available, and Python's standard library
    ``math``, or ``mpmath`` 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`` replaced ``Matrix`` with ``numpy.matrix``
    by default. As of release 1.0 ``numpy.array`` is the default.
    To get the old default behavior you must pass in ``[{'ImmutableDenseMatrix':
    numpy.matrix}, 'numpy']`` to the ``modules`` 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]])

    Usage
    =====

    (1) 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"))

    (2) 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

    (3) 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'

    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 the
    ``implemented_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 the ``use_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)

    r   )Symbol)flattenTNFr!   r    r   r   r#   __iter__r$   r7   z*numexpr must be the only item in 'modules'atoms)MpmathPrinter)SciPyPrinter)NumPyPrinter)NumExprPrinterr"   )TensorflowPrinter)SymPyPrinter)PythonCodePrinter)Zfully_qualified_modulesZinlineZallow_unknown_functionsuser_functionsnamec                s   g | ]\}}| kr|qS r4   r4   ).0Zvar_nameZvar_val)varr4   r5   
<listcomp>  s    zlambdify.<locals>.<listcomp>Zarg_Zmodule_importszfrom %s import %s)r   r
   Z_lambdifygeneratedz<lambdifygenerated-%s>execz	func({0})z, c             s   s   | ]}t |V  qd S )N)str)rG   ir4   r4   r5   	<genexpr>  s    zlambdify.<locals>.<genexpr>z        )Zsubsequent_indentN   K   z...zqCreated with lambdify. Signature:

{sig}

Expression:

{expr}

Source code:

{src}

Imported modules:

{imp_mods}
)sigexprsrcZimp_mods)6Zsympy.core.symbolr9   Zsympy.utilities.iterablesr:   r6   r/   append_imp_namespace
isinstancedictrK   hasattr_module_presentlen	TypeErrorlist_get_namespacer+   r=   Zsympy.printing.pycoder>   r?   r@   sympy.printing.lambdareprrA   rB   rC   rD   r   inspectZcurrentframef_backf_localsr0   	enumeraterF   getattrr   r   r
   _TensorflowEvaluatorPrinter_EvaluatorPrinterdoprint_lambdify_generated_countercompile
splitlines	linecachecacheformatjointextwrapZfillZwrap__doc__)#argsrR   r8   printerZuse_impsdummifyr9   r:   Zmodule_providedZ
namespacesr3   mZbufZsymsZtermZPrinterrE   knamesZcallers_local_varsnZ	name_listZimp_mod_linesr   keysr   funcnameZfuncprinterZfuncstrZ
funclocalsfilenamecfuncrQ   Zexpr_strr4   )rH   r5   lambdify   s     >





 



r|   c             C   s6   | |krdS x$|D ]}t |dr|j| krdS qW dS )NT__name__F)rX   r}   )modnameZmodlistrs   r4   r4   r5   rY     s    
rY   c             C   sL   t | trt|  t|  d S t | tr,| S t| dr<| jS td|  dS )z;
    This is used by _lambdify to parse its arguments.
    r   r.   z>Argument must be either a string, dict or module but it is: %sN)rV   r	   r6   r'   rW   rX   r.   r[   )rs   r4   r4   r5   r]     s    


r]   c                s  ddl m  ddlmmmmm dk	rft	r@}qrt
rXfdd}qrfdd}nddlm}  	fd	d
	 
fdd
 fddfdd| r2tfdd| D r2fddtt| D dfdd| D }t| ||d}dd||f S i }|rH	| |} n0t| trVn"t|  drxddd | D } |rt|trn

||}||}d| |f S )aa  
    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])'
    r   )DeferredVector)Dummysympifyr9   Functionr:   Nc                s      | S )N)rf   )rR   )rq   r4   r5   <lambda>*  s    zlambdastr.<locals>.<lambda>c                s
     | S )N)rf   )rR   )rq   r4   r5   r   ,  s    )
lambdareprc                s   t | tr| S t | r t| S t| rT fdd| D }ddd |D S t | fr~ } | |i t|S t| S d S )Nc                s   g | ]}| qS r4   r4   )rG   a)dummies_dictsub_argsr4   r5   rI   7  s    z/lambdastr.<locals>.sub_args.<locals>.<listcomp>,c             s   s   | ]}t |V  qd S )N)rK   )rG   r   r4   r4   r5   rM   8  s    z.lambdastr.<locals>.sub_args.<locals>.<genexpr>)rV   rK   r   rm   r+   )rp   r   Zdummies)r   r   r   r9   r:   r   )r   r5   r   1  s    

zlambdastr.<locals>.sub_argsc                s   y|   } W n tk
r   t| r.nt| tr| fdd|  D } fdd|  D }tt||} nFt| trt fdd| D } n t| tr fdd| D } Y nX | S )Nc                s   g | ]}| qS r4   r4   )rG   r   )r   sub_exprr   r4   r5   rI   I  s    z/lambdastr.<locals>.sub_expr.<locals>.<listcomp>c                s   g | ]}| qS r4   r4   )rG   r   )r   r   r   r4   r5   rI   J  s    c             3   s   | ]}| V  qd S )Nr4   )rG   r   )r   r   r   r4   r5   rM   M  s    z.lambdastr.<locals>.sub_expr.<locals>.<genexpr>c                s   g | ]}| qS r4   r4   )rG   r   )r   r   r   r4   r5   rI   O  s    )	xreplace	ExceptionrV   rW   rw   valuesziptupler\   )rR   r   rt   v)r   r   r   )r   r5   r   B  s    



zlambdastr.<locals>.sub_exprc                s   t | t tfdS )N)exclude)r   rK   r   )l)r   r4   r5   isiterS  s    zlambdastr.<locals>.isiterc             3   sN   d}xD| D ]<}|r6x& |D ]}|f| V  q W n|fV  |d7 }q
W d S )Nr   r7   r4   )r   rv   elndeep)flat_indexesr   r4   r5   r   V  s    
zlambdastr.<locals>.flat_indexesc             3   s   | ]} |V  qd S )Nr4   )rG   rL   )r   r4   r5   rM   b  s    zlambdastr.<locals>.<genexpr>c                s   g | ]}t  t |qS r4   )rK   )rG   rL   )r   r4   r5   rI   c  s    zlambdastr.<locals>.<listcomp>r   c          	      s4   g | ],} |d   d dd |dd D  qS )r    c             S   s   g | ]}d | qS )z[%s]r4   )rG   rt   r4   r4   r5   rI   f  s    z(lambdastr.<locals>.<listcomp>.<listcomp>r7   N)rm   )rG   ind)dum_argsr4   r5   rI   f  s   )rq   rr   zlambda %s: (%s)(%s))r   c             s   s   | ]}t |V  qd S )N)rK   )rG   r   r4   r4   r5   rM   t  s    zlambda %s: (%s))sympy.matricesr   r#   r   r   r9   r   r:   r_   
isfunctionisclassr^   r   anyr
   rZ   rm   	lambdastrrV   rK   r   )rp   rR   rq   rr   r   Zindexed_argsZlstrr   r4   )r   r   r   r9   r   r   r:   r   rq   r   r   r   r5   r     sB    

"

r   c               @   sf   e Zd ZdddZdd Zer,edd Zne	d	Z
ed
d Zdd Zdd Zdd Zdd ZdS )re   NFc             C   sx   || _ ddlm} |d kr | }t|r2|| _n8t|rB| }|j| _t|drZ|j	}t|drj|j
}| j| _d S )Nr   )LambdaPrinter_print_Symbol_print_Dummy)_dummifyr^   r   r_   r   	_exprreprr   rf   rX   r   r   _argrepr)selfrq   rr   r   Z
symbolreprZ	dummyreprr4   r4   r5   __init__  s    



z_EvaluatorPrinter.__init__c             C   s   ddl m} g }t|s|g}| ||\}}g }g }xH|D ]@}	t|	rr|| |  || |	|d  q<||	 q<W d|d	|}
|| 
| || |d| | |
g}|dd |D  d		|d	 S )
z1Returns the function definition code as a string.r   )r   r<   zdef {}({}):z, zreturn ({})c             s   s   | ]}d | V  qdS )z    Nr4   )rG   liner4   r4   r5   rM     s    z,_EvaluatorPrinter.doprint.<locals>.<genexpr>rP   )r#   r   r   _preprocessrT   r   extend_print_unpackingrl   rm   _print_funcargwrappingr   )r   rx   rp   rR   r   ZfuncbodyargstrsZfuncargsZ
unpackingsZargstrZfuncsigZ	funclinesr4   r4   r5   rf     s&    

z_EvaluatorPrinter.doprintc             C   s   t |to| ot| S )N)rV   rK   isidentifierkeyword	iskeyword)clsidentr4   r4   r5   _is_safe_ident  s    z _EvaluatorPrinter._is_safe_identz^[a-zA-Z_][a-zA-Z0-9_]*$c             C   s*   t |to(| j|o(t|p&|dk S )NNone)rV   rK   _safe_ident_rematchr   r   )r   r   r4   r4   r5   r     s    c                sx  ddl m m}m}m}m} ddlm} | j}|sLt	 fdd||D }g }	x|D ]}
t
|
r| |
|\}}|	| qXt|
|r|	t|
 qXt|
|st|
|r| |
}|s| |s  }|	| | | ||
|i}n
|	| qXt|
|r0  }|	| | | ||
|i}qX|r^  }|	| | | ||
|i}qX|	t|
 qXW |	|fS )zPreprocess args, expr to replace arguments that do not map
        to valid Python identifiers.

        Returns string form of args, and updated expr.
        r   )r   r9   MatrixSymbolr   r:   )r   c             3   s   | ]}t | V  qd S )N)rV   )rG   arg)r   r4   r5   rM     s    z0_EvaluatorPrinter._preprocess.<locals>.<genexpr>)r#   r   r9   r   r   r:   r   r   r   r   r   r   rT   rV   rK   r   r   _subexpr)r   rp   rR   r9   r   r   r:   r   rr   r   r   Znested_argstrsZargrepZdummyr4   )r   r5   r     s:    

z_EvaluatorPrinter._preprocessc                s   ddl m} ddlm y| }W n tk
r   t||rFnt|tr fdd| D } fdd|	 D }tt
||}nFt|trt fdd|D }n t|trڇ fd	d|D }Y nX |S )
Nr   )r   )r   c                s   g | ]} | qS r4   )r   )rG   r   )r   r   r   r4   r5   rI     s    z._EvaluatorPrinter._subexpr.<locals>.<listcomp>c                s   g | ]} | qS r4   )r   )rG   r   )r   r   r   r4   r5   rI     s    c             3   s   | ]} | V  qd S )N)r   )rG   r   )r   r   r   r4   r5   rM     s    z-_EvaluatorPrinter._subexpr.<locals>.<genexpr>c                s   g | ]} | qS r4   )r   )rG   r   )r   r   r   r4   r5   rI   	  s    )r   r   r#   r   r   r   rV   rW   rw   r   r   r   r\   )r   rR   r   r   rt   r   r4   )r   r   r   r5   r     s     



z_EvaluatorPrinter._subexprc             C   s   g S )zGenerate argument wrapping code.

        args is the argument list of the generated function (strings).

        Return value is a list of lines of code that will be inserted  at
        the beginning of the function definition.
        r4   )r   rp   r4   r4   r5   r     s    z(_EvaluatorPrinter._print_funcargwrappingc                s    fdd d  ||gS )zGenerate argument unpacking code.

        arg is the function argument to be unpacked (a string), and
        unpackto is a list or nested lists of the variable names (strings) to
        unpack to.
        c                s   d d fdd| D S )Nz[{}]z, c             3   s"   | ]}t |r |n|V  qd S )N)r   )rG   val)
unpack_lhsr4   r5   rM     s    zI_EvaluatorPrinter._print_unpacking.<locals>.unpack_lhs.<locals>.<genexpr>)rl   rm   )lvalues)r   r4   r5   r     s    z6_EvaluatorPrinter._print_unpacking.<locals>.unpack_lhsz{} = {})rl   )r   Zunpacktor   r4   )r   r5   r     s    z"_EvaluatorPrinter._print_unpacking)NF)r}   
__module____qualname__r   rf   r   classmethodr   r   rh   r   r   r   r   r   r4   r4   r4   r5   re     s   
$
.
re   c               @   s   e Zd Zdd ZdS )rd   c                sL   ddl m}  fdd dfdd |D }dd|||gS )	zGenerate argument unpacking code.

        This method is used when the input value is not interable,
        but can be indexed (see issue #14655).
        r   )r:   c             3   sN   d}xD| D ]<}t |r6x& |D ]}|f| V  q W n|fV  |d7 }q
W d S )Nr   r7   )r   )Zelemsrv   r   r   )r   r4   r5   r   ,  s    
zB_TensorflowEvaluatorPrinter._print_unpacking.<locals>.flat_indexesz, c          	   3   s&   | ]}d   dtt|V  qdS )z{}[{}]z][N)rl   rm   maprK   )rG   r   )rvaluer4   r5   rM   8  s   z?_TensorflowEvaluatorPrinter._print_unpacking.<locals>.<genexpr>z[{}] = [{}])r#   r:   rm   rl   )r   r   r   r:   Zindexedr4   )r   r   r5   r   $  s
    z,_TensorflowEvaluatorPrinter._print_unpackingN)r}   r   r   r   r4   r4   r4   r5   rd   #  s   rd   c       	      C   s   ddl m} |dkri }t| r<x| D ]}t|| q&W |S t| trtx(|  D ]\}}t|| t|| qPW |S t| dd}t||rt|dd}|dk	r| jj	}||kr|| |krt
d| |||< t| drx| jD ]}t|| qW |S )ak   Return namespace dict with function implementations

    We need to search for functions in anything that can be thrown at
    us - that is - anything that could be passed as `expr`.  Examples
    include sympy expressions, as well as tuples, lists and dicts that may
    contain sympy expressions.

    Parameters
    ----------
    expr : object
       Something passed to lambdify, that will generate valid code from
       ``str(expr)``.
    namespace : None or mapping
       Namespace to fill.  None results in new empty dict

    Returns
    -------
    namespace : dict
       dict with keys of implemented function names within `expr` and
       corresponding values being the numerical implementation of
       function

    Examples
    ========

    >>> from sympy.abc import x
    >>> from sympy.utilities.lambdify import implemented_function, _imp_namespace
    >>> from sympy import Function
    >>> f = implemented_function(Function('f'), lambda x: x+1)
    >>> g = implemented_function(Function('g'), lambda x: x*10)
    >>> namespace = _imp_namespace(f(g(x)))
    >>> sorted(namespace.keys())
    ['f', 'g']
    r   )FunctionClassNr{   _imp_z4We found more than one implementation with name "%s"rp   )sympy.core.functionr   r   rU   rV   rW   r0   rc   r{   r}   
ValueErrorrX   rp   )	rR   r3   r   r   keyr   r{   imprF   r4   r4   r5   rU   =  s2    $




rU   c             C   s`   ddl m} i }t| |r&| j}| j} t| trJ|| fdt|i|} nt| |s\td| S )a   Add numerical ``implementation`` to function ``symfunc``.

    ``symfunc`` can be an ``UndefinedFunction`` instance, or a name string.
    In the latter case we create an ``UndefinedFunction`` 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`` or ``UndefinedFunction`` instance
       If ``str``, then create new ``UndefinedFunction`` 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()`` or ``lambdify``

    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
    r   )UndefinedFunctionr   zCsymfunc should be either a string or an UndefinedFunction instance.)r   r   rV   _extra_kwargsr}   r	   staticmethodr   )Zsymfuncimplementationr   r   r4   r4   r5   implemented_function  s    &


r   )r%   )NNTF)NF)N)7ro   Z
__future__r   r   	functoolsr   r_   r   r   rn   rj   Zsympy.core.compatibilityr   r   r   r   r	   r
   r   r   r   Zsympy.utilities.decoratorr   ZMATHZMPMATHZNUMPYZSCIPYZ
TENSORFLOWZSYMPYZNUMEXPRZMATH_DEFAULTZMPMATH_DEFAULTZNUMPY_DEFAULTZSCIPY_DEFAULTZTENSORFLOW_DEFAULTZSYMPY_DEFAULTZNUMEXPR_DEFAULTZMATH_TRANSLATIONSZMPMATH_TRANSLATIONSZNUMPY_TRANSLATIONSZSCIPY_TRANSLATIONSZTENSORFLOW_TRANSLATIONSZNUMEXPR_TRANSLATIONSr'   r6   rg   r|   rY   r]   r   objectre   rd   rU   r   r4   r4   r4   r5   <module>   s   ,






<   L	
s %
D