ó
áp7]c           @  sh  d  Z  d d l m Z d d l m Z d d l Z e j ƒ  j Z	 d Z
 d „  Z d d i  e d „ Z d d i  d „ Z d d  i  d	 „ Z d d! i  e d
 „ Z e
 e d d d d d d d d d d ƒ e _  d d" i  e d „ Z e
 e d d d d d d d d d d ƒ e _  d d# i  d „ Z e
 e d d d d d d d d d d ƒ e _  e Z e j  d 7_  d S($   sx  numerical differentiation function, gradient, Jacobian, and Hessian

Author : josef-pkt
License : BSD

Notes
-----
These are simple forward differentiation, so that we have them available
without dependencies.

* Jacobian should be faster than numdifftools because it doesn't use loop over
  observations.
* numerical precision will vary and depend on the choice of stepsizes
iÿÿÿÿ(   t   print_function(   t   rangeNs  
    Calculate Hessian with finite difference derivative approximation

    Parameters
    ----------
    x : array_like
       value at which function derivative is evaluated
    f : function
       function of one array f(x, `*args`, `**kwargs`)
    epsilon : float or array-like, optional
       Stepsize used, if None, then stepsize is automatically chosen
       according to EPS**(1/%(scale)s)*x.
    args : tuple
        Arguments for function `f`.
    kwargs : dict
        Keyword arguments for function `f`.
    %(extra_params)s

    Returns
    -------
    hess : ndarray
       array of partial second derivatives, Hessian
    %(extra_returns)s

    Notes
    -----
    Equation (%(equation_number)s) in Ridout. Computes the Hessian as::

      %(equation)s

    where e[j] is a vector with element j == 1 and the rest are zero and
    d[i] is epsilon[i].

    References
    ----------:

    Ridout, M.S. (2009) Statistical applications of the complex-step method
        of numerical differentiation. The American Statistician, 63, 66-74
c         C  s˜   | d  k r6 t d | t j t j |  ƒ d ƒ } n^ t j | ƒ rd t j | ƒ } | j | ƒ n0 t j | ƒ } | j	 |  j	 k r” t
 d ƒ ‚ n  | S(   Ng      ð?gš™™™™™¹?s6   If h is not a scalar it must have the same shape as x.(   t   Nonet   EPSt   npt   maximumt   abst   isscalart   emptyt   fillt   asarrayt   shapet
   ValueError(   t   xt   st   epsilont   nt   h(    (    s8   lib/python2.7/site-packages/statsmodels/tools/numdiff.pyt   _get_epsilon^   s    *c         C  s  t  |  ƒ } | |  f | | Ž  } t j | ƒ j } t j | f | t j t |  j ƒ ƒ }	 t j | f t ƒ }
 | sô t |  d | | ƒ } xt	 | ƒ D]T } | | |
 | <| |  |
 f | | Ž  | | | |	 | d d … f <d |
 | <q™ Wnœ t |  d | | ƒ d } x€ t	 t  |  ƒ ƒ D]l } | | |
 | <| |  |
 f | | Ž  | |  |
 f | | Ž  d | | |	 | d d … f <d |
 | <q W|	 j
 ƒ  j S(   sN  
    Gradient of function, or Jacobian if function f returns 1d array

    Parameters
    ----------
    x : array
        parameters at which the derivative is evaluated
    f : function
        `f(*((x,)+args), **kwargs)` returning either one value or 1d array
    epsilon : float, optional
        Stepsize, if None, optimal stepsize is used. This is EPS**(1/2)*x for
        `centered` == False and EPS**(1/3)*x for `centered` == True.
    args : tuple
        Tuple of additional arguments for function `f`.
    kwargs : dict
        Dictionary of additional keyword arguments for function `f`.
    centered : bool
        Whether central difference should be returned. If not, does forward
        differencing.

    Returns
    -------
    grad : array
        gradient or Jacobian

    Notes
    -----
    If f returns a 1d array, it returns a Jacobian. If a 2d array is returned
    by f (e.g., with a value for each observation), it returns a 3d array
    with the Jacobian of each observation with shape xk x nobs x xk. I.e.,
    the Jacobian of the first observation would be [:, 0, :]
    i   Ng        i   g       @(   t   lenR   t
   atleast_1dR   t   zerost   promote_typest   floatt   dtypeR   R   t   squeezet   T(   R   t   fR   t   argst   kwargst   centeredR   t   f0t   dimt   gradt   eit   k(    (    s8   lib/python2.7/site-packages/statsmodels/tools/numdiff.pyt   approx_fprimem   s$    !(67c   
      C  sˆ   t  |  ƒ } t |  d | | ƒ } t j | ƒ d | } g  t | ƒ D]- \ } } | |  | | | Ž j | | ^ qE }	 t j |	 ƒ j S(   sÆ  
    Calculate gradient or Jacobian with complex step derivative approximation

    Parameters
    ----------
    x : array
        parameters at which the derivative is evaluated
    f : function
        `f(*((x,)+args), **kwargs)` returning either one value or 1d array
    epsilon : float, optional
        Stepsize, if None, optimal stepsize is used. Optimal step-size is
        EPS*x. See note.
    args : tuple
        Tuple of additional arguments for function `f`.
    kwargs : dict
        Dictionary of additional keyword arguments for function `f`.

    Returns
    -------
    partials : ndarray
       array of partial derivatives, Gradient or Jacobian

    Notes
    -----
    The complex-step derivative has truncation error O(epsilon**2), so
    truncation error can be eliminated by choosing epsilon to be very small.
    The complex-step derivative avoids the problem of round-off error with
    small epsilon because there is no subtraction.
    i   y              ð?(   R   R   R   t   identityt	   enumeratet   imagt   arrayR   (
   R   R   R   R   R   R   t
   incrementst   it   iht   partials(    (    s8   lib/python2.7/site-packages/statsmodels/tools/numdiff.pyt   approx_fprime_cs¤   s    !=c      
   C  s>  t  |  ƒ } t |  d | | ƒ } t j | ƒ } t j | | ƒ } t  |  ƒ } xé t | ƒ D]Û }	 xÒ t |	 | ƒ D]Á }
 | |  d | |	 d d … f | |
 d d … f f | | Ž  | |  d | |	 d d … f | |
 d d … f f | | Ž  j d | |	 |
 f | |	 |
 f <| |	 |
 f | |
 |	 f <qq Wq[ W| S(   s£  Calculate Hessian with complex-step derivative approximation

    Parameters
    ----------
    x : array_like
       value at which function derivative is evaluated
    f : function
       function of one array f(x)
    epsilon : float
       stepsize, if None, then stepsize is automatically chosen

    Returns
    -------
    hess : ndarray
       array of partial second derivatives, Hessian

    Notes
    -----
    based on equation 10 in
    M. S. RIDOUT: Statistical Applications of the Complex-step Method
    of Numerical Differentiation, University of Kent, Canterbury, Kent, U.K.

    The stepsize is the same for the complex and the finite difference part.
    i   y              ð?Ng       @(   R   R   R   t   diagt   outerR   R'   (   R   R   R   R   R   R   R   t   eet   hessR*   t   j(    (    s8   lib/python2.7/site-packages/statsmodels/tools/numdiff.pyt   approx_hess_csÎ   s    ¡"c         C  s‡  t  |  ƒ } t |  d | | ƒ } t j | ƒ } | |  f | | Ž  }	 t j | ƒ }
 xB t | ƒ D]4 } | |  | | d  d  … f f | | Ž  |
 | <qb Wt j | | ƒ } x² t | ƒ D]¤ } x› t | | ƒ D]Š } | |  | | d  d  … f | | d  d  … f f | | Ž  |
 | |
 | |	 | | | f | | | f <| | | f | | | f <qÏ Wq¹ W| r|
 |	 | } | | f S| Sd  S(   Ni   (   R   R   R   R.   R   R   R/   (   R   R   R   R   R   t   return_gradR   R   R0   R   t   gR*   R1   R2   R!   (    (    s8   lib/python2.7/site-packages/statsmodels/tools/numdiff.pyt   approx_hess1ù   s     2j"
t   scalet   3t   extra_paramssF   return_grad : bool
        Whether or not to also return the gradient
t   extra_returnss7   grad : nparray
        Gradient if return_grad == True
t   equation_numbert   7t   equationsB   1/(d_j*d_k) * ((f(x + d[j]*e[j] + d[k]*e[k]) - f(x + d[j]*e[j])))
c      	   C  s  t  |  ƒ } t |  d | | ƒ } t j | ƒ } | |  f | | Ž  }	 t j | ƒ }
 t j | ƒ } xp t | ƒ D]b } | |  | | d  d  … f f | | Ž  |
 | <| |  | | d  d  … f f | | Ž  | | <qq Wt j | | ƒ } xt | ƒ D]ø } xï t | | ƒ D]Þ } | |  | | d  d  … f | | d  d  … f f | | Ž  |
 | |
 | |	 | |  | | d  d  … f | | d  d  … f f | | Ž  | | | | |	 d | | | f | | | f <| | | f | | | f <qWqö W| r|
 |	 | } | | f S| Sd  S(   Ni   i   (   R   R   R   R.   R   R   R/   (   R   R   R   R   R   R4   R   R   R0   R   R5   t   ggR*   R1   R2   R!   (    (    s8   lib/python2.7/site-packages/statsmodels/tools/numdiff.pyt   approx_hess2  s$    .2¾"
t   8sã   1/(2*d_j*d_k) * ((f(x + d[j]*e[j] + d[k]*e[k]) - f(x + d[j]*e[j])) -
                 (f(x + d[k]*e[k]) - f(x)) +
                 (f(x - d[j]*e[j] - d[k]*e[k]) - f(x + d[j]*e[j])) -
                 (f(x - d[k]*e[k]) - f(x)))
c      
   C  sŸ  t  |  ƒ } t |  d | | ƒ } t j | ƒ } t j | | ƒ } xVt | ƒ D]H}	 x?t |	 | ƒ D].}
 | |  | |	 d  d  … f | |
 d  d  … f f | | Ž  | |  | |	 d  d  … f | |
 d  d  … f f | | Ž  | |  | |	 d  d  … f | |
 d  d  … f f | | Ž  | |  | |	 d  d  … f | |
 d  d  … f f | | Ž  d | |	 |
 f | |	 |
 f <| |	 |
 f | |
 |	 f <qe WqO W| S(   Ni   g      @(   R   R   R   R.   R/   R   (   R   R   R   R   R   R   R   R0   R1   R*   R2   (    (    s8   lib/python2.7/site-packages/statsmodels/tools/numdiff.pyt   approx_hess3J  s    ²="t   4t    t   9s	  1/(4*d_j*d_k) * ((f(x + d[j]*e[j] + d[k]*e[k]) - f(x + d[j]*e[j]
                                                     - d[k]*e[k])) -
                 (f(x - d[j]*e[j] + d[k]*e[k]) - f(x - d[j]*e[j]
                                                     - d[k]*e[k]))s&   
    This is an alias for approx_hess3(    (    (    (    (    (    (   t   __doc__t
   __future__R    t   statsmodels.compat.pythonR   t   numpyR   t   MachArt   epsR   t   _hessian_docsR   R   t   FalseR$   R-   R3   R6   t   dictR?   RA   t   approx_hess(    (    (    s8   lib/python2.7/site-packages/statsmodels/tools/numdiff.pyt   <module>   s8    (	7*+