Skip to Content

LSQ_LINEAR

Overview

The LSQ_LINEAR function solves linear least-squares problems with bound constraints by wrapping scipy.optimize.lsq_linear. It minimizes 12Axb22\frac{1}{2}\lVert Ax - b \rVert_2^2 subject to optional lower and upper bounds on the variables, offering both trust-region reflective and exact solvers. This example function is provided as-is without any representation of accuracy.

Usage

To fit a bounded linear system in Excel:

=LSQ_LINEAR(a_matrix, b_vector, [bounds_lower], [bounds_upper], [lsq_linear_method], [tol], [max_iter])
  • a_matrix (2D list, required): Coefficient matrix AA with one row per equation.
  • b_vector (2D list, required): Right-hand-side vector bb with one entry per row of AA.
  • bounds_lower (2D list, optional): Single row providing lower bounds for each variable.
  • bounds_upper (2D list, optional): Single row providing upper bounds for each variable.
  • lsq_linear_method (string (enum), optional, default="trf"): Solver choice. Valid options: Trust Region Reflective, Bounded Variable Least Squares.
  • tol (float, optional, default=1e-10): Termination tolerance (must be positive).
  • max_iter (int, optional): Maximum number of iterations allowed.

The function returns a single-row 2D list containing the fitted variables followed by the cost value 12Axb22\frac{1}{2}\lVert Ax - b \rVert_2^2, or an error message string if validation fails.

Examples

Example 1: Identity System

Inputs:

a_matrixb_vector
101
012

Excel formula:

=LSQ_LINEAR({1,0;0,1}, {1;2})

Expected output:

x₁x₂Cost
1.0002.0000.000

Example 2: Bounded Solution

Inputs:

a_matrixb_vectorbounds_lowerbounds_upper
1050-230
01-1

Excel formula:

=LSQ_LINEAR({1,0;0,1}, {5;-1}, {0,-2}, {3,0})

Expected output:

x₁x₂Cost
3.000-1.0002.000

Example 3: Overdetermined Exact Solver

Inputs:

a_matrixb_vectormethod
111bvls
122
132

Excel formula:

=LSQ_LINEAR({1,1;1,2;1,3}, {1;2;2}, , , "bvls")

Expected output:

x₁x₂Cost
0.6670.5000.083

Example 4: Custom Tolerance and Iterations

Inputs:

a_matrixb_vectorbounds_lowerbounds_uppertolmax_iter
2-11-1-1221E-08200
113
1-10

Excel formula:

=LSQ_LINEAR({2,-1;1,1;1,-1}, {1;3;0}, {-1,-1}, {2,2}, , 1E-08, 200)

Expected output:

x₁x₂Cost
1.3571.5710.036

Python Code

import math from typing import List, Optional import numpy as np from scipy.optimize import lsq_linear as scipy_lsq_linear def lsq_linear( a_matrix: List[List[float]], b_vector: List[List[float]], bounds_lower: Optional[List[List[float]]] = None, bounds_upper: Optional[List[List[float]]] = None, lsq_linear_method: str = 'trf', tol: float = 1e-10, max_iter: Optional[int] = None, ): """ Solve a bounded linear least-squares problem. Wraps scipy.optimize.lsq_linear to solve linear least-squares problems with bounds. See https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.lsq_linear.html Args: a_matrix: 2D list representing the coefficient matrix A. b_vector: 2D list representing the observation vector b. bounds_lower: Optional 2D list providing lower bounds for each variable. bounds_upper: Optional 2D list providing upper bounds for each variable. lsq_linear_method: Solver to use ('trf' or 'bvls'). tol: Tolerance for termination. max_iter: Maximum number of iterations for the solver. Returns: list[list[float]] or str: [[x1, x2, ..., cost]] on success, otherwise an error message string. This example function is provided as-is without any representation of accuracy. """ # Validate coefficient matrix try: a_mat = np.array(a_matrix, dtype=float) except Exception: return "Invalid input: a_matrix must be a 2D list of numeric values." if a_mat.ndim != 2: return "Invalid input: a_matrix must be two-dimensional." # Validate observation vector try: b_vec = np.array(b_vector, dtype=float).flatten() except Exception: return "Invalid input: b_vector must be a 2D list of numeric values." if b_vec.size != a_mat.shape[0]: return "Invalid input: Length of b_vector must equal number of rows in a_matrix." n_vars = a_mat.shape[1] # Process bounds lower = None upper = None if bounds_lower is not None: try: lower_array = np.array(bounds_lower, dtype=float) lower = lower_array.flatten() if lower_array.ndim > 1 else lower_array except Exception: return "Invalid input: bounds_lower must contain numeric values." if lower.size != n_vars: return "Invalid input: bounds_lower must have one value per variable." if bounds_upper is not None: try: upper_array = np.array(bounds_upper, dtype=float) upper = upper_array.flatten() if upper_array.ndim > 1 else upper_array except Exception: return "Invalid input: bounds_upper must contain numeric values." if upper.size != n_vars: return "Invalid input: bounds_upper must have one value per variable." if lower is not None and upper is not None: if np.any(lower > upper): return "Invalid input: Each lower bound must be less than or equal to the corresponding upper bound." if lower is None: lower = -math.inf * np.ones(n_vars) if upper is None: upper = math.inf * np.ones(n_vars) bounds = (lower, upper) # Validate method valid_methods = {'trf', 'bvls'} if lsq_linear_method not in valid_methods: return f"Invalid method: {lsq_linear_method}. Must be one of: {', '.join(sorted(valid_methods))}" # Validate tolerance and max_iter try: tol = float(tol) except (TypeError, ValueError): return "Invalid input: tol must be a float." if tol <= 0: return "Invalid input: tol must be positive." max_iter_param = None if max_iter is not None: try: max_iter_param = int(max_iter) except (TypeError, ValueError): return "Invalid input: max_iter must be an integer." if max_iter_param <= 0: return "Invalid input: max_iter must be positive." try: result = scipy_lsq_linear( a_mat, b_vec, bounds=bounds, method=lsq_linear_method, tol=tol, max_iter=max_iter_param, ) except ValueError as exc: return f"Error during lsq_linear: {exc}" except Exception as exc: return f"Error during lsq_linear: {exc}" if not result.success: return f"lsq_linear failed: {result.message}" try: solution_vector = [float(val) for val in result.x] except (TypeError, ValueError): return "Error converting solution vector to floats." cost = float(result.cost) if result.cost is not None else float(np.sum((a_mat @ result.x - b_vec) ** 2) / 2.0) return [solution_vector + [cost]]

Example Workbook

Link to Workbook 

Last updated on