
    S_f=                         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      Z
 G d	 d
e
      Z G d de      Z G d de      Zy)z@Hessian update strategies for quasi-Newton optimization methods.    N)norm)get_blas_funcs)warn)HessianUpdateStrategyBFGSSR1c                   (    e Zd ZdZd Zd Zd Zd Zy)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                     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_types      Glib/python3.12/site-packages/scipy/optimize/_hessian_update_strategy.py
initializez HessianUpdateStrategy.initialize$        " #9 : 	:    c                     t        d      )  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_grads      r   updatezHessianUpdateStrategy.update6   r   r   c                     t        d      )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   ps     r   dotzHessianUpdateStrategy.dotH   s     " #9 : 	:r   c                     t        d      )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   s    r   
get_matrixz HessianUpdateStrategy.get_matrixY   s     " #9 : 	:r   N)__name__
__module____qualname____doc__r   r   r    r"    r   r   r   r      s    0:$:$:":r   r   c                   x    e Zd ZdZ edd      Z edd      Z edd      ZddZd Z	d	 Z
d
 Zd Zd Zd Zy)FullHessianUpdateStrategyzKHessian update strategy with full dimensional internal representation.
    syrddtypesyr2symvc                 J    || _         d | _        d | _        d | _        d | _        y N)
init_scalefirst_iterationr   BH)r   r2   s     r   __init__z"FullHessianUpdateStrategy.__init__o   s)    $  $r   c                     d| _         || _        || _        |dvrt        d      | j                  dk(  r!t	        j
                  |t              | _        yt	        j
                  |t              | _        y)r   T)hessinv_hessz+`approx_type` must be 'hess' or 'inv_hess'.r8   r,   N)	r3   r   r   
ValueErrornpeyefloatr4   r5   r   s      r   r   z$FullHessianUpdateStrategy.initializex   sb      $&22JKKv%VVAU+DFVVAU+DFr   c                     t        j                  ||      }t        j                  ||      }t        j                  t        j                  ||            }|dk(  s
|dk(  s|dk(  ry| j                  dk(  r||z  S ||z  S )N        r      r8   )r;   r    absr   )r   r   r   s_norm2y_norm2yss         r   _auto_scalez%FullHessianUpdateStrategy._auto_scale   su     &&'*&&Z0VVBFF:w/0911v%R<<r   c                     t        d      )Nz9The method ``_update_implementation`` is not implemented.r   r   s      r   _update_implementationz0FullHessianUpdateStrategy._update_implementation   s    ! #9 : 	:r   c                    t        j                  |dk(        ryt        j                  |dk(        rt        dt        d       y| j                  rx| j
                  dk(  r| j                  ||      }nt        | j
                        }| j                  dk(  r| xj                  |z  c_	        n| xj                  |z  c_
        d| _        | j                  ||       y)	r   r?   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.   )
stacklevelautor8   F)r;   allr   UserWarningr3   r2   rE   r=   r   r4   r5   rG   )r   r   r   scales       r   r   z FullHessianUpdateStrategy.update   s     66'S.!66*#$ #
 , &(((*=doo.6)%%#(D ##GZ8r   c                     | j                   dk(  r| j                  d| j                  |      S | j                  d| j                  |      S )r   r8   r@   )r   _symvr4   r5   r   s     r   r    zFullHessianUpdateStrategy.dot   s@     v%::a++::a++r   c                     | j                   dk(  r t        j                  | j                        }nt        j                  | j                        }t        j
                  |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).
        r8   )k)r   r;   copyr4   r5   tril_indices_fromT)r   Mlis      r   r"   z$FullHessianUpdateStrategy.get_matrix   s\     v%AA!!!r*B"r   N)rK   )r#   r$   r%   r&   r   _syr_syr2rP   r6   r   rE   rG   r   r    r"   r'   r   r   r)   r)   g   sO    %s+D6-E6-E,4 :%9N,&r   r)   c                   :     e Zd ZdZ	 	 d fd	Zd Zd Zd Z x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).
    c                     |dk(  r||| _         n*d| _         n"|dk(  r||| _         nd| _         nt        d      t        |   |       || _        y )Nskip_update:0yE>damp_updateg?z<`exception_strategy` must be 'skip_update' or 'damp_update'.)min_curvaturer:   superr6   exception_strategy)r   rb   r`   r2   	__class__s       r   r6   zBFGS.__init__  sh    .(%2"%)"=0(%2"%(" 1 2 2 	$"4r   c                     | j                  d|z  ||| j                        | _        | j                  ||z   |dz  z  || j                        | _        y)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).
              arI   N)rZ   r5   rY   )r   rD   HyyHyss        r   _update_inverse_hessianzBFGS._update_inverse_hessian&  sJ    " D2Iq"7BsFBE>17r   c                     | j                  d|z  || j                        | _        | j                  d|z  || j                        | _        y)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      ?rf   re   N)rY   r4   )r   rD   BssBsys        r   _update_hessianzBFGS._update_hessian:  s@     38Q$&&14#:rTVV4r   c                 4   | j                   dk(  r|}|}n|}|}t        j                  ||      }| j                  |      }|j                  |      }|dk  r| j                  ||      }| j                   dk(  r.|t        j                  | j
                  t              z  | _        n-|t        j                  | j
                  t              z  | _        | j                  |      }|j                  |      }|| j                  |z  k  r[| j                  dk(  ry | j                  dk(  r<d| j                  z
  d||z  z
  z  }	|	|z  d|	z
  |z  z   }t        j                  ||      }| j                   dk(  r| j                  ||||       y | j                  ||||       y )Nr8   r?   r,   r]   r_   r@   )r   r;   r    rE   r<   r   r=   r4   r5   r`   rb   rp   rk   )
r   r   r   wzwzMwwMwrN   update_factors
             r   rG   zBFGS._update_implementationL  su   v%AAAAVVAq\XXa[ffQi #:$$Wj9E6)e!<<e!<<!B&&)C##c)) &&-7 ((M9!"4#5#5!5!bf* E!!Oq&::VVAq\v%  Ra0((Ra8r   )r]   NrK   )	r#   r$   r%   r&   r6   rk   rp   rG   __classcell__rc   s   @r   r   r      s'     D HL"5&8(5$+9r   r   c                   *     e Zd ZdZd fd	Zd Z x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).
    c                 2    || _         t        | 	  |       y r1   )min_denominatorra   r6   )r   r|   r2   rc   s      r   r6   zSR1.__init__  s    .$r   c                    | j                   dk(  r|}|}n|}|}| j                  |      }||z
  }t        j                  ||      }t        j                  |      | j                  t        |      z  t        |      z  k  ry | j                   dk(  r'| j                  d|z  || j                        | _        y | j                  d|z  || j                        | _        y )Nr8   r@   rf   )	r   r    r;   rA   r|   r   rY   r4   r5   )r   r   r   rr   rs   ru   
z_minus_Mwdenominators           r   rG   zSR1._update_implementation  s    v%AAAAXXa[V
ffQ
+ 66+$"6"6tAw">tJ?O"OOv%YYq}jDFFYCDFYYq}jDFFYCDFr   )r^   rK   )r#   r$   r%   r&   r6   rG   rx   ry   s   @r   r   r   z  s    6%Dr   r   )r&   numpyr;   numpy.linalgr   scipy.linalgr   warningsr   __all__r   r)   r   r   r'   r   r   <module>r      sW    F   '  3Y: Y:xF 5 FRG9$ G9T4D
# 4Dr   