Written and maintained by CASRAI Editorial Board
Last updated
To minimize a function with SciPy, call scipy.optimize.minimize(fun, x0) with your objective function and a starting guess, then read res.x for the solution and res.success to confirm the solver finished properly. This guide covers the call signature, which methods accept bounds and constraints, how to read the result object, what to do when success is False, and which other scipy.optimize functions fit different problems. Behaviour below is taken from the SciPy v1.18.0 documentation.
What scipy.optimize is used for in research
The SciPy reference describes the optimize module as providing “functions for minimizing (or maximizing) objective functions, possibly subject to constraints.” In research code that usually means estimating parameters: finding the values that minimize a loss, a sum of squared residuals, or a negative log-likelihood. For the likelihood case, see the likelihood function; for a worked curve-fitting case in an assay, see four-parameter logistic standard curve fitting. Fitting a distribution by minimizing a negative log-likelihood is also how Zipf’s distribution is fitted.
Maximizing is done by minimizing the negative of the function: minimize only minimizes, so pass lambda x: -f(x) and negate res.fun afterwards.
Install or access
SciPy’s install page lists python -m pip install scipy (ideally inside a virtual environment) for pip users, and conda install scipy or mamba install scipy for conda users, with Miniforge recommended. Source: SciPy install page, checked 2026-10-29. SciPy is free, open-source software. To keep an environment reproducible across a team, see sharing a reproducible conda environment. Then import the function:
from scipy.optimize import minimize
Minimize a function step by step
The full signature in the v1.18.0 reference is:
scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)
-
Write the objective function. It takes the array of variables as its first argument and returns one number. Extra fixed inputs (your data, say) go through
args=(...)rather than globals. -
Choose a starting point
x0. The solver iterates from this guess. The SciPy example usesx0 = [1.3, 0.7, 0.8, 1.9, 1.2]for the five-variable Rosenbrock function, whose minimum value is 0 at everyx_i = 1. -
Call
minimize. The documented example is:from scipy.optimize import minimize, rosen, rosen_der x0 = [1.3, 0.7, 0.8, 1.9, 1.2] res = minimize(rosen, x0, method='Nelder-Mead', tol=1e-6) res.x # array([1., 1., 1., 1., 1.]) -
Add a gradient if you have one. Passing
jac=rosen_derwithmethod='BFGS'supplies the analytic gradient, which is what makes the next comparison possible. -
Add bounds or constraints only when the problem needs them (next section).
How to choose a method
If you do not set method, the reference says it “is chosen to be one of BFGS, L-BFGS-B, SLSQP, depending on whether or not the problem has constraints or bounds”; the Notes give the default as BFGS. The documented methods are Nelder-Mead, Powell, CG, BFGS, Newton-CG, L-BFGS-B, TNC, COBYLA, COBYQA, SLSQP, trust-constr, dogleg, trust-ncg, trust-exact and trust-krylov, or a custom callable. What each accepts:
| You need | Methods that support it (SciPy v1.18.0 reference) |
|---|---|
Bounds on variables (bounds=) |
Nelder-Mead, L-BFGS-B, TNC, SLSQP, Powell, trust-constr, COBYLA, COBYQA |
Constraints (constraints=) |
COBYLA, COBYQA, SLSQP, trust-constr |
| Neither | Any method; BFGS is the default |
The tutorial shows both constraint styles on one problem whose solution is approximately [0.4149, 0.1701]. trust-constr takes Bounds, LinearConstraint and NonlinearConstraint objects and returned [0.41494531 0.17010937]. SLSQP takes constraint dictionaries with the keys type, fun and jac, and returned [0.41494475 0.1701105] with a value of 0.342717574857755. The two agree to about five decimal places.
Same problem, two methods
On the Rosenbrock problem the tutorial reports these costs:
| Setup | Iterations | Function evaluations | Gradient evaluations |
|---|---|---|---|
Nelder-Mead, options={'xatol': 1e-8, 'disp': True} |
339 | 571 | not used |
BFGS with jac=rosen_der |
25 (the tutorial notes this “may vary”) | 30 | 30 |
Both reach a value of 0.000000. The tutorial describes the simplex algorithm as “probably the simplest way to minimize a fairly well-behaved function,” and also advises: “If there are multiple candidates, try several and see which ones best meet your needs.” An analytic gradient cuts the work sharply here, so supply jac whenever you can write it.
One variable: minimize_scalar
For a function of a single variable use scipy.optimize.minimize_scalar, described in the reference as “Local minimization of scalar function of one variable.” With method='bounded' you must give an interval; the tutorial example minimizes the Bessel function j1 on (4, 7) and finds x of about 5.33144.
Output and how to read it
minimize returns an OptimizeResult. The fields documented for it are:
| Field | Meaning |
|---|---|
x |
The solution |
success |
Boolean: whether the optimizer exited successfully |
status |
Termination status as an integer; its meaning depends on the solver, so read message |
message |
Description of the cause of termination |
fun |
Value of the objective function at x |
jac |
The Jacobian (gradient) at x, where the solver provides it |
nfev, njev, nit |
Number of function evaluations, Jacobian evaluations and iterations |
maxcv |
Maximum constraint violation, for solvers that handle constraints |
The SciPy reference notes that solvers may omit some of these fields or add others, so check the attributes your chosen method actually returns. A sensible reporting routine is to check res.success, print res.message, then record res.x, res.fun and res.nit alongside the starting point and method so the run can be reproduced (see computational reproducibility).
Troubleshooting: success is False
When res.success is False, start with res.message, which states why the solver stopped. Because status codes differ between solvers, the message is more reliable than the integer. Then work through these checks, each of which follows from the documentation above:
- Bounds or constraints passed to a method that ignores them. Check your method against the support table. If you set
boundsorconstraintsand the method is not listed, switch to one that is, such as SLSQP or trust-constr. - No gradient supplied. Provide
jacif you can; the Rosenbrock comparison shows how much work this saves. - Method does not suit the problem. The tutorial’s advice is to try several methods and keep the one that best meets your needs.
- Objective is not well behaved. The simplex method is recommended for well-behaved functions; a noisy or discontinuous objective may need a global optimizer (next section).
Free alternatives within scipy.optimize
All of SciPy is free. When minimize is not the right fit, the module offers other functions. Descriptions are quoted from the SciPy v1.18.0 optimize reference.
| Function | SciPy description |
|---|---|
minimize_scalar |
Local minimization of scalar function of one variable. |
least_squares |
Solve a nonlinear least-squares problem with bounds on the variables. |
curve_fit |
Use non-linear least squares to fit a function, f, to data. |
differential_evolution |
Finds the global minimum of a multivariate function. |
basinhopping |
Find the global minimum of a function using the basin-hopping algorithm. |
dual_annealing |
Find the global minimum of a function using Dual Annealing. |
shgo |
Finds the global minimum of a function using SHG optimization. |
linprog |
Linear programming: minimize a linear objective function subject to linear equality and inequality constraints. |
root |
Find a root of a vector function. |
For fitting a model to measured data, curve_fit and least_squares are the purpose-built options; for a general objective, minimize is the starting point. For loading and reshaping the data you fit, see Python for exploratory data analysis.
FAQ
What is scipy optimize minimize?
scipy.optimize.minimize is SciPy’s general-purpose routine for minimizing a scalar function of one or more variables, optionally with bounds and constraints. You give it the function and a starting point; it returns an OptimizeResult.
How do I do optimization with SciPy?
Import minimize, define the objective, choose x0, call minimize(fun, x0), and check res.success before using res.x. Add bounds, constraints or jac only when the problem requires them.
Which method does scipy minimize use by default?
BFGS, or L-BFGS-B or SLSQP when you supply bounds or constraints, per the v1.18.0 reference.
How do I maximize a function with scipy minimize?
Minimize the negative of the function and negate the returned fun.
Can scipy minimize handle bounds?
Yes, with Nelder-Mead, L-BFGS-B, TNC, SLSQP, Powell, trust-constr, COBYLA or COBYQA. Constraints need COBYLA, COBYQA, SLSQP or trust-constr.
Sources
- scipy.optimize.minimize, SciPy v1.18.0 reference, checked 2026-10-29
- Optimization tutorial, SciPy v1.18.0, checked 2026-10-29
- scipy.optimize.OptimizeResult, SciPy v1.18.0 reference, checked 2026-10-29
- Optimization and root finding (scipy.optimize), SciPy v1.18.0 reference, checked 2026-10-29
- Install SciPy, checked 2026-10-29








