Code Red > AutoLISP (Vanilla / Visual)

nxn matrices - challenge

(1/4) > >>

ribarm:
I never had some math books ab matrices, so my research is totally unknown...

With this my examples, I realized that I can't get correct m/m if determinant is 0.0... Beside that, maybe I am wrong and maybe there is more elegant and efficient way to accomplish this task and what is more important my version isn't correct... It may give correct result in random cases but with this case I am pretty stuck... If I multiply 2 matrices and get their product, when I try to divide product with one of these 2 matrix I get wrong or error result (divide by zero)... Can someone reply with right direction?

--- Code - Auto/Visual Lisp: ---;;;***********************************************************************************;;;;;; (detm m) function calculates determinant of square martix                         ;;;;;; Marko Ribar, d.i.a.                                                               ;;;;;; Args: m - nxn matrix                                                              ;;;;;; (detm '((0 1) (1 0)))                                                             ;;;;;; (detm '((1.4 2.1 5.4 6.5) (4.1 9.3 4.5 8.5) (1.2 4.1 6.2 7.5) (4.7 8.5 9.3 0.1))) ;;;;;;***********************************************************************************;;;(defun detm ( m / d i j r )   (defun d ( k n / z )    (setq k (cdr k))    (setq k (apply 'mapcar (cons 'list k)))    (setq z -1)    (while (<= (setq z (1+ z)) (length k))      (if (eq z n)        (setq k (cdr k))        (setq k (reverse (cons (car k) (reverse (cdr k)))))      )    )    (setq k (apply 'mapcar (cons 'list k)))    (if (= (length k) 1) (caar k) k)  )   (if (not (eq (length m) 1))    (progn      (setq i -1)      (setq j -1)      (setq r 0)      (foreach e (car m)        (setq i (1+ i))        (setq j (* j (- 1)))        (setq r (+ r (* j e (if (listp (d m i)) (detm (d m i)) (d m i)))))      )      r    )    (caar m)  )) ;; TRP;; Transposes a matrix -Doug Wilson-;;;; Argument : a matrix (defun trp (m) (apply 'mapcar (cons 'list m))) ;; MXV;; Applies a transformation matrix to a vector -Vladimir Nesterovsky-;;;; Arguments : a matrix and a vector (defun mxv (m v)  (mapcar (function (lambda (r) (apply '+ (mapcar '* r v))))          m  )) ;; MXM;; Multiplies (combinates) two matrices -Vladimir Nesterovsky-;;;; Arguments : two matrices (defun mxm (m q)  (mapcar (function (lambda (r) (mxv (trp q) r))) m)) ;; M/V;; Applies a transformation matrix to a vector -Marko Ribar-;;;; Arguments : a matrix and a vector (defun m/v (m v)  (mapcar    (function      (lambda (r)        (apply '+               (mapcar '/ r (mapcar (function (lambda (r) (* -1 r))) v))        )      )    )    m  )) ;; M/M;; Divides two matrices -Marko Ribar-;;;; Arguments : two matrices (defun m/m (m q / Dq k j D mj mk)  (setq Dq (detm (trp q)))  (setq k -1)  (repeat (length m)    (setq k (1+ k))    (setq j -1)    (repeat (length (car (trp q)))      (setq j (1+ j))      (setq D             (detm               (mapcar                 (function                   (lambda (x y)                     (subst x (nth j y) y)                   )                 )                 (nth k m)                 (trp q)               )             )      )      (setq mj (cons (/ D Dq) mj))    )    (setq mj (reverse mj))    (setq mk (cons mj mk))    (setq mj nil)  )  (reverse mk)) (defun c:m1xm2 ()  (setq mat1 '(               (10. 20. 30.)               (40. 50. 60.)               (70. 80. 90.)              )  )  (setq mat2 '(               (90. 80. 70.)               (60. 50. 40.)               (30. 20. 10.)              )  )  (princ (setq mm (mxm mat1 mat2)))  (prin1)) (defun c:mm/m2 ()  (princ (m/m mm mat2))  (prin1)) (defun c:mm/m1 ()  (princ (m/m mm mat1))  (prin1))
M.R.

ribarm:
I figured that only with normal multiplications and divisions of matrices, results can be correct in both directions (m/m-n mm mat1) = mat2 and (m/m-n mm mat2) = mat1... With (transposed additional multiplication and division) direction is single : (mxm mat1 mat2) = mm; (m/m mm mat2) = mat1, but (m/m mm mat1) /= mat2...

Beside this with normal multiplication and division of matrices there can't be error (determinant isn't used in calculations, so no divide by zero error)

