o
    Ö­j¢-  ã                   @   s˜   d Z ddlZddlmZmZ ddlmZmZm	Z	 ddl
mZ ddlmZmZmZmZmZmZmZmZmZmZmZmZ dd	„ Zd
d„ Zdd„ Zdd„ ZdS )a	  
Dogleg algorithm with rectangular trust regions for least-squares minimization.

The description of the algorithm can be found in [Voglis]_. The algorithm does
trust-region iterations, but the shape of trust regions is rectangular as
opposed to conventional elliptical. The intersection of a trust region and
an initial feasible region is again some rectangle. Thus, on each iteration a
bound-constrained quadratic optimization problem is solved.

A quadratic problem is solved by well-known dogleg approach, where the
function is minimized along piecewise-linear "dogleg" path [NumOpt]_,
Chapter 4. If Jacobian is not rank-deficient then the function is decreasing
along this path, and optimization amounts to simply following along this
path as long as a point stays within the bounds. A constrained Cauchy step
(along the anti-gradient) is considered for safety in rank deficient cases,
in this situations the convergence might be slow.

If during iterations some variable hit the initial bound and the component
of anti-gradient points outside the feasible region, then a next dogleg step
won't make any progress. At this state such variables satisfy first-order
optimality conditions and they are excluded before computing a next dogleg
step.

Gauss-Newton step can be computed exactly by `numpy.linalg.lstsq` (for dense
Jacobian matrices) or by iterative procedure `scipy.sparse.linalg.lsmr` (for
dense and sparse matrices, or Jacobian being LinearOperator). The second
option allows to solve very large problems (up to couple of millions of
residuals on a regular PC), provided the Jacobian matrix is sufficiently
sparse. But note that dogbox is not very good for solving problems with
large number of constraints, because of variables exclusion-inclusion on each
iteration (a required number of function evaluations might be high or accuracy
of a solution will be poor), thus its large-scale usage is probably limited
to unconstrained problems.

References
----------
.. [Voglis] C. Voglis and I. E. Lagaris, "A Rectangular Trust Region Dogleg
            Approach for Unconstrained and Bound Constrained Nonlinear
            Optimization", WSEAS International Conference on Applied
            Mathematics, Corfu, Greece, 2004.
.. [NumOpt] J. Nocedal and S. J. Wright, "Numerical optimization, 2nd edition".
é    N)ÚlstsqÚnorm)ÚLinearOperatorÚaslinearoperatorÚlsmr)ÚOptimizeResulté   )Ústep_size_to_boundÚ	in_boundsÚupdate_tr_radiusÚevaluate_quadraticÚbuild_quadratic_1dÚminimize_quadratic_1dÚcompute_gradÚcompute_jac_scaleÚcheck_terminationÚscale_for_robust_loss_functionÚprint_header_nonlinearÚprint_iteration_nonlinearc                    s>   ˆ j \}}‡ ‡‡fdd„}‡ ‡‡fdd„}t||f||td�S )z¬Compute LinearOperator to use in LSMR by dogbox algorithm.

    `active_set` mask is used to excluded active variables from computations
    of matrix-vector products.
    c                    s"   |   ¡  ¡ }d|ˆ< ˆ  | ˆ ¡S ©Nr   )ÚravelÚcopyÚmatvec)ÚxÚx_free©ÚJopÚ
active_setÚd© úW/var/www/html/CropPilot/venv/lib/python3.10/site-packages/scipy/optimize/_lsq/dogbox.pyr   @   s   zlsmr_operator.<locals>.matvecc                    s   ˆˆ   | ¡ }d|ˆ< |S r   )Úrmatvec)r   Úrr   r   r    r!   E   s   zlsmr_operator.<locals>.rmatvec)r   r!   Údtype)Úshaper   Úfloat)r   r   r   ÚmÚnr   r!   r   r   r    Úlsmr_operator8   s   
r(   c                 C   sl   ||  }||  }t  || ¡}t  ||¡}t  ||¡}t  ||¡}	t  || ¡}
t  ||¡}||||	|
|fS )a  Find intersection of trust-region bounds and initial bounds.

    Returns
    -------
    lb_total, ub_total : ndarray with shape of x
        Lower and upper bounds of the intersection region.
    orig_l, orig_u : ndarray of bool with shape of x
        True means that an original bound is taken as a corresponding bound
        in the intersection region.
    tr_l, tr_u : ndarray of bool with shape of x
        True means that a trust-region bound is taken as a corresponding bound
        in the intersection region.
    )ÚnpÚmaximumÚminimumÚequal)r   Ú	tr_boundsÚlbÚubÚlb_centeredÚub_centeredÚlb_totalÚub_totalÚorig_lÚorig_uÚtr_lÚtr_ur   r   r    Úfind_intersectionM   s   r8   c                 C   sÚ   t | |||ƒ\}}	}
}}}tj| td�}t|||	ƒr||dfS tt | ¡| ||	ƒ\}}t||d|ƒd  | }|| }t||||	ƒ\}}d||dk |
@ < d||dk|@ < t |dk |@ |dk|@ B ¡}|||  ||fS )aú  Find dogleg step in a rectangular region.

    Returns
    -------
    step : ndarray, shape (n,)
        Computed dogleg step.
    bound_hits : ndarray of int, shape (n,)
        Each component shows whether a corresponding variable hits the
        initial bound after the step is taken:
            *  0 - a variable doesn't hit the bound.
            * -1 - lower bound is hit.
            *  1 - upper bound is hit.
    tr_hit : bool
        Whether the step hit the boundary of the trust-region.
    ©r#   Fr   éÿÿÿÿr   )r8   r)   Ú
