B
    &]\yg              	   @   s   d Z ddlmZmZmZ ddlmZ ddlmZ ddl	Z
ddlmZ ddd	d
ddgZG dd deZd,ddZd-dd
ZeZd.dd	Zd/ddZdd Zdd Zdd Zd0d dZd1d!d"Zd2d#d$Zd3d'd(Zd4d*d+ZdS )5z
Functions
---------
.. autosummary::
   :toctree: generated/

    line_search_armijo
    line_search_wolfe1
    line_search_wolfe2
    scalar_search_wolfe1
    scalar_search_wolfe2

    )divisionprint_functionabsolute_import)warn)minpack2N)xrangeLineSearchWarningline_search_wolfe1line_search_wolfe2scalar_search_wolfe1scalar_search_wolfe2line_search_armijoc               @   s   e Zd ZdS )r   N)__name__
__module____qualname__ r   r   8lib/python3.7/site-packages/scipy/optimize/linesearch.pyr      s   r   -C6??2   :0yE>+=c                s   |dkr	}t tr<d }d |f  dn d|gdgdg 	fdd}	fdd	}t|}t|||||||	|
||d

\}}}|d d ||d fS )a  
    As `scalar_search_wolfe1` but do a line search to direction `pk`

    Parameters
    ----------
    f : callable
        Function `f(x)`
    fprime : callable
        Gradient of `f`
    xk : array_like
        Current point
    pk : array_like
        Search direction

    gfk : array_like, optional
        Gradient of `f` at point `xk`
    old_fval : float, optional
        Value of `f` at point `xk`
    old_old_fval : float, optional
        Value of `f` at point preceding `xk`

    The rest of the parameters are the same as for `scalar_search_wolfe1`.

    Returns
    -------
    stp, f_count, g_count, fval, old_fval
        As in `line_search_wolfe1`
    gval : array
        Gradient of `f` at the final point

    N   r   FTc                s&   d  d7  < |   f  S )Nr   r   r   )s)argsffcpkxkr   r   phiU   s    zline_search_wolfe1.<locals>.phic                sX   |   f d< r0d  d7  < n d  t d 7  < td S )Nr   r   )lennpdot)r   )r   fprimegcgradientgvalnewargsr   r   r   r   derphiY   s
    z"line_search_wolfe1.<locals>.derphi)c1c2amaxaminxtol)
isinstancetupler!   r"   r   )r   r#   r   r   gfkold_fvalold_old_fvalr   r)   r*   r+   r,   r-   epsr   r(   derphi0stpZfvalr   )
r   r   r   r#   r$   r%   r&   r'   r   r   r   r	   "   s&    #

c
             C   s  |dkr| d}|dkr |d}|dk	rT|dkrTt dd||  | }
|
dk rXd}
nd}
|}|}tdtj}tdt}d}d	}xbt|D ]R}t|
|||||	|||||\}}}}|dd
 dkr|}
| |}||}qP qW d}|dd dks
|dd dkrd}|||fS )a  
    Scalar function search for alpha that satisfies strong Wolfe conditions

    alpha > 0 is assumed to be a descent direction.

    Parameters
    ----------
    phi : callable phi(alpha)
        Function at point `alpha`
    derphi : callable dphi(alpha)
        Derivative `d phi(alpha)/ds`. Returns a scalar.

    phi0 : float, optional
        Value of `f` at 0
    old_phi0 : float, optional
        Value of `f` at the previous point
    derphi0 : float, optional
        Value `derphi` at 0
    c1, c2 : float, optional
        Wolfe parameters
    amax, amin : float, optional
        Maximum and minimum step size
    xtol : float, optional
        Relative tolerance for an acceptable step.

    Returns
    -------
    alpha : float
        Step size, or None if no suitable step was found
    phi : float
        Value of `phi` at the new point `alpha`
    phi0 : float
        Value of `phi` at `alpha=0`

    Notes
    -----
    Uses routine DCSRCH from MINPACK.

    Ng        r   g      ?g)\( @)   )   s   STARTd   r6   s   FG   s   ERROR   s   WARN)minr!   ZzerosZintcfloatr   r   Zdcsrch)r   r(   phi0old_phi0r4   r)   r*   r+   r,   r-   alpha1phi1Zderphi1ZisaveZdsaveZtaskmaxiterir5   r   r   r   r   j   s8    +

