黄金分割法与Fibonacci法
2016-04-15 20:10
316 查看
最近在上一门最优化算法的课,于是就打算写一篇博客来将自己所学的知识做一个巩固,这两种方法都是用来选取函数的极值点,属于的一维搜索方法中的试探法,方式也是很简单那就是在值域[a,b][a, b]内选取两个点,通过两个值的函数值来缩小值域的取值范围
下面我们来看一下用两种方法,怎么求出函数
在区间[0,1][0,1]内的极大值点,容许误差为10−610^{-6},函数图像呢如下:
斐波那契法:
黄金分割法(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处的值。
下面我们来看一下用两种方法,怎么求出函数
在区间[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
相关文章推荐
- Java线程面试题 Top 50
- Spring声明式事务配置文件
- LeetCode——012
- I/O笔记
- UINavigationController
- 精----Java读取xml文件的四种方法
- windows下的theano以及GPU加速环境的搭建
- 安装Win7与Ubuntu双系统
- 集成手机归属地查询
- iOS个人整理40-定位和地图
- 经典算法——数组的循环右移K位
- linux下Bash编程字符测试与for循环语句(五)
- 图像特征提取方法
- poj 1276(多重背包)
- ubuntu14.04下python+Theano+cuba7.5
- 大数相加方法------2
- CNN初探
- 阿里云 centos node 简单记录
- Java读取、创建xml(通过dom方式)
- 【集训队互测 2012】Middle