B
    Zg=              	   @   sX  d Z ddlmZ ddlmZ ddlZe jZ	dZ
dd Zddi d	fd
dZddi fddZddi fddZdde
ddd edddddd  e_ ddi d	fddZe
edddddd e_ ddi d	fddZe
edddd d!d e_ ddi fd"d#Ze
ed$ddd%d&d e_ eZe j d'7  _ ed(krTddlmZ dd)lmZ ddlZejj Zej ej!d	d*e_!e"ej#ej!Z$e$j%d+d,Z&dd-d.d/gZ'e$j(Z)e$j*Z*e$j+Z,dRd2d3Z-d4d5 Z.d6d7 Z/d8d9 Z0d:Z1e2e1d; 3e1d<Z4ej56e1d;Z4e7dd=d;gZ8e7d>d>d>gZ8e8Z9e:e4e9d?ej56e1  Z;e:ej<=e4e;Z8d1Z>e;e4fZ?dd@l@mAZA eABe0dAe?ZCeDedBe.e>e4 ee8e/e>e?ZEee8e/e> e?ZFeDeEGd eDdC eDe:eEjHeE eDdD eDd=e:e4jHe4  eEeF dE ZIeDe:eIjHeI eDeJe8e0dFe? eJe8e0de?ZKeDdG eDeK eDdHd eDeKd d=e:e4jHe4   x@dID ]8ZeDdJe eDeJe8e0ee?d d=e:e4jHe4   qbW ee8e0e?dKZLeDdL eDeLd=e:e4jHe4   ee8e0e?dKZMeDdM eDeMd=e:e4jHe4   ddlNZOeOPdNdO ZQeQe8ZReDdP eDeRd=e:e4jHe4   eOSdQdO ZTeTe8ZUdS )Sax  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
    )print_function)rangeNa  
    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   sj   |d kr(t d|  tt| d }n>t|rHt|}|| nt|}|j| jkrft	d|S )Ng      ?g?z6If h is not a scalar it must have the same shape as x.)
EPSnpZmaximumabsZisscalaremptyZfillZasarrayshape
ValueError)xsepsilonnh r   8lib/python3.7/site-packages/statsmodels/tools/numdiff.py_get_epsilon^   s     


r   r   Fc             C   s:  t | }|| f| |}t|j}t|f| tt| j}	t|ft}
|st| d||}xt	|D ]D}|| |
|< || |
 f| || ||  |	|ddf< d|
|< qjW n|t| d||d }xht	t | D ]X}|| |
|< || |
 f| ||| |
 f| | d||   |	|ddf< d|
|< qW |	
 jS )aN  
    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, :]
       Ng           g       @)lenr   Z
atleast_1dr   zerosZpromote_typesfloatZdtyper   r   ZsqueezeT)r
   fr   argskwargsZcenteredr   f0ZdimgradZeikr   r   r   approx_fprimem   s$    !,.r   c                sR   t }td|t|d  } fddt|D }t|jS )a  
    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.
       y              ?c                s.   g | ]&\}}| f j |  qS r   )imag).0iZih)r   r   r   r   r
   r   r   
<listcomp>   s   z$approx_fprime_cs.<locals>.<listcomp>)r   r   r   Zidentity	enumeratearrayr   )r
   r   r   r   r   r   Z
incrementsZpartialsr   )r   r   r   r   r
   r   approx_fprime_cs   s    !r&   c          
   C   s   t | }t| d||}t|}t||}t | }xt|D ]}	xt|	|D ]}
|| d||	ddf   ||
ddf  f| ||| d||	ddf   ||
ddf  f| | jd ||	|
f  ||	|
f< ||	|
f ||
|	f< qNW q>W |S )a  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.
    r   y              ?Ng       @)r   r   r   diagouterr   r    )r
   r   r   r   r   r   r   eehessr"   jr   r   r   approx_hess_cs   s    
r,   z=Calculate Hessian with complex-step derivative approximation

