Ocaml矩阵乘法

问题描述

你好,我正在尝试自己学习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的笛卡尔积。

我们可以得出结论,我们需要以下原语来解决我们的任务。

  1. val transpose : matrix -> matrix该函数将获取行列表并返回该矩阵的列列表。我们将需要这样做,因为我们需要迭代矩阵B的列。

  2. 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]