o
    EbX                     @   s~   d dl Zd dlmZ ddlmZmZ ddlm	Z	 d dl
mZ dZG dd dZG d	d
 d
ZG dd dZG dd deZdS )    N   )approx_derivativegroup_columns)HessianUpdateStrategy)LinearOperator)z2-pointz3-pointcsc                   @   sT   e Zd ZdZ	dddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd ZdS )ScalarFunctiona  Scalar function and its derivatives.

    This class defines a scalar function F: R^n->R and methods for
    computing or approximating its first and second derivatives.

    Parameters
    ----------
    fun : callable
        evaluates the scalar function. Must be of the form ``fun(x, *args)``,
        where ``x`` is the argument in the form of a 1-D array and ``args`` is
        a tuple of any additional fixed parameters needed to completely specify
        the function. Should return a scalar.
    x0 : array-like
        Provides an initial set of variables for evaluating fun. Array of real
        elements of size (n,), where 'n' is the number of independent
        variables.
    args : tuple, optional
        Any additional fixed parameters needed to completely specify the scalar
        function.
    grad : {callable, '2-point', '3-point', 'cs'}
        Method for computing the gradient vector.
        If it is a callable, it should be a function that returns the gradient
        vector:

            ``grad(x, *args) -> array_like, shape (n,)``

        where ``x`` is an array with shape (n,) and ``args`` is a tuple with
        the fixed parameters.
        Alternatively, the keywords  {'2-point', '3-point', 'cs'} can be used
        to select a finite difference scheme for numerical estimation of the
        gradient with a relative step size. These finite difference schemes
        obey any specified `bounds`.
    hess : {callable, '2-point', '3-point', 'cs', HessianUpdateStrategy}
        Method for computing the Hessian matrix. If it is callable, it should
        return the  Hessian matrix:

            ``hess(x, *args) -> {LinearOperator, spmatrix, array}, (n, n)``

        where x is a (n,) ndarray and `args` is a tuple with the fixed
        parameters. Alternatively, the keywords {'2-point', '3-point', 'cs'}
        select a finite difference scheme for numerical estimation. Or, objects
        implementing `HessianUpdateStrategy` interface can be used to
        approximate the Hessian.
        Whenever the gradient is estimated via finite-differences, the Hessian
        cannot be estimated with options {'2-point', '3-point', 'cs'} and needs
        to be estimated using one of the quasi-Newton strategies.
    finite_diff_rel_step : None or array_like
        Relative step size to use. The absolute step size is computed as
        ``h = finite_diff_rel_step * sign(x0) * max(1, abs(x0))``, possibly
        adjusted to fit into the bounds. For ``method='3-point'`` the sign
        of `h` is ignored. If None then finite_diff_rel_step is selected
        automatically,
    finite_diff_bounds : tuple of array_like
        Lower and upper bounds on independent variables. Defaults to no bounds,
        (-np.inf, np.inf). Each bound must match the size of `x0` or be a
        scalar, in the latter case the bound will be the same for all
        variables. Use it to limit the range of function evaluation.
    epsilon : None or array_like, optional
        Absolute step size to use, possibly adjusted to fit into the bounds.
        For ``method='3-point'`` the sign of `epsilon` is ignored. By default
        relative steps are used, only if ``epsilon is not None`` are absolute
        steps used.

    Notes
    -----
    This class implements a memoization logic. There are methods `fun`,
    `grad`, hess` and corresponding attributes `f`, `g` and `H`. The following
    things should be considered:

        1. Use only public methods `fun`, `grad` and `hess`.
        2. After one of the methods is called, the corresponding attribute
           will be set. However, a subsequent call with a different argument
           of *any* of the methods may overwrite the attribute.
    Nc	                    s  t stvrtdt dt s%tv s%tts%tdt dtv r1tv r1tdt|t_	j	j
_d_d_d_d_d_d_d _tj_i tv rnd< |d< |d	< |d
< tv rd< |d< |d	< dd<  fddfdd}	|	_  t r fddfdd}
ntv rfdd}
|
_  t rt|g R  _d_ jd7  _tjr fddtj_n!tjtr fddn fddtt j_fdd}n4tv r-fdd}|  d_n ttrM_j!jd d_d _"d _#fdd}|_$ttr]fd d!}nfd"d!}|_%d S )#Nz)`grad` must be either callable or one of .z@`hess` must be either callable, HessianUpdateStrategy or one of zWhenever the gradient is estimated via finite-differences, we require the Hessian to be estimated using one of the quasi-Newton strategies.r   Fmethodrel_stepZabs_stepboundsTas_linear_operatorc              
      s    j d7  _ t| g R  }t|s4z	t| }W n ttfy3 } ztd|d }~ww |jk r?| _	|_|S )Nr   z@The user-provided objective function must return a scalar value.)
nfevnpcopyZisscalarasarrayitem	TypeError
ValueError	_lowest_f	_lowest_x)xZfxe)argsfunself J/usr/lib/python3/dist-packages/scipy/optimize/_differentiable_functions.pyfun_wrapped   s"   

z,ScalarFunction.__init__.<locals>.fun_wrappedc                          j _d S Nr   fr   r   r   r   r   
update_fun      z+ScalarFunction.__init__.<locals>.update_func                    s*    j d7  _ tt| g R  S Nr   )ngevr   
atleast_1dr   r   )r   gradr   r   r   grad_wrapped      z-ScalarFunction.__init__.<locals>.grad_wrappedc                      r   r    )r   gr   )r+   r   r   r   update_grad   r%   z,ScalarFunction.__init__.<locals>.update_gradc                      s6       jd7  _tjfdji _d S )Nr   f0)_update_funr'   r   r   r"   r-   r   finite_diff_optionsr   r   r   r   r.      s
   r   c                    s*    j d7  _ tt| g R  S r&   )nhevsps
csr_matrixr   r   r)   r   hessr   r   r   hess_wrapped   r,   z-ScalarFunction.__init__.<locals>.hess_wrappedc                    s$    j d7  _ t| g R  S r&   )r3   r   r   r)   r6   r   r   r8         c                    s0    j d7  _ ttt| g R  S r&   )r3   r   
atleast_2dr   r   r)   r6   r   r   r8      s   "c                      r   r    )r   Hr   r8   r   r   r   update_hess   r%   z,ScalarFunction.__init__.<locals>.update_hessc                      s*      tjfdji _jS Nr/   )_update_gradr   r   r-   r;   r   )r2   r+   r   r   r   r=      s
   r7   c                      s*        j j j  j j  d S r    )r?   r;   updater   x_prevr-   g_prevr   r   r   r   r=      s   "c                    H        j _ j _t| t _d _	d _
d _   d S NF)r?   r   rA   r-   rB   r   r(   astypefloat	f_updated	g_updated	H_updated_update_hessr)   rC   r   r   update_x   s   z)ScalarFunction.__init__.<locals>.update_xc                    (   t | t _d _d _d _d S rE   )r   r(   rF   rG   r   rH   rI   rJ   r)   rC   r   r   rL      s   
)&callable
FD_METHODSr   
isinstancer   r   r(   rF   rG   r   sizenr   r'   r3   rH   rI   rJ   r   infr   _update_fun_implr0   _update_grad_implr?   r   r;   r4   issparser5   r   r:   r   
initializerA   rB   _update_hess_impl_update_x_impl)r   r   x0r   r*   r7   finite_diff_rel_stepfinite_diff_boundsepsilonr$   r.   r=   rL   r   )	r   r2   r   r   r*   r+   r7   r8   r   r   __init__V   s   




zScalarFunction.__init__c                 C      | j s|   d| _ d S d S NTrH   rT   rC   r   r   r   r0         
zScalarFunction._update_func                 C   r_   r`   )rI   rU   rC   r   r   r   r?      rb   zScalarFunction._update_gradc                 C   r_   r`   rJ   rX   rC   r   r   r   rK     rb   zScalarFunction._update_hessc                 C   &   t || js| | |   | jS r    )r   array_equalr   rY   r0   r"   r   r   r   r   r   r        
zScalarFunction.func                 C   rd   r    )r   re   r   rY   r?   r-   rf   r   r   r   r*     rg   zScalarFunction.gradc                 C   rd   r    )r   re   r   rY   rK   r;   rf   r   r   r   r7     rg   zScalarFunction.hessc                 C   s4   t || js| | |   |   | j| jfS r    )r   re   r   rY   r0   r?   r"   r-   rf   r   r   r   fun_and_grad  s
   
zScalarFunction.fun_and_gradr    )__name__
__module____qualname____doc__r^   r0   r?   rK   r   r*   r7   rh   r   r   r   r   r      s    K
 $r   c                   @   sX   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd ZdS )VectorFunctiona  Vector function and its derivatives.

    This class defines a vector function F: R^n->R^m and methods for
    computing or approximating its first and second derivatives.

    Notes
    -----
    This class implements a memoization logic. There are methods `fun`,
    `jac`, hess` and corresponding attributes `f`, `J` and `H`. The following
    things should be considered:

        1. Use only public methods `fun`, `jac` and `hess`.
        2. After one of the methods is called, the corresponding attribute
           will be set. However, a subsequent call with a different argument
           of *any* of the methods may overwrite the attribute.
    c	                    sZ  t stvrtdtt s#tv s#tts#tdttv r/tv r/tdt|t	_
