# [PYTHON MATRIX-SIG] Linear Least Squares for LinAlg.py

Doug Heisterkamp drh@cherokee.unl.edu
Wed, 14 Aug 1996 23:12:54 -0500 (CDT)

```Hi,

I've written a linear least square function to add to LinAlg.py.  Let
me know if you find any problems with it.

Doug Heisterkamp
drh@cherokee.unl.edu

# Linear Least Squares

def solveLinearLeastSquares(a, b, rcond=1.e-10):
"""solveLinearLeastSquares(a,b) returns x,resids,rank,s
where x minimizes 2-norm(|b - Ax|)
resids is the sum square residuals
rank is the rank of A
s is an rank of the singual values of A in desending order
If b is a matrix then x is also a matrix with corresponding columns.
If the rank of A is less than the number of columns of A or greater than
the numer of rows, then residuals will be returned as an empty array
otherwise resids = sum((b-dot(A,x)**2).
Singular values less than s*rcond are treated as zero.
"""
one_eq = len(b.shape) == 1
if one_eq:
b = b[:, Numeric.NewAxis]
_assertRank2(a, b)
#   _assertSquareness(a)
m  = a.shape
n  = a.shape
n_rhs = b.shape
ldb = max(n,m)
if m != b.shape:
raise LinAlgError, 'Incompatible dimensions'
t =_commonType(a, b)
real_t = _array_type[_array_precision[t]]
lapack_routine = _findLapackRoutine('gelss', t)
bstar = Numeric.zeros((ldb,n_rhs),t)
bstar[:b.shape,:n_rhs] = cp(b)
a,bstar = _castCopyAndTranspose(t, a, bstar)
#   minimum value of lwork:3*min(n,m) + max([2*min(m,n),max(m,n),n_rhs])
lwork = 8*min(n,m) + max([2*min(m,n),max(m,n),n_rhs])
s = Numeric.zeros((min(m,n),),real_t)
work = Numeric.zeros((lwork,), t)
#   Note: in next version rcond will be passed directly to lapack module
#         by for now wrap it in an array
arcond = Numeric.array([rcond],real_t)
if _array_kind[t] == 1: # Complex routines take different arguments
rwork = Numeric.zeros((5*min(m,n)-1,), real_t)
results = lapack_routine( m, n, n_rhs, a, m, bstar,ldb , s, arcond,
0,work,lwork,rwork,0 )
else:
results = lapack_routine( m, n, n_rhs, a, m, bstar,ldb , s, arcond,
0,work,lwork,0 )
if results['info'] > 0:
raise LinAlgError, 'SVD did not converge in Linear Least Squares'
resids = Numeric.array([],t)
if one_eq:
x = cp(Numeric.ravel(bstar)[:n])
if (results['rank']==n) and (m>n):
resids = Numeric.array([Numeric.sum((Numeric.ravel(bstar)[n:])**2)])
else:
x = cp(transpose(bstar)[:n,:])
if (results['rank']==n) and (m>n):
resids = cp(Numeric.sum((transpose(bstar)[n:,:])**2))
return x,resids,results['rank'],cp(s[:min(n,m)])

=================
MATRIX-SIG  - SIG on Matrix Math for Python

send messages to: matrix-sig@python.org