--- Code - Auto/Visual Lisp: ---;;;***********************************************************************************;;;;;; (detm m) function calculates determinant of square martix                         ;;;;;; Marko Ribar, d.i.a.                                                               ;;;;;; Args: m - nxn matrix                                                              ;;;;;; (detm '((0 1) (1 0)))                                                             ;;;;;; (detm '((1.4 2.1 5.4 6.5) (4.1 9.3 4.5 8.5) (1.2 4.1 6.2 7.5) (4.7 8.5 9.3 0.1))) ;;;;;;***********************************************************************************;;;(defun detm ( m / d i j r )   (defun d ( k n / z )    (setq k (cdr k))    (setq k (apply 'mapcar (cons 'list k)))    (setq z -1)    (while (<= (setq z (1+ z)) (length k))      (if (eq z n)        (setq k (cdr k))        (setq k (reverse (cons (car k) (reverse (cdr k)))))      )    )    (setq k (apply 'mapcar (cons 'list k)))    (if (= (length k) 1) (caar k) k)  )   (if (not (eq (length m) 1))    (progn      (setq i -1)      (setq j -1)      (setq r 0)      (foreach e (car m)        (setq i (1+ i))        (setq j (* j (- 1)))        (setq r (+ r (* j e (if (listp (d m i)) (detm (d m i)) (d m i)))))      )      r    )    (caar m)  )) ;; TRP;; Transposes a matrix -Doug Wilson-;;;; Argument : a matrix (defun trp (m) (apply 'mapcar (cons 'list m))) ;; MXV;; Applies a transformation matrix to a vector -Vladimir Nesterovsky-;;;; Arguments : a matrix and a vector (defun mxv (m v) (mapcar (function (lambda (r) (apply '+ (mapcar '* r v))))         m )) ;; MXM;; Multiplies (combinates) two matrices -Vladimir Nesterovsky-;;;; Arguments : two matrices (defun mxm (m q) (mapcar (function (lambda (r) (mxv (trp q) r))) m)) ;; MXM-N;; Multiplies two matrices (normal) -Marko Ribar-;;;; Arguments : two matrices (defun mxm-n (m q) (mapcar (function (lambda (r j) (mapcar (function (lambda (a b) (* a b))) r j))) m q)) ;; M/V;; Applies a transformation matrix to a vector (inverse signs multiplication) -Marko Ribar-;;;; Arguments : a matrix and a vector (defun m/v (m v) (mapcar   (function     (lambda (r)       (apply '+              (mapcar '/ r (mapcar (function (lambda (r) (* -1 r))) v))       )     )   )   m )) ;; V/M;; Calculates vector of division of vector and matrix -Marko Ribar-;; (v/m (mxv mat v) mat) = v;; Arguments : a vector and a matrix (defun v/m (v m / Dm k D mk) (setq Dm (detm m)) (setq k -1) (repeat (length v)   (setq k (1+ k))   (setq D          (detm            (mapcar              (function                (lambda (x y)                  (subst x (nth k y) y)                )              )              v              m            )          )   )   (setq mk (cons (/ D Dm) mk)) ) (reverse mk)) ;; M/M;; Divides two matrices -Marko Ribar-;;;; Arguments : two matrices (defun m/m (m q / Dq k j D mj mk) (setq Dq (detm (trp q))) (setq k -1) (repeat (length m)   (setq k (1+ k))   (setq j -1)   (repeat (length (car (trp q)))     (setq j (1+ j))     (setq D            (detm              (mapcar                (function                  (lambda (x y)                    (subst x (nth j y) y)                  )                )                (nth k m)                (trp q)              )            )     )     (setq mj (cons (/ D Dq) mj))   )   (setq mj (reverse mj))   (setq mk (cons mj mk))   (setq mj nil) ) (reverse mk)) ;; M/M-N;; Divides two matrices (normal) -Marko Ribar-;;;; Arguments : two matrices (defun m/m-n (m q) (mapcar (function (lambda (r j) (mapcar (function (lambda (a b) (/ a b))) r j))) m q)) (defun c:m1xm2 () (setq mat1 '(              (1. 4. 7.)              (3. 6. 5.)              (2. 9. 8.)             ) ) (setq mat2 '(              (1. 5. 6.)              (3. 2. 8.)              (9. 7. 4.)             ) ) (princ (setq mm (mxm mat1 mat2))) (prin1)) (defun c:mm/m2 () (princ (m/m mm mat2)) (prin1)) (defun c:m1xm2-n () (setq mat1 '(              (1. 4. 7.)              (3. 6. 5.)              (2. 9. 8.)             ) ) (setq mat2 '(              (1. 5. 6.)              (3. 2. 8.)              (9. 7. 4.)             ) ) (princ (setq mm (mxm-n mat1 mat2))) (prin1)) (defun c:mm/m2-n () (princ (m/m-n mm mat2)) (prin1)) (defun c:mm/m1-n () (princ (m/m-n mm mat1)) (prin1))
M.R.

ribarm:

--- Code - Auto/Visual Lisp: ---;; V/M;; Calculates vector of division of vector and matrix -Marko Ribar-;; (v/m (mxv mat v) mat) = v;; Arguments : a vector and a matrix
M.R.

Stefan:
Hi Marko

Just a remark: (detm '((0 1) (1 0))) = 0 but it should be -1.

Try one of this http://www.theswamp.org/index.php?topic=30944.0

Lee Mac:
Here is an updated version of my code in that thread:

--- Code - Auto/Visual Lisp: ---;; Matrix Determinant  -  Lee Mac;; Args: m - nxn matrix (defun detm ( m / i j )    (setq i -1 j 0)    (cond        (   (null (cdr  m)) (caar m))        (   (null (cddr m)) (- (* (caar m) (cadadr m)) (* (cadar m) (caadr m))))        (   (apply '+                (mapcar                   '(lambda ( c ) (setq j (1+ j))                        (* c (setq i (- i))                            (detm                                (mapcar                                   '(lambda ( x / k )                                        (setq k 0)                                        (vl-remove-if '(lambda ( y ) (= j (setq k (1+ k)))) x)                                    )                                    (cdr m)                                )                            )                        )                    )                    (car m)                )            )        )    ))
--- Code - Auto/Visual Lisp: ---_\$ (detm '((0 1) (1 0)))-1_\$ (detm '((1.4 2.1 5.4 6.5) (4.1 9.3 4.5 8.5) (1.2 4.1 6.2 7.5) (4.7 8.5 9.3 0.1)))-577.975( Verification of last example )