zeros_likeÚintr
   r	   r   Úany)r   Únewton_stepÚgÚaÚbr-   r.   r/   r2   r3   r4   r5   r6   r7   Ú
bound_hitsÚ	to_boundsÚ_Úcauchy_stepÚ	step_diffÚ	step_sizeÚhitsÚtr_hitr   r   r    Údogleg_stepj   s    ÿ
ÿrJ   c           =      C   s~  |}|  ¡ }d}|}d}|d ur&||ƒ}dt |d ¡ }t|||ƒ\}}ndt ||¡ }t||ƒ}t|tƒo;|dk}|rEt|ƒ\}}n|d| }}t	|| tj
d�}|dkr[d}tj|td�}d|t ||¡< d|t ||¡< |}t |¡}|
d u r‚|jd	 }
d }d} d }!d }"|d
kr‘tƒ  	 || dk }#|# }$||$ }%|  ¡ }&d||#< t	|tj
d�}'|'|	k r´d}|d
krÁt| |||"|!|'ƒ |d usÉ||
krË�n_||$ }(||$ })||$ }*||$ }+|dkrû|d d …|$f },t|,| dd�d }-t|,|%|% ƒ\}.}/n*|dk�r%t|ƒ}0t|0||#ƒ}1t|1|fi |¤Žd |$  }-|-|+9 }-t|0|| ƒ\}.}/d}"|"dk�rÐ||
k �rÐ||+ }2t|(|-|%|.|/|2|)|*ƒ\}3}4}5| d¡ |3||$< |dk�rYt|,|%|3ƒ }6n|dk�ret|0||ƒ }6t || ||¡}7| |7ƒ}8|d7 }t	|| tj
d�}9t t |8¡¡�sŽd|9 }�q'|d u�rš||8dd�}:ndt |8|8¡ }:||: }"t||"|6|9|5ƒ\}};t	|ƒ}!t|"||!t	|ƒ|;||ƒ}|d u�rÆn
|"dk�rÐ||
k �s1|"dk�r!|4||$< |7}|dk}<||< ||<< |dk}<||< ||<< |8}|  ¡ }|:}|||ƒ}|d7 }|d u�r||ƒ}t|||ƒ\}}t||ƒ}|�r t||ƒ\}}nd}!d}"| d7 } q’|d u �r1d}t|||||&|'||||d�
S )Nr   g      à?r   Újac)Úordg      ð?r9   r:   éd   é   TÚexact)Úrcondr   g      ð¿g        g      Ð?)Ú	cost_only)
r   ÚcostÚfunrK   ÚgradÚ
optimalityÚactive_maskÚnfevÚnjevÚstatus) r   r)   Úsumr   Údotr   Ú
isinstanceÚstrr   r   Úinfr;   r<   r,   Ú
empty_likeÚsizer   r   r   r   r   r(   r   rJ   Úfillr   ÚclipÚallÚisfiniter   r   r   )=rS   rK   Úx0Úf0ÚJ0r.   r/   ÚftolÚxtolÚgtolÚmax_nfevÚx_scaleÚloss_functionÚ	tr_solverÚ
tr_optionsÚverboseÚfÚf_truerW   ÚJrX   ÚrhorR   r?   Ú	jac_scaleÚscaleÚ	scale_invÚDeltaÚon_boundr   ÚstepÚtermination_statusÚ	iterationÚ	step_normÚactual_reductionr   Úfree_setÚg_freeÚg_fullÚg_normr   Úlb_freeÚub_freeÚ
scale_freeÚJ_freer>   r@   rA   r   Úlsmr_opr-   Ú	step_freeÚon_bound_freerI   Úpredicted_reductionÚx_newÚf_newÚstep_h_normÚcost_newÚratioÚmaskr   r   r    Údogbox•   sþ   



ÿ

ÿ

ÿ

þÿ
Ô
.


€ �þ 
þr‘   )Ú__doc__Únumpyr)   Únumpy.linalgr   r   Úscipy.sparse.linalgr   r   r   Úscipy.optimizer   Úcommonr	   r
   r   r   r   r   r   r   r   r   r   r   r(   r8   rJ   r‘   r   r   r   r    Ú<module>   s    *8+