您的位置:首页 > 其它

黄金分割法与Fibonacci法

2016-04-15 20:10 316 查看
最近在上一门最优化算法的课,于是就打算写一篇博客来将自己所学的知识做一个巩固,这两种方法都是用来选取函数的极值点,属于的一维搜索方法中的试探法,方式也是很简单那就是在值域[a,b][a, b]内选取两个点,通过两个值的函数值来缩小值域的取值范围

下面我们来看一下用两种方法,怎么求出函数

在区间[0,1][0,1]内的极大值点,容许误差为10−610^{-6},函数图像呢如下:



斐波那契法:

var
golbal = {
cache: {
"1" : 1,
"2" : 1
},
a: 0,
b: 1
},
e = Math.E,
sin = Math.sin,
tan = Math.tan,
pow = Math.pow,
Fibonacci = function () {
return function (n) {
if (golbal.cache.hasOwnProperty(n)) {
return golbal.cache
;
} else {
golbal.cache
= Fibonacci(n - 1) + Fibonacci(n - 2);
return golbal.cache
;
}
}
}(),
getN = function (deviation) {
var fn = Math.round(1 / deviation),
n = 1;
while (fn > Fibonacci(n)) {
n++;
}
return n;
},
N = getN(Math.pow(10, -6)),
getT1 = function (max, min, k) {
return max + golbal.cache[N - k] / golbal.cache[N - k + 1] * (min - max);
},
getT2 = function (max, min, k) {
return min + golbal.cache[N - k] / golbal.cache[N - k + 1] * (max - min);
},
fn = function (x) {
return -( pow(sin(x), 6) * tan(1- x) * pow(e, 20 * x) );
},
t1 = getT1(golbal.b, golbal.a, 1),
t2 = getT2(golbal.b, golbal.a, 1);
for (var i = 2; i < N - 1; i++) {
if ( fn( t1 ) < fn( t2 ) ) {
golbal.b = t2;
t2 = t1;
t1 = getT1(golbal.b, golbal.a, i);
} else {
golbal.a = t1;
t1 = t2;
t2 = getT2(golbal.b, golbal.a, i);
}
}
var result = fn(t1) > fn(t2) ? t2 : t1;
console.log(result);   // 0.9586523941351989


黄金分割法(0.618法):

首先我们来看一下0.6180.618是怎么样来的:

我们将一个线段中选取两个点,使得较长的线段aa,较短的先打bb,满足aa+b=ba\frac{a}{a+b} = \frac{b}{a},经过计算,我们可以的出,5√−12\frac{\sqrt{5} - 1}{2},这也就是我们所说的0.6180.618,这样选取的目的使得我们在迭代时,只需要计算一次值,而另一个值即为这次的0.6180.618处的值。

var e = Math.E,
sin = Math.sin,
tan = Math.tan,
pow = Math.pow;
function GoldSplit (max, min, deviation, obj1, obj2) {
if (Math.abs(max - min) < deviation) {
return (max + min) / 2;
}
var t1 = obj1.t1 || min + 0.382 * (max - min),
t2 = obj2.t2 || min + 0.618 * (max - min),
f1 = obj1.f1 || -( pow(sin(t1), 6) * tan(1- t1) * pow(e, 30 * t1) );
f2 = obj2.t2 || -( pow(sin(t2), 6) * tan(1- t2) * pow(e, 30 * t2) );
if (f1 < f2) {
return GoldSplit(t2, min, deviation, {}, {
t2: t1,
f2: f1
});
} else if (f1 > f2) {
return GoldSplit(max, t1, deviation, {
t1: t2,
f1: f2
}, {});
} else {
return GoldSplit(t2, t1, deviation, {}, {});
}
}
console.log(GoldSplit(1, 0, Math.pow(10, -6), {}, {})); // 0.9442574673570285
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: