
    S_fq\                         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 dlmZmZ dZ G d d	      Z G d
 d      Z G d d      Z G d de      Zy)    N   )approx_derivativegroup_columns)HessianUpdateStrategy)LinearOperator)
atleast_ndarray_namespace)z2-pointz3-pointcsc                   D    e Zd ZdZ	 ddZd Zd Zd Zd Zd Z	d	 Z
d
 Zy)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	                 "    t              st        vrt        dt         d      t              s+t        v s#t        t              st        dt         d      t        v rt        v rt        d      t        |      x _        }	t        |d|	      }
|	j                  }|	j                  |
j                  d      r|
j                  }|	j                  |
|       _        | _         j                  j                   _        d _        d _        d _        d	 _        d	 _        d	 _        d  _        t.        j0                   _        i t        v rd
<   |d<   |d<   |d<   t        v rd
<   |d<   |d<   dd<    fd fd}| _         j7                          t              r fd fd}nt        v r fd} _         j;                          t              r t/        j<                  |      g  _        d _         xj$                  dz  c_        tA        jB                   j>                        r, fdtA        jD                   j>                         _        n`t         j>                  tF              r fdn> fdt/        jH                  t/        jJ                   j>                               _         fd}nut        v r fd} |        d _        nWt        t              rG _         j>                  jM                   j                  d       d _        d  _'        d  _(         fd} _)        t        t              r fd}| _*        y  fd}| _*        y )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   ndimxpreal floatingr   Fmethodrel_stepabs_stepboundsTas_linear_operatorc                 \   xj                   dz  c_          t        j                  |       g }t        j                  |      s$	 t        j                  |      j                         }|j                  k  r| _	        |_        |S # t        t        f$ r}t        d      |d }~ww xY w)Nr   z@The user-provided objective function must return a scalar value.)
nfevnpcopyisscalarasarrayitem	TypeError
ValueError	_lowest_f	_lowest_x)xfxeargsfunselfs      Hlib/python3.12/site-packages/scipy/optimize/_differentiable_functions.pyfun_wrappedz,ScalarFunction.__init__.<locals>.fun_wrapped   s    IINI RWWQZ'$'B;;r?B,,.B DNN"!"!#I ":. $6 s   	#B B+B&&B+c                  4      j                         _        y Nr#   fr*   r(   s   r)   
update_funz+ScalarFunction.__init__.<locals>.update_fun        (DF    c                     xj                   dz  c_         t        j                   t        j                  |       g       S Nr   )ngevr   
atleast_1dr   )r#   r&   gradr(   s    r)   grad_wrappedz-ScalarFunction.__init__.<locals>.grad_wrapped   s1    		Q	}}T"''!*%<t%<==r2   c                  4      j                         _        y r,   )r#   g)r8   r(   s   r)   update_gradz,ScalarFunction.__init__.<locals>.update_grad       %dff-r2   c                      j                          xj                  dz  c_        t        j                  fdj                  i _        y )Nr   f0)_update_funr5   r   r#   r.   r:   finite_diff_optionsr*   r(   s   r)   r;   z,ScalarFunction.__init__.<locals>.update_grad   sF      "		Q	*; B466 B-@Br2   c                     xj                   dz  c_         t        j                   t        j                  |       g       S r4   )nhevsps
csr_matrixr   r   r#   r&   hessr(   s    r)   hess_wrappedz-ScalarFunction.__init__.<locals>.hess_wrapped   s1    IINI>>$rwwqz*AD*ABBr2   c                 f    xj                   dz  c_          t        j                  |       g S r4   )rC   r   r   rF   s    r)   rH   z-ScalarFunction.__init__.<locals>.hess_wrapped   s(    IINI
2T22r2   c           	          xj                   dz  c_         t        j                  t        j                   t        j                  |       g             S r4   )rC   r   
atleast_2dr   r   rF   s    r)   rH   z-ScalarFunction.__init__.<locals>.hess_wrapped   s:    IINI==D4Kd4K)LMMr2   c                  4      j                         _        y r,   )r#   HrH   r(   s   r)   update_hessz,ScalarFunction.__init__.<locals>.update_hess   r<   r2   c                      j                          t        j                  fdj                  i _        j                  S Nr>   )_update_gradr   r#   r:   rM   )rA   r8   r(   s   r)   rO   z,ScalarFunction.__init__.<locals>.update_hess   sB    !!#*< BDFF B-@Bvvr2   rG   c                       j                           j                  j                   j                   j                  z
   j
                   j                  z
         y r,   )rR   rM   updater#   x_prevr:   g_prevr(   s   r)   rO   z,ScalarFunction.__init__.<locals>.update_hess   s;    !!#dfft{{2DFFT[[4HIr2   c                 :   j                          j                  _        j                  _        t        | dj                        }j                  j                  |j                        _        d_	        d_
        d_        j                          y Nr   r   F)rR   r#   rU   r:   rV   r   r   astypex_dtype	f_updated	g_updated	H_updated_update_hessr#   _xr(   s     r)   update_xz)ScalarFunction.__init__.<locals>.update_x   st    !!#"ff"ff  dgg6DLL9!&!&!&!!#r2   c                     t        | dj                        }j                  j                  |j                        _        d_        d_        d_        y rY   )r   r   rZ   r[   r#   r\   r]   r^   r`   s     r)   rb   z)ScalarFunction.__init__.<locals>.update_x   sF      dgg6DLL9!&!&!&r2   )+callable