$
   c                s  dgdgdgdg 
fdd}t 	trR 	
fddn	 
fdd|dkrf  }t|
}dk	r
fdd	}nd}t||||||	|
||d

\}}}}|dkrtdt nd }|d d |||fS )a	  Find alpha that satisfies strong Wolfe conditions.

    Parameters
    ----------
    f : callable f(x,*args)
        Objective function.
    myfprime : callable f'(x,*args)
        Objective function gradient.
    xk : ndarray
        Starting point.
    pk : ndarray
        Search direction.
    gfk : ndarray, optional
        Gradient value for x=xk (xk being the current parameter
        estimate). Will be recomputed if omitted.
    old_fval : float, optional
        Function value for x=xk. Will be recomputed if omitted.
    old_old_fval : float, optional
        Function value for the point preceding x=xk
    args : tuple, optional
        Additional arguments passed to objective function.
    c1 : float, optional
        Parameter for Armijo condition rule.
    c2 : float, optional
        Parameter for curvature condition rule.
    amax : float, optional
        Maximum step size
    extra_condition : callable, optional
        A callable of the form ``extra_condition(alpha, x, f, g)``
        returning a boolean. Arguments are the proposed step ``alpha``
        and the corresponding ``x``, ``f`` and ``g`` values. The line search 
        accepts the value of ``alpha`` only if this 
        callable returns ``True``. If the callable returns ``False`` 
        for the step length, the algorithm will continue with 
        new iterates. The callable is only called for iterates 
        satisfying the strong Wolfe conditions.
    maxiter : int, optional
        Maximum number of iterations to perform

    Returns
    -------
    alpha : float or None
        Alpha for which ``x_new = x0 + alpha * pk``,
        or None if the line search algorithm did not converge.
    fc : int
        Number of function evaluations made.
    gc : int
        Number of gradient evaluations made.
    new_fval : float or None
        New function value ``f(x_new)=f(x0+alpha*pk)``,
        or None if the line search algorithm did not converge.
    old_fval : float
        Old function value ``f(x0)``.
    new_slope : float or None
        The local slope along the search direction at the
        new value ``<myfprime(x_new), pk>``,
        or None if the line search algorithm did not converge.


    Notes
    -----
    Uses the line search algorithm to enforce strong Wolfe
    conditions.  See Wright and Nocedal, 'Numerical Optimization',
    1999, pg. 59-60.

    For the zoom phase it uses an algorithm by [...].

    r   Nc                s&   d  d7  < |   f  S )Nr   r   r   )alpha)r   r   r   r   r   r   r   r     s    zline_search_wolfe2.<locals>.phic                sf   d  t d 7  < d }d }|f  }||   f| d< | d< td S )Nr   r   )r    r!   r"   )rD   r3   r#   r'   )r   r   r   r&   
gval_alphamyfprimer   r   r   r   r(     s    z"line_search_wolfe2.<locals>.derphic                sB   d  d7  < |   f  d< | d< t d S )Nr   r   )r!   r"   )rD   )r   r#   r$   r&   rE   r   r   r   r   r(     s    c                s2   d | kr |  |   }| ||d S )Nr   r   )rD   r   x)r(   extra_conditionr&   rE   r   r   r   r   extra_condition2,  s    z,line_search_wolfe2.<locals>.extra_condition2)rA   z*The line search algorithm did not converge)r.   r/   r!   r"   r   r   r   )r   rF   r   r   r0   r1   r2   r   r)   r*   r+   rH   rA   r   r4   rI   
alpha_starphi_starderphi_starr   )r   r(   rH   r   r   r#   r$   r&   rE   rF   r   r   r   r
      s,    G
	c
             C   s  |dkr| d}|dkr(|dk	r(|d}d}
