def _select_function(sort, typ): if typ in ['F','D']: if callable(sort): # assume the user knows what they're doing sfunction = sort elif sort == 'lhp': sfunction = lambda x,y: (np.real(x/y) < 0.0) elif sort == 'rhp': sfunction = lambda x,y: (np.real(x/y) >= 0.0) elif sort == 'iuc': sfunction = lambda x,y: (abs(x/y) <= 1.0) elif sort == 'ouc': sfunction = lambda x,y: (abs(x/y) > 1.0) else: raise ValueError("sort parameter must be None, a callable, or " "one of ('lhp','rhp','iuc','ouc')") elif typ in ['f','d']: if callable(sort): # assume the user knows what they're doing sfunction = sort elif sort == 'lhp': sfunction = lambda x,y,z: (np.real((x+y*1j)/z) < 0.0) elif sort == 'rhp': sfunction = lambda x,y,z: (np.real((x+y*1j)/z) >= 0.0) elif sort == 'iuc': sfunction = lambda x,y,z: (abs((x+y*1j)/z) <= 1.0) elif sort == 'ouc': sfunction = lambda x,y,z: (abs((x+y*1j)/z) > 1.0) else: raise ValueError("sort parameter must be None, a callable, or " "one of ('lhp','rhp','iuc','ouc')") else: # to avoid an error later raise ValueError("dtype %s not understood" % typ) return sfunction
def set_bandwidth(self, bw_method=None): """Compute the estimator bandwidth with given method. The new bandwidth calculated after a call to `set_bandwidth` is used for subsequent evaluations of the estimated density. Parameters ---------- bw_method : str, scalar or callable, optional The method used to calculate the estimator bandwidth. This can be 'scott', 'silverman', a scalar constant or a callable. If a scalar, this will be used directly as `kde.factor`. If a callable, it should take a `gaussian_kde` instance as only parameter and return a scalar. If None (default), nothing happens; the current `kde.covariance_factor` method is kept. Notes ----- .. versionadded:: 0.11 Examples -------- >>> x1 = np.array([-7, -5, 1, 4, 5.]) >>> kde = stats.gaussian_kde(x1) >>> xs = np.linspace(-10, 10, num=50) >>> y1 = kde(xs) >>> kde.set_bandwidth(bw_method='silverman') >>> y2 = kde(xs) >>> kde.set_bandwidth(bw_method=kde.factor / 3.) >>> y3 = kde(xs) >>> fig = plt.figure() >>> ax = fig.add_subplot(111) >>> ax.plot(x1, np.ones(x1.shape) / (4. * x1.size), 'bo', ... label='Data points (rescaled)') >>> ax.plot(xs, y1, label='Scott (default)') >>> ax.plot(xs, y2, label='Silverman') >>> ax.plot(xs, y3, label='Const (1/3 * Silverman)') >>> ax.legend() >>> plt.show() """ if bw_method is None: pass elif bw_method == 'scott': self.covariance_factor = self.scotts_factor elif bw_method == 'silverman': self.covariance_factor = self.silverman_factor elif np.isscalar(bw_method) and not isinstance(bw_method, string_types): self._bw_method = 'use constant' self.covariance_factor = lambda: bw_method elif callable(bw_method): self._bw_method = bw_method self.covariance_factor = lambda: self._bw_method(self) else: msg = "`bw_method` should be 'scott', 'silverman', a scalar " \ "or a callable." raise ValueError(msg) self._compute_covariance()
def _init_function(self, r): # 选择径向基函数使用的方程,最终返回径向基函数用r计算后的距离 if isinstance(self.function, str): # 选择已提供的径向基函数形式,若self.function是一个字符串 self.function = self.function.lower() #字符串调整为小写 _mapped = { 'inverse': 'inverse_multiquadric', 'inverse multiquadric': 'inverse_multiquadric', 'thin-plate': 'thin_plate' } #函数字典 if self.function in _mapped: #若self.function在函数字典内,变为函数名 self.function = _mapped[self.function] func_name = "_h_" + self.function #调整函数真名 if hasattr(self, func_name): #若类中有该函数 self._function = getattr(self, func_name) #调用该函数 else: #若类中无函数真名 functionlist = [ x[3:] for x in dir(self) if x.startswith('_h_') ] #指向所有函数名 raise ValueError("function must be a callable or one of " + #抛出赋值异常,函数必须为一可调用对象 ", ".join(functionlist)) self._function = getattr(self, "_h_" + self.function) elif callable(self.function): # 若方程为一个可调用的对象:反正这段看不懂我特么就不看了吧算了我特么还是看看吧 allow_one = False # if hasattr(self.function, 'func_code') or \ hasattr(self.function, '__code__'): #若方程对象有func_code属性或__code__属性 val = self.function # val+函数对象 allow_one = True #allow_one设为1 elif hasattr(self.function, "im_func"): val = get_method_function(self.function) elif hasattr(self.function, "__call__"): val = get_method_function(self.function.__call__) else: raise ValueError( "Cannot determine number of arguments to function" ) #抛出赋值异常,不能确定有函数的赋值变量数 argcount = get_function_code(val).co_argcount #获取变量数 if allow_one and argcount == 1: self._function = self.function elif argcount == 2: if sys.version_info[0] >= 3: self._function = self.function.__get__(self, Rbf) else: import new self._function = new.instancemethod( self.function, self, Rbf) else: raise ValueError( "Function argument must take 1 or 2 arguments.") a0 = self._function(r) if a0.shape != r.shape: raise ValueError( "Callable must take array and return array of the same shape") return a0
def _init_function(self, r): if isinstance(self.function, str): self.function = self.function.lower() _mapped = { 'inverse': 'inverse_multiquadric', 'inverse multiquadric': 'inverse_multiquadric', 'thin-plate': 'thin_plate' } if self.function in _mapped: self.function = _mapped[self.function] func_name = "_h_" + self.function if hasattr(self, func_name): self._function = getattr(self, func_name) else: functionlist = [ x[3:] for x in dir(self) if x.startswith('_h_') ] raise ValueError("function must be a callable or one of " + ", ".join(functionlist)) self._function = getattr(self, "_h_" + self.function) elif callable(self.function): allow_one = False if hasattr(self.function, 'func_code') or \ hasattr(self.function, '__code__'): val = self.function allow_one = True elif hasattr(self.function, "im_func"): val = get_method_function(self.function) elif hasattr(self.function, "__call__"): val = get_method_function(self.function.__call__) else: raise ValueError( "Cannot determine number of arguments to function") argcount = get_function_code(val).co_argcount if allow_one and argcount == 1: self._function = self.function elif argcount == 2: if sys.version_info[0] >= 3: self._function = self.function.__get__(self, Rbf) else: import new self._function = new.instancemethod( self.function, self, Rbf) else: raise ValueError( "Function argument must take 1 or 2 arguments.") a0 = self._function(r) if a0.shape != r.shape: raise ValueError( "Callable must take array and return array of the same shape") return a0
def _init_function(self, r): if isinstance(self.function, str): self.function = self.function.lower() _mapped = {'inverse': 'inverse_multiquadric', 'inverse multiquadric': 'inverse_multiquadric', 'thin-plate': 'thin_plate'} if self.function in _mapped: self.function = _mapped[self.function] func_name = "_h_" + self.function if hasattr(self, func_name): self._function = getattr(self, func_name) else: functionlist = [x[3:] for x in dir(self) if x.startswith('_h_')] raise ValueError("function must be a callable or one of " + ", ".join(functionlist)) self._function = getattr(self, "_h_"+self.function) elif callable(self.function): allow_one = False if hasattr(self.function, 'func_code') or \ hasattr(self.function, '__code__'): val = self.function allow_one = True elif hasattr(self.function, "im_func"): val = get_method_function(self.function) elif hasattr(self.function, "__call__"): val = get_method_function(self.function.__call__) else: raise ValueError("Cannot determine number of arguments to function") argcount = get_function_code(val).co_argcount if allow_one and argcount == 1: self._function = self.function elif argcount == 2: if sys.version_info[0] >= 3: self._function = self.function.__get__(self, Rbf) else: import new self._function = new.instancemethod(self.function, self, Rbf) else: raise ValueError("Function argument must take 1 or 2 arguments.") a0 = self._function(r) if a0.shape != r.shape: raise ValueError("Callable must take array and return array of the same shape") return a0
def binned_statistic_dd(sample, values, statistic='mean', bins=10, range=None): """ Compute a multidimensional binned statistic for a set of data. This is a generalization of a histogramdd function. A histogram divides the space into bins, and returns the count of the number of points in each bin. This function allows the computation of the sum, mean, median, or other statistic of the values within each bin. .. versionadded:: 0.11.0 Parameters ---------- sample : array_like Data to histogram passed as a sequence of D arrays of length N, or as an (N,D) array. values : array_like The values on which the statistic will be computed. This must be the same shape as x. statistic : string or callable, optional The statistic to compute (default is 'mean'). The following statistics are available: * 'mean' : compute the mean of values for points within each bin. Empty bins will be represented by NaN. * 'median' : compute the median of values for points within each bin. Empty bins will be represented by NaN. * 'count' : compute the count of points within each bin. This is identical to an unweighted histogram. `values` array is not referenced. * 'sum' : compute the sum of values for points within each bin. This is identical to a weighted histogram. * function : a user-defined function which takes a 1D array of values, and outputs a single numerical statistic. This function will be called on the values in each bin. Empty bins will be represented by function([]), or NaN if this returns an error. bins : sequence or int, optional The bin specification: * A sequence of arrays describing the bin edges along each dimension. * The number of bins for each dimension (nx, ny, ... =bins) * The number of bins for all dimensions (nx=ny=...=bins). range : sequence, optional A sequence of lower and upper bin edges to be used if the edges are not given explicitely in `bins`. Defaults to the minimum and maximum values along each dimension. Returns ------- statistic : ndarray, shape(nx1, nx2, nx3,...) The values of the selected statistic in each two-dimensional bin edges : list of ndarrays A list of D arrays describing the (nxi + 1) bin edges for each dimension binnumber : 1-D ndarray of ints This assigns to each observation an integer that represents the bin in which this observation falls. Array has the same length as values. See Also -------- np.histogramdd, binned_statistic, binned_statistic_2d """ if type(statistic) == str: if statistic not in ['mean', 'median', 'count', 'sum', 'std']: raise ValueError('unrecognized statistic "%s"' % statistic) elif callable(statistic): pass else: raise ValueError("statistic not understood") # This code is based on np.histogramdd try: # Sample is an ND-array. N, D = sample.shape except (AttributeError, ValueError): # Sample is a sequence of 1D arrays. sample = np.atleast_2d(sample).T N, D = sample.shape nbin = np.empty(D, int) edges = D * [None] dedges = D * [None] try: M = len(bins) if M != D: raise AttributeError('The dimension of bins must be equal ' 'to the dimension of the sample x.') except TypeError: bins = D * [bins] # Select range for each dimension # Used only if number of bins is given. if range is None: smin = np.atleast_1d(np.array(sample.min(0), float)) smax = np.atleast_1d(np.array(sample.max(0), float)) else: smin = np.zeros(D) smax = np.zeros(D) for i in np.arange(D): smin[i], smax[i] = range[i] # Make sure the bins have a finite width. for i in np.arange(len(smin)): if smin[i] == smax[i]: smin[i] = smin[i] - .5 smax[i] = smax[i] + .5 # Create edge arrays for i in np.arange(D): if np.isscalar(bins[i]): nbin[i] = bins[i] + 2 # +2 for outlier bins edges[i] = np.linspace(smin[i], smax[i], nbin[i] - 1) else: edges[i] = np.asarray(bins[i], float) nbin[i] = len(edges[i]) + 1 # +1 for outlier bins dedges[i] = np.diff(edges[i]) nbin = np.asarray(nbin) # Compute the bin number each sample falls into. Ncount = {} for i in np.arange(D): Ncount[i] = np.digitize(sample[:, i], edges[i]) # Using digitize, values that fall on an edge are put in the right bin. # For the rightmost bin, we want values equal to the right # edge to be counted in the last bin, and not as an outlier. for i in np.arange(D): # Rounding precision decimal = int(-np.log10(dedges[i].min())) + 6 # Find which points are on the rightmost edge. on_edge = np.where( np.around(sample[:, i], decimal) == np.around( edges[i][-1], decimal))[0] # Shift these points one bin to the left. Ncount[i][on_edge] -= 1 # Compute the sample indices in the flattened statistic matrix. ni = nbin.argsort() xy = np.zeros(N, int) for i in np.arange(0, D - 1): xy += Ncount[ni[i]] * nbin[ni[i + 1:]].prod() xy += Ncount[ni[-1]] result = np.empty(nbin.prod(), float) if statistic == 'mean': result.fill(np.nan) flatcount = np.bincount(xy, None) flatsum = np.bincount(xy, values) a = flatcount.nonzero() result[a] = flatsum[a] / flatcount[a] elif statistic == 'std': result.fill(0) flatcount = np.bincount(xy, None) flatsum = np.bincount(xy, values) flatsum2 = np.bincount(xy, values**2) a = flatcount.nonzero() result[a] = np.sqrt(flatsum2[a] / flatcount[a] - (flatsum[a] / flatcount[a])**2) elif statistic == 'count': result.fill(0) flatcount = np.bincount(xy, None) a = np.arange(len(flatcount)) result[a] = flatcount elif statistic == 'sum': result.fill(0) flatsum = np.bincount(xy, values) a = np.arange(len(flatsum)) result[a] = flatsum elif statistic == 'median': result.fill(np.nan) for i in np.unique(xy): result[i] = np.median(values[xy == i]) elif callable(statistic): old = np.seterr(invalid='ignore') try: null = statistic([]) except: null = np.nan np.seterr(**old) result.fill(null) for i in np.unique(xy): result[i] = statistic(values[xy == i]) # Shape into a proper matrix result = result.reshape(np.sort(nbin)) for i in np.arange(nbin.size): j = ni.argsort()[i] result = result.swapaxes(i, j) ni[i], ni[j] = ni[j], ni[i] # Remove outliers (indices 0 and -1 for each dimension). core = D * [slice(1, -1)] result = result[core] if (result.shape != nbin - 2).any(): raise RuntimeError('Internal Shape Error') return result, edges, xy
def fmin_cobyla(func, x0, cons, args=(), consargs=None, rhobeg=1.0, rhoend=1e-4, iprint=1, maxfun=1000, disp=None): """ Minimize a function using the Constrained Optimization BY Linear Approximation (COBYLA) method. This method wraps a FORTRAN implentation of the algorithm. Parameters ---------- func : callable Function to minimize. In the form func(x, \\*args). x0 : ndarray Initial guess. cons : sequence Constraint functions; must all be ``>=0`` (a single function if only 1 constraint). Each function takes the parameters `x` as its first argument. args : tuple Extra arguments to pass to function. consargs : tuple Extra arguments to pass to constraint functions (default of None means use same extra arguments as those passed to func). Use ``()`` for no extra arguments. rhobeg : Reasonable initial changes to the variables. rhoend : Final accuracy in the optimization (not precisely guaranteed). This is a lower bound on the size of the trust region. iprint : {0, 1, 2, 3} Controls the frequency of output; 0 implies no output. Deprecated. disp : {0, 1, 2, 3} Over-rides the iprint interface. Preferred. maxfun : int Maximum number of function evaluations. Returns ------- x : ndarray The argument that minimises `f`. See also -------- minimize: Interface to minimization algorithms for multivariate functions. See the 'COBYLA' `method` in particular. Notes ----- This algorithm is based on linear approximations to the objective function and each constraint. We briefly describe the algorithm. Suppose the function is being minimized over k variables. At the jth iteration the algorithm has k+1 points v_1, ..., v_(k+1), an approximate solution x_j, and a radius RHO_j. (i.e. linear plus a constant) approximations to the objective function and constraint functions such that their function values agree with the linear approximation on the k+1 points v_1,.., v_(k+1). This gives a linear program to solve (where the linear approximations of the constraint functions are constrained to be non-negative). However the linear approximations are likely only good approximations near the current simplex, so the linear program is given the further requirement that the solution, which will become x_(j+1), must be within RHO_j from x_j. RHO_j only decreases, never increases. The initial RHO_j is rhobeg and the final RHO_j is rhoend. In this way COBYLA's iterations behave like a trust region algorithm. Additionally, the linear program may be inconsistent, or the approximation may give poor improvement. For details about how these issues are resolved, as well as how the points v_i are updated, refer to the source code or the references below. References ---------- Powell M.J.D. (1994), "A direct search optimization method that models the objective and constraint functions by linear interpolation.", in Advances in Optimization and Numerical Analysis, eds. S. Gomez and J-P Hennart, Kluwer Academic (Dordrecht), pp. 51-67 Powell M.J.D. (1998), "Direct search algorithms for optimization calculations", Acta Numerica 7, 287-336 Powell M.J.D. (2007), "A view of algorithms for optimization without derivatives", Cambridge University Technical Report DAMTP 2007/NA03 Examples -------- Minimize the objective function f(x,y) = x*y subject to the constraints x**2 + y**2 < 1 and y > 0:: >>> def objective(x): ... return x[0]*x[1] ... >>> def constr1(x): ... return 1 - (x[0]**2 + x[1]**2) ... >>> def constr2(x): ... return x[1] ... >>> fmin_cobyla(objective, [0.0, 0.1], [constr1, constr2], rhoend=1e-7) Normal return from subroutine COBYLA NFVALS = 64 F =-5.000000E-01 MAXCV = 1.998401E-14 X =-7.071069E-01 7.071067E-01 array([-0.70710685, 0.70710671]) The exact solution is (-sqrt(2)/2, sqrt(2)/2). """ err = "cons must be a sequence of callable functions or a single"\ " callable function." try: len(cons) except TypeError: if callable(cons): cons = [cons] else: raise TypeError(err) else: for thisfunc in cons: if not callable(thisfunc): raise TypeError(err) if consargs is None: consargs = args # build constraints con = tuple({'type': 'ineq', 'fun': c, 'args': consargs} for c in cons) # options if disp is not None: iprint = disp opts = {'rhobeg': rhobeg, 'tol': rhoend, 'iprint': iprint, 'disp': iprint != 0, 'maxiter': maxfun} return _minimize_cobyla(func, x0, args, constraints=con, **opts)['x']
def binned_statistic_dd(sample, values, statistic='mean', bins=10, range=None): """ Compute a multidimensional binned statistic for a set of data. This is a generalization of a histogramdd function. A histogram divides the space into bins, and returns the count of the number of points in each bin. This function allows the computation of the sum, mean, median, or other statistic of the values within each bin. .. versionadded:: 0.11.0 Parameters ---------- sample : array_like Data to histogram passed as a sequence of D arrays of length N, or as an (N,D) array. values : array_like The values on which the statistic will be computed. This must be the same shape as x. statistic : string or callable, optional The statistic to compute (default is 'mean'). The following statistics are available: * 'mean' : compute the mean of values for points within each bin. Empty bins will be represented by NaN. * 'median' : compute the median of values for points within each bin. Empty bins will be represented by NaN. * 'count' : compute the count of points within each bin. This is identical to an unweighted histogram. `values` array is not referenced. * 'sum' : compute the sum of values for points within each bin. This is identical to a weighted histogram. * function : a user-defined function which takes a 1D array of values, and outputs a single numerical statistic. This function will be called on the values in each bin. Empty bins will be represented by function([]), or NaN if this returns an error. bins : sequence or int, optional The bin specification: * A sequence of arrays describing the bin edges along each dimension. * The number of bins for each dimension (nx, ny, ... =bins) * The number of bins for all dimensions (nx=ny=...=bins). range : sequence, optional A sequence of lower and upper bin edges to be used if the edges are not given explicitely in `bins`. Defaults to the minimum and maximum values along each dimension. Returns ------- statistic : ndarray, shape(nx1, nx2, nx3,...) The values of the selected statistic in each two-dimensional bin edges : list of ndarrays A list of D arrays describing the (nxi + 1) bin edges for each dimension binnumber : 1-D ndarray of ints This assigns to each observation an integer that represents the bin in which this observation falls. Array has the same length as values. See Also -------- np.histogramdd, binned_statistic, binned_statistic_2d """ if type(statistic) == str: if statistic not in ['mean', 'median', 'count', 'sum', 'std']: raise ValueError('unrecognized statistic "%s"' % statistic) elif callable(statistic): pass else: raise ValueError("statistic not understood") # This code is based on np.histogramdd try: # Sample is an ND-array. N, D = sample.shape except (AttributeError, ValueError): # Sample is a sequence of 1D arrays. sample = np.atleast_2d(sample).T N, D = sample.shape nbin = np.empty(D, int) edges = D * [None] dedges = D * [None] try: M = len(bins) if M != D: raise AttributeError('The dimension of bins must be equal ' 'to the dimension of the sample x.') except TypeError: bins = D * [bins] # Select range for each dimension # Used only if number of bins is given. if range is None: smin = np.atleast_1d(np.array(sample.min(0), float)) smax = np.atleast_1d(np.array(sample.max(0), float)) else: smin = np.zeros(D) smax = np.zeros(D) for i in np.arange(D): smin[i], smax[i] = range[i] # Make sure the bins have a finite width. for i in np.arange(len(smin)): if smin[i] == smax[i]: smin[i] = smin[i] - .5 smax[i] = smax[i] + .5 # Create edge arrays for i in np.arange(D): if np.isscalar(bins[i]): nbin[i] = bins[i] + 2 # +2 for outlier bins edges[i] = np.linspace(smin[i], smax[i], nbin[i] - 1) else: edges[i] = np.asarray(bins[i], float) nbin[i] = len(edges[i]) + 1 # +1 for outlier bins dedges[i] = np.diff(edges[i]) nbin = np.asarray(nbin) # Compute the bin number each sample falls into. Ncount = {} for i in np.arange(D): Ncount[i] = np.digitize(sample[:, i], edges[i]) # Using digitize, values that fall on an edge are put in the right bin. # For the rightmost bin, we want values equal to the right # edge to be counted in the last bin, and not as an outlier. for i in np.arange(D): # Rounding precision decimal = int(-np.log10(dedges[i].min())) + 6 # Find which points are on the rightmost edge. on_edge = np.where(np.around(sample[:, i], decimal) == np.around(edges[i][-1], decimal))[0] # Shift these points one bin to the left. Ncount[i][on_edge] -= 1 # Compute the sample indices in the flattened statistic matrix. ni = nbin.argsort() xy = np.zeros(N, int) for i in np.arange(0, D - 1): xy += Ncount[ni[i]] * nbin[ni[i + 1:]].prod() xy += Ncount[ni[-1]] result = np.empty(nbin.prod(), float) if statistic == 'mean': result.fill(np.nan) flatcount = np.bincount(xy, None) flatsum = np.bincount(xy, values) a = flatcount.nonzero() result[a] = flatsum[a] / flatcount[a] elif statistic == 'std': result.fill(0) flatcount = np.bincount(xy, None) flatsum = np.bincount(xy, values) flatsum2 = np.bincount(xy, values ** 2) a = flatcount.nonzero() result[a] = np.sqrt(flatsum2[a] / flatcount[a] - (flatsum[a] / flatcount[a]) ** 2) elif statistic == 'count': result.fill(0) flatcount = np.bincount(xy, None) a = np.arange(len(flatcount)) result[a] = flatcount elif statistic == 'sum': result.fill(0) flatsum = np.bincount(xy, values) a = np.arange(len(flatsum)) result[a] = flatsum elif statistic == 'median': result.fill(np.nan) for i in np.unique(xy): result[i] = np.median(values[xy == i]) elif callable(statistic): old = np.seterr(invalid='ignore') try: null = statistic([]) except: null = np.nan np.seterr(**old) result.fill(null) for i in np.unique(xy): result[i] = statistic(values[xy == i]) # Shape into a proper matrix result = result.reshape(np.sort(nbin)) for i in np.arange(nbin.size): j = ni.argsort()[i] result = result.swapaxes(i, j) ni[i], ni[j] = ni[j], ni[i] # Remove outliers (indices 0 and -1 for each dimension). core = D * [slice(1, -1)] result = result[core] if (result.shape != nbin - 2).any(): raise RuntimeError('Internal Shape Error') return result, edges, xy
def resample(x, num, t=None, axis=0, window=None): """ Resample `x` to `num` samples using Fourier method along the given axis. The resampled signal starts at the same value as `x` but is sampled with a spacing of ``len(x) / num * (spacing of x)``. Because a Fourier method is used, the signal is assumed to be periodic. Parameters ---------- x : array_like The data to be resampled. num : int The number of samples in the resampled signal. t : array_like, optional If `t` is given, it is assumed to be the sample positions associated with the signal data in `x`. axis : int, optional The axis of `x` that is resampled. Default is 0. window : array_like, callable, string, float, or tuple, optional Specifies the window applied to the signal in the Fourier domain. See below for details. Returns ------- resampled_x or (resampled_x, resampled_t) Either the resampled array, or, if `t` was given, a tuple containing the resampled array and the corresponding resampled positions. Notes ----- The argument `window` controls a Fourier-domain window that tapers the Fourier spectrum before zero-padding to alleviate ringing in the resampled values for sampled signals you didn't intend to be interpreted as band-limited. If `window` is a function, then it is called with a vector of inputs indicating the frequency bins (i.e. fftfreq(x.shape[axis]) ). If `window` is an array of the same length as `x.shape[axis]` it is assumed to be the window to be applied directly in the Fourier domain (with dc and low-frequency first). For any other type of `window`, the function `scipy.signal.get_window` is called to generate the window. The first sample of the returned vector is the same as the first sample of the input vector. The spacing between samples is changed from dx to: dx * len(x) / num If `t` is not None, then it represents the old sample positions, and the new sample positions will be returned as well as the new samples. """ x = asarray(x) X = fft(x, axis=axis) Nx = x.shape[axis] if window is not None: if callable(window): W = window(fftfreq(Nx)) elif isinstance(window, ndarray) and window.shape == (Nx, ): W = window else: W = ifftshift(get_window(window, Nx)) newshape = ones(len(x.shape)) newshape[axis] = len(W) W.shape = newshape X = X * W sl = [slice(None)] * len(x.shape) newshape = list(x.shape) newshape[axis] = num N = int(np.minimum(num, Nx)) Y = zeros(newshape, 'D') sl[axis] = slice(0, (N + 1) // 2) Y[sl] = X[sl] sl[axis] = slice(-(N - 1) // 2, None) Y[sl] = X[sl] y = ifft(Y, axis=axis) * (float(num) / float(Nx)) if x.dtype.char not in ['F', 'D']: y = y.real if t is None: return y else: new_t = arange(0, num) * (t[1] - t[0]) * Nx / float(num) + t[0] return y, new_t
def asjacobian(J): """ Convert given object to one suitable for use as a Jacobian. """ spsolve = scipy.sparse.linalg.spsolve if isinstance(J, Jacobian): return J elif inspect.isclass(J) and issubclass(J, Jacobian): return J() elif isinstance(J, np.ndarray): if J.ndim > 2: raise ValueError('array must have rank <= 2') J = np.atleast_2d(np.asarray(J)) if J.shape[0] != J.shape[1]: raise ValueError('array must be square') return Jacobian(matvec=lambda v: dot(J, v), rmatvec=lambda v: dot(J.conj().T, v), solve=lambda v: solve(J, v), rsolve=lambda v: solve(J.conj().T, v), dtype=J.dtype, shape=J.shape) elif scipy.sparse.isspmatrix(J): if J.shape[0] != J.shape[1]: raise ValueError('matrix must be square') return Jacobian(matvec=lambda v: J*v, rmatvec=lambda v: J.conj().T * v, solve=lambda v: spsolve(J, v), rsolve=lambda v: spsolve(J.conj().T, v), dtype=J.dtype, shape=J.shape) elif hasattr(J, 'shape') and hasattr(J, 'dtype') and hasattr(J, 'solve'): return Jacobian(matvec=getattr(J, 'matvec'), rmatvec=getattr(J, 'rmatvec'), solve=J.solve, rsolve=getattr(J, 'rsolve'), update=getattr(J, 'update'), setup=getattr(J, 'setup'), dtype=J.dtype, shape=J.shape) elif callable(J): # Assume it's a function J(x) that returns the Jacobian class Jac(Jacobian): def update(self, x, F): self.x = x def solve(self, v, tol=0): m = J(self.x) if isinstance(m, np.ndarray): return solve(m, v) elif scipy.sparse.isspmatrix(m): return spsolve(m, v) else: raise ValueError("Unknown matrix type") def matvec(self, v): m = J(self.x) if isinstance(m, np.ndarray): return dot(m, v) elif scipy.sparse.isspmatrix(m): return m*v else: raise ValueError("Unknown matrix type") def rsolve(self, v, tol=0): m = J(self.x) if isinstance(m, np.ndarray): return solve(m.conj().T, v) elif scipy.sparse.isspmatrix(m): return spsolve(m.conj().T, v) else: raise ValueError("Unknown matrix type") def rmatvec(self, v): m = J(self.x) if isinstance(m, np.ndarray): return dot(m.conj().T, v) elif scipy.sparse.isspmatrix(m): return m.conj().T * v else: raise ValueError("Unknown matrix type") return Jac() elif isinstance(J, str): return dict(broyden1=BroydenFirst, broyden2=BroydenSecond, anderson=Anderson, diagbroyden=DiagBroyden, linearmixing=LinearMixing, excitingmixing=ExcitingMixing, krylov=KrylovJacobian)[J]() else: raise TypeError('Cannot convert object to a Jacobian')
def asjacobian(J): """ Convert given object to one suitable for use as a Jacobian. """ spsolve = scipy.sparse.linalg.spsolve if isinstance(J, Jacobian): return J elif inspect.isclass(J) and issubclass(J, Jacobian): return J() elif isinstance(J, np.ndarray): if J.ndim > 2: raise ValueError('array must have rank <= 2') J = np.atleast_2d(np.asarray(J)) if J.shape[0] != J.shape[1]: raise ValueError('array must be square') return Jacobian(matvec=lambda v: dot(J, v), rmatvec=lambda v: dot(J.conj().T, v), solve=lambda v: solve(J, v), rsolve=lambda v: solve(J.conj().T, v), dtype=J.dtype, shape=J.shape) elif scipy.sparse.isspmatrix(J): if J.shape[0] != J.shape[1]: raise ValueError('matrix must be square') return Jacobian(matvec=lambda v: J * v, rmatvec=lambda v: J.conj().T * v, solve=lambda v: spsolve(J, v), rsolve=lambda v: spsolve(J.conj().T, v), dtype=J.dtype, shape=J.shape) elif hasattr(J, 'shape') and hasattr(J, 'dtype') and hasattr(J, 'solve'): return Jacobian(matvec=getattr(J, 'matvec'), rmatvec=getattr(J, 'rmatvec'), solve=J.solve, rsolve=getattr(J, 'rsolve'), update=getattr(J, 'update'), setup=getattr(J, 'setup'), dtype=J.dtype, shape=J.shape) elif callable(J): # Assume it's a function J(x) that returns the Jacobian class Jac(Jacobian): def update(self, x, F): self.x = x def solve(self, v, tol=0): m = J(self.x) if isinstance(m, np.ndarray): return solve(m, v) elif scipy.sparse.isspmatrix(m): return spsolve(m, v) else: raise ValueError("Unknown matrix type") def matvec(self, v): m = J(self.x) if isinstance(m, np.ndarray): return dot(m, v) elif scipy.sparse.isspmatrix(m): return m * v else: raise ValueError("Unknown matrix type") def rsolve(self, v, tol=0): m = J(self.x) if isinstance(m, np.ndarray): return solve(m.conj().T, v) elif scipy.sparse.isspmatrix(m): return spsolve(m.conj().T, v) else: raise ValueError("Unknown matrix type") def rmatvec(self, v): m = J(self.x) if isinstance(m, np.ndarray): return dot(m.conj().T, v) elif scipy.sparse.isspmatrix(m): return m.conj().T * v else: raise ValueError("Unknown matrix type") return Jac() elif isinstance(J, str): return dict(broyden1=BroydenFirst, broyden2=BroydenSecond, anderson=Anderson, diagbroyden=DiagBroyden, linearmixing=LinearMixing, excitingmixing=ExcitingMixing, krylov=KrylovJacobian)[J]() else: raise TypeError('Cannot convert object to a Jacobian')
def nquad(func, ranges, args=None, opts=None): """ Integration over multiple variables. Wraps `quad` to enable integration over multiple variables. Various options allow improved integration of discontinuous functions, as well as the use of weighted integration, and generally finer control of the integration process. Parameters ---------- func : callable The function to be integrated. Has arguments of ``x0, ... xn``, ``t0, tm``, where integration is carried out over ``x0, ... xn``, which must be floats. Function signature should be ``func(x0, x1, ..., xn, t0, t1, ..., tm)``. Integration is carried out in order. That is, integration over ``x0`` is the innermost integral, and ``xn`` is the outermost. ranges : iterable object Each element of ranges may be either a sequence of 2 numbers, or else a callable that returns such a sequence. ``ranges[0]`` corresponds to integration over x0, and so on. If an element of ranges is a callable, then it will be called with all of the integration arguments available. e.g. if ``func = f(x0, x1, x2)``, then ``ranges[0]`` may be defined as either ``(a, b)`` or else as ``(a, b) = range0(x1, x2)``. args : iterable object, optional Additional arguments ``t0, ..., tn``, required by `func`. opts : iterable object or dict, optional Options to be passed to `quad`. May be empty, a dict, or a sequence of dicts or functions that return a dict. If empty, the default options from scipy.integrate.quadare used. If a dict, the same options are used for all levels of integraion. If a sequence, then each element of the sequence corresponds to a particular integration. e.g. opts[0] corresponds to integration over x0, and so on. The available options together with their default values are: - epsabs = 1.49e-08 - epsrel = 1.49e-08 - limit = 50 - points = None - weight = None - wvar = None - wopts = None The ``full_output`` option from `quad` is unavailable, due to the complexity of handling the large amount of data such an option would return for this kind of nested integration. For more information on these options, see `quad` and `quad_explain`. Returns ------- result : float The result of the integration. abserr : float The maximum of the estimates of the absolute error in the various integration results. See Also -------- quad : 1-dimensional numerical integration dblquad, tplquad : double and triple integrals fixed_quad : fixed-order Gaussian quadrature quadrature : adaptive Gaussian quadrature Examples -------- >>> from scipy import integrate >>> func = lambda x0,x1,x2,x3 : x0**2 + x1*x2 - x3**3 + np.sin(x0) + ( ... 1 if (x0-.2*x3-.5-.25*x1>0) else 0) >>> points = [[lambda (x1,x2,x3) : 0.2*x3 + 0.5 + 0.25*x1], [], [], []] >>> def opts0(*args, **kwargs): ... return {'points':[0.2*args[2] + 0.5 + 0.25*args[0]]} >>> integrate.nquad(func, [[0,1], [-1,1], [.13,.8], [-.15,1]], ... opts=[opts0,{},{},{}]) (1.5267454070738633, 2.9437360001402324e-14) >>> scale = .1 >>> def func2(x0, x1, x2, x3, t0, t1): ... return x0*x1*x3**2 + np.sin(x2) + 1 + (1 if x0+t1*x1-t0>0 else 0) >>> def lim0(x1, x2, x3, t0, t1): ... return [scale * (x1**2 + x2 + np.cos(x3)*t0*t1 + 1) - 1, ... scale * (x1**2 + x2 + np.cos(x3)*t0*t1 + 1) + 1] >>> def lim1(x2, x3, t0, t1): ... return [scale * (t0*x2 + t1*x3) - 1, ... scale * (t0*x2 + t1*x3) + 1] >>> def lim2(x3, t0, t1): ... return [scale * (x3 + t0**2*t1**3) - 1, ... scale * (x3 + t0**2*t1**3) + 1] >>> def lim3(t0, t1): ... return [scale * (t0+t1) - 1, scale * (t0+t1) + 1] >>> def opts0(x1, x2, x3, t0, t1): ... return {'points' : [t0 - t1*x1]} >>> def opts1(x2, x3, t0, t1): ... return {} >>> def opts2(x3, t0, t1): ... return {} >>> def opts3(t0, t1): ... return {} >>> integrate.nquad(func2, [lim0, lim1, lim2, lim3], args=(0,0), opts=[opts0, opts1, opts2, opts3]) (25.066666666666666, 2.7829590483937256e-13) """ depth = len(ranges) ranges = [rng if callable(rng) else _RangeFunc(rng) for rng in ranges] if args is None: args = () if opts is None: opts = [dict([])] * depth if isinstance(opts, dict): opts = [opts] * depth else: opts = [opt if callable(opt) else _OptFunc(opt) for opt in opts] return _NQuad(func, ranges, opts).integrate(*args)
def schur(a, output='real', lwork=None, overwrite_a=False, sort=None, check_finite=True): """ Compute Schur decomposition of a matrix. The Schur decomposition is:: A = Z T Z^H where Z is unitary and T is either upper-triangular, or for real Schur decomposition (output='real'), quasi-upper triangular. In the quasi-triangular form, 2x2 blocks describing complex-valued eigenvalue pairs may extrude from the diagonal. Parameters ---------- a : (M, M) array_like Matrix to decompose output : {'real', 'complex'}, optional Construct the real or complex Schur decomposition (for real matrices). lwork : int, optional Work array size. If None or -1, it is automatically computed. overwrite_a : bool, optional Whether to overwrite data in a (may improve performance). sort : {None, callable, 'lhp', 'rhp', 'iuc', 'ouc'}, optional Specifies whether the upper eigenvalues should be sorted. A callable may be passed that, given a eigenvalue, returns a boolean denoting whether the eigenvalue should be sorted to the top-left (True). Alternatively, string parameters may be used:: 'lhp' Left-hand plane (x.real < 0.0) 'rhp' Right-hand plane (x.real > 0.0) 'iuc' Inside the unit circle (x*x.conjugate() <= 1.0) 'ouc' Outside the unit circle (x*x.conjugate() > 1.0) Defaults to None (no sorting). check_finite : boolean, optional Whether to check that the input matrix contains only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Returns ------- T : (M, M) ndarray Schur form of A. It is real-valued for the real Schur decomposition. Z : (M, M) ndarray An unitary Schur transformation matrix for A. It is real-valued for the real Schur decomposition. sdim : int If and only if sorting was requested, a third return value will contain the number of eigenvalues satisfying the sort condition. Raises ------ LinAlgError Error raised under three conditions: 1. The algorithm failed due to a failure of the QR algorithm to compute all eigenvalues 2. If eigenvalue sorting was requested, the eigenvalues could not be reordered due to a failure to separate eigenvalues, usually because of poor conditioning 3. If eigenvalue sorting was requested, roundoff errors caused the leading eigenvalues to no longer satisfy the sorting condition See also -------- rsf2csf : Convert real Schur form to complex Schur form """ if not output in ['real','complex','r','c']: raise ValueError("argument must be 'real', or 'complex'") if check_finite: a1 = asarray_chkfinite(a) else: a1 = asarray(a) if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]): raise ValueError('expected square matrix') typ = a1.dtype.char if output in ['complex','c'] and typ not in ['F','D']: if typ in _double_precision: a1 = a1.astype('D') typ = 'D' else: a1 = a1.astype('F') typ = 'F' overwrite_a = overwrite_a or (_datacopied(a1, a)) gees, = get_lapack_funcs(('gees',), (a1,)) if lwork is None or lwork == -1: # get optimal work array result = gees(lambda x: None, a1, lwork=-1) lwork = result[-2][0].real.astype(numpy.int) if sort is None: sort_t = 0 sfunction = lambda x: None else: sort_t = 1 if callable(sort): sfunction = sort elif sort == 'lhp': sfunction = lambda x: (numpy.real(x) < 0.0) elif sort == 'rhp': sfunction = lambda x: (numpy.real(x) >= 0.0) elif sort == 'iuc': sfunction = lambda x: (abs(x) <= 1.0) elif sort == 'ouc': sfunction = lambda x: (abs(x) > 1.0) else: raise ValueError("sort parameter must be None, a callable, or " + "one of ('lhp','rhp','iuc','ouc')") result = gees(sfunction, a1, lwork=lwork, overwrite_a=overwrite_a, sort_t=sort_t) info = result[-1] if info < 0: raise ValueError('illegal value in %d-th argument of internal gees' % -info) elif info == a1.shape[0] + 1: raise LinAlgError('Eigenvalues could not be separated for reordering.') elif info == a1.shape[0] + 2: raise LinAlgError('Leading eigenvalues do not satisfy sort condition.') elif info > 0: raise LinAlgError("Schur form not found. Possibly ill-conditioned.") if sort_t == 0: return result[0], result[-3] else: return result[0], result[-3], result[1]
def minimize( fun, x0, args=(), method="BFGS", jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None, ): """ Minimization of scalar function of one or more variables. .. versionadded:: 0.11.0 Parameters ---------- fun : callable Objective function. x0 : ndarray Initial guess. args : tuple, optional Extra arguments passed to the objective function and its derivatives (Jacobian, Hessian). method : str, optional Type of solver. Should be one of - 'Nelder-Mead' - 'Powell' - 'CG' - 'BFGS' - 'Newton-CG' - 'Anneal' - 'L-BFGS-B' - 'TNC' - 'COBYLA' - 'SLSQP' - 'dogleg' - 'trust-ncg' jac : bool or callable, optional Jacobian (gradient) of objective function. Only for CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg. If `jac` is a Boolean and is True, `fun` is assumed to return the gradient along with the objective function. If False, the gradient will be estimated numerically. `jac` can also be a callable returning the gradient of the objective. In this case, it must accept the same arguments as `fun`. hess, hessp : callable, optional Hessian (matrix of second-order derivatives) of objective function or Hessian of objective function times an arbitrary vector p. Only for Newton-CG, dogleg, trust-ncg. Only one of `hessp` or `hess` needs to be given. If `hess` is provided, then `hessp` will be ignored. If neither `hess` nor `hessp` is provided, then the Hessian product will be approximated using finite differences on `jac`. `hessp` must compute the Hessian times an arbitrary vector. bounds : sequence, optional Bounds for variables (only for L-BFGS-B, TNC and SLSQP). ``(min, max)`` pairs for each element in ``x``, defining the bounds on that parameter. Use None for one of ``min`` or ``max`` when there is no bound in that direction. constraints : dict or sequence of dict, optional Constraints definition (only for COBYLA and SLSQP). Each constraint is defined in a dictionary with fields: type : str Constraint type: 'eq' for equality, 'ineq' for inequality. fun : callable The function defining the constraint. jac : callable, optional The Jacobian of `fun` (only for SLSQP). args : sequence, optional Extra arguments to be passed to the function and Jacobian. Equality constraint means that the constraint function result is to be zero whereas inequality means that it is to be non-negative. Note that COBYLA only supports inequality constraints. tol : float, optional Tolerance for termination. For detailed control, use solver-specific options. options : dict, optional A dictionary of solver options. All methods accept the following generic options: maxiter : int Maximum number of iterations to perform. disp : bool Set to True to print convergence messages. For method-specific options, see :func:`show_options()`. callback : callable, optional Called after each iteration, as ``callback(xk)``, where ``xk`` is the current parameter vector. Returns ------- res : Result The optimization result represented as a ``Result`` object. Important attributes are: ``x`` the solution array, ``success`` a Boolean flag indicating if the optimizer exited successfully and ``message`` which describes the cause of the termination. See `Result` for a description of other attributes. See also -------- minimize_scalar : Interface to minimization algorithms for scalar univariate functions show_options : Additional options accepted by the solvers Notes ----- This section describes the available solvers that can be selected by the 'method' parameter. The default method is *BFGS*. **Unconstrained minimization** Method *Nelder-Mead* uses the Simplex algorithm [1]_, [2]_. This algorithm has been successful in many applications but other algorithms using the first and/or second derivatives information might be preferred for their better performances and robustness in general. Method *Powell* is a modification of Powell's method [3]_, [4]_ which is a conjugate direction method. It performs sequential one-dimensional minimizations along each vector of the directions set (`direc` field in `options` and `info`), which is updated at each iteration of the main minimization loop. The function need not be differentiable, and no derivatives are taken. Method *CG* uses a nonlinear conjugate gradient algorithm by Polak and Ribiere, a variant of the Fletcher-Reeves method described in [5]_ pp. 120-122. Only the first derivatives are used. Method *BFGS* uses the quasi-Newton method of Broyden, Fletcher, Goldfarb, and Shanno (BFGS) [5]_ pp. 136. It uses the first derivatives only. BFGS has proven good performance even for non-smooth optimizations. This method also returns an approximation of the Hessian inverse, stored as `hess_inv` in the Result object. Method *Newton-CG* uses a Newton-CG algorithm [5]_ pp. 168 (also known as the truncated Newton method). It uses a CG method to the compute the search direction. See also *TNC* method for a box-constrained minimization with a similar algorithm. Method *Anneal* uses simulated annealing, which is a probabilistic metaheuristic algorithm for global optimization. It uses no derivative information from the function being optimized. Method *dogleg* uses the dog-leg trust-region algorithm [5]_ for unconstrained minimization. This algorithm requires the gradient and Hessian; furthermore the Hessian is required to be positive definite. Method *trust-ncg* uses the Newton conjugate gradient trust-region algorithm [5]_ for unconstrained minimization. This algorithm requires the gradient and either the Hessian or a function that computes the product of the Hessian with a given vector. **Constrained minimization** Method *L-BFGS-B* uses the L-BFGS-B algorithm [6]_, [7]_ for bound constrained minimization. Method *TNC* uses a truncated Newton algorithm [5]_, [8]_ to minimize a function with variables subject to bounds. This algorithm uses gradient information; it is also called Newton Conjugate-Gradient. It differs from the *Newton-CG* method described above as it wraps a C implementation and allows each variable to be given upper and lower bounds. Method *COBYLA* uses the Constrained Optimization BY Linear Approximation (COBYLA) method [9]_, [10]_, [11]_. The algorithm is based on linear approximations to the objective function and each constraint. The method wraps a FORTRAN implementation of the algorithm. Method *SLSQP* uses Sequential Least SQuares Programming to minimize a function of several variables with any combination of bounds, equality and inequality constraints. The method wraps the SLSQP Optimization subroutine originally implemented by Dieter Kraft [12]_. Note that the wrapper handles infinite values in bounds by converting them into large floating values. References ---------- .. [1] Nelder, J A, and R Mead. 1965. A Simplex Method for Function Minimization. The Computer Journal 7: 308-13. .. [2] Wright M H. 1996. Direct search methods: Once scorned, now respectable, in Numerical Analysis 1995: Proceedings of the 1995 Dundee Biennial Conference in Numerical Analysis (Eds. D F Griffiths and G A Watson). Addison Wesley Longman, Harlow, UK. 191-208. .. [3] Powell, M J D. 1964. An efficient method for finding the minimum of a function of several variables without calculating derivatives. The Computer Journal 7: 155-162. .. [4] Press W, S A Teukolsky, W T Vetterling and B P Flannery. Numerical Recipes (any edition), Cambridge University Press. .. [5] Nocedal, J, and S J Wright. 2006. Numerical Optimization. Springer New York. .. [6] Byrd, R H and P Lu and J. Nocedal. 1995. A Limited Memory Algorithm for Bound Constrained Optimization. SIAM Journal on Scientific and Statistical Computing 16 (5): 1190-1208. .. [7] Zhu, C and R H Byrd and J Nocedal. 1997. L-BFGS-B: Algorithm 778: L-BFGS-B, FORTRAN routines for large scale bound constrained optimization. ACM Transactions on Mathematical Software 23 (4): 550-560. .. [8] Nash, S G. Newton-Type Minimization Via the Lanczos Method. 1984. SIAM Journal of Numerical Analysis 21: 770-778. .. [9] Powell, M J D. A direct search optimization method that models the objective and constraint functions by linear interpolation. 1994. Advances in Optimization and Numerical Analysis, eds. S. Gomez and J-P Hennart, Kluwer Academic (Dordrecht), 51-67. .. [10] Powell M J D. Direct search algorithms for optimization calculations. 1998. Acta Numerica 7: 287-336. .. [11] Powell M J D. A view of algorithms for optimization without derivatives. 2007.Cambridge University Technical Report DAMTP 2007/NA03 .. [12] Kraft, D. A software package for sequential quadratic programming. 1988. Tech. Rep. DFVLR-FB 88-28, DLR German Aerospace Center -- Institute for Flight Mechanics, Koln, Germany. Examples -------- Let us consider the problem of minimizing the Rosenbrock function. This function (and its respective derivatives) is implemented in `rosen` (resp. `rosen_der`, `rosen_hess`) in the `scipy.optimize`. >>> from scipy.optimize import minimize, rosen, rosen_der A simple application of the *Nelder-Mead* method is: >>> x0 = [1.3, 0.7, 0.8, 1.9, 1.2] >>> res = minimize(rosen, x0, method='Nelder-Mead') >>> res.x [ 1. 1. 1. 1. 1.] Now using the *BFGS* algorithm, using the first derivative and a few options: >>> res = minimize(rosen, x0, method='BFGS', jac=rosen_der, ... options={'gtol': 1e-6, 'disp': True}) Optimization terminated successfully. Current function value: 0.000000 Iterations: 52 Function evaluations: 64 Gradient evaluations: 64 >>> res.x [ 1. 1. 1. 1. 1.] >>> print res.message Optimization terminated successfully. >>> res.hess [[ 0.00749589 0.01255155 0.02396251 0.04750988 0.09495377] [ 0.01255155 0.02510441 0.04794055 0.09502834 0.18996269] [ 0.02396251 0.04794055 0.09631614 0.19092151 0.38165151] [ 0.04750988 0.09502834 0.19092151 0.38341252 0.7664427 ] [ 0.09495377 0.18996269 0.38165151 0.7664427 1.53713523]] Next, consider a minimization problem with several constraints (namely Example 16.4 from [5]_). The objective function is: >>> fun = lambda x: (x[0] - 1)**2 + (x[1] - 2.5)**2 There are three constraints defined as: >>> cons = ({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + 2}, ... {'type': 'ineq', 'fun': lambda x: -x[0] - 2 * x[1] + 6}, ... {'type': 'ineq', 'fun': lambda x: -x[0] + 2 * x[1] + 2}) And variables must be positive, hence the following bounds: >>> bnds = ((0, None), (0, None)) The optimization problem is solved using the SLSQP method as: >>> res = minimize(fun, (2, 0), method='SLSQP', bounds=bnds, ... constraints=cons) It should converge to the theoretical solution (1.4 ,1.7). """ meth = method.lower() if options is None: options = {} # check if optional parameters are supported by the selected method # - jac if meth in ["nelder-mead", "powell", "anneal", "cobyla"] and bool(jac): warn("Method %s does not use gradient information (jac)." % method, RuntimeWarning) # - hess if meth not in ("newton-cg", "dogleg", "trust-ncg") and hess is not None: warn("Method %s does not use Hessian information (hess)." % method, RuntimeWarning) # - hessp if meth not in ("newton-cg", "dogleg", "trust-ncg") and hessp is not None: warn("Method %s does not use Hessian-vector product " "information (hessp)." % method, RuntimeWarning) # - constraints or bounds if meth in ["nelder-mead", "powell", "cg", "bfgs", "newton-cg", "dogleg", "trust-ncg"] and ( bounds is not None or any(constraints) ): warn("Method %s cannot handle constraints nor bounds." % method, RuntimeWarning) if meth in ["l-bfgs-b", "tnc"] and any(constraints): warn("Method %s cannot handle constraints." % method, RuntimeWarning) if meth == "cobyla" and bounds is not None: warn("Method %s cannot handle bounds." % method, RuntimeWarning) # - callback if meth in ["anneal", "cobyla", "slsqp"] and callback is not None: warn("Method %s does not support callback." % method, RuntimeWarning) # - return_all if meth in ["anneal", "l-bfgs-b", "tnc", "cobyla", "slsqp"] and options.get("return_all", False): warn("Method %s does not support the return_all option." % method, RuntimeWarning) # fun also returns the jacobian if not callable(jac): if bool(jac): fun = MemoizeJac(fun) jac = fun.derivative else: jac = None # set default tolerances if tol is not None: options = dict(options) if meth in ["nelder-mead", "newton-cg", "powell", "tnc"]: options.setdefault("xtol", tol) if meth in ["nelder-mead", "powell", "anneal", "l-bfgs-b", "tnc", "slsqp"]: options.setdefault("ftol", tol) if meth in ["bfgs", "cg", "l-bfgs-b", "tnc", "dogleg", "trust-ncg"]: options.setdefault("gtol", tol) if meth in ["cobyla"]: options.setdefault("tol", tol) if meth == "nelder-mead": return _minimize_neldermead(fun, x0, args, callback, **options) elif meth == "powell": return _minimize_powell(fun, x0, args, callback, **options) elif meth == "cg": return _minimize_cg(fun, x0, args, jac, callback, **options) elif meth == "bfgs": return _minimize_bfgs(fun, x0, args, jac, callback, **options) elif meth == "newton-cg": return _minimize_newtoncg(fun, x0, args, jac, hess, hessp, callback, **options) elif meth == "anneal": return _minimize_anneal(fun, x0, args, **options) elif meth == "l-bfgs-b": return _minimize_lbfgsb(fun, x0, args, jac, bounds, callback=callback, **options) elif meth == "tnc": return _minimize_tnc(fun, x0, args, jac, bounds, callback=callback, **options) elif meth == "cobyla": return _minimize_cobyla(fun, x0, args, constraints, **options) elif meth == "slsqp": return _minimize_slsqp(fun, x0, args, jac, bounds, constraints, **options) elif meth == "dogleg": return _minimize_dogleg(fun, x0, args, jac, hess, callback=callback, **options) elif meth == "trust-ncg": return _minimize_trust_ncg(fun, x0, args, jac, hess, hessp, callback=callback, **options) else: raise ValueError("Unknown solver %s" % method)
def minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None): """ Minimization of scalar function of one or more variables. .. versionadded:: 0.11.0 Parameters ---------- fun : callable Objective function. x0 : ndarray Initial guess. args : tuple, optional Extra arguments passed to the objective function and its derivatives (Jacobian, Hessian). method : str or callable, optional Type of solver. Should be one of - 'Nelder-Mead' - 'Powell' - 'CG' - 'BFGS' - 'Newton-CG' - 'Anneal (deprecated as of scipy version 0.14.0)' - 'L-BFGS-B' - 'TNC' - 'COBYLA' - 'SLSQP' - 'dogleg' - 'trust-ncg' - custom - a callable object (added in version 0.14.0) If not given, chosen to be one of ``BFGS``, ``L-BFGS-B``, ``SLSQP``, depending if the problem has constraints or bounds. jac : bool or callable, optional Jacobian (gradient) of objective function. Only for CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg. If `jac` is a Boolean and is True, `fun` is assumed to return the gradient along with the objective function. If False, the gradient will be estimated numerically. `jac` can also be a callable returning the gradient of the objective. In this case, it must accept the same arguments as `fun`. hess, hessp : callable, optional Hessian (matrix of second-order derivatives) of objective function or Hessian of objective function times an arbitrary vector p. Only for Newton-CG, dogleg, trust-ncg. Only one of `hessp` or `hess` needs to be given. If `hess` is provided, then `hessp` will be ignored. If neither `hess` nor `hessp` is provided, then the Hessian product will be approximated using finite differences on `jac`. `hessp` must compute the Hessian times an arbitrary vector. bounds : sequence, optional Bounds for variables (only for L-BFGS-B, TNC and SLSQP). ``(min, max)`` pairs for each element in ``x``, defining the bounds on that parameter. Use None for one of ``min`` or ``max`` when there is no bound in that direction. constraints : dict or sequence of dict, optional Constraints definition (only for COBYLA and SLSQP). Each constraint is defined in a dictionary with fields: type : str Constraint type: 'eq' for equality, 'ineq' for inequality. fun : callable The function defining the constraint. jac : callable, optional The Jacobian of `fun` (only for SLSQP). args : sequence, optional Extra arguments to be passed to the function and Jacobian. Equality constraint means that the constraint function result is to be zero whereas inequality means that it is to be non-negative. Note that COBYLA only supports inequality constraints. tol : float, optional Tolerance for termination. For detailed control, use solver-specific options. options : dict, optional A dictionary of solver options. All methods accept the following generic options: maxiter : int Maximum number of iterations to perform. disp : bool Set to True to print convergence messages. For method-specific options, see :func:`show_options()`. callback : callable, optional Called after each iteration, as ``callback(xk)``, where ``xk`` is the current parameter vector. Returns ------- res : OptimizeResult The optimization result represented as a ``OptimizeResult`` object. Important attributes are: ``x`` the solution array, ``success`` a Boolean flag indicating if the optimizer exited successfully and ``message`` which describes the cause of the termination. See `OptimizeResult` for a description of other attributes. See also -------- minimize_scalar : Interface to minimization algorithms for scalar univariate functions show_options : Additional options accepted by the solvers Notes ----- This section describes the available solvers that can be selected by the 'method' parameter. The default method is *BFGS*. **Unconstrained minimization** Method *Nelder-Mead* uses the Simplex algorithm [1]_, [2]_. This algorithm has been successful in many applications but other algorithms using the first and/or second derivatives information might be preferred for their better performances and robustness in general. Method *Powell* is a modification of Powell's method [3]_, [4]_ which is a conjugate direction method. It performs sequential one-dimensional minimizations along each vector of the directions set (`direc` field in `options` and `info`), which is updated at each iteration of the main minimization loop. The function need not be differentiable, and no derivatives are taken. Method *CG* uses a nonlinear conjugate gradient algorithm by Polak and Ribiere, a variant of the Fletcher-Reeves method described in [5]_ pp. 120-122. Only the first derivatives are used. Method *BFGS* uses the quasi-Newton method of Broyden, Fletcher, Goldfarb, and Shanno (BFGS) [5]_ pp. 136. It uses the first derivatives only. BFGS has proven good performance even for non-smooth optimizations. This method also returns an approximation of the Hessian inverse, stored as `hess_inv` in the OptimizeResult object. Method *Newton-CG* uses a Newton-CG algorithm [5]_ pp. 168 (also known as the truncated Newton method). It uses a CG method to the compute the search direction. See also *TNC* method for a box-constrained minimization with a similar algorithm. Method *Anneal* uses simulated annealing, which is a probabilistic metaheuristic algorithm for global optimization. It uses no derivative information from the function being optimized. Method *dogleg* uses the dog-leg trust-region algorithm [5]_ for unconstrained minimization. This algorithm requires the gradient and Hessian; furthermore the Hessian is required to be positive definite. Method *trust-ncg* uses the Newton conjugate gradient trust-region algorithm [5]_ for unconstrained minimization. This algorithm requires the gradient and either the Hessian or a function that computes the product of the Hessian with a given vector. **Constrained minimization** Method *L-BFGS-B* uses the L-BFGS-B algorithm [6]_, [7]_ for bound constrained minimization. Method *TNC* uses a truncated Newton algorithm [5]_, [8]_ to minimize a function with variables subject to bounds. This algorithm uses gradient information; it is also called Newton Conjugate-Gradient. It differs from the *Newton-CG* method described above as it wraps a C implementation and allows each variable to be given upper and lower bounds. Method *COBYLA* uses the Constrained Optimization BY Linear Approximation (COBYLA) method [9]_, [10]_, [11]_. The algorithm is based on linear approximations to the objective function and each constraint. The method wraps a FORTRAN implementation of the algorithm. Method *SLSQP* uses Sequential Least SQuares Programming to minimize a function of several variables with any combination of bounds, equality and inequality constraints. The method wraps the SLSQP Optimization subroutine originally implemented by Dieter Kraft [12]_. Note that the wrapper handles infinite values in bounds by converting them into large floating values. **Custom minimizers** It may be useful to pass a custom minimization method, for example when using a frontend to this method such as `scipy.optimize.basinhopping` or a different library. You can simply pass a callable as the ``method`` parameter. The callable is called as ``method(fun, x0, args, **kwargs, **options)`` where ``kwargs`` corresponds to any other parameters passed to `minimize` (such as `callback`, `hess`, etc.), except the `options` dict, which has its contents also passed as `method` parameters pair by pair. Also, if `jac` has been passed as a bool type, `jac` and `fun` are mangled so that `fun` returns just the function values and `jac` is converted to a function returning the Jacobian. The method shall return an ``OptimizeResult`` object. The provided `method` callable must be able to accept (and possibly ignore) arbitrary parameters; the set of parameters accepted by `minimize` may expand in future versions and then these parameters will be passed to the method. You can find an example in the scipy.optimize tutorial. References ---------- .. [1] Nelder, J A, and R Mead. 1965. A Simplex Method for Function Minimization. The Computer Journal 7: 308-13. .. [2] Wright M H. 1996. Direct search methods: Once scorned, now respectable, in Numerical Analysis 1995: Proceedings of the 1995 Dundee Biennial Conference in Numerical Analysis (Eds. D F Griffiths and G A Watson). Addison Wesley Longman, Harlow, UK. 191-208. .. [3] Powell, M J D. 1964. An efficient method for finding the minimum of a function of several variables without calculating derivatives. The Computer Journal 7: 155-162. .. [4] Press W, S A Teukolsky, W T Vetterling and B P Flannery. Numerical Recipes (any edition), Cambridge University Press. .. [5] Nocedal, J, and S J Wright. 2006. Numerical Optimization. Springer New York. .. [6] Byrd, R H and P Lu and J. Nocedal. 1995. A Limited Memory Algorithm for Bound Constrained Optimization. SIAM Journal on Scientific and Statistical Computing 16 (5): 1190-1208. .. [7] Zhu, C and R H Byrd and J Nocedal. 1997. L-BFGS-B: Algorithm 778: L-BFGS-B, FORTRAN routines for large scale bound constrained optimization. ACM Transactions on Mathematical Software 23 (4): 550-560. .. [8] Nash, S G. Newton-Type Minimization Via the Lanczos Method. 1984. SIAM Journal of Numerical Analysis 21: 770-778. .. [9] Powell, M J D. A direct search optimization method that models the objective and constraint functions by linear interpolation. 1994. Advances in Optimization and Numerical Analysis, eds. S. Gomez and J-P Hennart, Kluwer Academic (Dordrecht), 51-67. .. [10] Powell M J D. Direct search algorithms for optimization calculations. 1998. Acta Numerica 7: 287-336. .. [11] Powell M J D. A view of algorithms for optimization without derivatives. 2007.Cambridge University Technical Report DAMTP 2007/NA03 .. [12] Kraft, D. A software package for sequential quadratic programming. 1988. Tech. Rep. DFVLR-FB 88-28, DLR German Aerospace Center -- Institute for Flight Mechanics, Koln, Germany. Examples -------- Let us consider the problem of minimizing the Rosenbrock function. This function (and its respective derivatives) is implemented in `rosen` (resp. `rosen_der`, `rosen_hess`) in the `scipy.optimize`. >>> from scipy.optimize import minimize, rosen, rosen_der A simple application of the *Nelder-Mead* method is: >>> x0 = [1.3, 0.7, 0.8, 1.9, 1.2] >>> res = minimize(rosen, x0, method='Nelder-Mead') >>> res.x [ 1. 1. 1. 1. 1.] Now using the *BFGS* algorithm, using the first derivative and a few options: >>> res = minimize(rosen, x0, method='BFGS', jac=rosen_der, ... options={'gtol': 1e-6, 'disp': True}) Optimization terminated successfully. Current function value: 0.000000 Iterations: 52 Function evaluations: 64 Gradient evaluations: 64 >>> res.x [ 1. 1. 1. 1. 1.] >>> print res.message Optimization terminated successfully. >>> res.hess [[ 0.00749589 0.01255155 0.02396251 0.04750988 0.09495377] [ 0.01255155 0.02510441 0.04794055 0.09502834 0.18996269] [ 0.02396251 0.04794055 0.09631614 0.19092151 0.38165151] [ 0.04750988 0.09502834 0.19092151 0.38341252 0.7664427 ] [ 0.09495377 0.18996269 0.38165151 0.7664427 1.53713523]] Next, consider a minimization problem with several constraints (namely Example 16.4 from [5]_). The objective function is: >>> fun = lambda x: (x[0] - 1)**2 + (x[1] - 2.5)**2 There are three constraints defined as: >>> cons = ({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + 2}, ... {'type': 'ineq', 'fun': lambda x: -x[0] - 2 * x[1] + 6}, ... {'type': 'ineq', 'fun': lambda x: -x[0] + 2 * x[1] + 2}) And variables must be positive, hence the following bounds: >>> bnds = ((0, None), (0, None)) The optimization problem is solved using the SLSQP method as: >>> res = minimize(fun, (2, 0), method='SLSQP', bounds=bnds, ... constraints=cons) It should converge to the theoretical solution (1.4 ,1.7). """ if method is None: # Select automatically if constraints: method = 'SLSQP' elif bounds is not None: method = 'L-BFGS-B' else: method = 'BFGS' if callable(method): meth = "_custom" else: meth = method.lower() # deprecated methods if meth == 'anneal': warn('Method %s is deprecated in scipy 0.14.0' % method, DeprecationWarning) if options is None: options = {} # check if optional parameters are supported by the selected method # - jac if meth in ['nelder-mead', 'powell', 'anneal', 'cobyla'] and bool(jac): warn('Method %s does not use gradient information (jac).' % method, RuntimeWarning) # - hess if meth not in ('newton-cg', 'dogleg', 'trust-ncg', '_custom') and hess is not None: warn('Method %s does not use Hessian information (hess).' % method, RuntimeWarning) # - hessp if meth not in ('newton-cg', 'dogleg', 'trust-ncg', '_custom') and hessp is not None: warn('Method %s does not use Hessian-vector product ' 'information (hessp).' % method, RuntimeWarning) # - constraints or bounds if (meth in ['nelder-mead', 'powell', 'cg', 'bfgs', 'newton-cg', 'dogleg', 'trust-ncg'] and (bounds is not None or any(constraints))): warn('Method %s cannot handle constraints nor bounds.' % method, RuntimeWarning) if meth in ['l-bfgs-b', 'tnc'] and any(constraints): warn('Method %s cannot handle constraints.' % method, RuntimeWarning) if meth == 'cobyla' and bounds is not None: warn('Method %s cannot handle bounds.' % method, RuntimeWarning) # - callback if (meth in ['anneal', 'cobyla'] and callback is not None): warn('Method %s does not support callback.' % method, RuntimeWarning) # - return_all if (meth in ['anneal', 'l-bfgs-b', 'tnc', 'cobyla', 'slsqp'] and options.get('return_all', False)): warn('Method %s does not support the return_all option.' % method, RuntimeWarning) # fun also returns the jacobian if not callable(jac): if bool(jac): fun = MemoizeJac(fun) jac = fun.derivative else: jac = None # set default tolerances if tol is not None: options = dict(options) if meth in ['nelder-mead', 'newton-cg', 'powell', 'tnc']: options.setdefault('xtol', tol) if meth in ['nelder-mead', 'powell', 'anneal', 'l-bfgs-b', 'tnc', 'slsqp']: options.setdefault('ftol', tol) if meth in ['bfgs', 'cg', 'l-bfgs-b', 'tnc', 'dogleg', 'trust-ncg']: options.setdefault('gtol', tol) if meth in ['cobyla', '_custom']: options.setdefault('tol', tol) if meth == '_custom': return method(fun, x0, args=args, jac=jac, hess=hess, hessp=hessp, bounds=bounds, constraints=constraints, callback=callback, **options) elif meth == 'nelder-mead': return _minimize_neldermead(fun, x0, args, callback, **options) elif meth == 'powell': return _minimize_powell(fun, x0, args, callback, **options) elif meth == 'cg': return _minimize_cg(fun, x0, args, jac, callback, **options) elif meth == 'bfgs': return _minimize_bfgs(fun, x0, args, jac, callback, **options) elif meth == 'newton-cg': return _minimize_newtoncg(fun, x0, args, jac, hess, hessp, callback, **options) elif meth == 'anneal': return _minimize_anneal(fun, x0, args, **options) elif meth == 'l-bfgs-b': return _minimize_lbfgsb(fun, x0, args, jac, bounds, callback=callback, **options) elif meth == 'tnc': return _minimize_tnc(fun, x0, args, jac, bounds, callback=callback, **options) elif meth == 'cobyla': return _minimize_cobyla(fun, x0, args, constraints, **options) elif meth == 'slsqp': return _minimize_slsqp(fun, x0, args, jac, bounds, constraints, callback=callback, **options) elif meth == 'dogleg': return _minimize_dogleg(fun, x0, args, jac, hess, callback=callback, **options) elif meth == 'trust-ncg': return _minimize_trust_ncg(fun, x0, args, jac, hess, hessp, callback=callback, **options) else: raise ValueError('Unknown solver %s' % method)
def root(fun, x0, args=(), method="hybr", jac=None, tol=None, callback=None, options=None): """ Find a root of a vector function. 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`. tol : float, optional Tolerance for termination. For detailed control, use solver-specific options. 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'. options : dict, optional A dictionary of solver options. E.g. `xtol` or `maxiter`, see :obj:`show_options()` for details. Returns ------- sol : OptimizeResult The solution represented as a ``OptimizeResult`` 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 `OptimizeResult` for a description of other attributes. See also -------- show_options : Additional options accepted by the solvers 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. .. versionadded:: 0.11.0 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]) """ if not isinstance(args, tuple): args = (args,) 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 # set default tolerances if tol is not None: options = dict(options) if meth in ("hybr", "lm"): options.setdefault("xtol", tol) elif meth in ("broyden1", "broyden2", "anderson", "linearmixing", "diagbroyden", "excitingmixing", "krylov"): options.setdefault("xtol", tol) options.setdefault("xatol", np.inf) options.setdefault("ftol", np.inf) options.setdefault("fatol", np.inf) if meth == "hybr": sol = _root_hybr(fun, x0, args=args, jac=jac, **options) elif meth == "lm": sol = _root_leastsq(fun, x0, args=args, jac=jac, **options) 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) sol = _root_nonlin_solve(fun, x0, args=args, jac=jac, _method=meth, _callback=callback, **options) else: raise ValueError("Unknown solver %s" % method) return sol
def resample(x, num, t=None, axis=0, window=None): """ Resample `x` to `num` samples using Fourier method along the given axis. The resampled signal starts at the same value as `x` but is sampled with a spacing of ``len(x) / num * (spacing of x)``. Because a Fourier method is used, the signal is assumed to be periodic. Parameters ---------- x : array_like The data to be resampled. num : int The number of samples in the resampled signal. t : array_like, optional If `t` is given, it is assumed to be the sample positions associated with the signal data in `x`. axis : int, optional The axis of `x` that is resampled. Default is 0. window : array_like, callable, string, float, or tuple, optional Specifies the window applied to the signal in the Fourier domain. See below for details. Returns ------- resampled_x or (resampled_x, resampled_t) Either the resampled array, or, if `t` was given, a tuple containing the resampled array and the corresponding resampled positions. Notes ----- The argument `window` controls a Fourier-domain window that tapers the Fourier spectrum before zero-padding to alleviate ringing in the resampled values for sampled signals you didn't intend to be interpreted as band-limited. If `window` is a function, then it is called with a vector of inputs indicating the frequency bins (i.e. fftfreq(x.shape[axis]) ). If `window` is an array of the same length as `x.shape[axis]` it is assumed to be the window to be applied directly in the Fourier domain (with dc and low-frequency first). For any other type of `window`, the function `scipy.signal.get_window` is called to generate the window. The first sample of the returned vector is the same as the first sample of the input vector. The spacing between samples is changed from dx to: dx * len(x) / num If `t` is not None, then it represents the old sample positions, and the new sample positions will be returned as well as the new samples. """ x = asarray(x) X = fft(x, axis=axis) Nx = x.shape[axis] if window is not None: if callable(window): W = window(fftfreq(Nx)) elif isinstance(window, ndarray) and window.shape == (Nx,): W = window else: W = ifftshift(get_window(window, Nx)) newshape = ones(len(x.shape)) newshape[axis] = len(W) W.shape = newshape X = X * W sl = [slice(None)] * len(x.shape) newshape = list(x.shape) newshape[axis] = num N = int(np.minimum(num, Nx)) Y = zeros(newshape, 'D') sl[axis] = slice(0, (N + 1) / 2) Y[sl] = X[sl] sl[axis] = slice(-(N - 1) / 2, None) Y[sl] = X[sl] y = ifft(Y, axis=axis) * (float(num) / float(Nx)) if x.dtype.char not in ['F', 'D']: y = y.real if t is None: return y else: new_t = arange(0, num) * (t[1] - t[0]) * Nx / float(num) + t[0] return y, new_t
def minimize(fun, x0, args=(), method='BFGS', jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None): """ Minimization of scalar function of one or more variables. Parameters ---------- fun : callable Objective function. x0 : ndarray Initial guess. args : tuple, optional Extra arguments passed to the objective function and its derivatives (Jacobian, Hessian). method : str, optional - 'BFGS' jac : bool or callable, optional Jacobian of objective function. Only for CG, BFGS, Newton-CG. 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 the objective. In this case, it must accept the same arguments as `fun`. hess, hessp : callable, optional Hessian of objective function or Hessian of objective function times an arbitrary vector p. Only for Newton-CG. Only one of `hessp` or `hess` needs to be given. If `hess` is provided, then `hessp` will be ignored. If neither `hess` nor `hessp` is provided, then the hessian product will be approximated using finite differences on `jac`. `hessp` must compute the Hessian times an arbitrary vector. bounds : sequence, optional Bounds for variables (only for L-BFGS-B, TNC, COBYLA and SLSQP). ``(min, max)`` pairs for each element in ``x``, defining the bounds on that parameter. Use None for one of ``min`` or ``max`` when there is no bound in that direction. constraints : dict or sequence of dict, optional Constraints definition (only for COBYLA and SLSQP). Each constraint is defined in a dictionary with fields: type : str Constraint type: 'eq' for equality, 'ineq' for inequality. fun : callable The function defining the constraint. jac : callable, optional The Jacobian of `fun` (only for SLSQP). args : sequence, optional Extra arguments to be passed to the function and Jacobian. Equality constraint means that the constraint function result is to be zero whereas inequality means that it is to be non-negative. Note that COBYLA only supports inequality constraints. tol : float, optional Tolerance for termination. For detailed control, use solver-specific options. options : dict, optional A dictionary of solver options. All methods accept the following generic options: maxiter : int Maximum number of iterations to perform. disp : bool Set to True to print convergence messages. For method-specific options, see `show_options('minimize', method)`. callback : callable, optional Called after each iteration, as ``callback(xk)``, where ``xk`` is the current parameter vector. Returns ------- res : Result The optimization result represented as a ``Result`` object. Important attributes are: ``x`` the solution array, ``success`` a Boolean flag indicating if the optimizer exited successfully and ``message`` which describes the cause of the termination. See `Result` for a description of other attributes. Method *BFGS* uses the quasi-Newton method of Broyden, Fletcher, Goldfarb, and Shanno (BFGS) [5]_ pp. 136. It uses the first derivatives only. BFGS has proven good performance even for non-smooth optimizations """ meth = method.lower() if options is None: options = {} # fun also returns the jacobian if not callable(jac): if bool(jac): fun = MemoizeJac(fun) jac = fun.derivative else: jac = None # set default tolerances if tol is not None: options = dict(options) if meth in ['bfgs']: options.setdefault('gtol', tol) #call _minimize_bfgs in optimize_joe if meth == 'bfgs': return _minimize_bfgs(fun, x0, args, jac, callback, **options) else: raise ValueError('Unknown solver %s' % method)
def minimize_scalar(fun, bracket=None, bounds=None, args=(), method='brent', tol=None, options=None): """ Minimization of scalar function of one variable. .. versionadded:: 0.11.0 Parameters ---------- fun : callable Objective function. Scalar function, must return a scalar. bracket : sequence, optional For methods 'brent' and 'golden', `bracket` defines the bracketing interval and can either have three items `(a, b, c)` so that `a < b < c` and `fun(b) < fun(a), fun(c)` or two items `a` and `c` which are assumed to be a starting interval for a downhill bracket search (see `bracket`); it doesn't always mean that the obtained solution will satisfy `a <= x <= c`. bounds : sequence, optional For method 'bounded', `bounds` is mandatory and must have two items corresponding to the optimization bounds. args : tuple, optional Extra arguments passed to the objective function. method : str or callable, optional Type of solver. Should be one of - 'Brent' - 'Bounded' - 'Golden' - custom - a callable object (added in version 0.14.0) tol : float, optional Tolerance for termination. For detailed control, use solver-specific options. options : dict, optional A dictionary of solver options. maxiter : int Maximum number of iterations to perform. disp : bool Set to True to print convergence messages. See :func:`show_options()` for solver-specific options. Returns ------- res : OptimizeResult The optimization result represented as a ``OptimizeResult`` object. Important attributes are: ``x`` the solution array, ``success`` a Boolean flag indicating if the optimizer exited successfully and ``message`` which describes the cause of the termination. See `OptimizeResult` for a description of other attributes. See also -------- minimize : Interface to minimization algorithms for scalar multivariate functions show_options : Additional options accepted by the solvers Notes ----- This section describes the available solvers that can be selected by the 'method' parameter. The default method is *Brent*. Method *Brent* uses Brent's algorithm to find a local minimum. The algorithm uses inverse parabolic interpolation when possible to speed up convergence of the golden section method. Method *Golden* uses the golden section search technique. It uses analog of the bisection method to decrease the bracketed interval. It is usually preferable to use the *Brent* method. Method *Bounded* can perform bounded minimization. It uses the Brent method to find a local minimum in the interval x1 < xopt < x2. **Custom minimizers** It may be useful to pass a custom minimization method, for example when using some library frontend to minimize_scalar. You can simply pass a callable as the ``method`` parameter. The callable is called as ``method(fun, args, **kwargs, **options)`` where ``kwargs`` corresponds to any other parameters passed to `minimize` (such as `bracket`, `tol`, etc.), except the `options` dict, which has its contents also passed as `method` parameters pair by pair. The method shall return an ``OptimizeResult`` object. The provided `method` callable must be able to accept (and possibly ignore) arbitrary parameters; the set of parameters accepted by `minimize` may expand in future versions and then these parameters will be passed to the method. You can find an example in the scipy.optimize tutorial. Examples -------- Consider the problem of minimizing the following function. >>> def f(x): ... return (x - 2) * x * (x + 2)**2 Using the *Brent* method, we find the local minimum as: >>> from scipy.optimize import minimize_scalar >>> res = minimize_scalar(f) >>> res.x 1.28077640403 Using the *Bounded* method, we find a local minimum with specified bounds as: >>> res = minimize_scalar(f, bounds=(-3, -1), method='bounded') >>> res.x -2.0000002026 """ if callable(method): meth = "_custom" else: meth = method.lower() if options is None: options = {} if tol is not None: options = dict(options) if meth == 'bounded' and 'xatol' not in options: warn("Method 'bounded' does not support relative tolerance in x; " "defaulting to absolute tolerance.", RuntimeWarning) options['xatol'] = tol elif meth == '_custom': options.setdefault('tol', tol) else: options.setdefault('xtol', tol) if meth == '_custom': return method(fun, args=args, bracket=bracket, bounds=bounds, **options) elif meth == 'brent': return _minimize_scalar_brent(fun, bracket, args, **options) elif meth == 'bounded': if bounds is None: raise ValueError('The `bounds` parameter is mandatory for ' 'method `bounded`.') return _minimize_scalar_bounded(fun, bounds, args, **options) elif meth == 'golden': return _minimize_scalar_golden(fun, bracket, args, **options) else: raise ValueError('Unknown solver %s' % method)
def fmin_cobyla(func, x0, cons, args=(), consargs=None, rhobeg=1.0, rhoend=1e-4, iprint=1, maxfun=1000, disp=None, catol=1e-6): """ Minimize a function using the Constrained Optimization BY Linear Approximation (COBYLA) method. This method wraps a FORTRAN implentation of the algorithm. Parameters ---------- func : callable Function to minimize. In the form func(x, \\*args). x0 : ndarray Initial guess. cons : sequence Constraint functions; must all be ``>=0`` (a single function if only 1 constraint). Each function takes the parameters `x` as its first argument. args : tuple Extra arguments to pass to function. consargs : tuple Extra arguments to pass to constraint functions (default of None means use same extra arguments as those passed to func). Use ``()`` for no extra arguments. rhobeg : Reasonable initial changes to the variables. rhoend : Final accuracy in the optimization (not precisely guaranteed). This is a lower bound on the size of the trust region. iprint : {0, 1, 2, 3} Controls the frequency of output; 0 implies no output. Deprecated. disp : {0, 1, 2, 3} Over-rides the iprint interface. Preferred. maxfun : int Maximum number of function evaluations. catol : float Absolute tolerance for constraint violations. Returns ------- x : ndarray The argument that minimises `f`. See also -------- minimize: Interface to minimization algorithms for multivariate functions. See the 'COBYLA' `method` in particular. Notes ----- This algorithm is based on linear approximations to the objective function and each constraint. We briefly describe the algorithm. Suppose the function is being minimized over k variables. At the jth iteration the algorithm has k+1 points v_1, ..., v_(k+1), an approximate solution x_j, and a radius RHO_j. (i.e. linear plus a constant) approximations to the objective function and constraint functions such that their function values agree with the linear approximation on the k+1 points v_1,.., v_(k+1). This gives a linear program to solve (where the linear approximations of the constraint functions are constrained to be non-negative). However the linear approximations are likely only good approximations near the current simplex, so the linear program is given the further requirement that the solution, which will become x_(j+1), must be within RHO_j from x_j. RHO_j only decreases, never increases. The initial RHO_j is rhobeg and the final RHO_j is rhoend. In this way COBYLA's iterations behave like a trust region algorithm. Additionally, the linear program may be inconsistent, or the approximation may give poor improvement. For details about how these issues are resolved, as well as how the points v_i are updated, refer to the source code or the references below. References ---------- Powell M.J.D. (1994), "A direct search optimization method that models the objective and constraint functions by linear interpolation.", in Advances in Optimization and Numerical Analysis, eds. S. Gomez and J-P Hennart, Kluwer Academic (Dordrecht), pp. 51-67 Powell M.J.D. (1998), "Direct search algorithms for optimization calculations", Acta Numerica 7, 287-336 Powell M.J.D. (2007), "A view of algorithms for optimization without derivatives", Cambridge University Technical Report DAMTP 2007/NA03 Examples -------- Minimize the objective function f(x,y) = x*y subject to the constraints x**2 + y**2 < 1 and y > 0:: >>> def objective(x): ... return x[0]*x[1] ... >>> def constr1(x): ... return 1 - (x[0]**2 + x[1]**2) ... >>> def constr2(x): ... return x[1] ... >>> fmin_cobyla(objective, [0.0, 0.1], [constr1, constr2], rhoend=1e-7) Normal return from subroutine COBYLA NFVALS = 64 F =-5.000000E-01 MAXCV = 1.998401E-14 X =-7.071069E-01 7.071067E-01 array([-0.70710685, 0.70710671]) The exact solution is (-sqrt(2)/2, sqrt(2)/2). """ err = "cons must be a sequence of callable functions or a single"\ " callable function." try: len(cons) except TypeError: if callable(cons): cons = [cons] else: raise TypeError(err) else: for thisfunc in cons: if not callable(thisfunc): raise TypeError(err) if consargs is None: consargs = args # build constraints con = tuple({'type': 'ineq', 'fun': c, 'args': consargs} for c in cons) # options if disp is not None: iprint = disp opts = {'rhobeg': rhobeg, 'tol': rhoend, 'iprint': iprint, 'disp': iprint != 0, 'maxiter': maxfun, 'catol': catol} sol = _minimize_cobyla(func, x0, args, constraints=con, **opts) if iprint > 0 and not sol['success']: print("COBYLA failed to find a solution: %s" % (sol.message,)) return sol['x']
def schur(a, output='real', lwork=None, overwrite_a=False, sort=None, check_finite=True): """Compute Schur decomposition of a matrix. The Schur decomposition is:: A = Z T Z^H where Z is unitary and T is either upper-triangular, or for real Schur decomposition (output='real'), quasi-upper triangular. In the quasi-triangular form, 2x2 blocks describing complex-valued eigenvalue pairs may extrude from the diagonal. Parameters ---------- a : ndarray, shape (M, M) Matrix to decompose output : {'real', 'complex'}, optional Construct the real or complex Schur decomposition (for real matrices). lwork : int, optional Work array size. If None or -1, it is automatically computed. overwrite_a : bool, optional Whether to overwrite data in a (may improve performance). sort : {None, callable, 'lhp', 'rhp', 'iuc', 'ouc'}, optional Specifies whether the upper eigenvalues should be sorted. A callable may be passed that, given a eigenvalue, returns a boolean denoting whether the eigenvalue should be sorted to the top-left (True). Alternatively, string parameters may be used:: 'lhp' Left-hand plane (x.real < 0.0) 'rhp' Right-hand plane (x.real > 0.0) 'iuc' Inside the unit circle (x*x.conjugate() <= 1.0) 'ouc' Outside the unit circle (x*x.conjugate() > 1.0) Defaults to None (no sorting). check_finite : boolean, optional Whether to check the input matrixes contain only finite numbers. Disabling may give a performance gain, but may result to problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Returns ------- T : ndarray, shape (M, M) Schur form of A. It is real-valued for the real Schur decomposition. Z : ndarray, shape (M, M) An unitary Schur transformation matrix for A. It is real-valued for the real Schur decomposition. sdim : int If and only if sorting was requested, a third return value will contain the number of eigenvalues satisfying the sort condition. Raises ------ LinAlgError Error raised under three conditions: 1. The algorithm failed due to a failure of the QR algorithm to compute all eigenvalues 2. If eigenvalue sorting was requested, the eigenvalues could not be reordered due to a failure to separate eigenvalues, usually because of poor conditioning 3. If eigenvalue sorting was requested, roundoff errors caused the leading eigenvalues to no longer satisfy the sorting condition See also -------- rsf2csf : Convert real Schur form to complex Schur form """ if not output in ['real','complex','r','c']: raise ValueError("argument must be 'real', or 'complex'") if check_finite: a1 = asarray_chkfinite(a) else: a1 = asarray(a) if len(a1.shape) != 2 or (a1.shape[0] != a1.shape[1]): raise ValueError('expected square matrix') typ = a1.dtype.char if output in ['complex','c'] and typ not in ['F','D']: if typ in _double_precision: a1 = a1.astype('D') typ = 'D' else: a1 = a1.astype('F') typ = 'F' overwrite_a = overwrite_a or (_datacopied(a1, a)) gees, = get_lapack_funcs(('gees',), (a1,)) if lwork is None or lwork == -1: # get optimal work array result = gees(lambda x: None, a1, lwork=-1) lwork = result[-2][0].real.astype(numpy.int) if sort is None: sort_t = 0 sfunction = lambda x: None else: sort_t = 1 if callable(sort): sfunction = sort elif sort == 'lhp': sfunction = lambda x: (numpy.real(x) < 0.0) elif sort == 'rhp': sfunction = lambda x: (numpy.real(x) >= 0.0) elif sort == 'iuc': sfunction = lambda x: (abs(x) <= 1.0) elif sort == 'ouc': sfunction = lambda x: (abs(x) > 1.0) else: raise ValueError("sort parameter must be None, a callable, or " + "one of ('lhp','rhp','iuc','ouc')") result = gees(sfunction, a1, lwork=lwork, overwrite_a=overwrite_a, sort_t=sort_t) info = result[-1] if info < 0: raise ValueError('illegal value in %d-th argument of internal gees' % -info) elif info == a1.shape[0] + 1: raise LinAlgError('Eigenvalues could not be separated for reordering.') elif info == a1.shape[0] + 2: raise LinAlgError('Leading eigenvalues do not satisfy sort condition.') elif info > 0: raise LinAlgError("Schur form not found. Possibly ill-conditioned.") if sort_t == 0: return result[0], result[-3] else: return result[0], result[-3], result[1]
def root(fun, x0, args=(), method='hybr', jac=None, tol=None, callback=None, options=None): """ Find a root of a vector function. 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`. tol : float, optional Tolerance for termination. For detailed control, use solver-specific options. 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'. options : dict, optional A dictionary of solver options. E.g. `xtol` or `maxiter`, see :obj:`show_options()` for details. Returns ------- sol : OptimizeResult The solution represented as a ``OptimizeResult`` 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 `OptimizeResult` for a description of other attributes. See also -------- show_options : Additional options accepted by the solvers 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. .. versionadded:: 0.11.0 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]) """ if not isinstance(args, tuple): args = (args, ) 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 # set default tolerances if tol is not None: options = dict(options) if meth in ('hybr', 'lm'): options.setdefault('xtol', tol) elif meth in ('broyden1', 'broyden2', 'anderson', 'linearmixing', 'diagbroyden', 'excitingmixing', 'krylov'): options.setdefault('xtol', tol) options.setdefault('xatol', np.inf) options.setdefault('ftol', np.inf) options.setdefault('fatol', np.inf) if meth == 'hybr': sol = _root_hybr(fun, x0, args=args, jac=jac, **options) elif meth == 'lm': sol = _root_leastsq(fun, x0, args=args, jac=jac, **options) 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) sol = _root_nonlin_solve(fun, x0, args=args, jac=jac, _method=meth, _callback=callback, **options) else: raise ValueError('Unknown solver %s' % method) return sol