
    >h8=                        S r SSKrSSKJrJr  \R                  " \5      R                  r	Sr
S rSS0 S4S jrSS0 S4S	 jrSS0 4S
 jrSS0 4S jrSS0 4S jr\" SSSSSS9\" \
5      SS0 S4S j5       5       r\" SSSSSS9\" \
5      SS0 S4S j5       5       r\" SSSSSS9\" \
5      SS0 4S j5       5       r\r\=R                   S-  sl         g)ay  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 does not use loop over
  observations.
* numerical precision will vary and depend on the choice of stepsizes
    N)AppenderSubstitutiona  
    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                    UcM  [         SU-  -  [        R                  " [        R                  " [        R                  " U 5      5      S5      -  nO~[        R
                  " U5      (       a(  [        R                  " U5      nUR                  U5        O;[        R                  " U5      nUR                  U R                  :w  a  [        S5      e[        R                  " U5      $ )Ng      ?g?z6If h is not a scalar it must have the same shape as x.)
EPSnpmaximumabsasarrayisscalaremptyfillshape
ValueError)xsepsilonnhs        lC:\Users\julio\OneDrive\Documentos\Trabajo\Ideas Frescas\venv\Lib\site-packages\statsmodels/tools/numdiff.py_get_epsilonr   ^   s    "q&MBJJrvvbjjm'<cBB;;wAFF7O

7#Aww!''!  "0 1 1::a=     Fc                    [        U 5      nU" U 4U-   0 UD6n[        R                  " U5      R                  n[        R                  " U4U-   [        R
                  " [        U R                  5      5      n	[        R                  " U4[        5      n
U(       dF  [        U SX&5      n[        U5       H)  nX+   X'   U" X
-   4U-   0 UD6U-
  X+   -  XSS24'   SX'   M+     OW[        U SX&5      S-  n[        U5       H8  nX+   X'   U" X
-   4U-   0 UD6U" X
-
  4U-   0 UD6-
  SX+   -  -  XSS24'   SX'   M:     US:X  a  U	R                  $ U	R                  5       R                  $ )a  
Gradient of function, or Jacobian if function f returns 1d array

Parameters
----------
x : ndarray
    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 : ndarray
    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                  @   )lenr   
atleast_1dr   zerospromote_typesfloatdtyper   rangeTsqueeze)r   fr   argskwargscenteredr   f0dimgradeiks               r   approx_fprimer0   m   se   B 	AA	
aT$Y	"6	"B
--

!
!C88QD3J 0 0 @AD	1$	Bq!W0qAJBEqtgn882=wzIDAJBE 
 q!W025qAJBEqtgdl6v6qtgdl6v679:WZIDAJBE	  	Avvv||~r   c                    [         R                  " U 5      n SnU" U 4U-   0 UD6nU(       d#  [        U SX&5      nU" X-   4U-   0 UD6U-
  U-  n	U	$ [        U SX&5      S-  nU" X-   4U-   0 UD6U" X-
  4U-   0 UD6-
  SU-  -  n	U	$ )a  
Gradient of function vectorized for scalar parameter.

This assumes that the function ``f`` is vectorized for a scalar parameter.
The function value ``f(x)`` has then the same shape as the input ``x``.
The derivative returned by this function also has the same shape as ``x``.

Parameters
----------
x : ndarray
    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 : ndarray
    Array of derivatives, gradient evaluated at parameters ``x``.
r   r   r   r   )r   r
   r   )
r   r'   r   r(   r)   r*   r   r+   epsr-   s
             r   _approx_fprime_scalarr3      s    > 	

1A	A	
aT$Y	"6	"B1a,QUHtO//"4; K	 1a,r1QUHTM-f-QUHTM-f-.23c'; Kr   c           	      *   [        U 5      n[        U SX%5      n[        R                  " U5      S-  U-  n[	        U5       VVs/ s H"  u  pxU" X-   /UQ70 UD6R
                  X'   -  PM$     n	nn[        R                  " U	5      R                  $ s  snnf )ad  
Calculate gradient or Jacobian with complex step derivative approximation

Parameters
----------
x : ndarray
    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.
r                 ?)r   r   r   identity	enumerateimagarrayr%   )
r   r'   r   r(   r)   r   
incrementsiihpartialss
             r   approx_fprime_csr>      s    B 	AA1a,GQ"$w.J 'z242EA !$(((--
:2  4 88H4s   )Bc                     [         R                  " U 5      n U R                  S   n[        U SX%5      nSU-  nU" X-   /UQ70 UD6R                  U-  n[         R
                  " U5      $ )aN  
Calculate gradient for scalar parameter with complex step derivatives.

This assumes that the function ``f`` is vectorized for a scalar parameter.
The function value ``f(x)`` has then the same shape as the input ``x``.
The derivative returned by this function also has the same shape as ``x``.

Parameters
----------
x : ndarray
    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 derivatives, gradient evaluated for parameters ``x``.

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.
r   r5   )r   r
   r   r   r8   r9   )r   r'   r   r(   r)   r   r2   r=   s           r   _approx_fprime_cs_scalarrA     sf    J 	

