From: <ma...@ll...> - 2002-11-21 14:26:54
|
Jeff, below is your PINV code with some minor adjustments. The need for the extra CTRANSPOSE was probably due to MATLISP returning V^H, not V as Octave does. Also note that CTRANSPOSE of S is not needed since the singular values are real. Ray, I added some comments to the PINV code, written by Jeff, and I'd like to suggest that it be added to MATLISP. tnx mike ************************************************** Dr Michael A. Koerber Micro$oft Free Zone MIT/Lincoln Laboratory (defun pinv (a &optional (flag :svd)) " SYNTAX ====== (PINV2 A :FLAG) INPUT ----- A A Matlisp matrix, M x N FLAG A key indicating the type of computation to use for the pseudo-inverse. Default :SVD :LS Force least squares interpretation :SVD Force SVD based computation (default) OUTPUT ------ PINV Pseudo-inverse, a Matlisp matrix. DESCRIPTION =========== Given the equation Ax = b, solve for the value of A^+ which will solve x = A^+ b. A is assumed M x N. If A is M x M, and full rank, use (M:M/ A B). Use FLAG :LS when M > N and rank(A) = N. This is the canonical least squares problem. In this case A^+ = inv(A^H A) A^H. Use FLAG :SVD when rank(A) = r < N. For M < N, this is the underconstrained case for which A^+ is the minium norm solution. To compute pinv, A^+, in general, let A have an SVD A = USV^H define S^+ = diag(1/s1, 1/s2, ... 1/sr, 0 ... 0) where r is rank(A) Then the p-inv, A^+ = V S^+ U^H." (cond ((eq flag :ls) ;; force the least squares interpretation. (let ((ah (ctranspose a))) (m* (m/ (m* ah a)) ah))) ((eq flag :svd) ;; use svd method (multiple-value-bind(up sp vptranspose info) (svd a :s) ; use economy SVD (if (null info) (error "Computation of SVD failed.")) ;; form the reciprocal of the singular values (dotimes (n (min (number-of-rows sp) (number-of-cols sp))) (setf (matrix-ref sp n n) (/ (matrix-ref sp n n)))) ;; compute the pinv (m* (ctranspose vptranspose) (m* sp (ctranspose up))))) (t (error "Invalid Flag (~A) passed to PINV." flag)))) |