1 Star 0 Fork 64

天行有常/goNum

forked from 黑影/goNum 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
OptimizeSimplex_test.go 6.58 KB
一键复制 编辑 原始数据 按行查看 历史
黑影 提交于 2019-03-01 10:13 . update comments
// OptimizeSimplex_test
/*
------------------------------------------------------
作者 : Black Ghost
日期 : 2018-12-25
版本 : 0.0.0
------------------------------------------------------
Nelder-Mead单纯形法求解多自变量函数极小值
理论:
对于函数z=f(x0,x1,...,xn),取三个相异的点构成三角形,并按函数值
从小到大排序为B、G、W,依下列方法进行操作:
0. 取BG中点M = (B+G)/2;
1. 取反射点R = M+(M-W);
2. 取延伸点E = R+(R-M);
3. 收缩点C = zMin(C1=M+(W-M)/2, C2=M+(M-W)/2);
4. 收缩点S = (B+W)/2。
1~4每一步计算函数值并置换排序BGW
n个x需要n+1个初始点
参考:John H. Mathews and Kurtis D. Fink. Numerical
methods using MATLAB, 4th ed. Pearson
Education, 2004. ss 8.2.1
------------------------------------------------------
输入 :
fun 函数表达式
x0 初始点,nx(n+1),第一行x0,第二行x1,...
tol 控制误差
Nn 最大迭代步数
输出 :
sol 解,(n+1)x1
|xPath 自变量变化历程,二维浮点,可使用Slices2ToMatrix函数转换为Matrix类型
|fxPath 函数值变化历程,一维浮点,可使用Slices1ToMatrix函数转换为Matrix类型
|errPath 误差绝对值历程,一维浮点,可使用Slices1ToMatrix函数转换为Matrix类型
err 解出标志:false-未解出或达到边界;
true-全部解出
------------------------------------------------------
*/
package goNum_test
import (
"math"
"testing"
"github.com/chfenger/goNum"
)
// OptimizeSimplex Nelder-Mead单纯形法求解多自变量函数极小值
func OptimizeSimplex(fun func(goNum.Matrix) float64, x0 goNum.Matrix, tol float64, Nn int) (goNum.Matrix, bool) {
/*
Nelder-Mead单纯形法求解多自变量函数极小值
输入 :
fun 函数表达式
x0 初始点,nx(n+1),第一行x0,第二行x1,...
tol 控制误差
Nn 最大迭代步数
输出 :
sol 解,(n+1)x1
err 解出标志:false-未解出或达到边界;
true-全部解出
*/
//判断x0大小
n := x0.Rows //xi
if x0.Columns != n+1 { //初始点个数等于自变量个数加一
panic("Error in goNum.OptimizeSimplex: Initial values error")
}
//判断N
if Nn < 1 {
panic("Error in goNum.OptimizeSimplex: Iteration number error")
}
sol := goNum.ZeroMatrix(n+1, 1)
xPath := make([][]float64, 0)
fxPath := make([]float64, 0)
errPath := make([]float64, 0)
var err bool = false
//计算f(x)
for i := 0; i < n+1; i++ {
sol.Data[i] = fun(goNum.NewMatrix(n, 1, x0.ColumnOfMatrix(i)))
}
//取最大、最小、次大和次小序号
_, l0, _ := goNum.Min(sol.Data) //最小
_, h0, _ := goNum.Max(sol.Data) //最大
l1 := h0 //次小
h1 := l0 //次大
for i := 0; i < n+1; i++ {
if (i != l0) && (i != h0) && (sol.Data[i] < sol.Data[l1]) {
l1 = i
}
if (i != l0) && (i != h0) && (sol.Data[i] > sol.Data[h1]) {
h1 = i
}
}
xPath = append(xPath, x0.ColumnOfMatrix(l0))
fxPath = append(fxPath, sol.Data[l0])
errPath = append(errPath, math.Abs(sol.Data[h0]-sol.Data[l0]))
//迭代
for i := 0; i < Nn; i++ {
//中点M = (Sum-W)/n
temp0 := goNum.ZeroMatrix(n, 1)
for j := 0; j < n+1; j++ {
temp0 = goNum.AddMatrix(temp0, goNum.NewMatrix(n, 1, x0.ColumnOfMatrix(j)))
}
mm := goNum.NumProductMatrix(goNum.SubMatrix(temp0, goNum.NewMatrix(n, 1, x0.ColumnOfMatrix(h0))), 1.0/float64(n))
//反射点R = 2M-W
rr := goNum.SubMatrix(goNum.NumProductMatrix(mm, 2.0), goNum.NewMatrix(n, 1, x0.ColumnOfMatrix(h0)))
fr := fun(rr)
//判断
if fr < sol.Data[h1] { //fr<fh1, case1
if fr > sol.Data[l1] { //R-->W
for j := 0; j < n; j++ {
x0.SetMatrix(j, h0, rr.Data[j])
}
sol.Data[h0] = fr
} else { //延伸E
ee := goNum.SubMatrix(goNum.NumProductMatrix(rr, 2.0), mm)
fe := fun(ee)
if fe < sol.Data[l1] { //E-->W
for j := 0; j < n; j++ {
x0.SetMatrix(j, h0, ee.Data[j])
}
sol.Data[h0] = fe
} else { //R-->W
for j := 0; j < n; j++ {
x0.SetMatrix(j, h0, rr.Data[j])
}
sol.Data[h0] = fr
}
}
} else { //case 2
if fr < sol.Data[h0] {
for j := 0; j < n; j++ {
x0.SetMatrix(j, h0, rr.Data[j])
}
sol.Data[h0] = fr
}
//C1 = (W+M)/2, C2 = (R+M)/2,默认C=C1
cc := goNum.NumProductMatrix(goNum.AddMatrix(goNum.NewMatrix(n, 1, x0.ColumnOfMatrix(h0)), mm), 0.5)
fc := fun(cc)
c2 := goNum.NumProductMatrix(goNum.AddMatrix(rr, mm), 0.5)
fc2 := fun(c2)
//判断获得C
if fc > fc2 {
for j := 0; j < n; j++ {
cc.Data[j] = c2.Data[j]
}
fc = fc2
}
if fc < sol.Data[h0] {
for j := 0; j < n; j++ {
x0.SetMatrix(j, h0, cc.Data[j])
}
sol.Data[h0] = fc
} else { //xj = (xj+x0)/2
for j := 0; j < n+1; j++ {
if j != l0 {
temp1 := goNum.NumProductMatrix(goNum.AddMatrix(goNum.NewMatrix(n, 1, x0.ColumnOfMatrix(j)),
goNum.NewMatrix(n, 1, x0.ColumnOfMatrix(l0))), 0.5)
for k := 0; k < n; k++ {
x0.SetMatrix(k, j, temp1.Data[k])
}
sol.Data[j] = fun(temp1)
}
}
}
}
//下一步
_, l0, _ = goNum.Min(sol.Data) //最小
_, h0, _ = goNum.Max(sol.Data) //最大
l1 = h0 //次小
h1 = l0 //次大
for j := 0; j < n+1; j++ {
if (j != l0) && (j != h0) && (sol.Data[j] < sol.Data[l1]) {
l1 = j
}
if (j != l0) && (j != h0) && (sol.Data[j] > sol.Data[h1]) {
h1 = j
}
}
//记录历程
xPath = append(xPath, x0.ColumnOfMatrix(l0))
fxPath = append(fxPath, sol.Data[l0])
errPath = append(errPath, math.Abs(sol.Data[h0]-sol.Data[l0]))
//判断满足精度否
if errPath[i+1] < tol {
//将所有数据赋予sol,前n项为x,最后一项为f(x)
sol.Data[n] = sol.Data[l0]
for j := 0; j < n; j++ {
sol.Data[j] = x0.GetFromMatrix(j, l0)
}
err = true
return sol, err
}
}
return sol, err //,xPath,fxPath,errPath
}
func fun52(x goNum.Matrix) float64 {
sol := x.Data[0]*x.Data[0] - 4.0*x.Data[0] + x.Data[1]*x.Data[1] - x.Data[1] - x.Data[0]*x.Data[1]
return sol
}
func BenchmarkOptimizeSimplex(b *testing.B) {
x52 := goNum.NewMatrix(2, 3, []float64{0.0, 1.2, 0.0,
0.0, 0.0, 0.8})
for i := 0; i < b.N; i++ {
goNum.OptimizeSimplex(fun52, x52, 1e-6, 1e3) //{3.0, 2.0, -7.0}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/simondong1979/goNum.git
git@gitee.com:simondong1979/goNum.git
simondong1979
goNum
goNum
master

搜索帮助