M.Hiroi's Home Page

お気楽 Haskell プログラミング入門

線形代数編

Copyright (C) 2021 Makoto Hiroi
All rights reserved.

●hello, hmatrix!!

ghci> import Prelude hiding ((<>))
ghci> :m + Numeric.LinearAlgebra
ghci> v1 = vector [1,2,3]
ghci> :t v1
v1 :: Vector R
ghci> v1
[1.0,2.0,3.0]
ghci> v2 = vector [4,5,6]
ghci> v2
[4.0,5.0,6.0]
ghci> v1 + v2
[5.0,7.0,9.0]
ghci> v2 - v1
[3.0,3.0,3.0]
ghci> v1 <.> v2
32.0

ghci> m1 = (2><2) [1,2,3,4] :: Matrix R
ghci> m1
(2><2)
 [ 1.0, 2.0
 , 3.0, 4.0 ]
ghci> :t m1
m1 :: Matrix R
ghci> m2 = (2><2) [5,6,7,8] :: Matrix R
ghci> m2
(2><2)
 [ 5.0, 6.0
 , 7.0, 8.0 ]
ghci> m1 + m2
(2><2)
 [  6.0,  8.0
 , 10.0, 12.0 ]
ghci> m2 - m1
(2><2)
 [ 4.0, 4.0
 , 4.0, 4.0 ]
ghci> m1 <> m2
(2><2)
 [ 19.0, 22.0
 , 43.0, 50.0 ]
ghci> inv m1
(2><2)
 [ -1.9999999999999998,                  1.0
 ,  1.4999999999999998, -0.49999999999999994 ]
ghci> (inv m1) <> m1
(2><2)
 [ 1.0000000000000002, 4.440892098500626e-16
 ,                0.0,    0.9999999999999998 ]

●ベクトルと行列の基礎知識

●ベクトルの基本操作

ghci> v = vector [1,2]
ghci> v
[1.0,2.0]
ghci> w = fromList [3,4] :: Vector R
ghci> w
[3.0,4.0]
ghci> 5 |> [1..]
[1.0,2.0,3.0,4.0,5.0]
ghci> v ! 0
1.0
ghci> v ! 1
2.0
ghci> atIndex v 0
1.0
ghci> atIndex v 1
2.0
ghci> size w
2
ghci> toList w
[3.0,4.0]

●ベクトルの連結と分解

ghci> v1 = vector [1,2,3]
ghci> v2 = vector [4,5,6]
ghci> v3 = vector [7,8,9]
ghci> v4 = vjoin [v1,v2,v3]
ghci> v4
[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]
ghci> subVector 1 4 v4
[2.0,3.0,4.0,5.0]
ghci> takesV [2,3,4] v4
[[1.0,2.0],[3.0,4.0,5.0],[6.0,7.0,8.0,9.0]]

●ベクトルの計算

ghci> v
[1.0,2.0]
ghci> w
[3.0,4.0]
ghci> v + 10
[11.0,12.0]
ghci> 10 + v
[11.0,12.0]
ghci> v * 2
[2.0,4.0]
ghci> 2 * v
[2.0,4.0]
ghci> v - 10
[-9.0,-8.0]
ghci> 10 - v
[9.0,8.0]
ghci> v / 2
[0.5,1.0]
ghci> 1 / v
[1.0,0.5]
ghci> cmap (*2) v
[2.0,4.0]

ghci> v + w
[4.0,6.0]
ghci> w - v
[2.0,2.0]
ghci> v * w
[3.0,8.0]
ghci> v / w
[0.3333333333333333,0.5]

ghci> v <.> w
11.0
ghci> dot v w
11.0
ghci> norm_2 v
2.23606797749979
ghci> ev = v / scalar (norm_2 v)
ghci> ev
[0.4472135954999579,0.8944271909999159]
ghci> norm_2 ev
1.0

●行列の基本操作

ghci> (><) 2 3 [1..6]
(2><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0 ]
ghci> (2><3) [1..6]
(2><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0 ]
ghci> fromLists [[1,2,3],[4,5,6]]
(2><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0 ]
ghci> a = matrix 3 [1..6]
ghci> a
(2><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0 ]
ghci> b = matrix 3 [4..9]
ghci> b
(2><3)
 [ 4.0, 5.0, 6.0
 , 7.0, 8.0, 9.0 ]
ghci> size a
(2,3)
ghci> rows a
2
ghci> cols a
3

ghci> a ! 0
[1.0,2.0,3.0]
ghci> a ! 0 ! 0
1.0
ghci> a ! 1
[4.0,5.0,6.0]
ghci> a ! 1 ! 2
6.0
ghci> atIndex a (0,0)
1.0
ghci> atIndex a (1,2)
6.0
ghci> row [1,2,3]
(1><3)
 [ 1.0, 2.0, 3.0 ]
ghci> col [1,2,3]
(3><1)
 [ 1.0
 , 2.0
 , 3.0 ]
ghci> toLists a
[[1.0,2.0,3.0],[4.0,5.0,6.0]]
ghci> rand 3 3
(3><3)
 [  0.1819017982026105,    0.8054357985059898,  0.6154939842482535
 , 0.46874250353721086, 3.9034717734453606e-2, 0.27816141270015454
 ,  0.9679905604422049,   0.36524810612446074, 0.20691627413356503 ]

●行列の連結と分解

ghci> a = matrix 3 [1..6]
ghci> b = matrix 3 [7..12]
ghci> a
(2><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0 ]
ghci> b
(2><3)
 [  7.0,  8.0,  9.0
 , 10.0, 11.0, 12.0 ]
ghci> a ||| b
(2><6)
 [ 1.0, 2.0, 3.0,  7.0,  8.0,  9.0
 , 4.0, 5.0, 6.0, 10.0, 11.0, 12.0 ]
ghci> a === b
(4><3)
 [  1.0,  2.0,  3.0
 ,  4.0,  5.0,  6.0
 ,  7.0,  8.0,  9.0
 , 10.0, 11.0, 12.0 ]
ghci> fromBlocks [[a, b], [matrix 3 [1..9], 
matrix 3 [11..19]]]
(5><6)
 [ 1.0, 2.0, 3.0,  7.0,  8.0,  9.0
 , 4.0, 5.0, 6.0, 10.0, 11.0, 12.0
 , 1.0, 2.0, 3.0, 11.0, 12.0, 13.0
 , 4.0, 5.0, 6.0, 14.0, 15.0, 16.0
 , 7.0, 8.0, 9.0, 17.0, 18.0, 19.0 ]
ghci> a = matrix 5 [1..20]
ghci> a
(4><5)
 [  1.0,  2.0,  3.0,  4.0,  5.0
 ,  6.0,  7.0,  8.0,  9.0, 10.0
 , 11.0, 12.0, 13.0, 14.0, 15.0
 , 16.0, 17.0, 18.0, 19.0, 20.0 ]
ghci> takeRows 3 a
(3><5)
 [  1.0,  2.0,  3.0,  4.0,  5.0
 ,  6.0,  7.0,  8.0,  9.0, 10.0
 , 11.0, 12.0, 13.0, 14.0, 15.0 ]
ghci> dropRows 1 a
(3><5)
 [  6.0,  7.0,  8.0,  9.0, 10.0
 , 11.0, 12.0, 13.0, 14.0, 15.0
 , 16.0, 17.0, 18.0, 19.0, 20.0 ]
ghci> takeColumns 3 a
(4><3)
 [  1.0,  2.0,  3.0
 ,  6.0,  7.0,  8.0
 , 11.0, 12.0, 13.0
 , 16.0, 17.0, 18.0 ]
ghci> dropColumns 1 a
(4><4)
 [  2.0,  3.0,  4.0,  5.0
 ,  7.0,  8.0,  9.0, 10.0
 , 12.0, 13.0, 14.0, 15.0
 , 17.0, 18.0, 19.0, 20.0 ]
ghci> subMatrix (1,1) (2,2) a
(2><2)
 [  7.0,  8.0
 , 12.0, 13.0 ]
ghci> a ?? (Pos (idxs [3, 1]), All)
(2><5)
 [ 16.0, 17.0, 18.0, 19.0, 20.0
 ,  6.0,  7.0,  8.0,  9.0, 10.0 ]
ghci> a ?? (Pos (idxs [3, 1]), Range 4 (-2) 0)
(2><3)
 [ 20.0, 18.0, 16.0
 , 10.0,  8.0,  6.0 ]
ghci> a ?? (Take 3, Drop 2)
(3><3)
 [  3.0,  4.0,  5.0
 ,  8.0,  9.0, 10.0
 , 13.0, 14.0, 15.0 ]
ghci> a ?? (TakeLast 2, DropLast 2)
(2><3)
 [ 11.0, 12.0, 13.0
 , 16.0, 17.0, 18.0 ]

●行列の計算

ghci> a
(2><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0 ]
ghci> b
(2><3)
 [ 4.0, 5.0, 6.0
 , 7.0, 8.0, 9.0 ]
ghci> a * 2
(2><3)
 [ 2.0,  4.0,  6.0
 , 8.0, 10.0, 12.0 ]
