scipy.optimize.lsq_linear

scipy.optimize.lsq_linear(A, b, bounds=(-inf, inf), method='trf', tol=1e-10, lsq_solver=None, lsmr_tol=None, max_iter=None, verbose=0)[source]

Solve a linear least-squares problem with bounds on the variables.

lsq_linear finds a minimum of the cost function 0.5 * ||A x - b||**2, such that lb <= x <= ub. Where A is an m-by-n design matrix and b is a target vector with m elements.

Parameters:

A : array_like, sparse matrix of LinearOperator, shape (m, n)

Design matrix. Can be scipy.sparse.linalg.LinearOperator.

b : array_like, shape (m,)

Target vector.

bounds : 2-tuple of array_like, optional

Lower and upper bounds on independent variables. Defaults to no bounds. Each array must have shape (n,) or be a scalar, in the latter case a bound will be the same for all variables. Use np.inf with an appropriate sign to disable bounds on all or some variables.

method : ‘trf’ or ‘bvls’, optional

Method to perform minimization.

  • ‘trf’ : Trust Region Reflective algorithm adapted for a linear least-squares problem. This is an interior-point-like method and the required number of iterations is weakly correlated with the number of variables.
  • ‘bvls’ : Bounded-Variable Least-Squares algorithm. This is an active set method, which requires the number iterations comparable to the number of variables. Does not support sparse matrices.

tol : float, optional

Tolerance parameter. The algorithm terminates if the relative change of the cost function is less than tol on the last iteration. Additionally the first-order optimality measure is considered:

  • method='trf' terminates if the uniform norm of the gradient, scaled to account for the presence of the bounds, is less than tol.
  • method='bvls' terminates if Karush-Kuhn-Tucker conditions are violated by less than tol.

lsq_solver : {None, ‘exact’, ‘lsmr’}, optional

Method of solving unbounded least-squares problems throughout iterations:

  • ‘exact’ : Use dense QR or SVD decomposition approach. Can’t be used when A is sparse or LinearOperator.
  • ‘lsmr’ : Use scipy.sparse.linalg.lsmr iterative procedure which requires only matrix-vector product evaluations. Can’t be used with method='bvls'.

If None (default) the solver is chosen based on type of A.

lsmr_tol : None, float or ‘auto’, optional

Tolerance parameters ‘atol’ and ‘btol’ for ‘lsmr’ solver. If None (default), it is set to 1e-2 * tol. If ‘auto’, the tolerance will be adjusted based on the optimality of the current iterate. It can speed up the optimization process, but not always reliable.

max_iter : None or int, optional

Maximum number of iterations before termination. If None (default), it is set to 100 for method='trf' or to the number of variables for method='bvls' (not counting iterations for ‘bvls’ initialization).

verbose : {0, 1, 2}, optional

Level of algorithm’s verbosity:

  • 0 : work silently (default).
  • 1 : display a termination report.
  • 2 : display progress during iterations.
Returns:

OptimizeResult with the following fields defined:

x : ndarray, shape (n,)

Solution found.

cost : float

Value of the cost function at the solution.

fun : ndarray, shape (m,)

Vector of residuals at the solution.

optimality : float

First-order optimality measure. The exact meaning depends on method, refer to the description of tol parameter.

active_mask : ndarray of int, shape (n,)

Each component shows whether a corresponding constraint is active (that is, whether a variable is at the bound):

  • 0 : a constraint is not active.
  • -1 : a lower bound is active.
  • 1 : an upper bound is active.

Somewhat arbitrary because it is determined within a tolerance threshold.

nit : int

Number of iterations. Zero if the unconstrained solution is optimal.

status : int

Reason for algorithm termination:

  • -1 : the algorithm was not able to make progress on the last iteration.
  • 0 : the maximum number of iterations is exceeded.
  • 1 : the first-order optimality measure is less than tol.
  • 2 : the relative change of the cost function is less than tol.
  • 3 : the unconstrained solution is optimal.

message : str

Verbal description of the termination reason.

success : bool

True if one of the convergence criteria is satisfied (status > 0).

See also

nnls
Linear least squares with non-negativity constraint.
least_squares
Nonlinear least squares with bounds on the variables.

Notes

The algorithm first computes the unconstrained least-squares solution by numpy.linalg.lstsq or scipy.sparse.linalg.lsmr depending on lsq_solver. This solution is returned as optimal if it lies within the bounds.

Method ‘trf’ runs the adaptation of the algorithm described in [STIR] for a linear least-squares problem. The iterations are essentially the same as in the nonlinear least-squares algorithm, but as the quadratic function model is always accurate, we don’t need to track or modify the radius of a trust region. The line search (backtracking) is used as a safety net when a selected step does not decrease the cost function. Read more detailed description of the algorithm in scipy.optimize.least_squares.

Method ‘bvls’ runs a Python implementation of the algorithm described in [BVLS]. The algorithm maintains active and free sets of variables, on each iteration chooses a new variable to move from the active set to the free set and then solves the unconstrained least-squares problem on free variables. This algorithm is guaranteed to give an accurate solution eventually, but may require up to n iterations for a problem with n variables. Additionally, an ad-hoc initialization procedure is implemented, that determines which variables to set free or active initially. It takes some number of iterations before actual BVLS starts, but can significantly reduce the number of further iterations.

References

[STIR](1, 2) M. A. Branch, T. F. Coleman, and Y. Li, “A Subspace, Interior, and Conjugate Gradient Method for Large-Scale Bound-Constrained Minimization Problems,” SIAM Journal on Scientific Computing, Vol. 21, Number 1, pp 1-23, 1999.
[BVLS](1, 2) P. B. Start and R. L. Parker, “Bounded-Variable Least-Squares: an Algorithm and Applications”, Computational Statistics, 10, 129-141, 1995.

Examples

In this example a problem with a large sparse matrix and bounds on the variables is solved.

>>> from scipy.sparse import rand
>>> from scipy.optimize import lsq_linear
...
>>> np.random.seed(0)
...
>>> m = 20000
>>> n = 10000
...
>>> A = rand(m, n, density=1e-4)
>>> b = np.random.randn(m)
...
>>> lb = np.random.randn(n)
>>> ub = lb + 1
...
>>> res = lsq_linear(A, b, bounds=(lb, ub), lsmr_tol='auto', verbose=1)
# may vary
The relative change of the cost function is less than `tol`.
Number of iterations: 16, initial cost: 1.5039e+04,final cost 1.1112e+04, first-order optimality 4.66e-08.