ó
î&]\c           @` sú   d  Z  d d l m Z m Z m 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 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
 „  Z d „  Z  d „  Z! d „  Z" d S(   s	  
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".
i    (   t   divisiont   print_functiont   absolute_importN(   t   lstsqt   norm(   t   LinearOperatort   aslinearoperatort   lsmr(   t   OptimizeResult(   t   string_typesi   (   t   step_size_to_boundt	   in_boundst   update_tr_radiust   evaluate_quadratict   build_quadratic_1dt   minimize_quadratic_1dt   compute_gradt   compute_jac_scalet   check_terminationt   scale_for_robust_loss_functiont   print_header_nonlineart   print_iteration_nonlinearc         ` s[   ˆ  j  \ } } ‡  ‡ ‡ f d †  } ‡  ‡ ‡ f d †  } t | | f d | d | d t ƒS(   s¬   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-   |  j  ƒ  j ƒ  } d | ˆ <ˆ  j |  ˆ ƒ S(   Ni    (   t   ravelt   copyt   matvec(   t   xt   x_free(   t   Jopt
   active_sett   d(    s9   lib/python2.7/site-packages/scipy/optimize/_lsq/dogbox.pyR   C   s    
c         ` s!   ˆ ˆ  j  |  ƒ } d | ˆ <| S(   Ni    (   t   rmatvec(   R   t   r(   R   R   R   (    s9   lib/python2.7/site-packages/scipy/optimize/_lsq/dogbox.pyR   H   s    
R   R   t   dtype(   t   shapeR   t   float(   R   R   R   t   mt   nR   R   (    (   R   R   R   s9   lib/python2.7/site-packages/scipy/optimize/_lsq/dogbox.pyt   lsmr_operator;   s    c         C` s˜   | |  } | |  } t  j | | ƒ } t  j | | ƒ } t  j | | ƒ } t  j | | ƒ }	 t  j | | ƒ }
 t  j | | ƒ } | | | |	 |
 | f S(   s  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.
    (   t   npt   maximumt   minimumt   equal(   R   t	   tr_boundst   lbt   ubt   lb_centeredt   ub_centeredt   lb_totalt   ub_totalt   orig_lt   orig_ut   tr_lt   tr_u(    (    s9   lib/python2.7/site-packages/scipy/optimize/_lsq/dogbox.pyt   find_intersectionP   s    

c         C` s'  t  |  | | | ƒ \ } }	 }
 } } } t j |  d t ƒ} t | | |	 ƒ r[ | | t f St t j |  ƒ | | |	 ƒ \ } } t | | d | ƒ d | } | | } t | | | |	 ƒ \ } } d | | d k  |
 @<d | | d k | @<t j | d k  | @| d k | @Bƒ } | | | | | f S(   sú  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    i    iÿÿÿÿi   (	   R5   R&   t
   zeros_liket   intR   t   FalseR
   R   t   any(   R   t   newton_stept   gt   at   bR*   R+   R,   R/   R0   R1   R2   R3   R4   t
   bound_hitst	   to_boundst   _t   cauchy_stept	   step_difft	   step_sizet   hitst   tr_hit(    (    s9   lib/python2.7/site-packages/scipy/optimize/_lsq/dogbox.pyt   dogleg_stepm   s    $%
	'c   =      C` sK  | } | j  ƒ  } d } | } d } | d  k	 rn | | ƒ } d t j | d ƒ } t | | | ƒ \ } } n d t j | | ƒ } t | | ƒ } t | t ƒ o« | d k } | rÉ t	 | ƒ \ } } n | d | } } t
 | | d t j ƒ} | d k rd } n  t j | d t ƒ} d | t j | | ƒ <d | t j | | ƒ <| } t j | ƒ } |
 d  k rz| j d	 }
 n  d  } d }  d  }! d  }" | d
 k r¨t ƒ  n  xHt rò| | d k  }# |# }$ | |$ }% | j  ƒ  }& d | |# <t
 | d t j ƒ}' |' |	 k  rd } n  | d
 k r:t |  | | |" |! |' ƒ n  | d  k	 sR| |
 k rVPn  | |$ }( | |$ }) | |$ }* | |$ }+ | d k rÖ| d  d  … |$ f }, t |, | d d ƒd }- t |, |% |% ƒ \ }. }/ nk | d k rAt | ƒ }0 t |0 | |# ƒ }1 t |1 | |  d |$ }- |- |+ 9}- t |0 | | ƒ \ }. }/ n  d }" x«|" d k rô| |
 k  rô| |+ }2 t |( |- |% |. |/ |2 |) |* ƒ \ }3 }4 }5 | j d ƒ |3 | |$ <| d k rÏt |, |% |3 ƒ }6 n" | d k rñt |0 | | ƒ }6 n  | | }7 |  |7 ƒ }8 | d 7} t
 | | d t j ƒ}9 t j t j |8 ƒ ƒ sRd |9 } qJn  | d  k	 rs| |8 d t ƒ}: n d t j |8 |8 ƒ }: | |: }" t | |" |6 |9 |5 ƒ \ } }; t
 | ƒ }! t |" | |! t
 | ƒ |; | | ƒ } | d  k	 rJPqJqJW|" d k rÙ|4 | |$ <|7 } | d k }< | |< | |< <| d k }< | |< | |< <|8 } | j  ƒ  } |: } | | | ƒ } | d 7} | d  k	 r©| | ƒ } t | | | ƒ \ } } n  t | | ƒ } | råt	 | | ƒ \ } } qån d }! d }" |  d 7}  q«W| d  k rd } n  t  d | d | d | d | d |& d |' d | d | d | d | ƒ 
S(   Ni   g      à?i    t   jact   ordg      ð?R    iÿÿÿÿid   i   t   exactt   rcondR   g      ð¿g        g      Ð?t	   cost_onlyR   t   costt   funt   gradt
   optimalityt   active_maskt   nfevt   njevt   status(!   R   t   NoneR&   t   sumR   t   dotR   t
   isinstanceR	   R   R   t   infR6   R7   R)   t
   empty_liket   sizeR   t   TrueR   R   R   R   R%   R   RF   t   fillR   t   allt   isfiniteR   R   R   (=   RM   RG   t   x0t   f0t   J0R+   R,   t   ftolt   xtolt   gtolt   max_nfevt   x_scalet   loss_functiont	   tr_solvert
   tr_optionst   verboset   ft   f_trueRQ   t   JRR   t   rhoRL   R;   t	   jac_scalet   scalet	   scale_invt   Deltat   on_boundR   t   stept   termination_statust	   iterationt	   step_normt   actual_reductionR   t   free_sett   g_freet   g_fullt   g_normR   t   lb_freet   ub_freet
   scale_freet   J_freeR:   R<   R=   R   t   lsmr_opR*   t	   step_freet   on_bound_freeRE   t   predicted_reductiont   x_newt   f_newt   step_h_normt   cost_newt   ratiot   mask(    (    s9   lib/python2.7/site-packages/scipy/optimize/_lsq/dogbox.pyt   dogbox˜   sè    	
	

	





'
	



	!

	$(#   t   __doc__t
   __future__R    R   R   t   numpyR&   t   numpy.linalgR   R   t   scipy.sparse.linalgR   R   R   t   scipy.optimizeR   t   scipy._lib.sixR	   t   commonR
   R   R   R   R   R   R   R   R   R   R   R   R%   R5   RF   R‹   (    (    (    s9   lib/python2.7/site-packages/scipy/optimize/_lsq/dogbox.pyt   <module>*   s   R			+