LoginSignup
3
0

More than 5 years have passed since last update.

golangで手軽に行列のランク(階数)を取得する

Last updated at Posted at 2019-04-29

Goで行列のランクを取得する簡単な方法がパッと調べて出てこなかったのでメモ。

行列のランクはその非零な特異値の個数と一致することが知られているので、行列を特異値分解(Singular Value Decomposition; SVD)し、非零な特異値の個数を求めれば良い。
便利なことに、Goではgonum.org/v1/gonum/matに特異値分解専用のstruct mat.SVDがあるので、それを利用する。

// 浮動小数点のずれを考慮して、十分小さい値を0とみなす
const epsilon = 1e-15

func rank(m mat.Matrix) int {
    svd := new(mat.SVD)

    // 特異値分解
    svd.Factorize(m, mat.SVDNone)
    // 特異値を取得
    svs := svd.Values(nil)
    // 非零な特異値を数えて返す
    var count int
    for _, v := range svs {
        if v > epsilon {
            count++
        }
    }
    return count
}

これだけでランクを得ることができる。以下は検証用コード。

func main() {
    m := mat.NewDense(4, 5, nil)
    m.SetRow(0, []float64{1, 1, 1, 1})
    m.SetRow(1, []float64{0, 1, 1, 1})
    m.SetRow(2, []float64{0, 0, 1, 1})
    m.SetRow(3, []float64{0, 0, 0, 1})
    m.SetRow(4, []float64{0, 0, 0, 1})
    fmt.Println(rank(m)) // 4

    m.SetRow(3, []float64{0, 0, 1, 1})
    m.SetRow(4, []float64{0, 0, 1, 1})
    fmt.Println(rank(m)) // 3
}
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0