
    Yh/                         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 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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)_call_callback_maybe_halt   )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                 l      j         \  }} fd} fd}t          ||f||t                    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                     |                                                                  }d|<                       | z            S Nr   )ravelcopymatvec)xx_freeJop
active_setds     l/var/www/tools.fuzzalab.pt/emblema-extractor/venv/lib/python3.11/site-packages/scipy/optimize/_lsq/dogbox.pyr   zlsmr_operator.<locals>.matvecB   s:    !!zzz!a%       c                 B                         |           z  }d|<   |S r   )rmatvec)r   rr   r    r!   s     r"   r%   zlsmr_operator.<locals>.rmatvecG   s%    A*r#   )r   r%   dtype)shaper   float)r   r!   r    mnr   r%   s   ```    r"   lsmr_operatorr,   :   su     9DAq! ! ! ! ! ! !
      
 1a&NNNNr#   c                 &   || z
  }|| z
  }t          j        ||           }t          j        ||          }t          j        ||          }t          j        ||          }	t          j        ||           }
t          j        ||          }||||	|
|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_us               r"   find_intersectionr=   O   s     q&Kq&Kz+	z22Hz+y11HXh,,FXh,,F8Hyj))D8Hi((DXvvtT99r#   c                    t          | |||          \  }}	}
}}}t          j        | t                    }t	          |||	          r||dfS t          t          j        |           | ||	          \  }}t          ||d|          d          |z  }||z
  }t          ||||	          \  }}d||dk     |
z  <   d||dk    |z  <   t          j        |dk     |z  |dk    |z  z            }|||z  z   ||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
   )r=   r.   
zeros_likeintr   r   r   any)r   newton_stepgabr2   r3   r4   r7   r8   r9   r:   r;   r<   
bound_hits	to_bounds_cauchy_step	step_diff	step_sizehitstr_hits                         r"   dogleg_steprP   l   s/     6G	9b"6 62Hhd q,,,Jh11 .J--%bmA&6&6HhOOLIq )Aq)<<Q??!CKk)I(i)18= =OIt&(JqF"#&'JqF"#VTAX%T(99::FY..
FBBr#   c                 	   |}|                                 }d}|}d}|= ||          }dt          j        |d                   z  }t          |||          \  }}ndt          j        ||          z  }t          ||          }t          |t                    o|dk    }|rt          |          \  }}n|d|z  }}t          ||z  t          j
                  }|dk    rd}t          j        |t                    }d|t          j        ||          <   d|t          j        ||          <   |}t          j        |          }|

|j        d	z  }
d } d}!d }"d }#|d
k    rt!                       	 ||z  dk     }$|$ }%||%         }&|                                 }'d||$<   t          |t          j
                  }(|(|	k     rd} |d
k    rt#          |!|||#|"|(           | ||
k    rn||%         })||%         }*||%         }+||%         },|dk    r;|d d |%f         }-t%          |-| d          d         }.t'          |-|&|&           \  }/}0n[|dk    rUt)          |          }1t+          |1||$          }2t-          |2|fi |d         |%          }.|.|,z  }.t'          |1||           \  }/}0d}#|#dk    rh||
k     ra||,z  }3t/          |)|.|&|/|0|3|*|+          \  }4}5}6|                    d           |4||%<   |dk    rt3          |-|&|4           }7n|dk    rt3          |1||           }7t          j        ||z   ||          }8 | |8          }9|dz  }t          ||z  t          j
                  }:t          j        t          j        |9                    sd|:z  }| ||9d          };ndt          j        |9|9          z  };||;z
  }#t;          ||#|7|:|6          \  }}<t          |          }"t=          |#||"t          |          |<||          } | n|#dk    r||
k     a|#dk    r|5||%<   |8}|dk    }=||=         ||=<   |dk    }=||=         ||=<   |9}|                                 }|;} ||          }|dz  }| ||          }t          |||          \  }}t          ||          }|rt          ||          \  }}nd}"d}#|!dz  }!|+t?          |||!|          }>|;|>d<   tA          ||>          rd} nw| d} t?          |||||'|(|||| 
  
        S )Nr
   g      ?r   jac)ordg      ?r?   r@   d      Texact)rcondr   g      g        g      ?)	cost_only)r   funnitnfevcost)
r   r\   rY   rR   grad
optimalityactive_maskr[   njevstatus)!r   r.   sumr   dotr   
isinstancestrr   r   infrA   rB   r1   
empty_likesizer   r   r   r   r   r,   r   rP   fillr   clipallisfiniter   r   r   r	   )?rY   rR   x0f0J0r3   r4   ftolxtolgtolmax_nfevx_scaleloss_function	tr_solver
tr_optionsverbosecallbackff_truer[   Jra   rhor\   rE   	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_freerD   rF   rG   r   lsmr_opr2   	step_freeon_bound_freerO   predicted_reductionx_newf_newstep_h_normcost_newratiomaskintermediate_results?                                                                  r"   dogboxr      sZ   
AVVXXFD
AD mARVCF^^#-aC8811RVAq\\!QA7C((=W-=I 0,Q//yy"AKyiRV,,,Ezz}Rs+++H!#HRXb"!"HRXb"
A=D7S=II!||   M\A%
;8*aRV$$$D==!"a<<%it=M&/9 9 9 )TX-=-=8X,X,8_
 qqq({^F"555a8K &ffvg>>DAqq&  "1%%C $C
;;G99j99!<XFFK:%K &c1qb11DAq!##x
*I/:VQ9gw0P 0P,I}f IIcNNN&DNG##'9&&:C(E (E 'E##f$$'9#q$'G'G&G# GAHb"--ECJJEAIDti/RV<<<K6"+e,,-- {* ((=$???u!5!55#h+')<V LE5
 T

I!2 $	477E4"O "O "-Y !##x\ a!.HXAr>DhAdGq=DhAdGAVVXXFDAAAID(#mA&&5aC@@1Q""A C#4Q	#B#B yI Q	 "0	#6 #6 #6*2'(-   &("[M^ !
$F64d;MO O O Or#   )N)__doc__numpyr.   numpy.linalgr   r   scipy.sparse.linalgr   r   r   scipy.optimizer   scipy._lib._utilr	   commonr   r   r   r   r   r   r   r   r   r   r   r   r,   r=   rP   r    r#   r"   <module>r      si  ) )T     $ $ $ $ $ $ $ $ F F F F F F F F F F ) ) ) ) ) ) 6 6 6 6 6 67 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7O O O*: : ::(C (C (CX DHBO BO BO BO BO BOr#   