|dk	rT|dkrTt dd||  | }nd}|dk rdd}| |}|}|}|dkrdd }x`t|	D ]<}|dks|dk	r|
|krd}|}|}d}|dkrd}nd	d
|  }t|t P |||| |  ks||kr4|dkr4t|
||||| ||||||\}}}P ||}t|| | krj|||rj|}|}|}P |dkrt||
|||| ||||||\}}}P d| }|dk	rt ||}|}
|}|}| |}|}qW |}|}d}tdt ||||fS )a  Find alpha that satisfies strong Wolfe conditions.

    alpha > 0 is assumed to be a descent direction.

    Parameters
    ----------
    phi : callable f(x)
        Objective scalar function.
    derphi : callable f'(x), optional
        Objective function derivative (can be None)
    phi0 : float, optional
        Value of phi at s=0
    old_phi0 : float, optional
        Value of phi at previous point
    derphi0 : float, optional
        Value of derphi at s=0
    c1 : float, optional
        Parameter for Armijo condition rule.
    c2 : float, optional
        Parameter for curvature condition rule.
    amax : float, optional
        Maximum step size
    extra_condition : callable, optional
        A callable of the form ``extra_condition(alpha, phi_value)``
        returning a boolean. The line search accepts the value
        of ``alpha`` only if this callable returns ``True``.
        If the callable returns ``False`` for the step length,
        the algorithm will continue with new iterates.
        The callable is only called for iterates satisfying
        the strong Wolfe conditions.
    maxiter : int, optional
        Maximum number of iterations to perform

    Returns
    -------
    alpha_star : float or None
        Best alpha, or None if the line search algorithm did not converge.
    phi_star : float
        phi at alpha_star
    phi0 : float
        phi at 0
    derphi_star : float or None
        derphi at alpha_star, or None if the line search algorithm
        did not converge.

    Notes
    -----
    Uses the line search algorithm to enforce strong Wolfe
    conditions.  See Wright and Nocedal, 'Numerical Optimization',
    1999, pg. 59-60.

    For the zoom phase it uses an algorithm by [...].

    Ng        r   g      ?g)\( @c             S   s   dS )NTr   )rD   r   r   r   r   <lambda>  s    z&scalar_search_wolfe2.<locals>.<lambda>z7Rounding errors prevent the line search from convergingz4The line search algorithm could not find a solution zless than or equal to amax: %sr   r6   z*The line search algorithm did not converge)r;   r   r   r   _zoomabs)r   r(   r=   r>   r4   r)   r*   r+   rH   rA   alpha0r?   phi_a1phi_a0Z	derphi_a0rB   rJ   rK   rL   msgZ	derphi_a1alpha2r   r   r   r   D  st    ;





c          
   C   s*  t jdddd  y|}||  }||  }	||	 d ||	  }
t d}|	d |d< |d  |d< |	d  |d< |d |d	< t |t || ||  || ||	  g \}}||
 }||
 }|| d| |  }| | t | d|   }W n tk
r
   d
S X W d
Q R X t |s&d
S |S )z
    Finds the minimizer for a cubic polynomial that goes through the
    points (a,fa), (b,fb), and (c,fc) with derivative at a of fpa.

    If no minimizer can be found return None

    raise)divideoverinvalidr6   )r6   r6   )r   r   )r   r      )r   r   )r   r   N)	r!   errstateemptyr"   ZasarrayZflattensqrtArithmeticErrorisfinite)afafpabfbcr   CdbZdcZdenomZd1ABZradicalxminr   r   r   	_cubicmin  s,    

 rj   c       
   	   C   s   t jdddd\ y@|}|}|| d  }|| ||  ||  }| |d|   }	W n tk
rf   dS X W dQ R X t |	sdS |	S )z
    Finds the minimizer for a quadratic polynomial that goes through
    the points (a,fa), (b,fb) with derivative at a of fpa,

    rU   )rV   rW   rX   g      ?g       @N)r!   rZ   r]   r^   )
r_   r`   ra   rb   rc   Dre   rf   rh   ri   r   r   r   _quadmin  s    
rl   c             C   s  d}d}d}d}|}d}x~||  }|dk r8||  }}n
| | }}|dkrf|| }t | ||||||}|dks|dks||| ks||| k r|| }t| ||||}|dks||| ks||| k r| d|  }||}|||	| |  ks||kr
|}|}|}|}nn||}t||
 | kr@|||r@|}|}|}P |||   dkrd|}|}| }|}n|}| }|} |}|}|d7 }||krd}d}d}P qW |||fS )zG
    Part of the optimization algorithm in `scalar_search_wolfe2`.
    rC   r   g?g?Ng      ?r   )rj   rl   rO   )Za_loZa_hiZphi_loZphi_hiZ	derphi_lor   r(   r=   r4   r)   r*   rH   rA   rB   Zdelta1Zdelta2Zphi_recZa_recZdalphar_   rb   ZcchkZa_jZqchkZphi_ajZ	derphi_ajZa_starZval_starZvalprime_starr   r   r   rN   
  sb    