FD_METHODSr    
isinstancer   r	   r   r   float64isdtypedtyperZ   r#   r[   sizenr   r5   rC   r\   r]   r^   r"   r   infr!   _update_fun_implr?   _update_grad_implrR   r   rM   rD   issparserE   r   rK   r   
initializerU   rV   _update_hess_impl_update_x_impl)r(   r'   x0r&   r7   rG   finite_diff_rel_stepfinite_diff_boundsepsilonr   ra   _dtyper0   r;   rO   rb   rA   r*   r8   rH   s   `` ```          @@@@r)   __init__zScalarFunction.__init__W   s.   ~$j"8;J<qI  $*"4d$9:(\, 
 :$*"4 8 9 9
 'r**"r*::bhh0XXF 2v&			 :,0).B
+.5
+,>):,0).B
+.5
+8< 45	,	) !+ D>>. ZB "- D>"''"+--DF!DNIINI||DFF#C /DFFN33
N rzz$&&'9:. Z M!DN34DFFFdfff-!DNDKDKJ "-d12$, '' 'r2   c                 L    | j                   s| j                          d| _         y y NTr\   rm   rW   s    r)   r?   zScalarFunction._update_fun  !    ~~!!#!DN r2   c                 L    | j                   s| j                          d| _         y y rz   )r]   rn   rW   s    r)   rR   zScalarFunction._update_grad	  !    ~~""$!DN r2   c                 L    | j                   s| j                          d| _         y y rz   r^   rq   rW   s    r)   r_   zScalarFunction._update_hess  r~   r2   c                     t        j                  || j                        s| j                  |       | j	                          | j
                  S r,   )r   array_equalr#   rr   r?   r.   r(   r#   s     r)   r'   zScalarFunction.fun  s7    ~~a("vvr2   c                     t        j                  || j                        s| j                  |       | j	                          | j
                  S r,   )r   r   r#   rr   rR   r:   r   s     r)   r7   zScalarFunction.grad  7    ~~a("vvr2   c                     t        j                  || j                        s| j                  |       | j	                          | j
                  S r,   )r   r   r#   rr   r_   rM   r   s     r)   rG   zScalarFunction.hess  r   r2   c                     t        j                  || j                        s| j                  |       | j	                          | j                          | j                  | j                  fS r,   )r   r   r#   rr   r?   rR   r.   r:   r   s     r)   fun_and_gradzScalarFunction.fun_and_grad%  sL    ~~a("vvtvv~r2   r,   )__name__
