1 Star 0 Fork 63

caoweilin / goNum

forked from 黑影 / goNum 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
MatrixEigenClassicalJacobi.go 5.17 KB
一键复制 编辑 原始数据 按行查看 历史
黑影 提交于 2019-03-01 10:10 . update comments
// 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
}
Go
1
https://gitee.com/caoweilin/goNum.git
git@gitee.com:caoweilin/goNum.git
caoweilin
goNum
goNum
master

搜索帮助