1A	A1a,G
w,C*4*6*//'9H88Hr   c                    [        U 5      n[        U SX%5      n[        R                  " U5      n[        R                  " Xf5      n[        U 5      n[        U5       H  n	[        X5       H|  n
[        R                  " U" U SXySS24   -  -   XzSS24   -   4U-   0 UD6U" U SXySS24   -  -   XzSS24   -
  4U-   0 UD6-
  R                  S-  XU
4   -  5      XU
4'   XU
4   XU	4'   M~     M     U$ )aW  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   r5   Nr   )r   r   r   diagouterr$   r&   r8   r   r'   r   r(   r)   r   r   eehessr;   js              r   approx_hess_csrI   0  s   4 	AAQ7&A	B88A>DAA1XqAa"R1X+oa402T9EfERa4[2d8!; =d B ( &(()-b115d<DAJ
 dDAJ   Kr   3zFreturn_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])))
)scaleextra_paramsextra_returnsequation_numberequationc           	         [        U 5      n[        U SX&5      n[        R                  " U5      nU" U 4U-   0 UD6n	[        R                  " U5      n
[        U5       H  nU" XUS S 24   -   4U-   0 UD6X'   M     [        R                  " Xw5      n[        U5       HU  n[        X5       HC  nU" XUS S 24   -   XS S 24   -   4U-   0 UD6X   -
  X   -
  U	-   XU4   -  XU4'   XU4   XU4'   ME     MW     U(       a
  X-
  U-  nX4$ U$ )Nr   r   r   r   rC   r    r$   rD   )r   r'   r   r(   r)   return_gradr   r   rF   r+   gr;   rG   rH   r-   s                  r   approx_hess1rU   ]  s/    	AAQ7&A	B	
aT$Y	"6	"B
A1XAAhJ=%1&1  88A>D1XqAqad8|bAh684?KFK$!"&(*+,0AJ7DAJdDAJ  
 zzr   z7grad : ndarray
        Gradient if return_grad == True
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           
         [        U 5      n[        U SX&5      n[        R                  " U5      nU" U 4U-   0 UD6n	[        R                  " U5      n
[        R                  " U5      n[        U5       H1  nU" XUS S 24   -   4U-   0 UD6X'   U" XUS S 24   -
  4U-   0 UD6X'   M3     [        R                  " Xw5      n[        U5       H  n[        X5       Hr  nU" XUS S 24   -   XS S 24   -   4U-   0 UD6X   -
  X   -
  U	-   U" XUS S 24   -
  XS S 24   -
  4U-   0 UD6-   X   -
  X   -
  U	-   SXU4   -  -  XU4'   XU4   XU4'   Mt     M     U(       a
  X-
  U-  nX4$ U$ )Nr   r   rR   )r   r'   r   r(   r)   rS   r   r   rF   r+   rT   ggr;   rG   rH   r-   s                   r   approx_hess2rY     s   $ 	AAQ7&A	B	
aT$Y	"6	"B
A	!B1XAAhJ=%1&1Q!Q$xZM$&262  88A>D1XqAqad8|bAh684?KFK$!"&(*+qad8|bAh684?KFKL %  #%%( +-- 0141:~?DAJ dDAJ   zzr   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]))c                 $   [        U 5      n[        U SX%5      n[        R                  " U5      n[        R                  " Xf5      n[        U5       H  n	[        X5       H  n
[        R                  " U" XU	S S 24   -   XzS S 24   -   4U-   0 UD6U" XU	S S 24   -   XzS S 24   -
  4U-   0 UD6-
  U" XU	S S 24   -
  XzS S 24   -   4U-   0 UD6U" XU	S S 24   -
  XzS S 24   -
  4U-   0 UD6-
  -
  SXU
4   -  -  5      XU
4'   XU
4   XU	4'   M     M     U$ )N   g      @)r   r   r   rC   rD   r$   r&   rE   s              r   approx_hess3r_     sM    	AAQ7&A	B88A>D1XqAaQT(lR1X-/$6B6Bq!tHrQ$x/1D8DVDE1Xa402T9EfE1!Q$x<"T(24t;GGHI tqDzM	#DAJ dDAJ   Kr   z&
    This is an alias for approx_hess3)__doc__numpyr   statsmodels.compat.pandasr   r   finfor"   r2   r   _hessian_docsr   r0   r3   r>   rA   rI   rU   rY   r_   approx_hessr   r   r   <module>rf      so  Z  < 	hhuo&R !%2b5 7 t )-2b#(+\ $(b ) X ,0b ,^ "&Br *Z 
  
-#"RU  2 
  
-#"RU   < 
F	 
-#"R  	&    @ @ r   