brute(func, ranges, args=(), Ns=20, full_output=0, finish=<function fmin at 0x0000000>, disp=False, workers=1)
Uses the "brute force" method, i.e., computes the function's value at each point of a multidimensional grid of points, to find the global minimum of the function.
The function is evaluated everywhere in the range with the datatype of the first call to the function, as enforced by the vectorize
NumPy function. The value and type of the function evaluation returned when full_output=True
are affected in addition by the finish
argument (see Notes).
The brute force approach is inefficient because the number of grid points increases exponentially - the number of grid points to evaluate is Ns ** len(x)
. Consequently, even with coarse grid spacing, even moderately sized problems can take a long time to run, and/or run into memory limitations.
Note 1: The program finds the gridpoint at which the lowest value of the objective function occurs. If finish
is None, that is the point returned. When the global minimum occurs within (or not very far outside) the grid's boundaries, and the grid is fine enough, that point will be in the neighborhood of the global minimum.
However, users often employ some other optimization program to "polish" the gridpoint values, i.e., to seek a more precise (local) minimum near :None:None:`brute's`
best gridpoint. The brute
function's finish
option provides a convenient way to do that. Any polishing program used must take :None:None:`brute's`
output as its initial guess as a positional argument, and take :None:None:`brute's`
input values for :None:None:`args`
as keyword arguments, otherwise an error will be raised. It may additionally take :None:None:`full_output`
and/or :None:None:`disp`
as keyword arguments.
brute
assumes that the finish
function returns either an OptimizeResult
object or a tuple in the form: (xmin, Jmin, ... , statuscode)
, where xmin
is the minimizing value of the argument, Jmin
is the minimum value of the objective function, "..." may be some other returned values (which are not used by brute
), and statuscode
is the status code of the finish
program.
Note that when finish
is not None, the values returned are those of the finish
program, not the gridpoint ones. Consequently, while brute
confines its search to the input grid points, the finish
program's results usually will not coincide with any gridpoint, and may fall outside the grid's boundary. Thus, if a minimum only needs to be found over the provided grid points, make sure to pass in :None:None:`finish=None`
.
Note 2: The grid of points is a :None:None:`numpy.mgrid`
object. For brute
the :None:None:`ranges`
and :None:None:`Ns`
inputs have the following effect. Each component of the :None:None:`ranges`
tuple can be either a slice object or a two-tuple giving a range of values, such as (0, 5). If the component is a slice object, brute
uses it directly. If the component is a two-tuple range, brute
internally converts it to a slice object that interpolates :None:None:`Ns`
points from its low-value to its high-value, inclusive.
The objective function to be minimized. Must be in the form f(x, *args)
, where x
is the argument in the form of a 1-D array and args
is a tuple of any additional fixed parameters needed to completely specify the function.
Each component of the :None:None:`ranges`
tuple must be either a "slice object" or a range tuple of the form (low, high)
. The program uses these to create the grid of points on which the objective function will be computed. See :None:None:`Note 2`
for more detail.
Any additional fixed parameters needed to completely specify the function.
Number of grid points along the axes, if not otherwise specified. See :None:None:`Note2`
.
If True, return the evaluation grid and the objective function's values on it.
An optimization function that is called with the result of brute force minimization as initial guess. finish
should take :None:None:`func`
and the initial guess as positional arguments, and take :None:None:`args`
as keyword arguments. It may additionally take :None:None:`full_output`
and/or :None:None:`disp`
as keyword arguments. Use None if no "polishing" function is to be used. See Notes for more details.
Set to True to print convergence messages from the finish
callable.
If :None:None:`workers`
is an int the grid is subdivided into :None:None:`workers`
sections and evaluated in parallel (uses :None:None:`multiprocessing.Pool <multiprocessing>`
). Supply :None:None:`-1`
to use all cores available to the Process. Alternatively supply a map-like callable, such as :None:None:`multiprocessing.Pool.map`
for evaluating the grid in parallel. This evaluation is carried out as workers(func, iterable)
. Requires that :None:None:`func`
be pickleable.
A 1-D array containing the coordinates of a point at which the objective function had its minimum value. (See :None:None:`Note 1`
for which point is returned.)
Function value at the point :None:None:`x0`
. (Returned when :None:None:`full_output`
is True.)
Representation of the evaluation grid. It has the same length as :None:None:`x0`
. (Returned when :None:None:`full_output`
is True.)
Function values at each point of the evaluation grid, i.e., Jout = func(*grid)
. (Returned when :None:None:`full_output`
is True.)
Minimize a function over a given range by brute force.
We illustrate the use of brute
to seek the global minimum of a function of two variables that is given as the sum of a positive-definite quadratic and two deep "Gaussian-shaped" craters. Specifically, define the objective function f
as the sum of three other functions, f = f1 + f2 + f3
. We suppose each of these has a signature (z, *params)
, where z = (x, y)
, and params
and the functions are as defined below.
>>> params = (2, 3, 7, 8, 9, 10, 44, -1, 2, 26, 1, -2, 0.5)
... def f1(z, *params):
... x, y = z
... a, b, c, d, e, f, g, h, i, j, k, l, scale = params
... return (a * x**2 + b * x * y + c * y**2 + d*x + e*y + f)
>>> def f2(z, *params):
... x, y = z
... a, b, c, d, e, f, g, h, i, j, k, l, scale = params
... return (-g*np.exp(-((x-h)**2 + (y-i)**2) / scale))
>>> def f3(z, *params):
... x, y = z
... a, b, c, d, e, f, g, h, i, j, k, l, scale = params
... return (-j*np.exp(-((x-k)**2 + (y-l)**2) / scale))
>>> def f(z, *params):
... return f1(z, *params) + f2(z, *params) + f3(z, *params)
Thus, the objective function may have local minima near the minimum of each of the three functions of which it is composed. To use fmin
to polish its gridpoint result, we may then continue as follows:
>>> rranges = (slice(-4, 4, 0.25), slice(-4, 4, 0.25))
... from scipy import optimize
... resbrute = optimize.brute(f, rranges, args=params, full_output=True,
... finish=optimize.fmin)
... resbrute[0] # global minimum array([-1.05665192, 1.80834843])
>>> resbrute[1] # function value at global minimum -3.4085818767
Note that if finish
had been set to None, we would have gotten the gridpoint [-1.0 1.75] where the rounded function value is -2.892.
The following pages refer to to this document either explicitly or contain code examples using this.
scipy.optimize._optimize.brute
Hover to see nodes names; edges to Self not shown, Caped at 50 nodes.
Using a canvas is more power efficient and can get hundred of nodes ; but does not allow hyperlinks; , arrows or text (beyond on hover)
SVG is more flexible but power hungry; and does not scale well to 50 + nodes.
All aboves nodes referred to, (or are referred from) current nodes; Edges from Self to other have been omitted (or all nodes would be connected to the central node "self" which is not useful). Nodes are colored by the library they belong to, and scaled with the number of references pointing them