
    ^MhG                         d Z ddlZddlmZ ddlmZ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dS )z@Hessian update strategies for quasi-Newton optimization methods.    N)norm)get_blas_funcsissymmetric)warn)HessianUpdateStrategyBFGSSR1c                   0    e Zd ZdZd Zd Zd Zd Z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``. The matrix multiplication
    operator ``@`` is also defined to call the ``dot`` method.

    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      g/var/www/html/test/jupyter/venv/lib/python3.11/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.update7   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.dotI   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_matrixZ   s     " #9 : : 	:r   c                 ,    |                      |          S N)r!   r   s     r   
__matmul__z HessianUpdateStrategy.__matmul__g   s    xx{{r   N)	__name__
__module____qualname____doc__r   r   r!   r#   r&    r   r   r   r      si         2: : :$: : :$: : :": : :    r   r   c                       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dS )FullHessianUpdateStrategyzKHessian update strategy with full dimensional internal representation.
    syrddtypesyr2symvautoc                 L    || _         d | _        d | _        d | _        d | _        d S r%   )
init_scalefirst_iterationr   BH)r   r6   s     r   __init__z"FullHessianUpdateStrategy.__init__s   s-    $  $r   c                     d| _         || _        || _        |dvrt          d          | j        dk    r"t	          j        |t                    | _        dS t	          j        |t                    | _        dS )r   T)hessinv_hessz+`approx_type` must be 'hess' or 'inv_hess'.r<   r0   N)	r7   r   r   
ValueErrornpeyefloatr8   r9   r   s      r   r   z$FullHessianUpdateStrategy.initialize|   sx      $&222JKKKv%%VAU+++DFFFVAU+++DFFFr   c                     t          j        ||          }t          j        ||          }t          j        t          j        ||                    }|dk    s|dk    s|dk    rdS | j        dk    r||z  S ||z  S )N        r      r<   )r?   r!   absr   )r   r   r   s_norm2y_norm2yss         r   _auto_scalez%FullHessianUpdateStrategy._auto_scale   s     &'**&Z00VBF:w//00991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dS t          j        |dk              rt          dt          d           dS | j        rt          | j        t                    r"| j        dk    r|                     ||          }n| j        }d}t          j	        |          dk    rt          |          }nt          j        |          rt          d	          d
}| j        dk    r&t          j        | j                  }| j        j        }n%t          j        | j                  }| j        j        }t          j        ||d
          }|t          j        |          x}k    rt'          d| d| d          t)          |          st'          d          | j        dk    r|r|| _        n+| xj        |z  c_        n|r|| _        n| xj        |z  c_        d| _        |                     ||           dS )r   rC   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.   )