__module____qualname____doc__rx   r?   rR   r_   r'   r7   rG   r    r2   r)   r   r      s8    IV .2k'Z"
"
"
r2   r   c                   F    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zy)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	                     t              st        vrt        dt         d      t              s+t        v s#t        t              st        dt         d      t        v rt        v rt        d      t        |      x _        }	t        |d|	      }
|	j                  }|	j                  |
j                  d      r|
j                  }|	j                  |
|       _        | _         j                  j                   _        d _        d _        d _        d	 _        d	 _        d	 _        i t        v rGd
<   |d<   |t-        |      }||fd<   |d<   t/        j0                   j                         _        t        v r3d
<   |d<   dd<   t/        j0                   j                         _        t        v rt        v rt        d       fd fd}| _         |        t/        j6                   j8                         _         j:                  j                   _        t              r  j                         _        d _         xj"                  dz  c_        |s!|QtA        jB                   j>                        r2 fdtA        jD                   j>                         _        d _#        n}tA        jB                   j>                        r- fd j>                  jI                          _        d	 _#        n1 fdt/        jJ                   j>                         _        d	 _#         fd}nt        v rtM         j                  fd j8                  i _        d _        |s!|RtA        jB                   j>                        r3 fd}tA        jD                   j>                         _        d _#        ntA        jB                   j>                        r. fd} j>                  jI                          _        d	 _#        n2 fd}t/        jJ                   j>                         _        d	 _#         _'        t              r  j                   j:                         _(        d _         xj$                  dz  c_        tA        jB                   jP                        r+ fdtA        jD                   jP                         _(        n^t         jP                  tR              r fdn= fdt/        jJ                  t/        jT                   jP                               _(         fd}nzt        v rfd fd} |        d _        nWt        t              rG _(         jP                  jW                   j                  d        d _        d  _,        d  _-         fd!} _.        t        t              r fd"}| _/        y  fd#}| _/        y )$Nz(`jac` must be either callable or one of r   z?`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   r   r   r   Fr   r   sparsityr   Tr   c                 d    xj                   dz  c_         t        j                   |             S r4   )r   r   r6   )r#   r'   r(   s    r)   r*   z,VectorFunction.__init__.<locals>.fun_wrappedw  s#    IINI==Q((r2   c                  4      j                         _        y r,   r-   r/   s   r)   r0   z+VectorFunction.__init__.<locals>.update_fun{  r1   r2   c                 d    xj                   dz  c_         t        j                   |             S r4   )njevrD   rE   r#   jacr(   s    r)   jac_wrappedz,VectorFunction.__init__.<locals>.jac_wrapped  s#    IINI>>#a&11r2   c                 Z    xj                   dz  c_          |       j                         S r4   )r   toarrayr   s    r)   r   z,VectorFunction.__init__.<locals>.jac_wrapped  s!    IINIq6>>++r2   c                 d    xj                   dz  c_         t        j                   |             S r4   )r   r   rK   r   s    r)   r   z,VectorFunction.__init__.<locals>.jac_wrapped  s#    IINI==Q00r2   c                  4      j                         _        y r,   )r#   J)r   r(   s   r)   
update_jacz+VectorFunction.__init__.<locals>.update_jac  s    $TVV,r2   r>   c                      j                          t        j                  t        j                  fdj
                  i       _        y rQ   )r?   rD   rE   r   r#   r.   r   r@   s   r)   r   z+VectorFunction.__init__.<locals>.update_jac  sF    $$& ^^)+tvv A$&& A,?ABDFr2   c                      j                          t        j                  fdj                  i j	                         _        y rQ   )r?   r   r#   r.   r   r   r@   s   r)   r   z+VectorFunction.__init__.<locals>.update_jac  sC    $$&.{DFF Ftvv F1DFFMgi Fr2   c                      j                          t        j                  t        j                  fdj
                  i       _        y rQ   )r?   r   rK   r   r#   r.   r   r@   s   r)   r   z+VectorFunction.__init__.<locals>.update_jac  sF    $$&]])+tvv A$&& A,?ABDFr2   c                 f    xj                   dz  c_         t        j                   | |            S r4   )rC   rD   rE   r#   vrG   r(   s     r)   rH   z-VectorFunction.__init__.<locals>.hess_wrapped  s%    IINI>>$q!*55r2   c                 @    xj                   dz  c_          | |      S r4   )rC   r   s     r)   rH   z-VectorFunction.__init__.<locals>.hess_wrapped  s    IINI1:%r2   c                     xj                   dz  c_         t        j                  t        j                   | |                  S r4   )rC   r   rK   r   r   s     r)   rH   z-VectorFunction.__init__.<locals>.hess_wrapped  s.    IINI==DAJ)?@@r2   c                  J      j                   j                        _        y r,   )r#   r   rM   rN   s   r)   rO   z,VectorFunction.__init__.<locals>.update_hess  s    %dffdff5r2   c                 F     |       j                   j                  |      S r,   )Tdot)r#   r   r   s     r)   	jac_dot_vz*VectorFunction.__init__.<locals>.jac_dot_v  s    "1~''++A..r2   c                      j                          t        j                  fj                  j                  j                  j                        j                  fd _        y )N)r>   r&   )_update_jacr   r#   r   r   r   r   rM   )rA   r   r(   s   r)   rO   z,VectorFunction.__init__.<locals>.update_hess  sW      "*9dff B.2ffhhll466.B15	B .ABr2   rG   c                     j                          j                  j                  j                  j                  z
  } j                  j
                  j                  j                        j                  j
                  j                  j                        z
  }j                  j                  | |       y y y r,   )
