
    (phG                         S r SSKrSSKJr  SSKJrJr  SSKJ	r	  / SQr
 " S S5      r " S	 S
\5      r " S S\5      r " S S\5      rg)z@Hessian update strategies for quasi-Newton optimization methods.    N)norm)get_blas_funcsissymmetric)warn)HessianUpdateStrategyBFGSSR1c                   6    \ rS rSrSrS rS rS rS rS r	Sr
g	)
r      af  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                     [        S5      e)w  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      Z/var/www/html/venv/lib/python3.13/site-packages/scipy/optimize/_hessian_update_strategy.py
initialize HessianUpdateStrategy.initialize%        " #9 : 	:    c                     [        S5      e)  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   updateHessianUpdateStrategy.update7   r   r   c                     [        S5      e)   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   dotHessianUpdateStrategy.dotI   s     " #9 : 	:r   c                     [        S5      e)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_matrix HessianUpdateStrategy.get_matrixZ   s     " #9 : 	:r   c                 $    U R                  U5      $ N)r$   r"   s     r   
__matmul__ HessianUpdateStrategy.__matmul__g   s    xx{r    N)__name__
__module____qualname____firstlineno____doc__r   r   r$   r'   r+   __static_attributes__r-   r   r   r   r      s     2:$:$:":r   r   c                   p    \ rS rSrSr\" SSS9r\" SSS9r\" SSS9rSS jr	S	 r
S
 rS rS rS rS rSrg)FullHessianUpdateStrategyk   zKHessian update strategy with full dimensional internal representation.
    syrddtypesyr2symvc                 H    Xl         S U l        S U l        S U l        S U l        g r*   )
init_scalefirst_iterationr   BH)r   r>   s     r   __init__"FullHessianUpdateStrategy.__init__s   s'    $  $r   c                     SU l         Xl        X l        US;  a  [        S5      eU R                  S:X  a  [        R
                  " U[        S9U l        g[        R
                  " U[        S9U l        g)r   T)hessinv_hessz+`approx_type` must be 'hess' or 'inv_hess'.rE   r9   N)	r?   r   r   
