o
    h=                     @   sz   d Z ddlZddlmZ ddlmZ ddlmZ g dZ	G dd dZ
G d	d
 d
e
ZG dd deZG dd deZdS )z@Hessian update strategies for quasi-Newton optimization methods.    N)norm)get_blas_funcs)warn)HessianUpdateStrategyBFGSSR1c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )r   a]  Interface for implementing Hessian update strategies.

    Many optimization methods make use of Hessian (or inverse Hessian)
    approximations, such as the quasi-Newton methods BFGS, SR1, L-BFGS.
    Some of these  approximations, however, do not actually need to store
    the entire matrix or can compute the internal matrix product with a
    given vector in a very efficiently manner. This class serves as an
    abstract interface between the optimization algorithm and the
    quasi-Newton update strategies, giving freedom of implementation
    to store and update the internal matrix as efficiently as possible.
    Different choices of initialization and update procedure will result
    in different quasi-Newton strategies.

    Four methods should be implemented in derived classes: ``initialize``,
    ``update``, ``dot`` and ``get_matrix``.

    Notes
    -----
    Any instance of a class that implements this interface,
    can be accepted by the method ``minimize`` and used by
    the compatible solvers to approximate the Hessian (or
    inverse Hessian) used by the optimization algorithms.
    c                 C      t d)  Initialize internal matrix.

        Allocate internal memory for storing and updating
        the Hessian or its inverse.

        Parameters
        ----------
        n : int
            Problem dimension.
        approx_type : {'hess', 'inv_hess'}
            Selects either the Hessian or the inverse Hessian.
            When set to 'hess' the Hessian will be stored and updated.
            When set to 'inv_hess' its inverse will be used instead.
        z=The method ``initialize(n, approx_type)`` is not implemented.NotImplementedErrorselfnapprox_type r   b/var/www/html/scripts/venv/lib/python3.10/site-packages/scipy/optimize/_hessian_update_strategy.py
initialize$      z HessianUpdateStrategy.initializec                 C   r   )  Update internal matrix.

        Update Hessian matrix or its inverse (depending on how 'approx_type'
        is defined) using information about the last evaluated points.

        Parameters
        ----------
        delta_x : ndarray
            The difference between two points the gradient
            function have been evaluated at: ``delta_x = x2 - x1``.
        delta_grad : ndarray
            The difference between the gradients:
            ``delta_grad = grad(x2) - grad(x1)``.
        z>The method ``update(delta_x, delta_grad)`` is not implemented.r
   r   delta_x
delta_gradr   r   r   update6   r   zHessianUpdateStrategy.updatec                 C   r   )P  Compute the product of the internal matrix with the given vector.

        Parameters
        ----------
        p : array_like
            1-D array representing a vector.

        Returns
        -------
        Hp : array
            1-D represents the result of multiplying the approximation matrix
            by vector p.
        z)The method ``dot(p)`` is not implemented.r
   r   pr   r   r   dotH   s   zHessianUpdateStrategy.dotc                 C   r   )zReturn current internal matrix.

        Returns
        -------
        H : ndarray, shape (n, n)
            Dense matrix containing either the Hessian
            or its inverse (depending on how 'approx_type'
            is defined).
        z0The method ``get_matrix(p)`` is not implemented.r
   )r   r   r   r   
get_matrixY   s   
z HessianUpdateStrategy.get_matrixN)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   r      s    r   c                   @   sn   e Zd ZdZedddZedddZedd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S )FullHessianUpdateStrategyzKHessian update strategy with full dimensional internal representation.
    syrddtypesyr2symvautoc                 C   s"   || _ d | _d | _d | _d | _d S N)
init_scalefirst_iterationr   BH)r   r+   r   r   r   __init__o   s
   