r   rU   J_prevr#   r   r   r   r   rM   rT   )delta_xdelta_gr(   s     r)   rO   z,VectorFunction.__init__.<locals>.update_hess  s      " ;;*t{{/F"fft{{2G"ffhhll4662T[[]]5F5Ftvv5NNGFFMM'73 0G*r2   c                 :   j                          j                  _        j                  _        t        | dj                        }j                  j                  |j                        _        d_	        d_
        d_        j                          y rY   )r   r#   rU   r   r   r   r   rZ   r[   r\   	J_updatedr^   r_   r`   s     r)   rb   z)VectorFunction.__init__.<locals>.update_x  sr      ""ff"ffdgg6DLL9!&!&!&!!#r2   c                     t        | dj                        }j                  j                  |j                        _        d_        d_        d_        y rY   )r   r   rZ   r[   r#   r\   r   r^   r`   s     r)   rb   z)VectorFunction.__init__.<locals>.update_x  sD    dgg6DLL9!&!&!&r2   )0rd   re   r    rf   r   r	   r   r   rg   rh   ri   rZ   r#   r[   rj   rk   r   r   rC   r\   r   r^   r   r   r   x_diffrm   
zeros_liker.   r   mr   rD   ro   rE   sparse_jacobianr   rK   r   _update_jac_implrM   r   r   rp   rU   r   rq   rr   )r(   r'   rs   r   rG   rt   finite_diff_jac_sparsityru   r   r   ra   rw   sparsity_groupsr0   r   rO   rb   rA   r*   rH   r   r   s   `` ``            @@@@@r)   rx   zVectorFunction.__init__>  s    }J!6G
|STUVV$*"4d$9: @@J|1N O O *!3 + , ,
 'r**"r*::bhh0XXF 2v&			 *,/).B
+'3"/0H"I3K3B3D#J/,>)''$&&/DK:,0).B
+8< 45''$&&/DK*!3 + , ,	)	) !+tvv& C=[DF!DNIINI#+TVV0D2 /'+$dff%, )',$1 tvv.',$- J&{DFF >tvv >)<>DF!DN#+TVV0DB
 /'+$dff%P )',$B
 tvv.',$ * D>$&&$&&)DF!DNIINI||DFF#6 /DFFN3&
A rzz$&&'9:6Z/B M!DN34DFFFdfff-!DNDKDK4 "-d12	$$ '' 'r2   c                 b    t        j                  || j                        s|| _        d| _        y y )NF)r   r   r   r^   )r(   r   s     r)   	_update_vzVectorFunction._update_v  s'    ~~a(DF"DN )r2   c                 h    t        j                  || j                        s| j                  |       y y r,   )r   r   r#   rr   r   s     r)   	_update_xzVectorFunction._update_x  s'    ~~a(" )r2   c                 L    | j                   s| j                          d| _         y y rz   r{   rW   s    r)   r?   zVectorFunction._update_fun  r|   r2   c                 L    | j                   s| j                          d| _         y y rz   )r   r   rW   s    r)   r   zVectorFunction._update_jac  r|   r2   c                 L    | j                   s| j                          d| _         y y rz   r   rW   s    r)   r_   zVectorFunction._update_hess$  r~   r2   c                 \    | j                  |       | j                          | j                  S r,   )r   r?   r.   r   s     r)   r'   zVectorFunction.fun)  #    qvvr2   c                 \    | j                  |       | j                          | j                  S r,   )r   r   r   r   s     r)   r   zVectorFunction.jac.  r   r2   c                 ~    | j                  |       | j                  |       | j                          | j                  S r,   )r   r   r_   rM   r(   r#   r   s      r)   rG   zVectorFunction.hess3  s/    qqvvr2   N)r   r   r   r   rx   r   r   r?   r   r_   r'   r   rG   r   r2   r)   r   r   -  s6     Q'f#
#"
"
"


r2   r   c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)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                    |s|7t        j                  |      r"t        j                  |      | _        d| _        nft        j                  |      r|j                         | _        d| _        n4t        j                  t        j                  |            | _        d| _        | j                  j                  \  | _
        | _        t        |      x| _        }t        |d|      }|j                  }|j!                  |j"                  d      r|j"                  }|j%                  ||      | _        || _        | j                  j+                  | j&                        | _        d| _        t        j0                  | j                  t2              | _        t        j                  | j                  | j                  f      | _        y )NTFr   r   r   )ri   )rD   ro   rE   r   r   r   r   rK   r   shaper   rk   r	   r   r   rg   rh   ri   rZ   r#   r[   r   r.   r\   zerosfloatr   rM   )r(   Ars   r   r   ra   rw   s          r)   rx   zLinearVectorFunction.__init__B  s3   o5#,,q/^^A&DF#'D \\!_YY[DF#(D  ]]2::a=1DF#(D &r**"r*::bhh0XXF 2v&DFF#$&&. 01r2   c                     t        j                  || j                        sKt        |d| j                        }| j                  j                  || j                        | _        d| _        y y rY   )r   r   r#   r   r   rZ   r[   r\   )r(   r#   ra   s      r)   r   zLinearVectorFunction._update_x`  sL    ~~a(AA$''2BWW^^B5DF"DN )r2   c                     | j                  |       | j                  s'| j                  j                  |      | _        d| _        | j                  S rz   )r   r\   r   r   r.   r   s     r)   r'   zLinearVectorFunction.funf  s8    q~~VVZZ]DF!DNvvr2   c                 <    | j                  |       | j                  S r,   )r   r   r   s     r)   r   zLinearVectorFunction.jacm  s    qvvr2   c                 J    | j                  |       || _        | j                  S r,   )r   r   rM   r   s      r)   rG   zLinearVectorFunction.hessq  s    qvvr2   N)	r   r   r   r   rx   r   r'   r   rG   r   r2   r)   r   r   ;  s     2<#r2   r   c                   "     e Zd ZdZ fdZ x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                     t        |      }|s|t        j                  |d      }d}nt        j                  |      }d}t        |   |||       y )Ncsr)formatTF)lenrD   eyer   superrx   )r(   rs   r   rk   r   	__class__s        r)   rx   zIdentityVectorFunction.__init__~  sL    Go5%(A"Oq	A#OB0r2   )r   r   r   r   rx   __classcell__)r   s   @r)   r   r   w  s    1 1r2   r   )numpyr   scipy.sparsesparserD   _numdiffr   r   _hessian_update_strategyr   scipy.sparse.linalgr   scipy._lib._array_apir   r	   re   r   r   r   r   r   r2   r)   <module>r      sP      6 ; . = *
^ ^B	K K\9 9x11 1r2   