ghci> b / 2
(2><3)
 [ 2.0, 2.5, 3.0
 , 3.5, 4.0, 4.5 ]
ghci> cmap (*10) a
(2><3)
 [ 10.0, 20.0, 30.0
 , 40.0, 50.0, 60.0 ]

ghci> a + b
(2><3)
 [  5.0,  7.0,  9.0
 , 11.0, 13.0, 15.0 ]
ghci> b - a
(2><3)
 [ 3.0, 3.0, 3.0
 , 3.0, 3.0, 3.0 ]
ghci> a * b
(2><3)
 [  4.0, 10.0, 18.0
 , 28.0, 40.0, 54.0 ]
ghci> a / b
(2><3)
 [               0.25,   0.4,                0.5
 , 0.5714285714285714, 0.625, 0.6666666666666666 ]
ghci> a
(2><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0 ]
ghci> c = matrix 2 [1..6]
ghci> c
(3><2)
 [ 1.0, 2.0
 , 3.0, 4.0
 , 5.0, 6.0 ]
ghci> d = a <> c
ghci> d
(2><2)
 [ 22.0, 28.0
 , 49.0, 64.0 ]
ghci> vector [1,2] <# a
[9.0,12.0,15.0]
ghci> a #> vector [1,2,3]
[14.0,32.0]

ghci> e = ident 2
ghci> e
(2><2)
 [ 1.0, 0.0
 , 0.0, 1.0 ]
ghci> d <> e
(2><2)
 [ 22.0, 28.0
 , 49.0, 64.0 ]
ghci> e <> d
(2><2)
 [ 22.0, 28.0
 , 49.0, 64.0 ]
ghci> d <> e == d
True
ghci> e <> d == d
True
ghci> e <> e
(2><2)
 [ 1.0, 0.0
 , 0.0, 1.0 ]
ghci> e <> e == e
True

ghci> a1 = matrix 2 [2,3,4,7]
ghci> a1
(2><2)
 [ 2.0, 3.0
 , 4.0, 7.0 ]
ghci> ra1 = inv a1
ghci> ra1
(2><2)
 [  3.5, -1.5
 , -2.0,  1.0 ]
ghci> a1 <> ra1
(2><2)
 [ 1.0, 0.0
 , 0.0, 1.0 ]
ghci> ra1 #> vector [4,6]
[5.0,-2.0]
ghci> ra1 <> matrix 1 [4,6]
(2><1)
 [  5.0
 , -2.0 ]
ghci> linearSolve a1 $ matrix 1 [4,6]
Just (2><1)
 [  5.0
 , -2.0 ]
ghci> a1
(2><2)
 [ 2.0, 3.0
 , 4.0, 7.0 ]
ghci> det a1
2.0
ghci> rank a1
2
ghci> b1 = matrix 3 [1..9]
ghci> b1
(3><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0
 , 7.0, 8.0, 9.0 ]
ghci> det b1
6.661338147750939e-16
ghci> rank b1
2

ghci> trace m = sumElements $ takeDiag (m::Matrix R)
ghci> trace a1
9.0
ghci> trace b1
15.0

●ベクトルと行列の変換

ghci> a = matrix 3 [1..9]
ghci> a
(3><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0
 , 7.0, 8.0, 9.0 ]
ghci> toRows a
[[1.0,2.0,3.0],[4.0,5.0,6.0],[7.0,8.0,9.0]]
ghci> toColumns a
[[1.0,4.0,7.0],[2.0,5.0,8.0],[3.0,6.0,9.0]]
ghci> flatten a
[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]
ghci> reshape 3 $ vector [1..9]
(3><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0
 , 7.0, 8.0, 9.0 ]
ghci> asRow $ vector [1,2,3]
(1><3)
 [ 1.0, 2.0, 3.0 ]
ghci> asColumn $ vector [1,2,3]
(3><1)
 [ 1.0
 , 2.0
 , 3.0 ]
ghci> fromRows [vector [1,2,3], vector [4,5,6]]
(2><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0 ]
ghci> fromColumns [vector [1,2,3], vector [4,5,6]]
(3><2)
 [ 1.0, 4.0
 , 2.0, 5.0
 , 3.0, 6.0 ]

●ベクトルと行列の生成

ghci> konst 0 10 :: Vector R
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]
ghci> konst 1 10 :: Vector R
[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]
ghci> konst 2 10 :: Vector I
[2,2,2,2,2,2,2,2,2,2]
ghci> konst 0 (3, 3) :: Matrix R
(3><3)
 [ 0.0, 0.0, 0.0
 , 0.0, 0.0, 0.0
 , 0.0, 0.0, 0.0 ]