stacklevelr4   FrD   z3init_scale contains complex elements, must be real.Tr<   )r1   copyzMIf init_scale is an array, it must have the dimensions of the hess/inv_hess: z. Got .z}If init_scale is an array, it must be symmetric (passing scipy.linalg.issymmetric) to be an approximation of a hess/inv_hess.)r?   allr   UserWarningr7   
isinstancer6   strrI   sizerA   iscomplexobj	TypeErrorr   shaper8   r1   r9   arrayr>   r   rK   )r   r   r   scalereplacerX   r1   
init_shapes           r   r   z FullHessianUpdateStrategy.update   sO    6'S.!! 	F6*#$$ 	 #
 , , , , F 4	)$/3// (DOv4M4M((*==
 Gwu~~""e'' T !0 1 1 1 #v--HTV,,E FLEEHTV,,E FLEe$??? 28E??:Z;;$ &;IN&; &;-7&; &; &; < < < #5)) T$ &S T T T 6)) $"DFFFFeOFFF $"DFFFFeOFF#(D ##GZ88888r   c                     | j         dk    r|                     d| j        |          S |                     d| j        |          S )r   r<   rD   )r   _symvr8   r9   r   s     r   r!   zFullHessianUpdateStrategy.dot   sB     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).
        r<   )k)r   r?   rO   r8   r9   tril_indices_fromT)r   Mlis      r   r#   z$FullHessianUpdateStrategy.get_matrix  s[     v%%AAA!!r***B"r   N)r4   )r'   r(   r)   r*   r   _syr_syr2r^   r:   r   rI   rK   r   r!   r#   r+   r   r   r-   r-   k   s         >%s+++DN6---EN6---E   , , ,4     : : :N9 N9 N9`, , ,&    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, np.array, 'auto'}
        This parameter can be used to initialize the Hessian or its
        inverse. When a float is given, the relevant array is initialized
        to ``np.eye(n) * init_scale``, where ``n`` is the problem dimension.
        Alternatively, if a precisely ``(n, n)`` shaped, symmetric array is given,
        this array will be used. Otherwise an error is generated.
        Set it to 'auto' in order to use an automatic heuristic for choosing
        the initial scale. The heuristic is described in [1]_, p.143.
        The default is '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_updateNr4   c                     |dk    r||| _         n/d| _         n'|dk    r||| _         nd| _         nt          d          t                                          |           || _        d S )Nri   :0yE>damp_updateg?z<`exception_strategy` must be 'skip_update' or 'damp_update'.)min_curvaturer>   superr:   exception_strategy)r   ro   rm   r6   	__class__s       r   r:   zBFGS.__init__B  s    ..(%2""%)""=00(%2""%("" 1 2 2 2 	$$$"4r   c                     |                      d|z  ||| j                  | _        |                     ||z   |dz  z  || j                  | _        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).
              arM   N)rg   r9   rf   )r   rH   HyyHyss        r   _update_inverse_hessianzBFGS._update_inverse_hessianU  sQ    " D2Iq"77BHa/df==r   c                     |                      d|z  || j                  | _        |                      d|z  || j                  | _        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      ?rs   rr   N)rf   r8   )r   rH   BssBsys        r   _update_hessianzBFGS._update_hessiani  sF     38Q$&114#:rTV44r   c                    | j         dk    r|}|}n|}|}t          j        ||          }| |z  }|                    |          }|dk    r|                     ||          }| j         dk    r)|t          j        | j        t                    z  | _        n(|t          j        | j        t                    z  | _        | |z  }|                    |          }|| j	        |z  k    rN| j
        dk    rd S | j
        dk    r6d| j	        z
  d||z  z
  z  }	|	|z  d|	z
  |z  z   }t          j        ||          }| j         dk    r|                     ||||           d S |                     ||||           d S )Nr<   rC   r0   ri   rl   rD   )r   r?   r!   rI   r@   r   rA   r8   r9   rm   ro   r}   rx   )
r   r   r   wzwzMwwMwrZ   update_factors
             r   rK   zBFGS._update_implementation{  s   v%%AAAAAVAq\\AXffQii #::$$Wj99E6))e!<!<!<<e!<!<!<<B&&))C#c))) &-77 (M99!"4#5!5!bf* E!!Oq&::VAq\\v%%  Ra00000((Ra88888r   )ri   Nr4   )	r'   r(   r)   r*   r:   rx   r}   rK   __classcell__rp   s   @r   r   r     s        " "H HL"5 5 5 5 5 5&> > >(5 5 5$+9 +9 +9 +9 +9 +9 +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, np.array, 'auto'}, optional
        This parameter can be used to initialize the Hessian or its
        inverse. When a float is given, the relevant array is initialized
        to ``np.eye(n) * init_scale``, where ``n`` is the problem dimension.
        Alternatively, if a precisely ``(n, n)`` shaped, symmetric array is given,
        this array will be used. Otherwise an error is generated.
        Set it to 'auto' in order to use an automatic heuristic for choosing
        the initial scale. The heuristic is described in [1]_, p.143.
        The default is '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).
    rk   r4   c                 X    || _         t                                          |           d S r%   )min_denominatorrn   r:   )r   r   r6   rp   s      r   r:   zSR1.__init__  s)    .$$$$$r   c                    | j         dk    r|}|}n|}|}| |z  }||z
  }t          j        ||          }t          j        |          | j        t          |          z  t          |          z  k    rd S | j         dk    r'|                     d|z  || j                  | _        d S |                     d|z  || j                  | _        d S )Nr<   rD   rs   )	r   r?   r!   rE   r   r   rf   r8   r9   )r   r   r   r   r   r   
z_minus_Mwdenominators           r   rK   zSR1._update_implementation  s    v%%AAAAAAXV
fQ
++ 6+$"6tAww">tJ?O?O"OOOFv%%YYq}jDFYCCDFFFYYq}jDFYCCDFFFr   )rk   r4   )r'   r(   r)   r*   r:   rK   r   r   s   @r   r	   r	     s]         :% % % % % %D D D D D D Dr   r	   )r*   numpyr?   numpy.linalgr   scipy.linalgr   r   warningsr   __all__r   r-   r   r	   r+   r   r   <module>r      s8   F F           4 4 4 4 4 4 4 4       3
2
2] ] ] ] ] ] ] ]@o o o o o 5 o o odI9 I9 I9 I9 I9$ I9 I9 I9X6D 6D 6D 6D 6D
# 6D 6D 6D 6D 6Dr   