U
    ¦»|e¢-  ã                   @   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/website-v5/atlas_env/lib/python3.8/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ÚubZlb_centeredZub_centeredÚlb_totalÚub_totalÚorig_lÚorig_uÚtr_lÚtr_ur   r   r    Úfind_intersectionM   s    r6   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   )r6   r)   Ú
zeros_likeÚintr
   r	   r   Úany)r   Únewton_stepÚgÚaÚbr-   r.   r/   r0   r1   r2   r3   r4   r5   Z
bound_hitsZ	to_boundsÚ_Zcauchy_stepZ	step_diffÚ	step_sizeÚhitsÚtr_hitr   r   r    Údogleg_stepj   s(       ÿ
 ÿrD   c           =      C   sz  |}|  ¡ }d}|}d}|d k	rL||ƒ}dt |d ¡ }t|||ƒ\}}ndt ||¡ }t||ƒ}t|tƒov|dk}|rŠt|ƒ\}}n|d|  }}t	|| tj
d�}|dkr¶d}tj|td�}d|t ||¡< d|t ||¡< |}t |¡}|
d k�r|jd	 }
d }d} d }!d }"|d
k�r&tƒ  || dk }#|# }$||$ }%|  ¡ }&d||#< t	|tj
d�}'|'|	k �rld}|d
k�rˆt| |||"|!|'ƒ |d k	�sP||
k�r �qP||$ }(||$ })||$ }*||$ }+|dk�r|d d …|$f },t|,| dd�d }-t|,|%|% ƒ\}.}/nP|dk�rRt|ƒ}0t|0||#ƒ}1t|1|f|Žd |$  }-|-|+9 }-t|0|| ƒ\}.}/d}"|"dk�rš||
k �rš||+ }2t|(|-|%|.|/|2|)|*ƒ\}3}4}5| d¡ |3||$< |dk�rºt|,|%|3ƒ }6n|dk�rÒt|0||ƒ }6t || ||¡}7| |7ƒ}8|d7 }t	|| tj
d�}9t t |8¡¡�s$d|9 }�qV|d k	�r<||8dd�}:ndt |8|8¡ }:||: }"t||"|6|9|5ƒ\}};t	|ƒ}!t|"||!t	|ƒ|;||ƒ}|d k	�rV�qš�qV|"dk�r<|4||$< |7}|dk}<||< ||<< |dk}<||< ||<< |8}|  ¡ }|:}|||ƒ}|d7 }|d k	�r||ƒ}t|||ƒ\}}t||ƒ}|�rDt||ƒ\}}nd}!d}"| d7 } �q&|d k�r^d}t|||||&|'||||d�
S )Nr   g      à?r   Újac)Úordg      ð?r7   r8   éd   é   Úexact)Úrcondr   g      ð¿g        g      Ð?T)Ú	cost_only)
r   ÚcostÚfunrE   ÚgradÚ
optimalityÚactive_maskÚnfevÚnjevÚstatus) r   r)   Úsumr   Údotr   Ú
isinstanceÚstrr   r   Úinfr9   r:   r,   Ú
empty_likeÚsizer   r   r   r   r   r(   r   rD   Úfillr   ÚclipÚallÚisfiniter   r   r   )=rM   rE   Úx0Úf0ÚJ0r.   r/   ÚftolÚxtolÚgtolÚmax_nfevÚx_scaleÚloss_functionÚ	tr_solverÚ
tr_optionsÚverboseÚfÚf_truerQ   ÚJrR   ÚrhorL   r=   Ú	jac_scaleÚscaleÚ	scale_invÚDeltaZon_boundr   ÚstepÚtermination_statusÚ	iterationÚ	step_normÚactual_reductionr   Zfree_setZg_freeZg_fullÚg_normr   Zlb_freeZub_freeZ
scale_freeZJ_freer<   r>   r?   r   Úlsmr_opr-   Z	step_freeZon_bound_freerC   Ú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(   r6   rD   r�   r   r   r   r    Ú<module>   s   *8+