j
j_d_d_d_d_d_d_i  tv rv d< | d< |d urkt|}	||	f d< | d	< tj
_tv r d< | d< d
 d< tj
_tv rtv rtdfddfdd}
|
_|
  tj_jj_t rj
_d
_ jd7  _|s|d u rtjrfddtj_d
_n)tjrfddj  _d_nfddt!j_d_fdd}nctv rt"j
fdji _d
_|sB|d u rUtjrU fdd}tj_d
_n+tjrn fdd}j  _d_n fdd}t!j_d_|_#t r؈j
j_$d
_ jd7  _tj$rfddtj$_$n tj$t%rfddnfddt!t&j$_$fdd }n:tv rfd!d" fd#d }|  d
_n ttr_$j$'jd$ d
_d _(d _)fd%d }|_*ttr"fd&d'}nfd(d'}|_+d S ))Nz+`jac` must be either callable or one of {}.zB`hess` must be either callable,HessianUpdateStrategy or one of {}.zWhenever the Jacobian is estimated via finite-differences, we require the Hessian to be estimated using one of the quasi-Newton strategies.r   Fr
   r   Zsparsityr   Tr   c                        j d7  _ t | S r&   )r   r   r(   r)   )r   r   r   r   r   e     z,VectorFunction.__init__.<locals>.fun_wrappedc                      r   r    r!   r   r#   r   r   r$   i  r%   z+VectorFunction.__init__.<locals>.update_funr   c                    rn   r&   )njevr4   r5   r)   jacr   r   r   jac_wrappedz  ro   z,VectorFunction.__init__.<locals>.jac_wrappedc                    s    j d7  _  |  S r&   )rp   toarrayr)   rq   r   r   rs     s   c                    rn   r&   )rp   r   r:   r)   rq   r   r   rs     ro   c                      r   r    )r   Jr   )rs   r   r   r   
