ó
 nTMc           @   sf   d  Z  d d l m Z e Z d d d „  ƒ  YZ d „  Z d „  Z d „  Z d „  Z d	 d
 d „ Z	 d S(   s  
Automatic differentiation for functions of
any number of variables up to any order

An instance of the class DerivVar represents the value of a function
and the values of its partial X{derivatives} with respect to a list of
variables. All common mathematical operations and functions are
available for these numbers. There is no restriction on the type of
the numbers fed into the code; it works for real and complex numbers
as well as for any Python type that implements the necessary
operations.

If only first-order derivatives are required, the module
FirstDerivatives should be used. It is compatible to this
one, but significantly faster.

Example::

  print sin(DerivVar(2))

produces the output::

  (0.909297426826, [-0.416146836547])

The first number is the value of sin(2); the number in the following
list is the value of the derivative of sin(x) at x=2, i.e. cos(2).

When there is more than one variable, DerivVar must be called with
an integer second argument that specifies the number of the variable.

Example::

    >>>x = DerivVar(7., 0)
    >>>y = DerivVar(42., 1)
    >>>z = DerivVar(pi, 2)
    >>>print (sqrt(pow(x,2)+pow(y,2)+pow(z,2)))

    produces the output

    >>>(42.6950770511, [0.163953328662, 0.98371997197, 0.0735820818365])

The numbers in the list are the partial derivatives with respect
to x, y, and z, respectively.

Higher-order derivatives are requested with an optional third
argument to DerivVar.

Example::

    >>>x = DerivVar(3., 0, 3)
    >>>y = DerivVar(5., 1, 3)
    >>>print sqrt(x*y)

    produces the output

    >>>(3.87298334621,
    >>>    [0.645497224368, 0.387298334621],
    >>>      [[-0.107582870728, 0.0645497224368],
    >>>        [0.0645497224368, -0.0387298334621]],
    >>>          [[[0.053791435364, -0.0107582870728],
    >>>            [-0.0107582870728, -0.00645497224368]],
    >>>           [[-0.0107582870728, -0.00645497224368],
    >>>            [-0.00645497224368, 0.0116189500386]]])

The individual orders can be extracted by indexing::

    >>>print sqrt(x*y)[0]
    >>>3.87298334621
    >>>print sqrt(x*y)[1]
    >>>[0.645497224368, 0.387298334621]

An n-th order derivative is represented by a nested list of
depth n.

When variables with different differentiation orders are mixed,
the result has the lower one of the two orders. An exception are
zeroth-order variables, which are treated as constants.

Caution: Higher-order derivatives are implemented by recursively
using DerivVars to represent derivatives. This makes the code
very slow for high orders.

Note: It doesn't make sense to use multiple DerivVar objects with
different values for the same variable index in one calculation, but
there is no check for this. I.e.::

    >>>print DerivVar(3, 0)+DerivVar(5, 0)

    produces

    >>>(8, [2])

but this result is meaningless.
iÿÿÿÿ(   t   Nt   DerivVarc           B   sa  e  Z d  Z d d d& d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z	 d	 „  Z
 d
 „  Z d „  Z d „  Z d „  Z d „  Z e Z d „  Z d „  Z d „  Z e Z d „  Z d „  Z d& d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z  d „  Z! d „  Z" d  „  Z# d! „  Z$ d" „  Z% d# „  Z& d$ „  Z' d% „  Z( RS('   sJ   
    Numerical variable with automatic derivatives of arbitrary order
    i    i   c         C   s  | d k  r t  d ƒ ‚ n  | |  _ | r3 d } n d } t | ƒ t g  ƒ k r] | |  _ n¤ | d k ru g  |  _ nŒ | d k r› | d g | g |  _ nf g  |  _ x7 t | ƒ D]) } |  j j t d | | d d ƒ ƒ q± W|  j j t | | | d d ƒ ƒ | |  _ d S(   s×  
        @param value: the numerical value of the variable
        @type value: number
        @param index: the variable index, which serves to
            distinguish between variables and as an index for
            the derivative lists. Each explicitly created
            instance of DerivVar must have a unique index.
        @type index: C{int}
        @param order: the derivative order
        @type order: C{int}
        @raise ValueError: if order < 0
        i    s   Negative derivative orderi   N(   t
   ValueErrort   valuet   typet   derivt   ranget   appendR   t   order(   t   selfR   t   indexR   t	   recursivet   dt   i(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __init__r   s"    			'#c         C   sO   |  j  | k r |  S| d k r& |  j St |  j t | d d „ |  j ƒ | ƒ S(   sÀ   
        @param order: the highest derivative order to be kept
        @type order: C{int}
        @return: a DerivVar object with a lower derivative order
        @rtype: L{DerivVar}
        i    i   c         S   s   |  j  | ƒ S(   N(   t   toOrder(   t   xt   o(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   <lambda>ž   s    (   R   R   R   t   mapR   (   R	   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   “   s    c         C   s[   | d k  s | |  j  k r* t d ƒ ‚ n  | d k r= |  j St | d d „ |  j ƒ Sd S(   sà   
        @param order: derivative order
        @type order: C{int}
        @return: a list of all derivatives of the given order
        @rtype: C{list}
        @raise ValueError: if order < 0 or order > self.order
        i    s   Index out of rangei   c         S   s   t  |  | ƒ S(   N(   t   _indexDeriv(   R   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   ®   s    N(   R   R   R   R   R   (   R	   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __getitem__¡   s
    c         C   s,   t  t t |  d „ t |  j d ƒ ƒ ƒ ƒ S(   Nc         S   s   | |  S(   N(    (   t   nR   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   ±   s    i   (   t   reprt   tupleR   R   R   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __repr__°   s    c         C   s,   t  t t |  d „ t |  j d ƒ ƒ ƒ ƒ S(   Nc         S   s   | |  S(   N(    (   R   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   ´   s    i   (   t   strR   R   R   R   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __str__³   s    c         C   s‘   t  | ƒ rw |  j | j k s< |  j d k s< | j d k rF |  | f St |  j | j ƒ } |  j | ƒ | j | ƒ f S|  t | g  d ƒ f Sd  S(   Ni    (   t
   isDerivVarR   t   minR   R   (   R	   t   otherR   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt
   __coerce__¶   s    0
c         C   s   t  |  j | j ƒ S(   N(   t   cmpR   (   R	   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __cmp__¿   s    c         C   s&   t  |  j t d „  |  j ƒ |  j ƒ S(   Nc         S   s   |  S(   N(    (   t   a(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   Ã   s    (   R   R   R   R   R   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __neg__Â   s    c         C   s   |  S(   N(    (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __pos__Å   s    c         C   s;   t  |  j ƒ } t | t |  j | d „ |  j ƒ |  j ƒ S(   Nc         S   s   | |  S(   N(    (   R"   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   Ê   s    (   t   absR   R   R   R   R   (   R	   t   absvalue(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __abs__È   s    c         C   s   |  j  d k S(   Ni    (   R   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __nonzero__Í   s    c         C   s>   t  |  j | j t d „  |  j | j ƒ t |  j | j ƒ ƒ S(   Nc         S   s   |  | S(   N(    (   R"   t   b(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   Ò   s    (   R   R   t	   _mapderivR   t   maxR   (   R	   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __add__Ð   s    c         C   s>   t  |  j | j t d „  |  j | j ƒ t |  j | j ƒ ƒ S(   Nc         S   s   |  | S(   N(    (   R"   R)   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   Ø   s    (   R   R   R*   R   R+   R   (   R	   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __sub__Ö   s    c         C   s>   t  | j |  j t d „  | j |  j ƒ t |  j | j ƒ ƒ S(   Nc         S   s   |  | S(   N(    (   R"   R)   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   Ý   s    (   R   R   R*   R   R+   R   (   R	   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __rsub__Û   s    c         C   s¾   |  j  d k  r |  j } n |  j |  j  d ƒ } | j  d k  rL | j } n | j | j  d ƒ } t |  j | j t d „  t | d „ |  j ƒ t | d „ | j ƒ ƒ t |  j  | j  ƒ ƒ S(   Ni   i   c         S   s   |  | S(   N(    (   R"   R)   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   ê   s    c         S   s   | |  S(   N(    (   R   t   f(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   ë   s    c         S   s   | |  S(   N(    (   R   R/   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   ì   s    (   R   R   R   R   R*   R   R   R+   (   R	   R   t   s1t   o1(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __mul__à   s    	c      
   C   sñ   | j  s t d ƒ ‚ n  |  j d k  r3 |  j  } n |  j |  j d ƒ } | j d k  rh d | j  } n d | j | j d ƒ } t t |  j  ƒ | j  t d „  t | d „ |  j ƒ t | t	 | d ƒ d „ | j ƒ ƒ t
 |  j | j ƒ ƒ S(   Ns   DerivVar divisioni   i   g      ð?c         S   s   |  | S(   N(    (   R"   R)   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   ü   s    c         S   s   |  | S(   N(    (   R   R/   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   ý   s    c         S   s   | |  S(   N(    (   R   R/   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   þ   s    (   R   t   ZeroDivisionErrorR   R   R   t   _toFloatR*   R   R   t   powR+   (   R	   R   R0   t   o1i(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __div__ð   s    		c         C   s   | |  S(   N(    (   R	   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __rdiv__  s    c         C   sí   | d  k	 r t d ƒ ‚ n  t | j ƒ d k rJ t j t j |  ƒ | ƒ S|  j d k  r| | j t	 |  j | j d ƒ } n- | j t	 |  j
 |  j d ƒ | j d ƒ } t t	 |  j | j ƒ t | d „ |  j ƒ t |  j | j ƒ ƒ Sd  S(   Ns'   DerivVar does not support ternary pow()i    i   i   c         S   s   | |  S(   N(    (   R   R/   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR     s    (   t   Nonet	   TypeErrort   lenR   t   Numerict   expt   logR   R   R5   R   R   R   R+   (   R	   R   t   zt   ps1(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __pow__  s    #-c         C   s   t  | |  ƒ S(   N(   R5   (   R	   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   __rpow__  s    c         C   sk   |  j  d k  r! | |  j ƒ } n | |  j |  j  d ƒ ƒ } t | |  j ƒ t | d „ |  j ƒ |  j  ƒ S(   Ni   i   c         S   s   | |  S(   N(    (   R   R/   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR     s    (   R   R   R   R   R   R   (   R	   R/   R   t   fd(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt	   _mathfunc  s
    $c         C   s   |  j  t j t j ƒ S(   N(   RD   R<   R=   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR=     s    c         C   s   |  j  t j d „  ƒ S(   Nc         S   s   d |  S(   Ng      ð?(    (   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   !  s    (   RD   R<   R>   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR>      s    c         C   s   |  j  t j d „  ƒ S(   Nc         S   s   d |  t  j d ƒ S(   Ng      ð?i
   (   R<   R>   (   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   $  s    (   RD   R<   t   log10(   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRE   #  s    c         C   s   |  j  t j d „  ƒ S(   Nc         S   s   d t  j |  ƒ S(   Ng      à?(   R<   t   sqrt(   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   '  s    (   RD   R<   RF   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRF   &  s    c         C   s4   |  j  d k r t d ƒ ‚ n  |  j t j d „  ƒ S(   Ni    s"   can't differentiate sign() at zeroc         S   s   d S(   Ni    (    (   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   ,  s    (   R   R   RD   R<   t   sign(   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRG   )  s    c         C   s   |  j  t j t j ƒ S(   N(   RD   R<   t   sint   cos(   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRH   .  s    c         C   s   |  j  t j d „  ƒ S(   Nc         S   s   t  j |  ƒ S(   N(   R<   RH   (   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   2  s    (   RD   R<   RI   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRI   1  s    c         C   s   |  j  t j d „  ƒ S(   Nc         S   s   d t  t j |  ƒ d ƒ S(   Ng      ð?i   (   R5   R<   t   tan(   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   5  s    (   RD   R<   RJ   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRJ   4  s    c         C   s   |  j  t j t j ƒ S(   N(   RD   R<   t   sinht   cosh(   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRK   7  s    c         C   s   |  j  t j t j ƒ S(   N(   RD   R<   RL   RK   (   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRL   :  s    c         C   s   |  j  t j d „  ƒ S(   Nc         S   s   d t  t j |  ƒ d ƒ S(   Ng      ð?i   (   R5   R<   RL   (   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   >  s    (   RD   R<   t   tanh(   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRM   =  s    c         C   s   |  j  t j d „  ƒ S(   Nc         S   s   d t  j d t |  d ƒ ƒ S(   Ng      ð?i   (   R<   RF   R5   (   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   B  s    (   RD   R<   t   arcsin(   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRN   A  s    c         C   s   |  j  t j d „  ƒ S(   Nc         S   s   d t  j d t |  d ƒ ƒ S(   Ng      ð¿g      ð?i   (   R<   RF   R5   (   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   F  s    (   RD   R<   t   arccos(   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRO   E  s    c         C   s   |  j  t j d „  ƒ S(   Nc         S   s   d d t  |  d ƒ S(   Ng      ð?i   i   (   R5   (   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   J  s    (   RD   R<   t   arctan(   R	   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRP   I  s    c         C   sì   |  j  d k  r |  j } n |  j |  j  d ƒ } | j  d k  rL | j } n | j | j  d ƒ } | | | | } | | } | | } t t j |  j | j ƒ t d „  t | d „ |  j ƒ t | d „ | j ƒ ƒ t	 |  j  | j  ƒ ƒ S(   Ni   i   c         S   s   |  | S(   N(    (   R"   R)   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   Z  s    c         S   s   |  | S(   N(    (   R   R/   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   [  s    c         S   s   |  | S(   N(    (   R   R/   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   \  s    (
   R   R   R   R   R<   t   arctan2R*   R   R   R+   (   R	   R   R0   R1   t   den(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyRQ   M  s    

	N()   t   __name__t
   __module__t   __doc__R9   R   R   R   R   R   R   R!   R#   R$   R'   R(   R,   t   __radd__R-   R.   R2   t   __rmul__R7   R8   RA   RB   RD   R=   R>   RE   RF   RG   RH   RI   RJ   RK   RL   RM   RN   RO   RP   RQ   (    (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   l   sL   !																																	c         C   s+   t  |  d ƒ o* t  |  d ƒ o* t  |  d ƒ S(   sx   
    @param x: an arbitrary object
    @return: True if x is a DerivVar object, False otherwise
    @rtype: C{bool}
    R   R   R   (   t   hasattr(   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   a  s    c         C   sa   t  t | ƒ t | ƒ ƒ } | | t | ƒ d g } | | t | ƒ d g } t |  | | ƒ S(   Ni    (   R+   R;   R   (   t   funcR"   R)   t   nvars(    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR*   l  s    c         C   s   t  |  t ƒ r t |  ƒ S|  S(   N(   t
   isinstancet   intt   float(   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR4   t  s    
c         C   s3   t  |  ƒ r |  | S| d k r/ t d ƒ ‚ n  |  S(   Ni    s   Internal error(   R   R   (   R   R   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyR   {  s
    i    i   c      	   C   s„   d d l  m } t |  ƒ rD t | ƒ rD t | ƒ rD | |  | | ƒ S| t |  | | ƒ t | | d | ƒ t | | d | ƒ ƒ Sd S(   sö  
    @param x: x component of the vector
    @type x: number
    @param y: y component of the vector
    @type y: number
    @param z: z component of the vector
    @type z: number
    @param index: the DerivVar index for the x component. The y and z
                  components receive consecutive indices.
    @type index: C{int}
    @param order: the derivative order
    @type order: C{int}
    @return: a vector whose components are DerivVar objects
    @rtype: L{Scientific.Geometry.Vector}
    iÿÿÿÿ(   t   Vectori   i   N(   t    Scientific.Geometry.VectorModuleR^   R   R   (   R   t   yR?   R
   R   R^   (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   DerivVector„  s    $N(    (
   RU   t
   ScientificR    R<   R   R   R*   R4   R   Ra   (    (    (    sA   C:\Python27\Lib\site-packages\Scientific\Functions\Derivatives.pyt   <module>d   s    õ					