def _root_leastsq(func, x0, args=(), jac=None, col_deriv=0, xtol=1.49012e-08, ftol=1.49012e-08, gtol=0.0, maxiter=0, eps=0.0, factor=100, diag=None, **unknown_options): _check_unknown_options(unknown_options) x, cov_x, info, msg, ier = leastsq(func, x0, args=args, Dfun=jac, full_output=True, col_deriv=col_deriv, xtol=xtol, ftol=ftol, gtol=gtol, maxfev=maxiter, epsfcn=eps, factor=factor, diag=diag) sol = Result(x=x, message=msg, status=ier, success=ier in (1, 2, 3, 4), cov_x=cov_x, fun=info.pop('fvec')) sol.update(info) return sol
def _root_nonlin_solve(func, x0, args=(), jac=None, _callback=None, _method=None, nit=None, disp=False, maxiter=None, ftol=None, fatol=None, xtol=None, xatol=None, tol_norm=None, line_search='armijo', jac_options=None, **unknown_options): _check_unknown_options(unknown_options) f_tol = fatol f_rtol = ftol x_tol = xatol x_rtol = xtol verbose = disp if jac_options is None: jac_options = dict() jacobian = {'broyden1': nonlin.BroydenFirst, 'broyden2': nonlin.BroydenSecond, 'anderson': nonlin.Anderson, 'linearmixing': nonlin.LinearMixing, 'diagbroyden': nonlin.DiagBroyden, 'excitingmixing': nonlin.ExcitingMixing, 'krylov': nonlin.KrylovJacobian }[_method] if args: if jac == True: def f(x): return func(x, *args)[0] else: def f(x): return func(x, *args) else: f = func x, info = nonlin.nonlin_solve(f, x0, jacobian=jacobian(**jac_options), iter=nit, verbose=verbose, maxiter=maxiter, f_tol=f_tol, f_rtol=f_rtol, x_tol=x_tol, x_rtol=x_rtol, tol_norm=tol_norm, line_search=line_search, callback=_callback, full_output=True, raise_exception=False) sol = Result(x=x) sol.update(info) return sol
def _minimize_anneal(func, x0, args=(), schedule='fast', T0=None, Tf=1e-12, maxfev=None, maxaccept=None, maxiter=400, boltzmann=1.0, learn_rate=0.5, ftol=1e-6, quench=1.0, m=1.0, n=1.0, lower=-100, upper=100, dwell=50, disp=False, **unknown_options): """ Minimization of scalar function of one or more variables using the simulated annealing algorithm. Options for the simulated annealing algorithm are: disp : bool Set to True to print convergence messages. schedule : str Annealing schedule to use. One of: 'fast', 'cauchy' or 'boltzmann'. T0 : float Initial Temperature (estimated as 1.2 times the largest cost-function deviation over random points in the range). Tf : float Final goal temperature. maxfev : int Maximum number of function evaluations to make. maxaccept : int Maximum changes to accept. maxiter : int Maximum number of iterations to perform. boltzmann : float Boltzmann constant in acceptance test (increase for less stringent test at each temperature). learn_rate : float Scale constant for adjusting guesses. ftol : float Relative error in ``fun(x)`` acceptable for convergence. quench, m, n : float Parameters to alter fast_sa schedule. lower, upper : float or ndarray Lower and upper bounds on `x`. dwell : int The number of times to search the space at each temperature. This function is called by the `minimize` function with `method=anneal`. It is not supposed to be called directly. """ _check_unknown_options(unknown_options) maxeval = maxfev feps = ftol x0 = asarray(x0) lower = asarray(lower) upper = asarray(upper) schedule = eval(schedule + '_sa()') # initialize the schedule schedule.init(dims=shape(x0), func=func, args=args, boltzmann=boltzmann, T0=T0, learn_rate=learn_rate, lower=lower, upper=upper, m=m, n=n, quench=quench, dwell=dwell) current_state, last_state, best_state = _state(), _state(), _state() if T0 is None: x0 = schedule.getstart_temp(best_state) else: best_state.x = None best_state.cost = numpy.Inf last_state.x = asarray(x0).copy() fval = func(x0, *args) schedule.feval += 1 last_state.cost = fval if last_state.cost < best_state.cost: best_state.cost = fval best_state.x = asarray(x0).copy() schedule.T = schedule.T0 fqueue = [100, 300, 500, 700] iters = 0 while 1: for n in xrange(dwell): current_state.x = schedule.update_guess(last_state.x) current_state.cost = func(current_state.x, *args) schedule.feval += 1 dE = current_state.cost - last_state.cost if schedule.accept_test(dE): last_state.x = current_state.x.copy() last_state.cost = current_state.cost if last_state.cost < best_state.cost: best_state.x = last_state.x.copy() best_state.cost = last_state.cost schedule.update_temp() iters += 1 # Stopping conditions # 0) last saved values of f from each cooling step # are all very similar (effectively cooled) # 1) Tf is set and we are below it # 2) maxeval is set and we are past it # 3) maxiter is set and we are past it # 4) maxaccept is set and we are past it fqueue.append(squeeze(last_state.cost)) fqueue.pop(0) af = asarray(fqueue) * 1.0 if all(abs((af - af[0]) / af[0]) < feps): retval = 0 if abs(af[-1] - best_state.cost) > feps * 10: retval = 5 if disp: print "Warning: Cooled to %f at %s but this is not" \ % (squeeze(last_state.cost), str(squeeze(last_state.x))) \ + " the smallest point found." break if (Tf is not None) and (schedule.T < Tf): retval = 1 break if (maxeval is not None) and (schedule.feval > maxeval): retval = 2 break if (iters > maxiter): if disp: print "Warning: Maximum number of iterations exceeded." retval = 3 break if (maxaccept is not None) and (schedule.accepted > maxaccept): retval = 4 break result = Result(x=best_state.x, fun=best_state.cost, T=schedule.T, nfev=schedule.feval, nit=iters, accept=schedule.accepted, status=retval, success=(retval <= 1), message={ 0: 'Points no longer changing', 1: 'Cooled to final temperature', 2: 'Maximum function evaluations', 3: 'Maximum cooling iterations reached', 4: 'Maximum accepted query locations reached', 5: 'Final point not the minimum amongst ' 'encountered points' }[retval]) return result
def _minimize_tnc(fun, x0, args=(), jac=None, bounds=None, options=None): """ Minimize a scalar function of one or more variables using a truncated Newton (TNC) algorithm. Options for the TNC algorithm are: eps: float Step size used for numerical approximation of the jacobian. scale : list of floats Scaling factors to apply to each variable. If None, the factors are up-low for interval bounded variables and 1+|x] fo the others. Defaults to None offset : float Value to substract from each variable. If None, the offsets are (up+low)/2 for interval bounded variables and x for the others. disp : bool Set to True to print convergence messages. maxCGit : int Maximum number of hessian*vector evaluations per main iteration. If maxCGit == 0, the direction chosen is -gradient if maxCGit < 0, maxCGit is set to max(1,min(50,n/2)). Defaults to -1. maxfev : int Maximum number of function evaluation. if None, `maxfev` is set to max(100, 10*len(x0)). Defaults to None. eta : float Severity of the line search. if < 0 or > 1, set to 0.25. Defaults to -1. stepmx : float Maximum step for the line search. May be increased during call. If too small, it will be set to 10.0. Defaults to 0. accuracy : float Relative precision for finite difference calculations. If <= machine_precision, set to sqrt(machine_precision). Defaults to 0. minfev : float Minimum function value estimate. Defaults to 0. ftol : float Precision goal for the value of f in the stoping criterion. If ftol < 0.0, ftol is set to 0.0 defaults to -1. xtol : float Precision goal for the value of x in the stopping criterion (after applying x scaling factors). If xtol < 0.0, xtol is set to sqrt(machine_precision). Defaults to -1. pgtol : float Precision goal for the value of the projected gradient in the stopping criterion (after applying x scaling factors). If pgtol < 0.0, pgtol is set to 1e-2 * sqrt(accuracy). Setting it to 0.0 is not recommended. Defaults to -1. rescale : float Scaling factor (in log10) used to trigger f value rescaling. If 0, rescale at each iteration. If a large value, never rescale. If < 0, rescale is set to 1.3. This function is called by the `minimize` function with `method=TNC`. It is not supposed to be called directly. """ if options is None: options = {} # retrieve useful options epsilon = options.get('eps', 1e-8) scale = options.get('scale') offset = options.get('offset') mesg_num = options.get('mesg_num') maxCGit = options.get('maxCGit', -1) maxfun = options.get('maxfev') eta = options.get('eta', -1) stepmx = options.get('stepmx', 0) accuracy = options.get('accuracy', 0) fmin = options.get('minfev', 0) ftol = options.get('ftol', -1) xtol = options.get('xtol', -1) pgtol = options.get('pgtol', -1) rescale = options.get('rescale', -1) disp = options.get('disp', False) x0 = asarray(x0, dtype=float).tolist() n = len(x0) if bounds is None: bounds = [(None,None)] * n if len(bounds) != n: raise ValueError('length of x0 != length of bounds') if mesg_num is not None: messages = {0:MSG_NONE, 1:MSG_ITER, 2:MSG_INFO, 3:MSG_VERS, 4:MSG_EXIT, 5:MSG_ALL}.get(mesg_num, MSG_ALL) elif disp: messages = MSG_ALL else: messages = MSG_NONE if jac is None: def func_and_grad(x): x = asarray(x) f = fun(x, *args) g = approx_fprime(x, fun, epsilon, *args) return f, list(g) else: def func_and_grad(x): x = asarray(x) f = fun(x, *args) g = jac(x, *args) return f, list(g) """ low, up : the bounds (lists of floats) if low is None, the lower bounds are removed. if up is None, the upper bounds are removed. low and up defaults to None """ low = [0]*n up = [0]*n for i in range(n): if bounds[i] is None: l, u = -inf, inf else: l,u = bounds[i] if l is None: low[i] = -inf else: low[i] = l if u is None: up[i] = inf else: up[i] = u if scale is None: scale = [] if offset is None: offset = [] if maxfun is None: maxfun = max(100, 10*len(x0)) rc, nf, x = moduleTNC.minimize(func_and_grad, x0, low, up, scale, offset, messages, maxCGit, maxfun, eta, stepmx, accuracy, fmin, ftol, xtol, pgtol, rescale) xopt = array(x) funv, jacv = func_and_grad(xopt) return Result(x=xopt, fun=funv, jac=jacv, nfev=nf, status=rc, message=RCSTRINGS[rc], success=(-1 < rc < 3))
def _minimize_cobyla(fun, x0, args=(), constraints=(), options=None): """ Minimize a scalar function of one or more variables using the Constrained Optimization BY Linear Approximation (COBYLA) algorithm. Options for the COBYLA algorithm are: rhobeg : float Reasonable initial changes to the variables. rhoend : float Final accuracy in the optimization (not precisely guaranteed). This is a lower bound on the size of the trust region. disp : bool Set to True to print convergence messages. If False, `verbosity` is ignored as set to 0. maxfev : int Maximum number of function evaluations. This function is called by the `minimize` function with `method=COBYLA`. It is not supposed to be called directly. """ if options is None: options = {} # retrieve useful options rhobeg = options.get('rhobeg', 1.0) rhoend = options.get('rhoend', 1e-4) iprint = options.get('iprint', 1) maxfun = options.get('maxfev', 1000) disp = options.get('disp', False) if not disp: iprint = 0 # check constraints if isinstance(constraints, dict): constraints = (constraints, ) for ic, con in enumerate(constraints): # check type try: ctype = con['type'].lower() except KeyError: raise KeyError('Constraint %d has no type defined.' % ic) except TypeError: raise TypeError('Constraints must be defined using a ' 'dictionary.') except AttributeError: raise TypeError("Constraint's type must be a string.") else: if ctype != 'ineq': raise ValueError("Constraints of type '%s' not handled by " "COBYLA." % con['type']) # check function if 'fun' not in con: raise KeyError('Constraint %d has no function defined.' % ic) # check extra arguments if 'args' not in con: con['args'] = () m = len(constraints) def calcfc(x, con): f = fun(x, *args) for k, c in enumerate(constraints): con[k] = c['fun'](x, *c['args']) return f xopt = _cobyla.minimize(calcfc, m=m, x=copy(x0), rhobeg=rhobeg, rhoend=rhoend, iprint=iprint, maxfun=maxfun) return Result(x=xopt)
def _minimize_slsqp(func, x0, args=(), jac=None, bounds=None, constraints=(), maxiter=100, ftol=1.0E-6, iprint=1, disp=False, eps=_epsilon, **unknown_options): """ Minimize a scalar function of one or more variables using Sequential Least SQuares Programming (SLSQP). Options for the SLSQP algorithm are: ftol : float Precision goal for the value of f in the stopping criterion. eps : float Step size used for numerical approximation of the jacobian. disp : bool Set to True to print convergence messages. If False, `verbosity` is ignored and set to 0. maxiter : int Maximum number of iterations. This function is called by the `minimize` function with `method=SLSQP`. It is not supposed to be called directly. """ _check_unknown_options(unknown_options) fprime = jac iter = maxiter acc = ftol epsilon = eps if not disp: iprint = 0 # Constraints are triaged per type into a dictionnary of tuples if isinstance(constraints, dict): constraints = (constraints, ) cons = {'eq': (), 'ineq': ()} for ic, con in enumerate(constraints): # check type try: ctype = con['type'].lower() except KeyError: raise KeyError('Constraint %d has no type defined.' % ic) except TypeError: raise TypeError('Constraints must be defined using a ' 'dictionary.') except AttributeError: raise TypeError("Constraint's type must be a string.") else: if ctype not in ['eq', 'ineq']: raise ValueError("Unknown constraint type '%s'." % con['type']) # check function if 'fun' not in con: raise ValueError('Constraint %d has no function defined.' % ic) # check jacobian cjac = con.get('jac') if cjac is None: # approximate jacobian function def cjac(x, *args): return approx_jacobian(x, con['fun'], epsilon, *args) # update constraints' dictionary cons[ctype] += ({'fun' : con['fun'], 'jac' : cjac, 'args': con.get('args', ())}, ) exit_modes = { -1 : "Gradient evaluation required (g & a)", 0 : "Optimization terminated successfully.", 1 : "Function evaluation required (f & c)", 2 : "More equality constraints than independent variables", 3 : "More than 3*n iterations in LSQ subproblem", 4 : "Inequality constraints incompatible", 5 : "Singular matrix E in LSQ subproblem", 6 : "Singular matrix C in LSQ subproblem", 7 : "Rank-deficient equality constraint subproblem HFTI", 8 : "Positive directional derivative for linesearch", 9 : "Iteration limit exceeded" } # Wrap func feval, func = wrap_function(func, args) # Wrap fprime, if provided, or approx_jacobian if not if fprime: geval, fprime = wrap_function(fprime, args) else: geval, fprime = wrap_function(approx_jacobian, (func, epsilon)) # Transform x0 into an array. x = asfarray(x0).flatten() # Set the parameters that SLSQP will need # meq, mieq: number of equality and inequality constraints meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['eq']])) mieq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['ineq']])) # m = The total number of constraints m = meq + mieq # la = The number of constraints, or 1 if there are no constraints la = array([1,m]).max() # n = The number of independent variables n = len(x) # Define the workspaces for SLSQP n1 = n+1 mineq = m - meq + n1 + n1 len_w = (3*n1+m)*(n1+1)+(n1-meq+1)*(mineq+2) + 2*mineq+(n1+mineq)*(n1-meq) \ + 2*meq + n1 +(n+1)*n/2 + 2*m + 3*n + 3*n1 + 1 len_jw = mineq w = zeros(len_w) jw = zeros(len_jw) # Decompose bounds into xl and xu if bounds is None or len(bounds) == 0: xl, xu = array([-1.0E12]*n), array([1.0E12]*n) else: bnds = array(bounds, float) if bnds.shape[0] != n: raise IndexError('SLSQP Error: the length of bounds is not ' 'compatible with that of x0.') bnderr = where(bnds[:, 0] > bnds[:, 1])[0] if bnderr.any(): raise ValueError('SLSQP Error: lb > ub in bounds %s.' % ', '.join(str(b) for b in bnderr)) xl, xu = bnds[:, 0], bnds[:, 1] # filter -inf and inf values infbnd = isinf(bnds) xl[infbnd[:, 0]] = -1.0E12 xu[infbnd[:, 1]] = 1.0E12 # Initialize the iteration counter and the mode value mode = array(0,int) acc = array(acc,float) majiter = array(iter,int) majiter_prev = 0 # Print the header if iprint >= 2 if iprint >= 2: print "%5s %5s %16s %16s" % ("NIT","FC","OBJFUN","GNORM") while 1: if mode == 0 or mode == 1: # objective and constraint evaluation requird # Compute objective function fx = func(x) # Compute the constraints if cons['eq']: c_eq = concatenate([atleast_1d(con['fun'](x, *con['args'])) for con in cons['eq']]) else: c_eq = zeros(0) if cons['ineq']: c_ieq = concatenate([atleast_1d(con['fun'](x, *con['args'])) for con in cons['ineq']]) else: c_ieq = zeros(0) # Now combine c_eq and c_ieq into a single matrix c = concatenate((c_eq, c_ieq)) if mode == 0 or mode == -1: # gradient evaluation required # Compute the derivatives of the objective function # For some reason SLSQP wants g dimensioned to n+1 g = append(fprime(x),0.0) # Compute the normals of the constraints if cons['eq']: a_eq = vstack([con['jac'](x, *con['args']) for con in cons['eq']]) else: # no equality constraint a_eq = zeros((meq, n)) if cons['ineq']: a_ieq = vstack([con['jac'](x, *con['args']) for con in cons['ineq']]) else: # no inequality constraint a_ieq = zeros((mieq, n)) # Now combine a_eq and a_ieq into a single a matrix if m == 0: # no constraints a = zeros((la, n)) else: a = vstack((a_eq, a_ieq)) a = concatenate((a,zeros([la,1])),1) # Call SLSQP slsqp(m, meq, x, xl, xu, fx, c, g, a, acc, majiter, mode, w, jw) # Print the status of the current iterate if iprint > 2 and the # major iteration has incremented if iprint >= 2 and majiter > majiter_prev: print "%5i %5i % 16.6E % 16.6E" % (majiter,feval[0], fx,linalg.norm(g)) # If exit mode is not -1 or 1, slsqp has completed if abs(mode) != 1: break majiter_prev = int(majiter) # Optimization loop complete. Print status if requested if iprint >= 1: print exit_modes[int(mode)] + " (Exit mode " + str(mode) + ')' print " Current function value:", fx print " Iterations:", majiter print " Function evaluations:", feval[0] print " Gradient evaluations:", geval[0] return Result(x=x, fun=fx, jac=g, nit=int(majiter), nfev=feval[0], njev=geval[0], status=int(mode), message=exit_modes[int(mode)], success=(mode == 0))
def _root_nonlin_solve(func, x0, args=(), jac=None, _callback=None, _method=None, nit=None, disp=False, maxiter=None, ftol=None, fatol=None, xtol=None, xatol=None, tol_norm=None, line_search='armijo', jac_options=None, **unknown_options): _check_unknown_options(unknown_options) f_tol = fatol f_rtol = ftol x_tol = xatol x_rtol = xtol verbose = disp if jac_options is None: jac_options = dict() jacobian = { 'broyden1': nonlin.BroydenFirst, 'broyden2': nonlin.BroydenSecond, 'anderson': nonlin.Anderson, 'linearmixing': nonlin.LinearMixing, 'diagbroyden': nonlin.DiagBroyden, 'excitingmixing': nonlin.ExcitingMixing, 'krylov': nonlin.KrylovJacobian }[_method] if args: if jac == True: def f(x): return func(x, *args)[0] else: def f(x): return func(x, *args) else: f = func x, info = nonlin.nonlin_solve(f, x0, jacobian=jacobian(**jac_options), iter=nit, verbose=verbose, maxiter=maxiter, f_tol=f_tol, f_rtol=f_rtol, x_tol=x_tol, x_rtol=x_rtol, tol_norm=tol_norm, line_search=line_search, callback=_callback, full_output=True, raise_exception=False) sol = Result(x=x) sol.update(info) return sol
def _minimize_cobyla(fun, x0, args=(), constraints=(), rhobeg=1.0, tol=1e-4, iprint=1, maxiter=1000, disp=False, **unknown_options): """ Minimize a scalar function of one or more variables using the Constrained Optimization BY Linear Approximation (COBYLA) algorithm. Options for the COBYLA algorithm are: rhobeg : float Reasonable initial changes to the variables. tol : float Final accuracy in the optimization (not precisely guaranteed). This is a lower bound on the size of the trust region. disp : bool Set to True to print convergence messages. If False, `verbosity` is ignored as set to 0. maxiter : int Maximum number of function evaluations. This function is called by the `minimize` function with `method=COBYLA`. It is not supposed to be called directly. """ _check_unknown_options(unknown_options) maxfun = maxiter rhoend = tol if not disp: iprint = 0 # check constraints if isinstance(constraints, dict): constraints = (constraints, ) for ic, con in enumerate(constraints): # check type try: ctype = con['type'].lower() except KeyError: raise KeyError('Constraint %d has no type defined.' % ic) except TypeError: raise TypeError('Constraints must be defined using a ' 'dictionary.') except AttributeError: raise TypeError("Constraint's type must be a string.") else: if ctype != 'ineq': raise ValueError("Constraints of type '%s' not handled by " "COBYLA." % con['type']) # check function if 'fun' not in con: raise KeyError('Constraint %d has no function defined.' % ic) # check extra arguments if 'args' not in con: con['args'] = () m = len(constraints) def calcfc(x, con): f = fun(x, *args) for k, c in enumerate(constraints): con[k] = c['fun'](x, *c['args']) return f info = np.zeros(4, np.float64) xopt, info = _cobyla.minimize(calcfc, m=m, x=np.copy(x0), rhobeg=rhobeg, rhoend=rhoend, iprint=iprint, maxfun=maxfun, dinfo=info) return Result(x=xopt, status=int(info[0]), success=info[0] == 1, message={ 1: 'Optimization terminated successfully.', 2: 'Maximum number of function evaluations has ' 'been exceeded.', 3: 'Rounding errors are becoming damaging in ' 'COBYLA subroutine.' }.get(info[0], 'Unknown exit status.'), nfev=int(info[1]), fun=info[2], maxcv=info[3])
def _root_hybr(func, x0, args=(), jac=None, col_deriv=0, xtol=1.49012e-08, maxfev=0, band=None, eps=0.0, factor=100, diag=None, full_output=0, **unknown_options): """ Find the roots of a multivariate function using MINPACK's hybrd and hybrj routines (modified Powell method). Options for the hybrd algorithm are: col_deriv : bool Specify whether the Jacobian function computes derivatives down the columns (faster, because there is no transpose operation). xtol : float The calculation will terminate if the relative error between two consecutive iterates is at most `xtol`. maxfev : int The maximum number of calls to the function. If zero, then ``100*(N+1)`` is the maximum where N is the number of elements in `x0`. band : tuple If set to a two-sequence containing the number of sub- and super-diagonals within the band of the Jacobi matrix, the Jacobi matrix is considered banded (only for ``fprime=None``). eps : float A suitable step length for the forward-difference approximation of the Jacobian (for ``fprime=None``). If `eps` is less than the machine precision, it is assumed that the relative errors in the functions are of the order of the machine precision. factor : float A parameter determining the initial step bound (``factor * || diag * x||``). Should be in the interval ``(0.1, 100)``. diag : sequence N positive entries that serve as a scale factors for the variables. This function is called by the `root` function with `method=hybr`. It is not supposed to be called directly. """ _check_unknown_options(unknown_options) epsfcn = eps x0 = array(x0, ndmin=1) n = len(x0) if type(args) != type(()): args = (args,) _check_func('fsolve', 'func', func, x0, args, n, (n,)) Dfun = jac if Dfun is None: if band is None: ml, mu = -10,-10 else: ml, mu = band[:2] if (maxfev == 0): maxfev = 200*(n + 1) retval = _minpack._hybrd(func, x0, args, 1, xtol, maxfev, ml, mu, epsfcn, factor, diag) else: _check_func('fsolve', 'fprime', Dfun, x0, args, n, (n,n)) if (maxfev == 0): maxfev = 100*(n + 1) retval = _minpack._hybrj(func, Dfun, x0, args, 1, col_deriv, xtol, maxfev, factor,diag) x, status = retval[0], retval[-1] errors = {0:["Improper input parameters were entered.",TypeError], 1:["The solution converged.", None], 2:["The number of calls to function has " "reached maxfev = %d." % maxfev, ValueError], 3:["xtol=%f is too small, no further improvement " "in the approximate\n solution " "is possible." % xtol, ValueError], 4:["The iteration is not making good progress, as measured " "by the \n improvement from the last five " "Jacobian evaluations.", ValueError], 5:["The iteration is not making good progress, " "as measured by the \n improvement from the last " "ten iterations.", ValueError], 'unknown': ["An error occurred.", TypeError]} if status != 1 and not full_output: if status in [2,3,4,5]: msg = errors[status][0] warnings.warn(msg, RuntimeWarning) else: try: raise errors[status][1](errors[status][0]) except KeyError: raise errors['unknown'][1](errors['unknown'][0]) info = retval[1] info['fun'] = info.pop('fvec') sol = Result(x=x, success=(status==1), status=status) sol.update(info) try: sol['message'] = errors[status][0] except KeyError: info['message'] = errors['unknown'][0] return sol
def _root_hybr(func, x0, args=(), jac=None, col_deriv=0, xtol=1.49012e-08, maxfev=0, band=None, eps=0.0, factor=100, diag=None, full_output=0, **unknown_options): """ Find the roots of a multivariate function using MINPACK's hybrd and hybrj routines (modified Powell method). Options for the hybrd algorithm are: col_deriv : bool Specify whether the Jacobian function computes derivatives down the columns (faster, because there is no transpose operation). xtol : float The calculation will terminate if the relative error between two consecutive iterates is at most `xtol`. maxfev : int The maximum number of calls to the function. If zero, then ``100*(N+1)`` is the maximum where N is the number of elements in `x0`. band : tuple If set to a two-sequence containing the number of sub- and super-diagonals within the band of the Jacobi matrix, the Jacobi matrix is considered banded (only for ``fprime=None``). eps : float A suitable step length for the forward-difference approximation of the Jacobian (for ``fprime=None``). If `eps` is less than the machine precision, it is assumed that the relative errors in the functions are of the order of the machine precision. factor : float A parameter determining the initial step bound (``factor * || diag * x||``). Should be in the interval ``(0.1, 100)``. diag : sequence N positive entries that serve as a scale factors for the variables. This function is called by the `root` function with `method=hybr`. It is not supposed to be called directly. """ _check_unknown_options(unknown_options) epsfcn = eps x0 = array(x0, ndmin=1) n = len(x0) if type(args) != type(()): args = (args, ) _check_func('fsolve', 'func', func, x0, args, n, (n, )) Dfun = jac if Dfun is None: if band is None: ml, mu = -10, -10 else: ml, mu = band[:2] if (maxfev == 0): maxfev = 200 * (n + 1) retval = _minpack._hybrd(func, x0, args, 1, xtol, maxfev, ml, mu, epsfcn, factor, diag) else: _check_func('fsolve', 'fprime', Dfun, x0, args, n, (n, n)) if (maxfev == 0): maxfev = 100 * (n + 1) retval = _minpack._hybrj(func, Dfun, x0, args, 1, col_deriv, xtol, maxfev, factor, diag) x, status = retval[0], retval[-1] errors = { 0: ["Improper input parameters were entered.", TypeError], 1: ["The solution converged.", None], 2: [ "The number of calls to function has " "reached maxfev = %d." % maxfev, ValueError ], 3: [ "xtol=%f is too small, no further improvement " "in the approximate\n solution " "is possible." % xtol, ValueError ], 4: [ "The iteration is not making good progress, as measured " "by the \n improvement from the last five " "Jacobian evaluations.", ValueError ], 5: [ "The iteration is not making good progress, " "as measured by the \n improvement from the last " "ten iterations.", ValueError ], 'unknown': ["An error occurred.", TypeError] } if status != 1 and not full_output: if status in [2, 3, 4, 5]: msg = errors[status][0] warnings.warn(msg, RuntimeWarning) else: try: raise errors[status][1](errors[status][0]) except KeyError: raise errors['unknown'][1](errors['unknown'][0]) info = retval[1] info['fun'] = info.pop('fvec') sol = Result(x=x, success=(status == 1), status=status) sol.update(info) try: sol['message'] = errors[status][0] except KeyError: info['message'] = errors['unknown'][0] return sol
def _minimize_lbfgsb(fun, x0, args=(), jac=None, bounds=None, disp=None, maxcor=10, ftol=2.2204460492503131e-09, gtol=1e-5, eps=1e-8, maxfun=15000, maxiter=15000, iprint=-1, callback=None, **unknown_options): """ Minimize a scalar function of one or more variables using the L-BFGS-B algorithm. Options for the L-BFGS-B algorithm are: disp : bool Set to True to print convergence messages. maxcor : int The maximum number of variable metric corrections used to define the limited memory matrix. (The limited memory BFGS method does not store the full hessian but uses this many terms in an approximation to it.) factr : float The iteration stops when ``(f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr * eps``, where ``eps`` is the machine precision, which is automatically generated by the code. Typical values for `factr` are: 1e12 for low accuracy; 1e7 for moderate accuracy; 10.0 for extremely high accuracy. gtol : float The iteration will stop when ``max{|proj g_i | i = 1, ..., n} <= gtol`` where ``pg_i`` is the i-th component of the projected gradient. eps : float Step size used for numerical approximation of the jacobian. disp : int Set to True to print convergence messages. maxfun : int Maximum number of function evaluations. maxiter : int Maximum number of iterations. This function is called by the `minimize` function with `method=L-BFGS-B`. It is not supposed to be called directly. """ _check_unknown_options(unknown_options) m = maxcor epsilon = eps pgtol = gtol factr = ftol / np.finfo(float).eps x0 = asarray(x0).ravel() n, = x0.shape if bounds is None: bounds = [(None, None)] * n if len(bounds) != n: raise ValueError('length of x0 != length of bounds') if disp is not None: if disp == 0: iprint = -1 else: iprint = disp if jac is None: def func_and_grad(x): f = fun(x, *args) g = approx_fprime(x, fun, epsilon, *args) return f, g else: def func_and_grad(x): f = fun(x, *args) g = jac(x, *args) return f, g nbd = zeros(n, int32) low_bnd = zeros(n, float64) upper_bnd = zeros(n, float64) bounds_map = {(None, None): 0, (1, None): 1, (1, 1): 2, (None, 1): 3} for i in range(0, n): l, u = bounds[i] if l is not None: low_bnd[i] = l l = 1 if u is not None: upper_bnd[i] = u u = 1 nbd[i] = bounds_map[l, u] x = array(x0, float64) f = array(0.0, float64) g = zeros((n, ), float64) wa = zeros(2 * m * n + 5 * n + 11 * m * m + 8 * m, float64) iwa = zeros(3 * n, int32) task = zeros(1, 'S60') csave = zeros(1, 'S60') lsave = zeros(4, int32) isave = zeros(44, int32) dsave = zeros(29, float64) task[:] = 'START' n_function_evals = 0 n_iterations = 0 while 1: # x, f, g, wa, iwa, task, csave, lsave, isave, dsave = \ _lbfgsb.setulb(m, x, low_bnd, upper_bnd, nbd, f, g, factr, pgtol, wa, iwa, task, iprint, csave, lsave, isave, dsave) task_str = task.tostring() if task_str.startswith(asbytes('FG')): if n_function_evals > maxfun: task[:] = 'STOP: TOTAL NO. of f AND g EVALUATIONS EXCEEDS LIMIT' else: # minimization routine wants f and g at the current x n_function_evals += 1 # Overwrite f and g: f, g = func_and_grad(x) elif task_str.startswith(asbytes('NEW_X')): # new iteration if n_iterations > maxiter: task[:] = 'STOP: TOTAL NO. of ITERATIONS EXCEEDS LIMIT' else: n_iterations += 1 if callback is not None: callback(x) else: break task_str = task.tostring().strip(asbytes('\x00')).strip() if task_str.startswith(asbytes('CONV')): warnflag = 0 elif n_function_evals > maxfun: warnflag = 1 elif n_iterations > maxiter: warnflag = 1 else: warnflag = 2 return Result(fun=f, jac=g, nfev=n_function_evals, nit=n_iterations, status=warnflag, message=task_str, x=x, success=(warnflag == 0))
def root(fun, x0, args=(), method="hybr", jac=None, options=None, callback=None): """ Find a root of a vector function. .. versionadded:: 0.11.0 Parameters ---------- fun : callable A vector function to find a root of. x0 : ndarray Initial guess. args : tuple, optional Extra arguments passed to the objective function and its Jacobian. method : str, optional Type of solver. Should be one of - 'hybr' - 'lm' - 'broyden1' - 'broyden2' - 'anderson' - 'linearmixing' - 'diagbroyden' - 'excitingmixing' - 'krylov' jac : bool or callable, optional If `jac` is a Boolean and is True, `fun` is assumed to return the value of Jacobian along with the objective function. If False, the Jacobian will be estimated numerically. `jac` can also be a callable returning the Jacobian of `fun`. In this case, it must accept the same arguments as `fun`. options : dict, optional A dictionary of solver options. E.g. `xtol` or `maxiter`, see ``show_options('root', method)`` for details. callback : function, optional Optional callback function. It is called on every iteration as ``callback(x, f)`` where `x` is the current solution and `f` the corresponding residual. For all methods but 'hybr' and 'lm'. Returns ------- sol : Result The solution represented as a ``Result`` object. Important attributes are: ``x`` the solution array, ``success`` a Boolean flag indicating if the algorithm exited successfully and ``message`` which describes the cause of the termination. See `Result` for a description of other attributes. Notes ----- This section describes the available solvers that can be selected by the 'method' parameter. The default method is *hybr*. Method *hybr* uses a modification of the Powell hybrid method as implemented in MINPACK [1]_. Method *lm* solves the system of nonlinear equations in a least squares sense using a modification of the Levenberg-Marquardt algorithm as implemented in MINPACK [1]_. Methods *broyden1*, *broyden2*, *anderson*, *linearmixing*, *diagbroyden*, *excitingmixing*, *krylov* are inexact Newton methods, with backtracking or full line searches [2]_. Each method corresponds to a particular Jacobian approximations. See `nonlin` for details. - Method *broyden1* uses Broyden's first Jacobian approximation, it is known as Broyden's good method. - Method *broyden2* uses Broyden's second Jacobian approximation, it is known as Broyden's bad method. - Method *anderson* uses (extended) Anderson mixing. - Method *Krylov* uses Krylov approximation for inverse Jacobian. It is suitable for large-scale problem. - Method *diagbroyden* uses diagonal Broyden Jacobian approximation. - Method *linearmixing* uses a scalar Jacobian approximation. - Method *excitingmixing* uses a tuned diagonal Jacobian approximation. .. warning:: The algorithms implemented for methods *diagbroyden*, *linearmixing* and *excitingmixing* may be useful for specific problems, but whether they will work may depend strongly on the problem. References ---------- .. [1] More, Jorge J., Burton S. Garbow, and Kenneth E. Hillstrom. 1980. User Guide for MINPACK-1. .. [2] C. T. Kelley. 1995. Iterative Methods for Linear and Nonlinear Equations. Society for Industrial and Applied Mathematics. <http://www.siam.org/books/kelley/> Examples -------- The following functions define a system of nonlinear equations and its jacobian. >>> def fun(x): ... return [x[0] + 0.5 * (x[0] - x[1])**3 - 1.0, ... 0.5 * (x[1] - x[0])**3 + x[1]] >>> def jac(x): ... return np.array([[1 + 1.5 * (x[0] - x[1])**2, ... -1.5 * (x[0] - x[1])**2], ... [-1.5 * (x[1] - x[0])**2, ... 1 + 1.5 * (x[1] - x[0])**2]]) A solution can be obtained as follows. >>> from scipy import optimize >>> sol = optimize.root(fun, [0, 0], jac=jac, method='hybr') >>> sol.x array([ 0.8411639, 0.1588361]) """ meth = method.lower() if options is None: options = {} if callback is not None and meth in ("hybr", "lm"): warn("Method %s does not accept callback." % method, RuntimeWarning) # fun also returns the jacobian if not callable(jac) and meth in ("hybr", "lm"): if bool(jac): fun = MemoizeJac(fun) jac = fun.derivative else: jac = None if meth == "hybr": sol = _root_hybr(fun, x0, args=args, jac=jac, options=options) elif meth == "lm": col_deriv = options.get("col_deriv", 0) xtol = options.get("xtol", 1.49012e-08) ftol = options.get("ftol", 1.49012e-08) gtol = options.get("gtol", 0.0) maxfev = options.get("maxfev", 0) epsfcn = options.get("epsfcn", 0.0) factor = options.get("factor", 100) diag = options.get("diag", None) x, cov_x, info, msg, ier = leastsq( fun, x0, args=args, Dfun=jac, full_output=True, col_deriv=col_deriv, xtol=xtol, ftol=ftol, gtol=gtol, maxfev=maxfev, epsfcn=epsfcn, factor=factor, diag=diag, ) sol = Result(x=x, message=msg, status=ier, success=ier in (1, 2, 3, 4), cov_x=cov_x, fun=info.pop("fvec")) sol.update(info) elif meth in ("broyden1", "broyden2", "anderson", "linearmixing", "diagbroyden", "excitingmixing", "krylov"): if jac is not None: warn("Method %s does not use the jacobian (jac)." % method, RuntimeWarning) jacobian = { "broyden1": nonlin.BroydenFirst, "broyden2": nonlin.BroydenSecond, "anderson": nonlin.Anderson, "linearmixing": nonlin.LinearMixing, "diagbroyden": nonlin.DiagBroyden, "excitingmixing": nonlin.ExcitingMixing, "krylov": nonlin.KrylovJacobian, }[meth] nit = options.get("nit") verbose = options.get("disp", False) maxiter = options.get("maxiter") f_tol = options.get("ftol") f_rtol = options.get("frtol") x_tol = options.get("xtol") x_rtol = options.get("xrtol") tol_norm = options.get("tol_norm") line_search = options.get("line_search", "armijo") jac_opts = options.get("jac_options", dict()) if args: def f(x): if jac == True: r = fun(x, *args)[0] else: r = fun(x, *args) return r else: f = fun x, info = nonlin.nonlin_solve( f, x0, jacobian=jacobian(**jac_opts), iter=nit, verbose=verbose, maxiter=maxiter, f_tol=f_tol, f_rtol=f_rtol, x_tol=x_tol, x_rtol=x_rtol, tol_norm=tol_norm, line_search=line_search, callback=callback, full_output=True, raise_exception=False, ) sol = Result(x=x) sol.update(info) else: raise ValueError("Unknown solver %s" % method) return sol
def root(fun, x0, args=(), method='hybr', jac=None, options=None, callback=None): """ Find a root of a vector function. .. versionadded:: 0.11.0 Parameters ---------- fun : callable A vector function to find a root of. x0 : ndarray Initial guess. args : tuple, optional Extra arguments passed to the objective function and its Jacobian. method : str, optional Type of solver. Should be one of - 'hybr' - 'lm' - 'broyden1' - 'broyden2' - 'anderson' - 'linearmixing' - 'diagbroyden' - 'excitingmixing' - 'krylov' jac : bool or callable, optional If `jac` is a Boolean and is True, `fun` is assumed to return the value of Jacobian along with the objective function. If False, the Jacobian will be estimated numerically. `jac` can also be a callable returning the Jacobian of `fun`. In this case, it must accept the same arguments as `fun`. options : dict, optional A dictionary of solver options. E.g. `xtol` or `maxiter`, see ``show_options('root', method)`` for details. callback : function, optional Optional callback function. It is called on every iteration as ``callback(x, f)`` where `x` is the current solution and `f` the corresponding residual. For all methods but 'hybr' and 'lm'. Returns ------- sol : Result The solution represented as a ``Result`` object. Important attributes are: ``x`` the solution array, ``success`` a Boolean flag indicating if the algorithm exited successfully and ``message`` which describes the cause of the termination. See `Result` for a description of other attributes. Notes ----- This section describes the available solvers that can be selected by the 'method' parameter. The default method is *hybr*. Method *hybr* uses a modification of the Powell hybrid method as implemented in MINPACK [1]_. Method *lm* solves the system of nonlinear equations in a least squares sense using a modification of the Levenberg-Marquardt algorithm as implemented in MINPACK [1]_. Methods *broyden1*, *broyden2*, *anderson*, *linearmixing*, *diagbroyden*, *excitingmixing*, *krylov* are inexact Newton methods, with backtracking or full line searches [2]_. Each method corresponds to a particular Jacobian approximations. See `nonlin` for details. - Method *broyden1* uses Broyden's first Jacobian approximation, it is known as Broyden's good method. - Method *broyden2* uses Broyden's second Jacobian approximation, it is known as Broyden's bad method. - Method *anderson* uses (extended) Anderson mixing. - Method *Krylov* uses Krylov approximation for inverse Jacobian. It is suitable for large-scale problem. - Method *diagbroyden* uses diagonal Broyden Jacobian approximation. - Method *linearmixing* uses a scalar Jacobian approximation. - Method *excitingmixing* uses a tuned diagonal Jacobian approximation. .. warning:: The algorithms implemented for methods *diagbroyden*, *linearmixing* and *excitingmixing* may be useful for specific problems, but whether they will work may depend strongly on the problem. References ---------- .. [1] More, Jorge J., Burton S. Garbow, and Kenneth E. Hillstrom. 1980. User Guide for MINPACK-1. .. [2] C. T. Kelley. 1995. Iterative Methods for Linear and Nonlinear Equations. Society for Industrial and Applied Mathematics. <http://www.siam.org/books/kelley/> Examples -------- The following functions define a system of nonlinear equations and its jacobian. >>> def fun(x): ... return [x[0] + 0.5 * (x[0] - x[1])**3 - 1.0, ... 0.5 * (x[1] - x[0])**3 + x[1]] >>> def jac(x): ... return np.array([[1 + 1.5 * (x[0] - x[1])**2, ... -1.5 * (x[0] - x[1])**2], ... [-1.5 * (x[1] - x[0])**2, ... 1 + 1.5 * (x[1] - x[0])**2]]) A solution can be obtained as follows. >>> from scipy import optimize >>> sol = optimize.root(fun, [0, 0], jac=jac, method='hybr') >>> sol.x array([ 0.8411639, 0.1588361]) """ meth = method.lower() if options is None: options = {} if callback is not None and meth in ('hybr', 'lm'): warn('Method %s does not accept callback.' % method, RuntimeWarning) # fun also returns the jacobian if not callable(jac) and meth in ('hybr', 'lm'): if bool(jac): fun = MemoizeJac(fun) jac = fun.derivative else: jac = None if meth == 'hybr': sol = _root_hybr(fun, x0, args=args, jac=jac, options=options) elif meth == 'lm': col_deriv = options.get('col_deriv', 0) xtol = options.get('xtol', 1.49012e-08) ftol = options.get('ftol', 1.49012e-08) gtol = options.get('gtol', 0.0) maxfev = options.get('maxfev', 0) epsfcn = options.get('epsfcn', 0.0) factor = options.get('factor', 100) diag = options.get('diag', None) x, cov_x, info, msg, ier = leastsq(fun, x0, args=args, Dfun=jac, full_output=True, col_deriv=col_deriv, xtol=xtol, ftol=ftol, gtol=gtol, maxfev=maxfev, epsfcn=epsfcn, factor=factor, diag=diag) sol = Result(x=x, message=msg, status=ier, success=ier in (1, 2, 3, 4), cov_x=cov_x, fun=info.pop('fvec')) sol.update(info) elif meth in ('broyden1', 'broyden2', 'anderson', 'linearmixing', 'diagbroyden', 'excitingmixing', 'krylov'): if jac is not None: warn('Method %s does not use the jacobian (jac).' % method, RuntimeWarning) jacobian = { 'broyden1': nonlin.BroydenFirst, 'broyden2': nonlin.BroydenSecond, 'anderson': nonlin.Anderson, 'linearmixing': nonlin.LinearMixing, 'diagbroyden': nonlin.DiagBroyden, 'excitingmixing': nonlin.ExcitingMixing, 'krylov': nonlin.KrylovJacobian }[meth] nit = options.get('nit') verbose = options.get('disp', False) maxiter = options.get('maxiter') f_tol = options.get('ftol') f_rtol = options.get('frtol') x_tol = options.get('xtol') x_rtol = options.get('xrtol') tol_norm = options.get('tol_norm') line_search = options.get('line_search', 'armijo') jac_opts = options.get('jac_options', dict()) if args: def f(x): if jac == True: r = fun(x, *args)[0] else: r = fun(x, *args) return r else: f = fun x, info = nonlin.nonlin_solve(f, x0, jacobian=jacobian(**jac_opts), iter=nit, verbose=verbose, maxiter=maxiter, f_tol=f_tol, f_rtol=f_rtol, x_tol=x_tol, x_rtol=x_rtol, tol_norm=tol_norm, line_search=line_search, callback=callback, full_output=True, raise_exception=False) sol = Result(x=x) sol.update(info) else: raise ValueError('Unknown solver %s' % method) return sol