def line_search(self,x,p,F,GradF,func,smax=np.inf,maxiter=40):
        """
        Finds steplength along search direction p that 
        satisfies the strong Wolfe conditions.
        
        Parameters
        ----------
        x : current point (ndarray)
        p : search direction (ndarray)
        F : function value at `x` (float)
        GradF : gradient of function at `x` (ndarray)
        func : function of `x` that returns function object with attributes `F` and `GradF` (function)
        smax : maximum allowed steplength (float)
           
        Returns
        -------
        s : stephlength that satisfies the Wolfe conditions (float).           
        """
        
        # Parameters of line search
        c1 = 1e-4
        c2 = 5e-1

        # Initialize lower bound, upper bound and step
        l = 0.
        if 1. < smax:
            s = 1.
        else:
            s = smax
        u = np.NaN        

        phi = F
        dphi = np.dot(GradF,p)
        
        # Check that p is descent direction
        if dphi >= 0:
            raise OptSolverError_BadSearchDir(self)

        # Bisection
        for i in range(0,maxiter):
            
            xsp = x+s*p
            
            fdata = func(xsp)
            phis = fdata.F
            dphis = np.dot(fdata.GradF,p)
            
            if phis > phi + c1*s*dphi:
                u = s
            elif dphis > 0 and dphis > -c2*dphi:
                u = s
            elif dphis < 0 and -dphis > -c2*dphi:
                l = s
                if s >= smax:
                    return s,fdata
            else:
                return s,fdata

            if np.isnan(u):
                s = np.min([2.*s,smax])
            else:
                s = (l + u)/2.

        raise OptSolverError_LineSearch(self)
def line_search ( self , x , p , F , GradF , func , smax = np . inf , maxiter = 40 ) : c1 = 1e-4 c2 = 5e-1 l = 0. if 1. < smax : s = 1. else : s = smax u = np . NaN phi = F dphi = np . dot ( GradF , p ) if dphi >= 0 : raise OptSolverError_BadSearchDir ( self ) for i in range ( 0 , maxiter ) : xsp = x + s * p fdata = func ( xsp ) phis = fdata . F dphis = np . dot ( fdata . GradF , p ) if phis > phi + c1 * s * dphi : u = s elif dphis > 0 and dphis > - c2 * dphi : u = s elif dphis < 0 and - dphis > - c2 * dphi : l = s if s >= smax : return s , fdata else : return s , fdata if np . isnan ( u ) : s = np . min ( [ 2. * s , smax ] ) else : s = ( l + u ) / 2. raise OptSolverError_LineSearch ( self )
Finds steplength along search direction p that 
        satisfies the strong Wolfe conditions.
        
        Parameters
        ----------
        x : current point (ndarray)
        p : search direction (ndarray)
        F : function value at `x` (float)
        GradF : gradient of function at `x` (ndarray)
        func : function of `x` that returns function object with attributes `F` and `GradF` (function)
        smax : maximum allowed steplength (float)
           
        Returns
        -------
        s : stephlength that satisfies the Wolfe conditions (float).