问题描述
你好,我正在尝试自己学习ocaml,并且正在实现列表列表的矩阵乘法,但是我不知道该怎么做。我正在尝试不使用任何列表功能的方法,但是似乎我遇到的大多数解决方案都使用list.map。
这就是我实现添加的方式
let rec m_row r1 r2 =
match r1,r2 with
_ -> []
| r1s :: r1',r2s :: r2' -> r1s + r2s :: m_row r1' r2'
let rec m_add x y =
match x,y with
_ -> []
| xs :: x',ys :: y' -> m_row xs ys :: m_add x' y'
解决方法
您必须将您的任务分成多个小子任务,然后将它们组合起来以得到最终程序。但是在开始编码之前,我们必须了解问题。我们将矩阵表示为行的集合,例如,具有M行和N列的矩阵表示为,
[[a11; ...; a1N];
[a21; ...; a2N];
...
[aM1; ...; aMN]]
给出一些PxQ矩阵B,
[[b11; ...; b1Q];
[b21; ...; b2Q];
...
[bP1; ...; bPQ]]
我们想形成一个MxQ矩阵C,它是矩阵A和B的乘法,
[[c11; ...; c1Q];
[c21; ...; c2Q];
...
[cM1; ...; cMQ]]
其中矩阵的每个元素cIJ是矩阵A的行I和矩阵B的列J的笛卡尔积。
我们可以得出结论,我们需要以下原语来解决我们的任务。
-
val transpose : matrix -> matrix
该函数将获取行列表并返回该矩阵的列列表。我们将需要这样做,因为我们需要迭代矩阵B的列。 -
val product : vector -> vector -> scalar
,我们将使用它来获取矩阵A的行和矩阵B的列以获取矩阵C的元素。[x1; ...; xS]
和[y1; ...; yS]
的乘积是等于x1 * y1 + ... + xS * yS
请注意,我在此处介绍了类型别名,例如,我们可以将其定义为
type scalar = int
type vector = scalar list
type matrix = vector list
现在,我们接近最终的矩阵乘法过程。要获得矩阵C的一行,我们需要遍历B'的列(其中B'是转置矩阵B),例如map (product row) columns
,其中columns
是列向量的列表,本质上就是我们的矩阵B'。因此,我们的最终矩阵C为
[map (product r1) columns;
map (product r2) columns;
....
map (product rM) columns]
,它是矩阵A行的映射(本质上是矩阵A的表示形式),
let mul matA matB =
let columns = transpose matB in
map (fun row -> map (product row) columns) matA
其中map f [x1; ...; xM]
被定义为[f x1; ...; f xM]