方案中的矩阵乘法,列表列表 [英] Matrix multiplication in scheme, List of lists

查看:18
本文介绍了方案中的矩阵乘法,列表列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始学习Scheme,但有些不懂.我正在使用 DrRacket.

I started to study Scheme and I do not understand some of it. I'm using 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 中,我将转置矩阵 B 的每个向量中的矩阵 A 相乘.它工作正常.

In mult_mat, I multiply the matrix A in each vector of the transpose matrix B. It works fine.

我在网上找到了一个代码,它以一种我不理解的方式进行乘法:

I found a code on the web that makes the multiplication in a way that I don't understand:

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

在这段代码中,row是矩阵A的列表的列表,但我不明白column是如何更新的.

In this code, row is a list of the lists of matrix A, but I don't understand how the column updates.

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

This part of the code: (apply + (map * row column)) is the dot product of vector row and vector column

例如:A 是一个矩阵 2X3 而 B 是一个矩阵 3X2 如果不是 (apply + (map * row column)) 我写的是 1,然后我将得到一个矩阵 2X2,其条目值为 1

For example: A is a matrix 2X3 and B is a matrix 3X2 and if instead of (apply + (map * row column)) I write 1, then I'll get a matrix 2X2 with entries valued 1

我不明白它是如何工作的.

I don't understand how it works.

谢谢.

推荐答案

啊,老的 ( apply map foo _a_list_ ) 把戏.很聪明.

Ah, the old ( apply map foo _a_list_ ) trick. Very clever.

实际上(apply map (cons list A))(apply map list A)是一样的.这就是 apply 被定义为工作的方式.

In fact (apply map (cons list A)) is the same as (apply map list A). That's just how apply is defined to work.

尝试一些具体的例子通常有助于明白":

Trying out some concrete examples usually helps to "get it":

(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地图 ... 表格.

so that the elements of the last argument, '((1 2 3) (10 20 30)), are spliced in into the wholeapply map ... form.

矩阵转置(真正的列表列表).

所以你有

(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 ...) xyz)中,当输入lambda时,args 获取打包在一个列表中的所有参数:

Notice it's (λ B_column ..., without parentheses. In ((λ args ...) x y z), when the lambda is entered, args gets all the arguments packaged in a list:

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

另请注意

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

遵循相同的棘手"图案.其实是一样的

follows the same "tricky" pattern. It's in fact the same as

      (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的定义.

因此,通过应用map,矩阵被打开"了.将行放入其元素列表中,然后当多参数 map 开始处理这些行作为其参数时,lambda 函数将相应地应用于每一行的后续数字;从而达到与显式转置相同的效果.但现在额外的好处是,我们不需要像第一个版本那样将结果转回正确的形式.

Thus, by applying the map, the matrix is "opened up" into the list of its elements the rows, and then when the multi-argument map gets to work on these rows as its arguments, the lambda function gets applied to each row's subsequent numbers, in unison, correspondingly; thus achieving the same effect as the explicit transposition would. But now the added bonus is, we don't need to transpose the result back into the proper form, as we had to with the first version.

非常聪明,而且很好.

This is very clever, and nice.

因此,在了解了所有这些之后,让我们尝试重新阅读原始代码,看看我们是否也能看到它的原貌.

So, armed with all this understanding, let's try re-reading the original code and see if we can see into it as it is as well.

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

这读作:对于 matrix1 中的每个 row,多参数 map 一个 lambda over 矩阵2.matrix2 本身也是一个行列表;当我们对行进行 multi-arg-map 时,lambda 依次应用于行中的每一列.

This reads: for each row in matrix1, multi-arg map a lambda over matrix2. matrix2 is itself also a list of rows; when we multi-arg-map over the rows, the lambda gets applied to each column in the rows in turn.

因此,对于 matrix1 中的每个 row,对于 matrix2 中的每个 column,将该行乘以按元素列并对结果求和;从而将每一行转换为这些总和的列表.这显然只有在行的长度和每一列的长度相同时才有效:如果宽度"小于的第一个矩阵和高度"第二个矩阵的相同.

So, for each row in matrix1, for each column in matrix2, multiply that row and that column element-wise and sum the results; thus transforming each row into the list of these sums. This obviously works out only if the length of the row and the lengths of each of the columns are the same: if the "width" of the first matrix and the "height" of the second matrix are the same.

这篇关于方案中的矩阵乘法,列表列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