Personal tools
You are here: Home ブログ 学習経過 Haskell で行列式を求める
« December 2010 »
Su Mo Tu We Th Fr Sa
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Recent entries
sysfs tips 02 ohyama 2010-09-09
sysfs tips ohyama 2010-09-02
Haskell で周波数スペクトルを得る ohyama 2010-07-29
Haskell で線形識別関数の学習を行う ohyama 2010-07-19
Haskell で逆行列を求める ohyama 2010-07-16
Recent comments
Re:vim に lisp 機能をつける t.mimori 2010-12-16
Re:Haskell で周波数スペクトルを得る H.OHYAMA 2010-08-01
Re:lkml でお勉強 (その1-1) Hiroyasu OHYAMA 2009-08-21
Re:lkml でお勉強 (その1-1) kosaki 2009-08-20
Re:vim に lisp 機能をつける ohyama 2008-05-08
Categories
学習経過
GNU/Linux
 
Document Actions

Haskell で行列式を求める

  前回紹介した、数の組み合わせのリストを返す処理を使って、正方行列の行列式を求めるプログラムを作成する。
  ここでは、行列式の定義 [1] から求めているので、基本変形等を用いた手法よりも若干効率が悪いかもしれない。

  コードの全文は次のようになる。

mxA = [[1,3,-4,2],
[2,9,1,1],
[0,-2,6,1],
[-1,3,9,2]]

main = print $ determinant mxA

determinant :: [[Int]] -> Int
determinant mx = arrayAdd $ map (\xs -> (arrayMul $ selectArray 1 xs) * (oversetSign xs)) $
makePerm $ length mx
where
selectArray :: Int -> [Int] -> [Int]
selectArray cnt xs | null xs = []
| True = (head $ reverse $ take (head xs) $ head $ reverse $ take cnt mx):
selectArray (cnt+1) (tail xs)

-- 配列の転倒数から符号を求める
oversetSign :: [Int] -> Int
oversetSign xs = if (mod (oversetNum xs) 2) > 0 then -1 else 1
where
oversetNum :: [Int] -> Int
oversetNum (x:xs) | xs == [] = 0
| True = arrayAdd (map (\y -> if x > y then 1 else 0) xs) + oversetNum xs

-- 配列の合計値を求める
arrayAdd :: [Int] -> Int
arrayAdd (x:xs) | xs == [] = x
| True = x + (arrayAdd xs)

-- 配列の各要素の積算
arrayMul :: [Int] -> Int
arrayMul (x:xs) | xs == [] = x
| True = x * (arrayMul xs)

makePerm :: Int -> [[Int]]
makePerm n = (perm $ makeArray n) n
where
perm :: [Int] -> Int -> [[Int]]
perm [] _ = []
perm xs 0 = [[]]
perm xs 1 = map (:[]) xs
perm xs n = concatMap (pm n) $ divid xs
where pm _ (_,[]) = []
pm n (hs,(t:ts)) = map (t:) $ perm (hs ++ ts) (n-1)

divid :: [Int] -> [([Int],[Int])]
divid xxs@(x:xs) = ([],xxs) : [(x:ys,zs) | (ys,zs) <- divid xs]
divid [] = [([],[])]

makeArray :: Int -> [Int]
makeArray i | i == 0 = []
| True = i:(makeArray (i-1))


  makePerm 関数が、前回までに話した、数の組み合わせのリストを求める関数である。
  determinant が行列式を求めるメイン処理になり、makePerm 関数によって得たリストを map 関数に渡し、各要素について selectArray 関数を呼び出している。
  ここでは makePerm によって得た組み合わせの数をインデックスとた配列を、行列の中から取得するという処理である。具体的に [2,4,3,1] が渡された場合には、行列 M の [m12, m24, m33, m31] を返す。
  そして arrayMul 関数で受け取ったリストの各項目に対する積算を行う。そして、oversetSign 関数で makePerm 関数から得た数列の転倒数から符号を設定し、最後に各項目に対する加算を arrayAdd 関数で行っている。

[1] http://ja.wikipedia.org/wiki/%E8%A1%8C%E5%88%97%E5%BC%8F

Category(s)
学習経過
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/ohyama/haskell-884c52175f0f30926c423081308b/tbping
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
(Required)
(Required)
(Required)
(Required)
This helps us prevent automated spamming.
Captcha Image


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.