목적:
http://stackoverflow.com/questions/1907709/a-simple-wrapper-for-f-to-do-matrix-operations 에 올려진 소스에서 String.spit 관련를 문제 해결하자.
테스트를 위해 필요한 자료: dnAnalytics
F# Power Pack
// 파일명: TestFSharpMatrix.fs (원래 소스)
#r @"FSharp.PowerPack.dll"
open dnAnalytics.LinearAlgebra
open Microsoft.FSharp.Math
open dnAnalytics.LinearAlgebra.Decomposition
// F# matrix -> ndAnalytics DenseMatrix
let mat2dnmat (mat:matrix) =
let m = new DenseMatrix(mat.ToArray2D())
m
// ndAnalytics DenseMatrix -> F# matrix
let dnmat2mat (dnmat:DenseMatrix) =
let n = dnmat.Rows
let m = dnmat.Columns
let mat = Matrix.create n m 0.
for i=0 to n-1 do
for j=0 to m-1 do
mat.[i,j] <- dnmat.Item(i,j)
mat
// random matrix
let randmat n m =
let r = new System.Random()
let ranlist m =
[ for i in 1..m do yield r.NextDouble() ]
matrix ([1..n] |> List.map (fun x-> ranlist m))
// is square matrix
let issqr (m:matrix) =
let n, m = m.Dimensions
n = m
// is postive definite
let ispd m =
if not (issqr m) then false
else
let m1 = mat2dnmat m
let qrsolver = dnAnalytics.LinearAlgebra.Decomposition.Cholesky(m1)
qrsolver.IsPositiveDefinite()
// determinant
let det m =
let m1 = mat2dnmat m
let lusolver = dnAnalytics.LinearAlgebra.Decomposition.LU(m1)
lusolver.Determinant ()
// is full rank
let isfull m =
let m1 = mat2dnmat m
let qrsolver = dnAnalytics.LinearAlgebra.Decomposition.GramSchmidt(m1)
qrsolver.IsFullRank()
// rank
let rank m =
let m1 = mat2dnmat m
let svdsolver = dnAnalytics.LinearAlgebra.Decomposition.Svd(m1, false)
svdsolver.Rank()
// inversion by lu
let inv m =
let m1 = mat2dnmat m
let lusolver = dnAnalytics.LinearAlgebra.Decomposition.LU(m1)
lusolver.Inverse()
// lu
let lu m =
let m1 = mat2dnmat m
let lusolver = dnAnalytics.LinearAlgebra.Decomposition.LU(m1)
let l = dnmat2mat (DenseMatrix (lusolver.LowerFactor ()))
let u = dnmat2mat (DenseMatrix (lusolver.UpperFactor ()))
(l,u)
// qr
let qr m =
let m1 = mat2dnmat m
let qrsolver = dnAnalytics.LinearAlgebra.Decomposition.GramSchmidt(m1)
let q = dnmat2mat (DenseMatrix (qrsolver.Q()))
let r = dnmat2mat (DenseMatrix (qrsolver.R()))
(q, r)
// svd
let svd m =
let m1 = mat2dnmat m
let svdsolver = dnAnalytics.LinearAlgebra.Decomposition.Svd(m1, true)
let u = dnmat2mat (DenseMatrix (svdsolver.U()))
let w = dnmat2mat (DenseMatrix (svdsolver.W()))
let vt = dnmat2mat (DenseMatrix (svdsolver.VT()))
(u, w, vt.Transpose)
// and test code
(* todo: read matrix market format ref: http://math.nist.gov/MatrixMarket/formats.html *)
let readmat (filename:string) =
System.IO.File.ReadAllLines(filename) |> Array.map (fun x-> (x |> String.split [' '] |> List.toArray |> Array.map float))
|> matrix
let timeit f str=
let watch = new System.Diagnostics.Stopwatch()
watch.Start()
let res = f()
watch.Stop()
printfn "%s Needed %f ms" str watch.Elapsed.TotalMilliseconds
res
let test() =
let testlu() =
for i=1 to 10 do
let a,b = lu (randmat 1000 1000)
()
()
let testsvd() =
for i=1 to 10 do
let u,w,v = svd (randmat 300 300)
()
()
let testdet() =
for i=1 to 10 do
let d = det (randmat 650 650)
()
()
timeit testlu "lu"
timeit testsvd "svd"
timeit testdet "det"
1. 우선 위의 소스를 그대로 컴파일하였다.
컴파일하니 아래와 같이 에러가 뜬다.
D:\test\f#>fsc TestFSharpMatrix.fsx
Microsoft (R) F# 2.0 Compiler build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
TestFSharpMatrix.fsx(106,85): error FS0039: The field, constructor or member 'sp
lit' is not defined
2. 파일 확장명 바꾸고, #r 디렉티브 수정하기
dll 파일을 현재 디렉토리에 놓고 컴파일하기 위해 소스 선두의 #r 디렉티브를 수정하였다.
파일 확장명도 fsx로 바꾸었다.
// 1차 수정된 파일명: TestFSharpMatrix.fsx (소스의 선두 #r 디렉티브 부분 수정)
#r @".\FSharp.PowerPack.dll"
open dnAnalytics.LinearAlgebra
open Microsoft.FSharp.Math
open dnAnalytics.LinearAlgebra.Decomposition
// 이하 생략
컴파일하면 이전과 동일한 에러메세지가 뜬다,
D:\test\f#>fsc TestFSharpMatrix.fsx
Microsoft (R) F# 2.0 Compiler build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
TestFSharpMatrix.fsx(106,85): error FS0039: The field, constructor or member 'sp
lit' is not defined
3. FSharp.PowerPack.Compatibility.dll 도 사용하자.
F# Power Pack 의 FSharp.PowerPack.Compatibility.dll 을 현재 디렉토리에 넣어 준다.
// 2차 수정된 파일명: testFShapMatrix.fsx (FSharp.PowerPack.Compatibility.dll 을 #r 리렉티브에 추가)
#r @".\FSharp.PowerPack.dll"
#r @".\FSharp.PowerPack.Compatibility.dll"
open dnAnalytics.LinearAlgebra
open Microsoft.FSharp.Math
open dnAnalytics.LinearAlgebra.Decomposition
// 이하 생략
2차 수정된 소스는 컴파일은 되지만 실행 결과가 없다.
D:\test\f#>fsc TestFSharpMatrix.fsx
Microsoft (R) F# 2.0 Compiler build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
TestFSharpMatrix.fsx(136,1): warning FS0988: Main module of program is empty: no
thing will happen when it is run
4, 실행위한 Main 모듈을 추가하자.
// 3차 수정된 파일명: testString.fsx (소스의 7째 줄 Split을 String.split로 수정)
// 3차 수정된 파일명: testFShapMatrix.fsx (FSharp.PowerPack.Compatibility.dll 을 #r 리렉티브에 추가)
#r @".\FSharp.PowerPack.dll"
#r @".\FSharp.PowerPack.Compatibility.dll";;
open dnAnalytics.LinearAlgebra
open Microsoft.FSharp.Math
open dnAnalytics.LinearAlgebra.Decomposition
// 중략
timeit testlu "lu"
timeit testsvd "svd"
timeit testdet "det"
[<EntryPoint>]
let main args =
test()
0 // Return 0. This indicates success.
이제는 컴파일도 잘 되고, 실행도 잘 된다.
실행 후 잠시 기다리면 실행에 소요된 시간이 밀리초 단위로 컨솔에 출력된다.
D:\test\f#>fsc TestFSharpMatrix.fsx
Microsoft (R) F# 2.0 Compiler build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
D:\test\f#>TestFSharpMatrix
lu Needed 21519.869700 ms
svd Needed 6146.898400 ms
det Needed 4221.604900 ms
* 이로서 이 글의 선두에 적어 놓은 목적이 해결되었다.
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
'프로그래밍 > F#' 카테고리의 다른 글
Hello 예제 for F# (0) | 2010.07.12 |
---|---|
if...else... 조건문 사용 예제 for F# (0) | 2010.07.12 |
F# 프로그래밍에서 정수인지 부동소수점수인지 구분하기 (0) | 2010.07.12 |
F# 프로그래밍에서 한글 문제 (0) | 2010.07.12 |
F# 프로그래밍에서 String.split 가 없다고 불평할 때 (0) | 2010.07.08 |