ONLY DO WHAT ONLY YOU CAN DO

こけたら立ちなはれ 立ったら歩きなはれ

Go 言語で固有値・固有ベクトルを求める (反復法)

f:id:fornext1119:20150711180736p:plain
f:id:fornext1119:20150806130031p:plain の正方行列 f:id:fornext1119:20150805175030p:plain
f:id:fornext1119:20150806130112p:plain次元のベクトル f:id:fornext1119:20150806130206p:plain について
f:id:fornext1119:20150806130322p:plain (ただし f:id:fornext1119:20150806130436p:plain ) が成り立つとき
f:id:fornext1119:20150806130626p:plain固有値, f:id:fornext1119:20150806130206p:plain固有ベクトルという.
最初に適当なベクトル f:id:fornext1119:20150806130721p:plain から始めて f:id:fornext1119:20150806130857p:plain を反復すると
f:id:fornext1119:20150806130945p:plain は行列 f:id:fornext1119:20150805175030p:plain の最大固有値に対応する固有ベクトルに収束する.
固有値はレイリー(Rayleigh)商
f:id:fornext1119:20150806131340p:plain
により求める.
べき乗法、累乗法とも言う.

package main

import "fmt"
import "math"

const N = 4

// ベキ乗法で最大固有値を求める
func main() {
    var a [N][N]float64 = [N][N]float64{{5.0, 4.0, 1.0, 1.0}, 
                                        {4.0, 5.0, 1.0, 1.0}, 
                                        {1.0, 1.0, 4.0, 2.0},
                                        {1.0, 1.0, 2.0, 4.0}}
    var x               = []float64     {1.0 ,0.0 ,0.0 ,0.0}

    // ベキ乗法
    var lambda float64 = power(a, x)

    fmt.Println("\neigenvalue")
    fmt.Printf("%14.10f\n", lambda)

    fmt.Println("eigenvector")
    disp_vector(x)
}

// ベキ乗法
func power(a[N][N]float64, x0[]float64) float64 {
    var lambda float64 = 0.0

    // 正規化 (ベクトル x0 の長さを1にする)
    normarize(x0)
    var e0 float64 = 0.0
    for i := 0; i < N; i++ {
        e0 += x0[i]
    }

    for k := 1; k < 200; k++ {
        // 1次元配列を表示
        fmt.Printf("%3d\t", k)
        disp_vector(x0)

        // 行列の積 x1 = A × x0 
        var x1 = []float64  {0.0 ,0.0 ,0.0 ,0.0}
        for i := 0; i < N; i++ {
            for j := 0; j < N; j++ {
                x1[i] += a[i][j] * x0[j]
            }
        }
        
        // 内積
        var p0 float64 = 0.0
        var p1 float64 = 0.0
        for i := 0; i < N; i++ {
            p0 += x1[i] * x1[i]
            p1 += x1[i] * x0[i]
        }
        // 固有値
        lambda = p0 / p1

        // 正規化 (ベクトル x1 の長さを1にする)
        normarize(x1)
        var e1 float64 = 0.0
        // 収束判定
        for i := 0; i < N; i++ {
            e1 += x1[i]
        }
        if (math.Fabs(e0 - e1) < 0.00000000001) {
            break
        }

        for i := 0; i < N; i++ {
            x0[i] = x1[i]
        }
        e0 = e1
    }
    return lambda
}
// 1次元配列を表示
func disp_vector(row[]float64) {
    for _, col := range row {
        fmt.Printf("%14.10f\t", col)
    }
    fmt.Println("")
}
// 正規化 (ベクトルの長さを1にする)
func normarize(x[]float64) {
    var s float64 = 0.0

    for i := 0; i < N; i++ {
        s += x[i] * x[i]
    }
    s = math.Sqrt(s)
    
    for i := 0; i < N; i++ {
        x[i] /= s
    }
}
z:\go>8g GO1101.go

z:\go>8l -o GO1101.exe GO1101.8

z:\go>GO1101
  1       1.0000000000    0.0000000000    0.0000000000    0.0000000000
  2       0.7624928517    0.6099942813    0.1524985703    0.1524985703
  3       0.6745979924    0.6589096670    0.2353248811    0.2353248811
  4       0.6517382447    0.6501601860    0.2761602732    0.2761602732
  5       0.6421032522    0.6419452154    0.2963188771    0.2963188771
  6       0.6373267026    0.6373108932    0.3063082594    0.3063082594
  7       0.6349074765    0.6349058954    0.3112772079    0.3112772079
  8       0.6336860412    0.6336858831    0.3137548428    0.3137548428
  9       0.6330719648    0.6330719490    0.3149919005    0.3149919005
 10       0.6327640473    0.6327640457    0.3156099832    0.3156099832
 11       0.6326098648    0.6326098646    0.3159189122    0.3159189122
 12       0.6325327172    0.6325327172    0.3160733485    0.3160733485
 13       0.6324941293    0.6324941293    0.3161505596    0.3161505596
 14       0.6324748319    0.6324748319    0.3161891634    0.3161891634
 15       0.6324651822    0.6324651822    0.3162084649    0.3162084649
 16       0.6324603572    0.6324603572    0.3162181155    0.3162181155
 17       0.6324579446    0.6324579446    0.3162229408    0.3162229408
 18       0.6324567383    0.6324567383    0.3162253534    0.3162253534
 19       0.6324561352    0.6324561352    0.3162265597    0.3162265597
 20       0.6324558336    0.6324558336    0.3162271629    0.3162271629
 21       0.6324556828    0.6324556828    0.3162274644    0.3162274644
 22       0.6324556074    0.6324556074    0.3162276152    0.3162276152
 23       0.6324555697    0.6324555697    0.3162276906    0.3162276906
 24       0.6324555509    0.6324555509    0.3162277283    0.3162277283
 25       0.6324555415    0.6324555415    0.3162277472    0.3162277472
 26       0.6324555367    0.6324555367    0.3162277566    0.3162277566
 27       0.6324555344    0.6324555344    0.3162277613    0.3162277613
 28       0.6324555332    0.6324555332    0.3162277637    0.3162277637
 29       0.6324555326    0.6324555326    0.3162277648    0.3162277648
 30       0.6324555323    0.6324555323    0.3162277654    0.3162277654
 31       0.6324555322    0.6324555322    0.3162277657    0.3162277657
 32       0.6324555321    0.6324555321    0.3162277659    0.3162277659
 33       0.6324555321    0.6324555321    0.3162277659    0.3162277659
 34       0.6324555321    0.6324555321    0.3162277660    0.3162277660
 35       0.6324555320    0.6324555320    0.3162277660    0.3162277660

eigenvalue
 10.0000000000
eigenvector
  0.6324555320    0.6324555320    0.3162277660    0.3162277660
参考文献