2012-07-12 85 views
3

Common Lisp新手。编写lisp代码与编写C++/java完全不同,就像我之前写的那样。写一个简单的矩阵类在普通的lisp练习

我想写一个简单的矩阵类在普通的lisp练习。有些代码这样的:

(defun make-matrix (row col) 
    (make-list row :initial-element (make-list col :initial-element nil))) 

(defun init-matrix (matrix init-value) 
    (labels ((set-element-value (lst) 
           (if (and lst 
             (listp lst)) 
            (mapcar #'set-element-value lst) 
           (setf lst init-value)))) 
    (set-element-value matrix))) 

(defun matrix+ (&rest matrices) 
    (apply #'mapcar (lambda (&rest rows) 
        (apply #'mapcar #'+ rows)) matrices)) 

我的问题是我能写一个矩阵+接受不同数量的不“适用”的论点,或者更好的办法?在某种程度上,lisp应该是?

如何矩阵*,可以有人向我展示一些令人敬畏的代码接受矩阵*中的任意数量的参数?谢谢。

+0

@wvxvw稍后我会看一看。 – Boris 2012-07-12 15:26:44

回答

6

Common Lisp有n维数组。我会用这些矩阵操作。

见:​​,AREF,...

通常我还会再编写一个二进制(取两个参数)矩阵运算。然后使用REDUCE对矩阵列表进行操作。

CL-USER > (make-array '(3 5) :initial-element 0) 
#2A((0 0 0 0 0) (0 0 0 0 0) (0 0 0 0 0)) 

上面创建一个尺寸为3x5的2维数组作为初始内容。

+0

也许我应该停止这个简单的练习,然后找到一些东西......我会看到更详细的文档。谢谢。 – Boris 2012-07-12 15:25:25

3

矩阵乘法。我不能保证这是最好的例子,但它非常简单。这是给你使用数组而不是列表。此外,当然,你可以优化方阵,或特殊情况下,如单位矩阵等等。但是这仅仅意味着简单,效率不高,等等

(defun matrix* (&rest matrices) 
    (assert (cdr matrices) nil 
      "You will achieve nothing by multiplying a single matrix.") 
    (reduce 
    #'(lambda (a b) 
     (assert (= (array-dimension a 0) (array-dimension b 1)) nil 
       "The number of rows in the first matrix should be the number ~ 
       of columns in the second matrix") 
     (let ((result 
       (make-array 
       (list (array-dimension a 1) (array-dimension b 0)) 
       :initial-element 0))) 
     (dotimes (i (array-dimension a 1) result) 
      (dotimes (j (array-dimension b 0)) 
      (dotimes (k (array-dimension a 0)) 
       (incf (aref result i j) (* (aref a k i) (aref b j k)))))))) 
    matrices)) 

(format t "result: ~s~&" (matrix* #2A((1 2) (3 4)) #2A((5 6) (7 8)))) 
;; #2A((23 31) (34 46)) = 
;; (1 * 5 + 3 * 6 = 23) (1 * 7 + 3 * 8 = 31) 
;; (2 * 5 + 4 * 6 = 34) (2 * 7 + 4 * 8 = 46)