update_jac  r%   z+VectorFunction.__init__.<locals>.update_jacr/   c                      .      ttjfdji _d S r>   )r0   r4   r5   r   r   r"   ru   r   r1   r   r   rv        
c                      s,      tjfdji  _d S r>   )r0   r   r   r"   rt   ru   r   r1   r   r   rv     s   c                      rw   r>   )r0   r   r:   r   r   r"   ru   r   r1   r   r   rv     rx   c                    s    j d7  _ t | |S r&   )r3   r4   r5   r   vr7   r   r   r   r8     s   z-VectorFunction.__init__.<locals>.hess_wrappedc                    s    j d7  _  | |S r&   )r3   ry   r{   r   r   r8     s   
c                    s$    j d7  _ tt | |S r&   )r3   r   r:   r   ry   r{   r   r   r8     r9   c                      s    j j_d S r    )r   rz   r;   r   r<   r   r   r=     s   z,VectorFunction.__init__.<locals>.update_hessc                    s    | j |S r    )Tdotry   )rs   r   r   	jac_dot_v  r%   z*VectorFunction.__init__.<locals>.jac_dot_vc                      s8      tjfjjjjfd _d S )N)r/   r   )_update_jacr   r   ru   r|   r}   rz   r;   r   )r2   r~   r   r   r   r=     s   
r7   c                     sb        jd ur- jd ur/ j j }  jj j jj j } j	| | d S d S d S r    )
r   rA   J_prevr   ru   r|   r}   rz   r;   r@   )Zdelta_xZdelta_grC   r   r   r=     s    c                    rD   rE   )r   r   rA   ru   r   r   r(   rF   rG   rH   	J_updatedrJ   rK   r)   rC   r   r   rL     s   z)VectorFunction.__init__.<locals>.update_xc                    rM   rE   )r   r(   rF   rG   r   rH   r   rJ   r)   rC   r   r   rL     s   
),rN   rO   r   formatrP   r   r   r(   rF   rG   r   rQ   rR   r   rp   r3   rH   r   rJ   r   r   Zx_diffrT   Z
zeros_liker"   rz   mru   r4   rV   r5   sparse_jacobianrt   r:   r   _update_jac_implr;   r   r   rW   rA   r   rX   rY   )r   r   rZ   rr   r7   r[   Zfinite_diff_jac_sparsityr\   r   Zsparsity_groupsr$   rv   r=   rL   r   )	r2   r   r   r7   r8   rr   r~   rs   r   r   r^   3  s   







	

zVectorFunction.__init__c                 C   s"   t || js|| _d| _d S d S rE   )r   re   rz   rJ   )r   rz   r   r   r   	_update_v  s   
zVectorFunction._update_vc                 C   s    t || js| | d S d S r    )r   re   r   rY   rf   r   r   r   	_update_x  s   zVectorFunction._update_xc                 C   r_   r`   ra   rC   r   r   r   r0     rb   zVectorFunction._update_func                 C   r_   r`   )r   r   rC   r   r   r   r     rb   zVectorFunction._update_jacc                 C   r_   r`   rc   rC   r   r   r   rK     rb   zVectorFunction._update_hessc                 C      |  | |   | jS r    )r   r0   r"   rf   r   r   r   r        
zVectorFunction.func                 C   r   r    )r   r   ru   rf   r   r   r   rr     r   zVectorFunction.jacc                 C   s"   |  | | | |   | jS r    )r   r   rK   r;   r   r   rz   r   r   r   r7     s   

zVectorFunction.hessN)ri   rj   rk   rl   r^   r   r   r0   r   rK   r   rr   r7   r   r   r   r   rm   "  s     Krm   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )LinearVectorFunctionzLinear vector function and its derivatives.

    Defines a linear function F = A x, where x is N-D vector and
    A is m-by-n matrix. The Jacobian is constant and equals to A. The Hessian
    is identically zero and it is returned as a csr matrix.
    c                 C   s   |s|d u rt |rt || _d| _nt |r#| | _d| _ntt|| _d| _| jj	\| _
| _t|t| _| j| j| _d| _tj| j
td| _t | j| jf| _d S )NTF)Zdtype)r4   rV   r5   ru   r   rt   r   r:   r   shaper   rR   r(   rF   rG   r   r}   r"   rH   Zzerosrz   r;   )r   ArZ   r   r   r   r   r^   .  s   

zLinearVectorFunction.__init__c                 C   s.   t || jst |t| _d| _d S d S rE   )r   re   r   r(   rF   rG   rH   rf   r   r   r   r   C  s   
zLinearVectorFunction._update_xc                 C   s*   |  | | js| j|| _d| _| jS r`   )r   rH   ru   r}   r"   rf   r   r   r   r   H  s
   