z"FullHessianUpdateStrategy.__init__c                 C   sT   d| _ || _|| _|dvrtd| jdkr tj|td| _dS tj|td| _dS )r	   T)hessinv_hessz+`approx_type` must be 'hess' or 'inv_hess'.r0   r%   N)	r,   r   r   
ValueErrornpeyefloatr-   r.   r   r   r   r   r   x   s   
z$FullHessianUpdateStrategy.initializec                 C   s`   t ||}t ||}t t ||}|dks!|dks!|dkr#dS | jdkr,|| S || S )N        r      r0   )r3   r   absr   )r   r   r   s_norm2y_norm2ysr   r   r   _auto_scale   s   
z%FullHessianUpdateStrategy._auto_scalec                 C   r   )Nz9The method ``_update_implementation`` is not implemented.r
   r   r   r   r   _update_implementation   s   z0FullHessianUpdateStrategy._update_implementationc                 C   s   t |dkr	dS t |dkrtdt dS | jrB| jdkr&| ||}nt| j}| jdkr8|  j	|9  _	n|  j
|9  _
d| _| || dS )r   r6   Nzdelta_grad == 0.0. Check if the approximated function is linear. If the function is linear better results can be obtained by defining the Hessian as zero instead of using quasi-Newton approximations.r)   r0   F)r3   allr   UserWarningr,   r+   r<   r5   r   r-   r.   r=   )r   r   r   scaler   r   r   r      s    


z FullHessianUpdateStrategy.updatec                 C   s*   | j dkr| d| j|S | d| j|S )r   r0   r7   )r   _symvr-   r.   r   r   r   r   r      s   
zFullHessianUpdateStrategy.dotc                 C   sD   | j dkrt| j}nt| j}tj|dd}|j| ||< |S )zReturn the current internal matrix.

        Returns
        -------
        M : ndarray, shape (n, n)
            Dense matrix containing either the Hessian or its inverse
            (depending on how `approx_type` was defined).
        r0   )k)r   r3   copyr-   r.   tril_indices_fromT)r   Mlir   r   r   r      s   
	z$FullHessianUpdateStrategy.get_matrixN)r)   )r   r   r    r!   r   _syr_syr2rA   r/   r   r<   r=   r   r   r   r   r   r   r   r"   g   s    
	&r"   c                       s>   e Zd ZdZ		d fdd	Zdd Zd	d
 Zdd Z  ZS )r   a  Broyden-Fletcher-Goldfarb-Shanno (BFGS) Hessian update strategy.

    Parameters
    ----------
    exception_strategy : {'skip_update', 'damp_update'}, optional
        Define how to proceed when the curvature condition is violated.
        Set it to 'skip_update' to just skip the update. Or, alternatively,
        set it to 'damp_update' to interpolate between the actual BFGS
        result and the unmodified matrix. Both exceptions strategies
        are explained  in [1]_, p.536-537.
    min_curvature : float
        This number, scaled by a normalization factor, defines the
        minimum curvature ``dot(delta_grad, delta_x)`` allowed to go
        unaffected by the exception strategy. By default is equal to
        1e-8 when ``exception_strategy = 'skip_update'`` and equal
        to 0.2 when ``exception_strategy = 'damp_update'``.
    init_scale : {float, 'auto'}
        Matrix scale at first iteration. At the first
        iteration the Hessian matrix or its inverse will be initialized
        with ``init_scale*np.eye(n)``, where ``n`` is the problem dimension.
        Set it to 'auto' in order to use an automatic heuristic for choosing
        the initial scale. The heuristic is described in [1]_, p.143.
        By default uses 'auto'.

    Notes
    -----
    The update is based on the description in [1]_, p.140.

    References
    ----------
    .. [1] Nocedal, Jorge, and Stephen J. Wright. "Numerical optimization"
           Second Edition (2006).
    skip_updateNr)   c                    s^   |dkr|d ur|| _ nd| _ n|dkr |d ur|| _ nd| _ ntdt | || _d S )NrK   :0yE>damp_updateg?z<`exception_strategy` must be 'skip_update' or 'damp_update'.)min_curvaturer2   superr/   exception_strategy)r   rP   rN   r+   	__class__r   r   r/     s   
zBFGS.__init__c                 C   s>   | j d| ||| jd| _| j|| |d  || jd| _dS )a  Update the inverse Hessian matrix.

        BFGS update using the formula:

            ``H <- H + ((H*y).T*y + s.T*y)/(s.T*y)^2 * (s*s.T)
                     - 1/(s.T*y) * ((H*y)*s.T + s*(H*y).T)``

        where ``s = delta_x`` and ``y = delta_grad``. This formula is
        equivalent to (6.17) in [1]_ written in a more efficient way
        for implementation.

        References
        ----------
        .. [1] Nocedal, Jorge, and Stephen J. Wright. "Numerical optimization"
               Second Edition (2006).
              a   N)rJ   r.   rI   )r   r;   HyyHysr   r   r   _update_inverse_hessian%  s   $zBFGS._update_inverse_hessianc                 C   s4   | j d| || jd| _| j d| || jd| _dS )a  Update the Hessian matrix.

        BFGS update using the formula:

            ``B <- B - (B*s)*(B*s).T/s.T*(B*s) + y*y^T/s.T*y``

        where ``s`` is short for ``delta_x`` and ``y`` is short
        for ``delta_grad``. Formula (6.19) in [1]_.

        References
        ----------
        .. [1] Nocedal, Jorge, and Stephen J. Wright. "Numerical optimization"
               Second Edition (2006).
        g      ?rT   rS   N)rI   r-   )r   r;   BssBsyr   r   r   _update_hessian9  s   zBFGS._update_hessianc           
      C   s*  | j dkr
|}|}n|}|}t||}| |}||}|dkrN| ||}| j dkr9|tj| jtd | _n|tj| jtd | _| |}||}|| j	| kr|| j
dkr\d S | j
dkr|d| j	 d||   }	|	| d|	 |  }t||}| j dkr| |||| d S | |||| d S )Nr0   r6   r%   rK   rM   r7   )r   r3   r   r<   r4   r   r5   r-   r.   rN   rP   r^   rZ   )
r   r   r   wzwzMwwMwr@   update_factorr   r   r   r=   K  s2   








zBFGS._update_implementation)rK   Nr)   )	r   r   r    r!   r/   rZ   r^   r=   __classcell__r   r   rQ   r   r      s    "r   c                       s*   e Zd ZdZd fdd	Zdd Z  ZS )	r   a  Symmetric-rank-1 Hessian update strategy.

    Parameters
    ----------
    min_denominator : float
        This number, scaled by a normalization factor,
        defines the minimum denominator magnitude allowed
        in the update. When the condition is violated we skip
        the update. By default uses ``1e-8``.
    init_scale : {float, 'auto'}, optional
        Matrix scale at first iteration. At the first
        iteration the Hessian matrix or its inverse will be initialized
        with ``init_scale*np.eye(n)``, where ``n`` is the problem dimension.
        Set it to 'auto' in order to use an automatic heuristic for choosing
        the initial scale. The heuristic is described in [1]_, p.143.
        By default uses 'auto'.

    Notes
    -----
    The update is based on the description in [1]_, p.144-146.

    References
    ----------
    .. [1] Nocedal, Jorge, and Stephen J. Wright. "Numerical optimization"
           Second Edition (2006).
    rL   r)   c                    s   || _ t | d S r*   )min_denominatorrO   r/   )r   rf   r+   rQ   r   r   r/     s   zSR1.__init__c                 C   s   | j dkr
|}|}n|}|}| |}|| }t||}t|| jt| t| kr/d S | j dkrB| jd| || jd| _d S | jd| || jd| _d S )Nr0   r7   rT   )	r   r   r3   r8   rf   r   rI   r-   r.   )r   r   r   r_   r`   rb   
z_minus_Mwdenominatorr   r   r   r=     s   

 
zSR1._update_implementation)rL   r)   )r   r   r    r!   r/   r=   re   r   r   rQ   r   r   y  s    r   )r!   numpyr3   numpy.linalgr   scipy.linalgr   warningsr   __all__r   r"   r   r   r   r   r   r   <module>   s    \ 	 