B
    0d-                 @   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 )zCompute 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   )Zravelcopymatvec)xx_free)Jop
active_setd L/var/www/html/venv/lib/python3.7/site-packages/scipy/optimize/_lsq/dogbox.pyr   @   s    zlsmr_operator.<locals>.matvecc                s     |  }d|< |S )Nr   )rmatvec)r   r)r   r   r   r   r   r   E   s    zlsmr_operator.<locals>.rmatvec)r   r   dtype)shaper   float)r   r   r   mnr   r   r   )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    r3   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   )r3   r&   
zeros_likeintr
   r	   r   any)r   newton_stepgabr*   r+   r,   r-   r.   r/   r0   r1   r2   Z
bound_hitsZ	to_bounds_Zcauchy_stepZ	step_diffZ	step_sizehitstr_hitr   r   r   dogleg_stepj   s    
r?   c       =      C   s  |}|  }d}|}d}|d k	rL||}dt|d  }t|||\}}ndt|| }t||}t|tov|dk}|rt|\}}n|d|  }}t	|| tj
d}|dkrd}tj|td}d|t||< d|t||< |}t|}|
d kr|jd	 }
d }d} d }!d }"|d
kr&t  x.|| dk }#|# }$||$ }%|  }&d||#< t	|tj
d}'|'|	k rpd}|d
krt| |||"|!|' |d k	s||
krP ||$ }(||$ })||$ }*||$ }+|dkr|d d |$f },t|,| ddd }-t|,|%|% \}.}/nP|dkrTt|}0t|0||#}1t|1|f|d |$  }-|-|+9 }-t|0|| \}.}/d}"xD|"dkr||
k r||+ }2t|(|-|%|.|/|2|)|*\}3}4}5|d |3||$< |dkrt|,|%|3 }6n|dkrt|0|| }6t|| ||}7| |7}8|d7 }t	|| tj
d}9tt|8s*d|9 }q\|d k	rB||8dd}:ndt|8|8 }:||: }"t||"|6|9|5\}};t	|}!t|"||!t	||;||}|d k	r\P q\W |"dkrB|4||$< |7}|dk}<||< ||<< |dk}<||< ||<< |8}|  }|:}|||}|d7 }|d k	r"||}t|||\}}t||}|rJt||\}}nd}!d}"| d7 } q*W |d krfd}t|||||&|'||||d
S )Nr   g      ?r   jac)ordg      ?)r    r4   d      exact)Zrcondr   g      g        g      ?T)Z	cost_only)
r   costfunr@   ZgradZ
optimalityZactive_masknfevnjevstatus) r   r&   sumr   dotr   
isinstancestrr   r   infr5   r6   r)   Z
empty_likesizer   r   r   r   r   r%   r   r?   fillr   Zclipallisfiniter   r   r   )=rF   r@   Zx0Zf0ZJ0r+   r,   ZftolZxtolZgtolZmax_nfevZx_scaleZloss_functionZ	tr_solverZ
tr_optionsverbosefZf_truerG   JrH   rhorE   r9   Z	jac_scalescaleZ	scale_invDeltaZon_boundr   stepZtermination_status	iterationZ	step_normZactual_reductionr   Zfree_setZg_freeZg_fullZg_normr   Zlb_freeZub_freeZ
scale_freeZJ_freer8   r:   r;   r   Zlsmr_opr*   Z	step_freeZon_bound_freer>   Zpredicted_reductionZx_newZf_newZstep_h_normZcost_newratiomaskr   r   r   dogbox   s    




















r]   )__doc__numpyr&   Znumpy.linalgr   r   Zscipy.sparse.linalgr   r   r   Zscipy.optimizer   commonr	   r
   r   r   r   r   r   r   r   r   r   r   r%   r3   r?   r]   r   r   r   r   <module>*   s   8+