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 _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 _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 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