行列の積
Data.List
線形代数の教科書を読むときなど、小さい行列の計算ができると便利だ。Haskell でやってみる。Data.List モジュールの転置行列を作る関数 transpose を利用したいのでインポートしておく。
Prelude> :m Data.List Prelude Data.List>
ベクトルの計算
ベクトルはリストで表すことにする。縦ベクトルと横ベクトルがあるが、それは適当に頭の中で読み替えることにする。
Prelude Data.List> a = [1,2,3]; b = [4,5,6] Prelude Data.List> a [1,2,3]
ベクトルの加算 add とスカラ積 scala 、ドット積 dot のプログラムは簡単だ。
Prelude Data.List> add x y = zipWith (+) x y Prelude Data.List> scala a x = map (*a) x Prelude Data.List> dot x y = sum $ zipWith (*) x y Prelude Data.List> add a b [5,7,9] Prelude Data.List> scala 10 a [10,20,30] Prelude Data.List> dot a b 32
行列の計算
行列は行ベクトルのリストで表すことにする。
Prelude Data.List> m1 = [[1,2],[3,4]]; m2 = [[5,6],[7,8]] Prelude Data.List> m1 [[1,2],[3,4]]
行列の加算はベクトルの加算 add を利用して定義する。
Prelude Data.List> addm m n = zipWith add m n Prelude Data.List> addm m1 m2 [[6,8],[10,12]]
行列の積はちょっと面倒だが、行列の積の要素は、第1項の行ベクトルと、第2項の列ベクトルであることに注目する。第2項の列ベクトルを取り出すのに transpose 関数を用いて第2項の転置行列を作るのが工夫だ。
Prelude Data.List> elements m n = [dot x y| x <- m, y <- transpose n] Prelude Data.List> elements m1 m2 [19,22,43,50]
これでは1本の長いリストになってしまうので、これを切り分けて行ベクトルのリストにする関数 slice を作る。
Prelude Data.List> slice _ [] = []; slice n x = take n x : slice n (drop n x) Prelude Data.List> slice 2 [19,22,43,50] [[19,22],[43,50]]
最終的に両列の積 multm は次のようになる。
Prelude Data.List> multm m n = slice (length m) $ elements m n Prelude Data.List> multm m1 m2 [[19,22],[43,50]] Prelude Data.List> multm m1 [[1,0],[0,1]] [[1,2],[3,4]]
Haskell では行列の積だって for ループを使わないで計算できる。