Files
sjy01-image-proc/vendor/github.com/nuknal/goNum/Muller.go
2024-10-24 15:46:01 +08:00

116 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Muller
/*
------------------------------------------------------
作者 : Black Ghost
日期 : 2018-12-20
版本 : 0.0.0
------------------------------------------------------
Muller法求解非线性方程f(x)=0的解
理论:
参考 John H. Mathews and Kurtis D. Fink. Numerical
methods using MATLAB, 4th ed. Pearson
Education, 2004. ss 2.5.2.
------------------------------------------------------
输入 :
fun 求解函数
x0 初值自变量三个不同点3x1
tol 控制误差
n 最大迭代步数
输出 :
sol 解
err 解出标志false-未解出或达到步数上限;
true-全部解出
------------------------------------------------------
*/
package goNum
import (
"math"
)
// Muller Muller法求解非线性方程f(x)=0的解
func Muller(fun func(float64) float64, x0 Matrix, tol float64, n int) (float64, bool) {
/*
Muller法求解非线性方程f(x)=0的解
输入 :
fun 求解函数
x0 初值自变量三个不同点3x1
tol 控制误差
n 最大迭代步数
输出 :
sol 解
err 解出标志false-未解出或达到步数上限;
true-全部解出
*/
//判断tol
if tol <= 0.0 {
panic("Error in goNum.Muller: tol less than or euqals to zero")
}
var sol float64
var err bool = false
//x0赋给p0并计算对应的y0
p0 := ZeroMatrix(x0.Rows, x0.Columns+1)
x0sort, _ := MinMaxSort(x0.Data)
for i := 0; i < x0.Rows; i++ {
p0.SetMatrix(i, 0, x0sort[i])
p0.SetMatrix(i, 1, fun(x0sort[i]))
}
//迭代计算
for i := 0; i < n; i++ {
//准备系数
h0 := p0.GetFromMatrix(0, 0) - p0.GetFromMatrix(2, 0)
h1 := p0.GetFromMatrix(1, 0) - p0.GetFromMatrix(2, 0)
c := p0.GetFromMatrix(2, 1)
e0 := p0.GetFromMatrix(0, 1) - c
e1 := p0.GetFromMatrix(1, 1) - c
b := h1*h0*h0 - h0*h1*h1
a := (e0*h1 - e1*h0) / b
b = (e1*h0*h0 - e0*h1*h1) / b
//求根
z2 := b*b - 4.0*a*c
if z2 < 0 {
//panic("Error in goNum.Muller: There is complex values exist")
z2 = 0
}
var z float64
if b < 0 {
z = -2.0 * c / (b - math.Sqrt(z2))
}
z = -2.0 * c / (b + math.Sqrt(z2))
z = p0.GetFromMatrix(2, 0) + z
//判断解
if math.Abs(fun(z)) < tol {
err = true
sol = z
return sol, err
}
//删除离z最远的点
dis := []float64{
z - p0.GetFromMatrix(0, 0),
z - p0.GetFromMatrix(1, 0),
z - p0.GetFromMatrix(2, 0)}
_, deli, _ := MaxAbs(dis)
for j := 0; j < 3; j++ {
if deli == j {
p0.SetMatrix(j, 0, z)
}
}
x0sort, _ = MinMaxSort(p0.ColumnOfMatrix(0))
for j := 0; j < 3; j++ {
p0.SetMatrix(j, 0, x0sort[j])
p0.SetMatrix(j, 1, fun(x0sort[j]))
}
}
err = false
return sol, err
}