(  rN   r   c                sj   t dg fdd}|dkr6|d}	n|}	t |}
t||	|
||d\}}|d |fS )a  Minimize over alpha, the function ``f(xk+alpha pk)``.

    Parameters
    ----------
    f : callable
        Function to be minimized.
    xk : array_like
        Current point.
    pk : array_like
        Search direction.
    gfk : array_like
        Gradient of `f` at point `xk`.
    old_fval : float
        Value of `f` at point `xk`.
    args : tuple, optional
        Optional arguments.
    c1 : float, optional
        Value to control stopping criterion.
    alpha0 : scalar, optional
        Value of `alpha` at start of the optimization.

    Returns
    -------
    alpha
    f_count
    f_val_at_alpha

    Notes
    -----
    Uses the interpolation algorithm (Armijo backtracking) as suggested by
    Wright and Nocedal in 'Numerical Optimization', 1999, pg. 56-57

    r   c                s&   d  d7  < |   f  S )Nr   r   r   )r?   )r   r   r   r   r   r   r   r     s    zline_search_armijo.<locals>.phiNg        )r)   rP   )r!   Z
atleast_1dr"   scalar_search_armijo)r   r   r   r0   r1   r   r)   rP   r   r=   r4   rD   r@   r   )r   r   r   r   r   r   r   ^  s    "


c       	   
   C   s0   t | |||||||d}|d |d d|d fS )z8
    Compatibility wrapper for `line_search_armijo`
    )r   r)   rP   r   r   r6   )r   )	r   r   r   r0   r1   r   r)   rP   rr   r   r   line_search_BFGS  s    ro   c             C   s  | |}|||| |  kr$||fS | |d  d || ||   }| |}|||| |  krj||fS x&||kr|d |d  ||  }	|d || ||   |d || ||    }
|
|	 }
|d  || ||   |d || ||    }||	 }| t t|d d|
 |   d|
  }| |}|||| |  krT||fS || |d ksxd||  dk r|d }|}|}|}|}qnW d|fS )a(  Minimize over alpha, the function ``phi(alpha)``.

    Uses the interpolation algorithm (Armijo backtracking) as suggested by
    Wright and Nocedal in 'Numerical Optimization', 1999, pg. 56-57

    alpha > 0 is assumed to be a descent direction.

    Returns
    -------
    alpha
    phi1

    r6   g       @rY   g      @r   gQ?N)r!   r\   rO   )r   r=   r4   r)   rP   r,   rR   r?   rQ   Zfactorr_   rb   rT   Zphi_a2r   r   r   rm     s4    ",$rm   皙?      ?c             C   s  |d }t |}	d}