ValueErrornpeyefloatr@   rA   r   s      r   r   $FullHessianUpdateStrategy.initialize|   s^      $&22JKKv%VVAU+DFVVAU+DFr   c                    [         R                  " X5      n[         R                  " X"5      n[         R                  " [         R                  " X!5      5      nUS:X  d  US:X  d  US:X  a  gU R                  S:X  a  XE-  $ XT-  $ )N        r      rE   )rH   r$   absr   )r   r   r   s_norm2y_norm2yss         r   _auto_scale%FullHessianUpdateStrategy._auto_scale   sk     &&*&&0VVBFF:/0911v%<<r   c                     [        S5      e)Nz9The method ``_update_implementation`` is not implemented.r   r   s      r   _update_implementation0FullHessianUpdateStrategy._update_implementation   s    ! #9 : 	:r   c                    [         R                  " US:H  5      (       a  g[         R                  " US:H  5      (       a  [        S[        SS9  gU R                  (       Ga  [        U R                  [        5      (       a"  U R                  S:X  a  U R                  X5      nOU R                  nSn[         R                  " U5      S:X  a  [        U5      nGO[         R                  " U5      (       a  [        S	5      eS
nU R                  S:X  a7  [         R                  " U R                  5      nU R                  R                   nO6[         R                  " U R"                  5      nU R"                  R                   n[         R$                  " X6S
S9nU[         R                  " U5      =n:w  a  ['        SU SU S35      e[)        U5      (       d  ['        S5      eU R                  S:X  a$  U(       a  X0l        O9U =R                  U-  sl        O#U(       a  X0l        OU =R"                  U-  sl        SU l        U R+                  X5        g)r   rM   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autoFrN   z3init_scale contains complex elements, must be real.TrE   )r:   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.)rH   allr   UserWarningr?   
isinstancer>   strrS   sizerJ   iscomplexobj	TypeErrorr   shaper@   r:   rA   arrayrG   r   rV   )r   r   r   scalereplacere   r:   
init_shapes           r   r    FullHessianUpdateStrategy.update   s    66'S.!!66*#$$ #
 , $//3//DOOv4M((=
 Gwwu~"e'' !0 1 1 ##v-HHTVV,E FFLLEHHTVV,E FFLLE$? 288E?:Z;$ &IIN P--7L&; < < #5))$ &S T T 6)"FFFeOF"FFFeOF#(D ##G8r   c                     U R                   S:X  a  U R                  SU R                  U5      $ U R                  SU R                  U5      $ )r!   rE   rN   )r   _symvr@   rA   r"   s     r   r$   FullHessianUpdateStrategy.dot   s@     v%::a++::a++r   c                     U R                   S:X  a!  [        R                  " U R                  5      nO [        R                  " U R                  5      n[        R
                  " USS9nUR                  U   X'   U$ )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).
rE   )k)r   rH   r\   r@   rA   tril_indices_fromT)r   Mlis      r   r'   $FullHessianUpdateStrategy.get_matrix  sZ     v%AA!!!r*Br   )r@   rA   r   r?   r>   r   N)r[   )r.   r/   r0   r1   r2   r   _syr_syr2rl   rB   r   rS   rV   r   r$   r'   r3   r-   r   r   r5   r5   k   sP    %s+D6-E6-E,4 :N9`,&r   r5   c                   F   ^  \ rS rSrSr  SU 4S jjrS rS rS rSr	U =r
$ )	r   i  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).
c                    > US:X  a  Ub  X l         O+SU l         O#US:X  a  Ub  X l         OSU l         O[        S5      e[        TU ]  U5        Xl        g )Nskip_update:0yE>damp_updateg?z<`exception_strategy` must be 'skip_update' or 'damp_update'.)min_curvaturerG   superrB   exception_strategy)r   r   r}   r>   	__class__s       r   rB   BFGS.__init__B  sb    .(%2"%)"=0(%2"%(" 1 2 2 	$"4r   c                     U R                  SU-  XBU R                  S9U l        U R                  X-   US-  -  X@R                  S9U l        g)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).
      arY   N)rw   rA   rv   )r   rR   HyyHyss        r   _update_inverse_hessianBFGS._update_inverse_hessianU  sE    " D2Iq7BHa/ff=r   c                     U R                  SU-  X@R                  S9U l        U R                  SU-  X R                  S9U l        g)aT  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      ?r   r   N)rv   r@   )r   rR   BssBsys        r   _update_hessianBFGS._update_hessiani  s<     38Q&&14#:rVV4r   c                    U R                   S:X  a  UnUnOUnUn[        R                  " X45      nX-  nUR                  U5      nUS::  a  U R                  X5      nU R                   S:X  a,  U[        R                  " U R
                  [        S9-  U l        O+U[        R                  " U R
                  [        S9-  U l        X-  nUR                  U5      nXPR                  U-  ::  a[  U R                  S:X  a  g U R                  S:X  a:  SU R                  -
  SXW-  -
  -  n	X-  SU	-
  U-  -   n[        R                  " X45      nU R                   S:X  a  U R                  XVXt5        g U R                  XVXt5        g )NrE   rM   r9   rz   r|   rN   )r   rH   r$   rS   rI   r   rJ   r@   rA   r}   r   r   r   )
r   r   r   wzwzMwwMwrg   update_factors
             r   rV   BFGS._update_implementation{  sU   v%AAAAVVA\XffQi #:$$W9E6)e!<<e!<<B&&)C##c)) &&-7 ((M9!"4#5#5!5!bf* E!Oq&::VVA\v%  0((8r   )r@   rA   r   r}   )rz   Nr[   )r.   r/   r0   r1   r2   rB   r   r   rV   r3   __classcell__r   s   @r   r   r     s,    "H HL"5&>(5$+9 +9r   r   c                   6   ^  \ rS rSrSrSU 4S jjrS rSrU =r$ )r	   i  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).
c                 0   > Xl         [        TU ]	  U5        g r*   )min_denominatorr~   rB   )r   r   r>   r   s      r   rB   SR1.__init__  s    .$r   c                    U R                   S:X  a  UnUnOUnUnX-  nXE-
  n[        R                  " X65      n[        R                  " U5      U R                  [        U5      -  [        U5      -  ::  a  g U R                   S:X  a#  U R                  SU-  X`R                  S9U l        g U R                  SU-  X`R                  S9U l        g )NrE   rN   r   )	r   rH   r$   rO   r   r   rv   r@   rA   )r   r   r   r   r   r   
z_minus_Mwdenominators           r   rV   SR1._update_implementation  s    v%AAAAXV
ffQ+ 66+$"6"6tAw">tJ?O"OOv%YYq}jFFYCDFYYq}jFFYCDFr   )r@   rA   r   )r{   r[   )	r.   r/   r0   r1   r2   rB   rV   r3   r   r   s   @r   r	   r	     s    :%D Dr   r	   )r2   numpyrH   numpy.linalgr   scipy.linalgr   r   warningsr   __all__r   r5   r   r	   r-   r   r   <module>r      sW    F   4  3] ]@o 5 odI9$ I9X6D
# 6Dr   