3

CommonLisp初心者。lispコードを書くことは、私が以前に書いたように、c ++/javaを書くこととはかなり異なります。

私は練習のためにcommonlispで単純な行列クラスを書き込もうとしています。そのようないくつかのコード:

(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はあるべきですか?

そして、行列*はどうですか、誰かが行列*で任意の数の引数を受け入れる素晴らしいコードを見せてくれますか?ありがとう。

4

2 に答える 2

5

Common Lisp には n 次元配列があります。それらを行列演算に使用します。

参照: MAKE-ARRAYAREF、 ...

通常、バイナリ (2 つの引数を取る) 行列演算も記述します。thenREDUCEを使用して、行列のリストを操作します。

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))

上記は、初期コンテンツとして 0 を持つサイズ 3x5 の 2 次元配列を作成します。

于 2012-07-12T10:48:54.523 に答える
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)
于 2012-07-12T16:23:17.223 に答える