ghci> konst 1 (2, 3) :: Matrix R
(2><3)
 [ 1.0, 1.0, 1.0
 , 1.0, 1.0, 1.0 ]
ghci> konst 1 (2, 2) :: Matrix I
(2><2)
 [ 1, 1
 , 1, 1 ]

ghci> build 10 id :: Vector R
[0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]
ghci> build 10 (*2) :: Vector R
[0.0,2.0,4.0,6.0,8.0,10.0,12.0,14.0,16.0,18.0]
ghci> build 10 (**2) :: Vector R
[0.0,1.0,4.0,9.0,16.0,25.0,36.0,49.0,64.0,81.0]
ghci> build (3, 3) (+) :: Matrix R
(3><3)
 [ 0.0, 1.0, 2.0
 , 1.0, 2.0, 3.0
 , 2.0, 3.0, 4.0 ]
ghci> build (3, 3) (\i j -> i * 3 + j) :: Matrix R
(3><3)
 [ 0.0, 1.0, 2.0
 , 3.0, 4.0, 5.0
 , 6.0, 7.0, 8.0 ]
ghci> build (3, 3) (\i j -> j * 3 + i) :: Matrix R
(3><3)
 [ 0.0, 3.0, 6.0
 , 1.0, 4.0, 7.0
 , 2.0, 5.0, 8.0 ]

ghci> assoc 5 0 [(1,10), (3,20)] :: Vector R
[0.0,10.0,0.0,20.0,0.0]
ghci> assoc 5 1 [(1,10), (3,20)] :: Vector R
[1.0,10.0,1.0,20.0,1.0]
ghci> assoc 7 2 [(1,10), (3,20), (5,30)] :: Vector R
[2.0,10.0,2.0,20.0,2.0,30.0,2.0]
ghci> assoc (3, 3) 0 [((0,0),1), ((2,2),2)] :: Matrix R
(3><3)
 [ 1.0, 0.0, 0.0
 , 0.0, 0.0, 0.0
 , 0.0, 0.0, 2.0 ]
ghci> assoc (3, 3) 1 [((1,0),11), ((2,1),12)] :: Matrix R
(3><3)
 [  1.0,  1.0, 1.0
 , 11.0,  1.0, 1.0
 ,  1.0, 12.0, 1.0 ]
ghci> assoc (3, 3) 2 [((1,0),21), ((0,2),22), ((2,1),23)] 
:: Matrix R
(3><3)
 [  2.0,  2.0, 22.0
 , 21.0,  2.0,  2.0
 ,  2.0, 23.0,  2.0 ]

ghci> a = vector [1,2,3,4,5,6,7,8]
ghci> a
[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0]
ghci> accum a (+) [(2,10), (5,20)]
[1.0,2.0,13.0,4.0,5.0,26.0,7.0,8.0]
ghci> accum a (-) [(1,10), (6,20)]
[1.0,8.0,3.0,4.0,5.0,6.0,13.0,8.0]
ghci> accum a const [(2,10), (4,20), (6, 30)]
[1.0,2.0,10.0,4.0,20.0,6.0,30.0,8.0]
ghci> b = matrix 3 [1..9]
ghci> b
(3><3)
 [ 1.0, 2.0, 3.0
 , 4.0, 5.0, 6.0
 , 7.0, 8.0, 9.0 ]
ghci> accum b (+) [((0,0),10), ((2,1),20), ((1,2), 30)]
(3><3)
 [ 11.0,  2.0,  3.0
 ,  4.0,  5.0, 36.0
 ,  7.0, 28.0,  9.0 ]
ghci> accum b (*) [((0,0),10), ((2,1),20), ((1,2), 30)]
(3><3)
 [ 10.0,   2.0,   3.0
 ,  4.0,   5.0, 180.0
 ,  7.0, 160.0,   9.0 ]
ghci> accum b const [((0,0),10), ((2,1),20), ((1,2), 30)]
(3><3)
 [ 10.0,  2.0,  3.0
 ,  4.0,  5.0, 30.0
 ,  7.0, 20.0,  9.0 ]

ghci> linspace 5 (1,5) :: Vector R
[1.0,2.0,3.0,4.0,5.0]
ghci> linspace 9 (1,5) :: Vector R
[1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0]
ghci> linspace 10 (0,9) :: Vector R
[0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]
ghci> linspace 19 (0,9) :: Vector R
[0.0,0.5,1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5,7.0,7.5,8.0,8.5,9.0]

初版 2021 年 8 月 15 日