zLinearVectorFunction.func                 C   s   |  | | jS r    )r   ru   rf   r   r   r   rr   O  s   
zLinearVectorFunction.jacc                 C   s   |  | || _| jS r    )r   rz   r;   r   r   r   r   r7   S  s   
zLinearVectorFunction.hessN)	ri   rj   rk   rl   r^   r   r   rr   r7   r   r   r   r   r   '  s    r   c                       s    e Zd ZdZ fddZ  ZS )IdentityVectorFunctionzIdentity vector function and its derivatives.

    The Jacobian is the identity matrix, returned as a dense array when
    `sparse_jacobian=False` and as a csr matrix otherwise. The Hessian is
    identically zero and it is returned as a csr matrix.
    c                    sJ   t |}|s
|d u rtj|dd}d}nt|}d}t ||| d S )NZcsr)r   TF)lenr4   Zeyer   superr^   )r   rZ   r   rR   r   	__class__r   r   r^   `  s   
zIdentityVectorFunction.__init__)ri   rj   rk   rl   r^   __classcell__r   r   r   r   r   Y  s    r   )Znumpyr   Zscipy.sparseZsparser4   Z_numdiffr   r   Z_hessian_update_strategyr   Zscipy.sparse.linalgr   rO   r   rm   r   r   r   r   r   r   <module>   s        2