d}d}x||
|  }| |\}}||	| ||
d  |  krX|
}P |
d | |d|
 d |   }|||  }| |\}}||	| ||d  |  kr| }P |d | |d| d |   }t|||
 ||
 }
t||| || }qW ||||fS )a>  
    Nonmonotone backtracking line search as described in [1]_

    Parameters
    ----------
    f : callable
        Function returning a tuple ``(f, F)`` where ``f`` is the value
        of a merit function and ``F`` the residual.
    x_k : ndarray
        Initial position
    d : ndarray
        Search direction
    prev_fs : float
        List of previous merit function values. Should have ``len(prev_fs) <= M``
        where ``M`` is the nonmonotonicity window parameter.
    eta : float
        Allowed merit function increase, see [1]_
    gamma, tau_min, tau_max : float, optional
        Search parameters, see [1]_

    Returns
    -------
    alpha : float
        Step length
    xp : ndarray
        Next position
    fp : float
        Merit function value at next position
    Fp : ndarray
        Residual at next position

    References
    ----------
    [1] "Spectral residual method without gradient information for solving
        large-scale nonlinear systems of equations." W. La Cruz,
        J.M. Martinez, M. Raydan. Math. Comp. **75**, 1429 (2006).

    r   r6   )maxr!   clip)r   x_kdZprev_fsetagammatau_mintau_maxf_kZf_baralpha_palpha_mrD   xpfpFpalpha_tpalpha_tmr   r   r   _nonmonotone_line_search_cruz  s*    (  r   333333?c             C   s,  d}d}d}x|||  }| |\}}||| ||d  |  krH|}P |d | |d| d |   }|||  }| |\}}||| ||d  |  kr| }P |d | |d| d |   }t ||| |	| }t ||| |	| }qW |
| d }|
| ||  | | }|}||||||fS )a  
    Nonmonotone line search from [1]

    Parameters
    ----------
    f : callable
        Function returning a tuple ``(f, F)`` where ``f`` is the value
        of a merit function and ``F`` the residual.
    x_k : ndarray
        Initial position
    d : ndarray
        Search direction
    f_k : float
        Initial merit function value
    C, Q : float
        Control parameters. On the first iteration, give values
        Q=1.0, C=f_k
    eta : float
        Allowed merit function increase, see [1]_
    nu, gamma, tau_min, tau_max : float, optional
        Search parameters, see [1]_

    Returns
    -------
    alpha : float
        Step length
    xp : ndarray
        Next position
    fp : float
        Merit function value at next position
    Fp : ndarray
        Residual at next position
    C : float
        New value for the control parameter C
    Q : float
        New value for the control parameter Q

    References
    ----------
    .. [1] W. Cheng & D.-H. Li, ''A derivative-free nonmonotone line
           search and its application to the spectral residual
           method'', IMA J. Numer. Anal. 29, 814 (2009).

    r   r6   )r!   rt   )r   ru   rv   r{   re   Qrw   rx   ry   rz   Znur|   r}   rD   r~   r   r   r   r   ZQ_nextr   r   r   _nonmonotone_line_search_cheng!  s,    /  r   )	NNNr   r   r   r   r   r   )NNNr   r   r   r   r   )	NNNr   r   r   NNrC   )	NNNNr   r   NNrC   )r   r   r   )r   r   r   )r   r   r   )r   rp   rq   )r   rp   rq   r   )__doc__Z
__future__r   r   r   warningsr   Zscipy.optimizer   Znumpyr!   Zscipy._lib.sixr   __all__RuntimeWarningr   r	   r   Zline_searchr
   r   rj   rl   rN   r   ro   rm   r   r   r   r   r   r   <module>   sD      
E  
P  
   
 "T
4
	
?
H 