【最优化】黄金分割法

最优化算法学习

一位搜索中的黄金分割法的算法实现



前言

一维搜索是最优化结构里的重要且基础的模块,学习一位搜索对研究最优性条件、收敛性的证明、算法速度的设计有着极其重要的作用。


一、什么是一维搜索?

一维搜索的定义

二、一维搜索的方法

 精确一维搜索通常有两种实现方式:
 **试探法**和**函数逼近法**。
 其中
 **试探法** 常见的有 *黄金分割法*(0.618法)和   *斐波那契法*(Fibonacci法)
 **函数逼近法** 常见的有 牛顿法、割线法、抛物线法、插值法 等。
 本文只浅谈试探法中的黄金分割法。

1.黄金分割法(0.618法)

0.618法的基本思想:
通过取试探点使包含极小点的区间不断缩短,当区间长度小到一定程度时,区间上各点的函数值均接近极小值,因此任意一点都可以作为极小点的近似。
####步骤:
1. 置初始区间 [ a[1], b[1] ]及精度要求L>0,
计算 r[1] = a[1] + 0.382 x ( b[1] - a[1] ),
u[1] = a[1] + 0.618 x ( b[1]-a[1] ).
计算f( r[1] ) 和 f( u[1] ).令 k = 1.
2. 若 b[k] - a[k] < L,则停止计算;否则当 f(r[k])>f(u[k])时,转3,当 f(r[k])<f(u[k])时,转4.
3. 置a[k+1] = r[k] , b[k+1] = b[k] , r[k+1]=u[k] , u[k+1] = a[k+1] + 0.618 x (b[k+1] - a[k+1]), 计算f(u[k+1]) , 转5.
4. 置a[k+1] = a[k] , b[k+1] = u[k] , u[k+1]=r[k] , r[k+1] = a[k+1] + 0.382 x (b[k+1] - a[k+1]), 计算f(r[k+1]) , 转5.
5. 置 k=k+1, 返回2.

代码如下:

//黄金分割法:0.618法求极小值; 

//黄金分割法:0.618法求极小值; 

#include<iostream>
#include<iomanip>
#include<stdio.h>
#include<cmath>
using namespace std;


double func(double x){
	
	//此处需要按实际情况修改函数表达式
	double s=-5*x+exp(x);
	return s;
}

int main(){
	double L,a1,b1;
	cout<<"请输入初始区间:";
	cin>>a1>>b1;
	cout<<"请输入容忍值:";
	cin>>L;
	 
	int k;
	double a[20];
	double b[20];
	double r[20];
	double u[20];
	
	a[1]=a1;
	b[1]=b1;

	k=1;
	double fr,fu;
	    cout<<"------------------------------------------------------------------------------------"<<endl;
	    printf("\t%s \t%s \t%s \t%s \t%s \t%s \t%s\n", "echo", "a_k", "b_k","r_k","u_k","f(r_k)","f(u_k)");
	    cout<<"------------------------------------------------------------------------------------"<<endl;
	    
	    r[k]=a[k]+0.382*(b[k]-a[k]);
		u[k]=a[k]+0.618*(b[k]-a[k]);
	while(b[k]-a[k] >=L){
		
		
		fr=func(r[k]);
		fu=func(u[k]);
	
		printf("\t%d %8.3f %8.3f %8.3f %8.3f %8.4f %8.4f\n", k, a[k], b[k],r[k],u[k],fr,fu);
		cout<<"------------------------------------------------------------------------------------"<<endl;
		if(fr<fu){
			b[k+1]=u[k];
			a[k+1]=a[k];
			r[k+1]=a[k+1]+0.382*(b[k+1]-a[k+1]);
		    u[k+1]=r[k];
		}
		else if(fr>fu){
			a[k+1]=r[k];
			b[k+1]=b[k];
		    r[k+1]=u[k];
		    u[k+1]=a[k+1]+0.618*(b[k+1]-a[k+1]);
		}
		
		k++;
	}
	printf("\t%d %8.3f %8.3f \n", k, a[k], b[k]);
	cout<<"------------------------------------------------------------------------------------"<<endl;
	cout<<"\t迭代"<<k-1<<"次,达到要求!"<<endl;
	printf("\tb[%d]-a[%d]=%8.3f \n", k,k,b[k]-a[k]); 
	printf("\t最优值在区间 [%8.3f, %8.3f]\n",a[k],b[k]);
	
	
} 

2.验证

该处 f(x) = e^x - 5x . 初始区间为 [1 , 2 ] , 精度要求L=0.04.
代码验证


总结

以上就是今天要讲的内容,本文仅仅简单介绍了黄金分割的算法实现,,而Fibonacci法与0.618法相似,大家可以自行编写Fibonacci法。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值