B
    &]\2                 @   s   d Z ddlmZmZmZ ddlZddlZddlm	Z	 ddl
mZ ddlmZmZ G dd	 d	eZdddZdddZdddZdd Zdd ZdS ) z,
Spectral Algorithm for Nonlinear Equations
    )divisionabsolute_importprint_functionN)OptimizeResult)_check_unknown_options   )_nonmonotone_line_search_cruz_nonmonotone_line_search_chengc               @   s   e Zd ZdS )_NoConvergenceN)__name__
__module____qualname__ r   r   7lib/python3.7/site-packages/scipy/optimize/_spectral.pyr
      s   r
   r   :0yE>Yn  F
   绽|=      ?cruzc       *   	      sB  t | |dkrtd|f d|
dkr6 fdd}
|dkrLfdd}fd	d
}dg}t| |||||\}}}}}d} |}||}tg|	}d} }d}d}x\||}|rtd|||f  |dk	r||| ||| | k rd}d}P t|d| kr"d| t| }nt||k r4|}| | }|
|||} yV|dkrrt	||||| d\}!}"}#}$n,|dkrt
|||||| d\}!}"}#}$}}W n tk
r   P Y nX |"| }%|$| }&t|%|%t|%|& }|"}|$}|#|dkr||# |d7 }qW t|||d}'t||}(t|'|||(|d |d})|)S )a  
    Solve nonlinear equation with the DF-SANE method

    Options
    -------
    ftol : float, optional
        Relative norm tolerance.
    fatol : float, optional
        Absolute norm tolerance.
        Algorithm terminates when ``||func(x)|| < fatol + ftol ||func(x_0)||``.
    fnorm : callable, optional
        Norm to use in the convergence check. If None, 2-norm is used.
    maxfev : int, optional
        Maximum number of function evaluations.
    disp : bool, optional
        Whether to print convergence process to stdout.
    eta_strategy : callable, optional
        Choice of the ``eta_k`` parameter, which gives slack for growth
        of ``||F||**2``.  Called as ``eta_k = eta_strategy(k, x, F)`` with
        `k` the iteration number, `x` the current iterate and `F` the current
        residual. Should satisfy ``eta_k > 0`` and ``sum(eta, k=0..inf) < inf``.
        Default: ``||F||**2 / (1 + k)**2``.
    sigma_eps : float, optional
        The spectral coefficient is constrained to ``sigma_eps < sigma < 1/sigma_eps``.
        Default: 1e-10
    sigma_0 : float, optional
        Initial spectral coefficient.
        Default: 1.0
    M : int, optional
        Number of iterates to include in the nonmonotonic line search.
        Default: 10
    line_search : {'cruz', 'cheng'}
        Type of line search to employ. 'cruz' is the original one defined in
        [Martinez & Raydan. Math. Comp. 75, 1429 (2006)], 'cheng' is
        a modified search defined in [Cheng & Li. IMA J. Numer. Anal. 29, 814 (2009)].
        Default: 'cruz'

    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).
    .. [2] W. La Cruz, Opt. Meth. Software, 29, 24 (2014).
    .. [3] W. Cheng, D.-H. Li. IMA J. Numer. Anal. **29**, 814 (2009).

    )chengr   z"Invalid value %r for 'line_search'   Nc                s    d|  d  S )Nr   r   r   )kxF)f_0r   r   eta_strategyL   s    z#_root_df_sane.<locals>.eta_strategyc                s    d  S )Ng      ?r   )r   )f_knexpr   r   fnormQ   s    z_root_df_sane.<locals>.fnormc                s   t j|   S )N)npZlinalgZnorm)r   )r   r   r   fmeritU   s    z_root_df_sane.<locals>.fmeritr   g      ?Fz&too many function evaluations requiredziter %d: ||F|| = %g, sigma = %gzsuccessful convergenceTr   r   )etar   )shape)r   ZsuccessmessageZfunnfevZnit)r   
ValueError
_wrap_funccollectionsdequeprintabsr!   Zsignr   r	   r
   Zvdotappend_wrap_resultr   )*funcx0argsZftolZfatolmaxfevr    callbackZdispMr   Z	sigma_epsZsigma_0Zline_searchZunknown_optionsr"   r&   fZx_kZx_shapeZF_k
is_complexr   Zsigma_kZF_0_normZprev_fsQCZ	convergedr%   ZF_k_normdr#   ZalphaZxpfpZFpZs_kZy_kr   r   resultr   )r   r   r   r   _root_df_sane   st    1



&


r<   c       	         s   t |}|jt |f   }t |p:t |}| }dd< |rx fdd}t|}t|}n fdd}|||||fS )a  
    Wrap a function and an initial value so that (i) complex values
    are wrapped to reals, and (ii) value for a merit function
    fmerit(x, f) is computed at the same time, (iii) iteration count
    is maintained and an exception is raised if it is exceeded.

    Parameters
    ----------
    func : callable
        Function to wrap
    x0 : ndarray
        Initial value
    fmerit : callable
        Merit function fmerit(f) for computing merit value from residual.
    nfev_list : list
        List to store number of evaluations in. Should be [0] in the beginning.
    maxfev : int
        Maximum number of evaluations before _NoConvergence is raised.
    args : tuple
        Extra arguments to func

    Returns
    -------
    wrap_func : callable
        Wrapped function, to be called as
        ``F, fp = wrap_func(x0)``
    x0_wrap : ndarray of float
        Wrapped initial value; raveled to 1D and complex
        values mapped to reals.
    x0_shape : tuple
        Shape of the initial value array
    f : float
        Merit function at F
    F : ndarray of float
        Residual at x0_wrap
    is_complex : bool
        Whether complex values were mapped to reals

    r   r   c                s`   d krt  d  d7  < t| }t|f   }t|}|}||fS )Nr   r   )r
   _real2complexreshaper!   asarrayravel_complex2real)r   zvr   r5   )r1   r"   r/   r2   	nfev_listx0_shaper   r   	wrap_func   s    z_wrap_func.<locals>.wrap_funcc                sT   d krt  d  d7  < | } t| f   }|}||fS )Nr   r   )r
   r>   r!   r?   r@   )r   r   r5   )r1   r"   r/   r2   rD   rE   r   r   rF      s    
)r!   r?   r$   r@   ZiscomplexobjrA   )	r/   r0   r"   rD   r2   r1   r   r6   rF   r   )r1   r"   r/   r2   rD   rE   r   r(      s    (


	r(   c             C   s(   |rt | }n| }|dk	r$||}|S )zA
    Convert from real to complex and reshape result arrays.
    N)r=   r>   )r;   r6   r$   rB   r   r   r   r.      s    

r.   c             C   s   t j| tdt jS )N)dtype)r!   ascontiguousarrayfloatviewZ
complex128)r   r   r   r   r=      s    r=   c             C   s   t j| tdt jS )N)rG   )r!   rH   complexrJ   Zfloat64)rB   r   r   r   rA     s    rA   )r   r   r   r   NNFr   Nr   r   r   )r   )N)__doc__Z
__future__r   r   r   r)   Znumpyr!   Zscipy.optimizer   Zscipy.optimize.optimizer   Z
linesearchr   r	   	Exceptionr
   r<   r(   r.   r=   rA   r   r   r   r   <module>   s     
 
J
