代码之家  ›  专栏  ›  技术社区  ›  Asaf

scheme中的矩阵乘法,列表列表

  •  2
  • Asaf  · 技术社区  · 6 年前

    我开始研究这个计划,但我不懂其中的一些。我在用DrRacket。

    (define mult_mat
      (λ (A B)
        (Trans_Mat (map (λ (x) (mul_Mat_vec A x))
                        (Trans_Mat B)))))
    

    使用此函数的:

    (define Trans_Mat
      (λ (A)
        (apply map (cons list A))))
    

    (define mul_Mat_vec
      (λ (A v)
        (map (λ (x) (apply + (map * x v)))
             A)))
    

    mult_mat 很好用。

    我在网上发现了一个代码,它以一种我不懂的方式进行乘法:

    (define (matrix-multiply matrix1 matrix2)
      (map
       (λ (row)
         (apply map
           (λ column
             (apply + (map * row column)))
           matrix2))
       matrix1))
    

    在这个代码中, row 是矩阵a的列表,但我不明白 column

    这部分代码: (apply + (map * row column)) 和向量

    (应用+(映射*行-列)) 我写作 1 ,那么我将得到一个矩阵2X2,其值为

    我不明白它是怎么工作的。

    谢谢。

    1 回复  |  直到 6 年前
        1
  •  5
  •   Will Ness Derri Leahy    4 年前

    啊,老家伙 ( apply map foo _a_list_ ) 诡计。非常聪明。

    事实上 (apply map (cons list A)) (apply map list A) . 就是这样 apply 定义为工作。

    尝试一些具体的例子通常有助于“得到它”:

    (apply map       list '((1 2 3)  (10 20 30)) )
    =
    (apply map (cons list '((1 2 3)  (10 20 30))))
    =
    (apply map (list list  '(1 2 3) '(10 20 30) ))
    =
    (      map       list  '(1 2 3) '(10 20 30)  )
    =
    '((1 10) (2 20) (3 30))
    

    '((1 2 3) (10 20 30)) ,是 拼接 融入整体 apply map ... 形式。

    矩阵变换 (列表列表,真的)。

    所以你有

    (define (mult_mat A B)
        (Trans_Mat (map (λ (B_column) (mul_Mat_vec A B_column))
                        (Trans_Mat B))))
    
    (define (Trans_Mat A)
        (apply map list A))
    
    (define (mul_Mat_vec A v)
        (map (λ (A_row) (apply + (map * A_row v)))
             A))
    
    (define (matrix-multiply A B)
      (map
        (λ (A_row)
          (apply map
                 (λ B_column
                   (apply + (map * A_row B_column)))
                 B))
        A))
    

    (λ B_column ... ,没有括号。在 ((λ args ...) x y z) ,输入lambda时, args 获取打包在列表中的所有参数:

    ((λ args ...) x y z)
    =
    (let ([args (list x y z)])
      ...)
    

    同时注意

          (apply map
                 (λ B_column
                   (apply + (map * A_row B_column)))
                 B)
    

    遵循同样的“棘手”模式。事实上这和

          (apply map (cons
                 (λ B_column
                   (apply + (map * A_row B_column)))
                 B    ) )
    =
          (      map
                 (λ B_column
                    (apply + (map * A_row B_column)))
                 B_row1
                 B_row2
                 ....
                 B_rowN )
    =
         (cons (let ([B_column_1 (map car B)])
                  (apply + (map * A_row B_column_1)))
               (map (λ B_column
                        (apply + (map * A_row B_column)))
                 (cdr B_row1)
                 (cdr B_row2)
                 ....
                 (cdr B_rowN)) )
    =
         (cons 
           (apply (λ B_column (apply + (map * A_row B_column)))
                  (map car B))
           (apply map
                  (λ B_column
                     (apply + (map * A_row B_column)))
                  (map cdr B)))
    

    根据定义 map

    因此,通过 这个 地图 ,则矩阵被“打开”成其元素的列表行,然后当多个参数 如果要将这些行作为参数处理,lambda函数将相应地统一应用于每一行的后续数字;从而实现与 显式换位 会的。但现在额外的好处是,我们不需要像第一个版本那样,将结果转换回正确的形式。

    这个 很聪明,很好。


    (define (matrix-multiply matrix1 matrix2)
      (map
       (λ (row)
         (apply map
           (λ column      ;; <<------ no parens!
             (apply + (map * row column)))
           matrix2))
       matrix1))
    

    上面写着:每个 row matrix1 ,多参数 地图 lambda 结束 matrix2 . 矩阵2 地图 排成一排的 λ

    所以,对于每个 在里面 ,对于每个 矩阵2 ,将该行和该列元素相乘,并对结果求和;从而将每行转换为这些和的列表。很明显,只有当行的长度和每列的长度相同时,才能这样做:如果第一个矩阵的“宽度”和第二个矩阵的“高度”相同。

        2
  •  0
  •   Jacob K    4 年前

    这不是最有效的方法(到目前为止),但很容易理解

    1.  (define (getRow mat i)
          (nthElement mat i))
      
      (define (nthElement lisT n)
          (if (= n 0)
              (car lisT)                                                 
              (nthElement (cdr lisT) (- n 1))))
      
    2. (define (getCol mat i)
          (define col (list))
          (define row 0)
          (while (< row (length mat))
              (set! col (append col (list (valueAtIJ mat row i))))
              (set! row (+ row 1)))
           col)
      
      (define (valueAtIJ mat i j)
          (nthElement (nthElement mat i) j))
      
    3. listmultlist1 list2:对两个列表执行按元素相乘

      (define (listMult list1 list2)
          (if (not (null? list1))
              (cons (* (car list1) (car list2)) (listMult (cdr list1) (cdr list2)))
              null))
      
    4. 求和列表:计算列表中所有元素的总和

      (define (sum aList)
          (if (null? aList)
              0
              (+ (car aList) (sum (cdr aList)))))
      
    5. 长度列表:查找列表的长度

      (define (length lisT)
          (if (null? lisT)                                               
              0
              (+ 1 (length (cdr lisT)))))
      
    6. newMatrix m n val:创建一个用val填充的m x n矩阵

      (define (newMatrix m n val)                        
          (define i 0)
          (define row (list val))
          (define mat (list))
          (if (= n 0)
              (list)                                          
              (begin 
                  (while (< i (- n 1))
                      (set! row (append row (list val))) 
                      (set! i (+ i 1)))
                  (set! i 0)
                  (while (< i m)
                      (set! mat (append mat (list row)))     
                      (set! i (+ i 1)))
          mat)))
      
    7. setValueAtIJ mat i j val:在mat中的位置i,j处设置值val(基于0)

      (define (setValueAtIJ mat i j val)
          (set! mat (setNthElementFinal mat i (setNthElementFinal (nthElement mat i) j val)))
          mat) 
      
      

    这些都可以结合起来创建矩阵乘法函数

    (define (matrixMult mat1 mat2)
        (define mat1Dim (list (length mat1) (length (nthElement mat1 0))))      
        (define mat2Dim (list (length mat2) (length (nthElement mat2 0))))      
        (define i 0)
        (define j 0)
        (define newMat (newMatrix (car mat1Dim) (car (cdr mat2Dim)) 0))        
        (if (not (= (car (cdr mat1Dim)) (car mat2Dim)))
            null                                                                
            (begin
                (while (< i (length newMat))
                    (while (< j (length (nthElement newMat 0)))
                        (set! newMat (setValueAtIJ newMat i j (sum (listMult (getRow mat1 i) (getCol mat2 j)))))
                        (set! j (+ j 1)))
                    (set! j 0)
                    (set! i (+ i 1)))
            newMat)))