r   3 Z10zk1/(2*d_j*d_k) * imag(f(x + i*d[j]*e[j] + d[k]*e[k]) -
                     f(x + i*d[j]*e[j] - d[k]*e[k]))
)ZscaleZextra_paramsZextra_returnsZequation_numberZequationc             C   s0  t | }t| d||}t|}|| f| |}	t|}
x4t|D ](}|| ||d d f  f| ||
|< qDW t||}xt|D ]}x~t||D ]p}|| ||d d f  ||d d f  f| ||
|  |
|  |	 |||f  |||f< |||f |||f< qW qW |r(|
|	 | }||fS |S d S )Nr   )r   r   r   r'   r   r   r(   )r
   r   r   r   r   return_gradr   r   r)   r   gr"   r*   r+   r   r   r   r   approx_hess1  s     

(Xr2   zFreturn_grad : bool
        Whether or not to also return the gradient
z7grad : nparray
        Gradient if return_grad == True
7zB1/(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|}|| f| |}	t|}
t|}xXt|D ]L}|| ||d d f  f| ||
|< || ||d d f  f| |||< qNW t||}xt|D ]}xt||D ]}|| ||d d f  ||d d f  f| ||
|  |
|  |	 || ||d d f  ||d d f  f| | ||  ||  |	 d|||f   |||f< |||f |||f< qW qW |r|
|	 | }||fS |S d S )Nr   r   )r   r   r   r'   r   r   r(   )r
   r   r   r   r   r0   r   r   r)   r   r1   Zggr"   r*   r+   r   r   r   r   approx_hess2(  s$    


$(r4   8z1/(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   sF  t | }t| d||}t|}t||}xt|D ]}	xt|	|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< qJW q8W |S )N   g      @)r   r   r   r'   r(   r   )r
   r   r   r   r   r   r   r)   r*   r"   r+   r   r   r   approx_hess3U  s    
2r7   49a	  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]))z&
    This is an alias for approx_hess3__main__)approx_fhess_p)ZprependZnewton)methodg      ?gffffff?i#B;ư>c                s,    fdd}t | ||t | ||  d S )Nc                s   t |  ddS )Ng#B;)r   r   )r&   )r
   )r   funcr   r   r     s    z approx_hess_cs_old.<locals>.gradg       @)r   )r
   r?   r   r   r   r   r   )r   r?   r   approx_hess_cs_old  s    
r@   c             C   s   t || dS )Nr   )r   dotsum)betar
   r   r   r   fun  s    rD   c             C   s   t || }|| d S )Nr   )r   rA   )rC   yr
   Zxbr   r   r   fun1  s    rF   c             C   s   t | ||dS )Nr   )rF   rB   )rC   rE   r
   r   r   r   fun2  s    rG      r   r   g      ?g?)optimize)r   r   r   )r   r   r   z
np.dot(jac.T, jac)z
2*np.dot(x.T, x)g       @gMbP?Zhessfdz	epsilon =)gMbP?g-C6?gh㈵>gư>zeps =)r   hcs2hfd3c             C   s   t | ttS )N)rG   rE   r
   )ar   r   r   <lambda>  s    rN   Znumdiffc             C   s   t | ttS )N)rG   rE   r
   )rM   r   r   r   rN     s    )r   r=   r>   )V__doc__Z
__future__r   Zstatsmodels.compat.pythonr   Znumpyr   ZMachArZepsr   Z_hessian_docsr   r   r&   r,   joinsplitdictr2   r4   r7   Zapprox_hess__name__Zstatsmodels.apiZapiZsmZscipy.optimize.optimizer;   ZdatasetsZspectorloaddataZadd_constantZexogZProbitZendogmodZfitZresZtest_paramsZloglikeZllfZscoreZhessianr*   r@   rD   rF   rG   ZnobsZarangeZreshaper
   ZrandomZrandnr%   ZxkrC   rA   rE   ZlinalgZpinvr   r   ZscipyrJ   ZfminZxfminprintZjacZjacminrB   r   Zjac2Zapprox_hess_oldZherK   rL   ZnumdifftoolsZndZHessianZhndZhessndZGradientZgndZgradndr   r   r   r   <module>   s    
(7*)

	


.