fixed dependencies
This commit is contained in:
188
vendor/github.com/nuknal/goNum/MatrixEigenClassicalJacobi.go
generated
vendored
Normal file
188
vendor/github.com/nuknal/goNum/MatrixEigenClassicalJacobi.go
generated
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
// MatrixEigenClassicalJacobi
|
||||
/*
|
||||
------------------------------------------------------
|
||||
作者 : Black Ghost
|
||||
日期 : 2018-11-30
|
||||
版本 : 0.0.0
|
||||
------------------------------------------------------
|
||||
求解n阶对称矩阵A的全部特征值及其特征向量,经典雅可比法
|
||||
理论:
|
||||
参考 李信真, 车刚明, 欧阳洁, 等. 计算方法. 西北工业大学
|
||||
出版社, 2000, pp 84-89.
|
||||
------------------------------------------------------
|
||||
输入 :
|
||||
A 系数矩阵
|
||||
tol 最大容许误差
|
||||
n 最大迭代步数
|
||||
输出 :
|
||||
Bbar 主特征值矩阵(n阶对角矩阵)
|
||||
Rbar 主特征值所对应的特征向量(n维矩阵,第i列即对应于
|
||||
第i个特征值的特征向量)
|
||||
(err) 解出标志:false-未解出或达到步数上限;
|
||||
true-全部解出
|
||||
------------------------------------------------------
|
||||
*/
|
||||
|
||||
package goNum
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
//判断矩阵是否对称
|
||||
func isSymMatrix_MatrixEigenClassicalJacobi(A Matrix) bool {
|
||||
//是否方阵
|
||||
if A.Columns != A.Rows {
|
||||
return false
|
||||
}
|
||||
|
||||
//是否对称
|
||||
for i := 0; i < A.Rows; i++ {
|
||||
for j := 0; j < A.Columns; j++ {
|
||||
if j != i {
|
||||
if A.GetFromMatrix(i, j) != A.GetFromMatrix(j, i) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
//取最大非对角元素
|
||||
func maxElementElse_MatrixEigenClassicalJacobi(A Matrix) (int, int) {
|
||||
var p, q int
|
||||
var max float64
|
||||
for i := 0; i < A.Rows-1; i++ {
|
||||
for j := i + 1; j < A.Rows; j++ {
|
||||
c := A.GetFromMatrix(i, j)
|
||||
if math.Abs(max) < math.Abs(c) {
|
||||
max = c
|
||||
p = i
|
||||
q = j
|
||||
}
|
||||
}
|
||||
}
|
||||
return p, q
|
||||
}
|
||||
|
||||
//计算cos(theta)及sin(theta)
|
||||
func cosSinTheta_MatrixEigenClassicalJacobi(A Matrix, p, q int) (float64, float64) {
|
||||
apq := A.GetFromMatrix(p, q)
|
||||
app := A.GetFromMatrix(p, p)
|
||||
aqq := A.GetFromMatrix(q, q)
|
||||
|
||||
//情况1,app-aqq=0
|
||||
if app == aqq {
|
||||
c := math.Sqrt(2.0) / 2.0
|
||||
switch {
|
||||
case apq < 0:
|
||||
return c, -1.0 * c
|
||||
case apq > 0:
|
||||
return c, c
|
||||
default:
|
||||
panic("MatrixEigenClassicalJacobi/cosSinTheta: A(p, q) = 0")
|
||||
}
|
||||
}
|
||||
|
||||
//其他情况
|
||||
c := (app - aqq) / (2.0 * apq)
|
||||
d := 2.0 * apq / (app - aqq)
|
||||
//如果|apq| << |app - aqq|,用d
|
||||
if 1000.0*math.Abs(apq) < math.Abs(app-aqq) {
|
||||
tant := d / (1.0 + math.Sqrt(1.0+d*d))
|
||||
cost := 1.0 / math.Sqrt(1.0+tant*tant)
|
||||
sint := tant * cost
|
||||
return cost, sint
|
||||
}
|
||||
// 用c
|
||||
switch {
|
||||
case c > 0:
|
||||
tant := 1.0 / (c + math.Sqrt(1.0+c*c))
|
||||
cost := 1.0 / math.Sqrt(1.0+tant*tant)
|
||||
sint := tant * cost
|
||||
return cost, sint
|
||||
case c < 0:
|
||||
tant := -1.0 / (math.Abs(c) + math.Sqrt(1.0+c*c))
|
||||
cost := 1.0 / math.Sqrt(1.0+tant*tant)
|
||||
sint := tant * cost
|
||||
return cost, sint
|
||||
default:
|
||||
panic("MatrixEigenClassicalJacobi/cosSinTheta: A(p, q) = 0, c = 0")
|
||||
}
|
||||
return 0.0, 0.0
|
||||
}
|
||||
|
||||
//非主对角元素平方之和
|
||||
func sum2Else_MatrixEigenClassicalJacobi(A Matrix) float64 {
|
||||
var sum2 float64
|
||||
for i := 0; i < A.Rows-1; i++ {
|
||||
for j := i + 1; j < A.Columns; j++ {
|
||||
if i != j {
|
||||
sum2 += A.GetFromMatrix(i, j) * A.GetFromMatrix(i, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
return 2.0 * sum2
|
||||
}
|
||||
|
||||
// MatrixEigenClassicalJacobi 求解n阶对称矩阵A的全部特征值及其特征向量,经典雅可比法
|
||||
func MatrixEigenClassicalJacobi(A Matrix, tol float64, n int) (Matrix, Matrix, bool) {
|
||||
/*
|
||||
求解n阶对称矩阵A的全部特征值及其特征向量,经典雅可比法
|
||||
输入 :
|
||||
A 系数矩阵
|
||||
tol 最大容许误差
|
||||
n 最大迭代步数
|
||||
输出 :
|
||||
Bbar 主特征值矩阵(n阶对角矩阵)
|
||||
Rbar 主特征值所对应的特征向量(n维矩阵,第i列即对应于
|
||||
第i个特征值的特征向量)
|
||||
(err) 解出标志:false-未解出或达到步数上限;
|
||||
true-全部解出
|
||||
*/
|
||||
|
||||
//判断A是否对称矩阵
|
||||
if !isSymMatrix_MatrixEigenClassicalJacobi(A) {
|
||||
return ZeroMatrix(A.Rows, A.Columns), ZeroMatrix(A.Rows, A.Columns), false
|
||||
}
|
||||
|
||||
//第一步
|
||||
//Rbar最终为特征向量矩阵
|
||||
Rbar := IdentityE(A.Rows)
|
||||
//复制A矩阵为B,B为迭代过程中逐渐改变的矩阵,最终将成为特征值矩阵
|
||||
B := ZeroMatrix(A.Rows, A.Columns)
|
||||
Bbar := ZeroMatrix(A.Rows, A.Columns)
|
||||
for i := 0; i < len(A.Data); i++ {
|
||||
B.Data[i] = A.Data[i]
|
||||
}
|
||||
|
||||
//迭代步
|
||||
for i := 0; i < n; i++ {
|
||||
//第二步,最大元素所在行列号
|
||||
p, q := maxElementElse_MatrixEigenClassicalJacobi(B)
|
||||
//第三步,计算cos(theta)及sin(theta)
|
||||
cost, sint := cosSinTheta_MatrixEigenClassicalJacobi(B, p, q)
|
||||
//第四步,计算R及Rbar,迭代B矩阵
|
||||
//R为迭代矩阵
|
||||
R := IdentityE(A.Rows)
|
||||
R.SetMatrix(p, p, cost)
|
||||
R.SetMatrix(p, q, sint)
|
||||
R.SetMatrix(q, p, -1.0*sint)
|
||||
R.SetMatrix(q, q, cost)
|
||||
Bbar = DotPruduct(DotPruduct(R, B), R.Transpose()) //A1 = RARt
|
||||
//Rbar = Rbar*Rt
|
||||
Rbar = DotPruduct(Rbar, R.Transpose())
|
||||
//第五步,判断误差
|
||||
if sum2Else_MatrixEigenClassicalJacobi(Bbar) <= tol {
|
||||
return Bbar, Rbar, true
|
||||
}
|
||||
//A = A1
|
||||
for i := 0; i < len(Bbar.Data); i++ {
|
||||
B.Data[i] = Bbar.Data[i]
|
||||
}
|
||||
}
|
||||
|
||||
return ZeroMatrix(A.Rows, A.Columns), ZeroMatrix(A.Rows, A.Columns), false
|
||||
}
|
||||
Reference in New Issue
Block a user