启发式算法

常用的启发式算法

什么是启发式算法

启发式算法一般用于解决NP-hard问题,其中NP是指非确定性多项式。

你可能不懂NP-HARD问题是什么(关于NP-hard,NPC,NP,P问题,下期再说),简单来说,NPH问题就是用电脑直接算不出来的问题,然后你要用启发式算法,得到很可能正确的结果,但可以省下时间、空间,电脑就能跑起来了。

例如,著名的旅行商问题(Travel Saleman Problem or TSP):假设一个推销员需要从南京出发,经过广州,北京,上海,…,等 n 个城市, 最后返回香港。 任意两个城市之间都有飞机直达,但票价不等。假设公司只给报销 C 元钱,问是否存在一个行程安排,使得他能遍历所有城市,而且总的路费小于 C?

旅行商问题可以直接看做求最短路径问题,当规模小的时候你可以直接通过Dijkstra或Floyd算法求,但是当规模大的时候,这些算法就解决不聊了,所以我们要寻找其他算法。

推销员旅行问题显然是 NP 的。因为如果你任意给出一个行程安排,可以很容易算出旅行总开销。但是,要想知道一条总路费小于 C 的行程是否存在,在最坏情况下,必须检查所有可能的旅行安排。

启发式算法是相对于最优化算法提出的,是基于直观或者经验构造的算法,在可接受的开销(时间和空间)内给出待解决组合优化问题的一个可行解。

目前通用的启发式算法

目前比较通用的启发式算法一般有模拟退火算法(SA)、遗传算法(GA)、蚁群算法(ACO)、人工神经网络(ANN)、萤火虫算法(FA)等。

模拟退火算法(SA)

简介

模拟退火算法(Simulated Annealing, SA)的思想借鉴于固体的退火原理,当固体的温度很高的时候,内能比较大,固体的内部粒子处于快速无序运动,当温度慢慢降低的过程中,固体的内能减小,粒子的慢慢趋于有序,最终,当固体处于常温时,内能达到最小,此时,粒子最为稳定。模拟退火算法便是基于这样的原理设计而成。

模拟退火算法步骤

  1. 初始化温度T(充分大),温度下限Tmin(充分小),初始解X,每个T值迭代次数L

  2. 随机生成临域解x_new;

  3. 设f(x)函数来计算用来计算解得好坏,计算出f(x_new)-f(x);

  4. 如果f(x_new)-f(x)>0,说明新解比原来的解好,则无条件接受,如果f(x_new)-f(x)<0,则说明旧解比新解好,则以概率exp((f(xnew)-f(x))/k*T)接受x_new作为解。

  5. 如果当前温度

代码示例

求解函数最小值问题: 其中,0<=x<=100,给定任意y值,求x为多少时,F(x)最小。

public class SATest {
 public static final int T = 1000;// 初始化温度
 public static final double Tmin = 1;// 温度的下界
 public static final int k = 100;// 迭代的次数
 public static final double delta = 0.98;// 温度的下降率public static double getX() {
 return Math.random() * 100;
 }/**
 * 评价函数的值,即对应上文中的f(x)
 * 
 * @param x目标函数中的一个参数
 * @param y目标函数中的另一个参数
 * @return函数值
 */
 public static double getFuncResult(double x, double y) {
 double result = 6 * Math.pow(x, 7) + 8 * Math.pow(x, 6) + 7
 * Math.pow(x, 3) + 5 * Math.pow(x, 2) - x * y;return result;
 }/**
 * 模拟退火算法的过程
 * @param y目标函数中的指定的参数
 * @return最优解
 */
 public static double getSA(double y) {
 double result = Double.MAX_VALUE;// 初始化最终的结果
 double x[] = new double[k];
 // 初始化初始解
 for (int i = 0; i < k; i++) {
 x[i] = getX();
 }
 // 迭代的过程
 while (t > Tmin) {
 for (int i = 0; i < k; i++) {
 // 计算此时的函数结果
 double funTmp = getFuncResult(x[i], y);
 // 在邻域内产生新的解
 double x_new = x[i] + (Math.random() * 2 - 1);
 // 判断新的x不能超出界
 if (x_new >= 0 && x_new <= 100) {
 double funTmp_new = getFuncResult(x_new, y);
 if (funTmp_new - funTmp < 0) {
 // 替换
 x[i] = x_new;
 } else {
 // 以概率替换
 double p = 1 / (1 + Math
 .exp(-(funTmp_new - funTmp) / T));
 if (Math.random() < p) {
 x[i] = x_new;
 }
 }
 }
 }
 T = T * delta;
 }
 for (int i = 0; i < k; i++) {
 result = Math.min(result, getFuncResult(x[i], y));
 }
 return result;
 }public static void main(String args[]) {
 // 设置y的值
 int y = 0;
 System.out.println("最优解为:" + getSA(y));
 }}

遗传算法(GA)

简介

遗传算法(Genetic Algorithm, GA)起源于对生物系统所进行的计算机模拟研究。它是模仿自然界生物进化机制发展起来的随机全局搜索和优化方法,借鉴了达尔文的进化论和孟德尔的遗传学说。其本质是一种高效、并行、全局搜索的方法,能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最佳解。

相关术语

  • 编码(coding):将物体的表现型用编码的方式转为程序可控的基因型。

  • 解码(decoding):基因型到表现型的映射。

  • 基因型(genotype):参数的因子;

  • 表现型(phenotype):根据不同因子最终展现的形态;

  • 适应度(fitness):度量某个结果的好坏。

  • 进化(evolution):不断剔除差的结果,最终逐步留下好的结果。

  • 选择(selection):以一定的概率从种群中选择若干个个体留下,并繁殖。选择过程是一种基于适应度的优胜劣汰的过程。

  • 复制(reproduction):将父本、母本的基因复制,以便产生下一代。

  • 交叉(crossover):两个染色体的某一相同位置处DNA被切断,前后两串分别交叉组合形成两个新的染色体。也称基因重组或杂交;

  • 变异(mutation):交叉后可能(很小的概率)对染色体进行更改,来防止算法过早收敛而陷入局部最优解中。

  • 个体(individual):指染色体带有特征的实体;

  • 种群(population):个体的集合,该集合内个体数称为种群的大小

在此,关于编码方法,交叉方法,变异方法,选择方法等都不做详尽概述。

蚁群算法(ACO)

简介

我们尝试复原一下蚂蚁寻找食物的场景。想象有一只蚂蚁找到了食物,这时它需要将食物带回蚁穴。对于这一只蚂蚁而言,它显然并不知道应该怎么走。那么,这只蚂蚁有可能会随机选择一条路线。

这条路线很可能是一条远路。但是,蚂蚁一路上留下了记号,也就是信息素。如果这只蚂蚁继续不停地搬运食物,或者有许多其他蚂蚁一块搬运的话。他们总会在运气好的时候走到更快往返的路线上。蚂蚁选择的路越好,相同时间内往返的次数也就更多,也就在路上留下了更多的信息素。

于是,蚂蚁们总会发现,有一些路径的信息素更浓,这些路径就是更好的路线。于是蚂蚁也就更多地向信息素更浓的路径上偏移。蚂蚁们不停重复这个过程,最终总能找到一条确定的路线,而这条路线就是蚂蚁们找到的最优路径。

蚁群算法步骤

  1. 初始化蚂蚁数量、可行路段、每条路段距离、每条路段的初始信息素大小等信息

  2. 设定蚂蚁的起点、终点。

  3. 蚂蚁从起点出发根据信息素浓度,有一定的概率性选择路段,浓度越高,概率越大,逐步回到终点。

  4. 在蚂蚁走过的路径上,根据每条路段的长度按比例释放信息素,短的路段释放的信息素多,长的路段释放的信息素少。

  5. 对所有路段的信息素进行挥发。

  6. 回到第二步进行循环,直到蚂蚁数量迭代完。

萤火虫算法(FA)

简介

该算法的基本思想是利用在一定范围内萤火虫发光低的向发光高的萤火虫移动,从而有效的实现寻找最优解。
由于萤火虫算法原理相对简单、且易于实现;而且还具有良好的全局寻优能力,能够快速地收敛于最优解等特性,现在萤火虫算法已经应用到工业优化、动态路径规划、图像处理、经济调度等领域。

算法流程

  1. 初始化问题,将个体转化为萤火虫,设置亮度函数,并初始化所有参数β,γ,α
  2. 确定每个萤火虫两两之间的距离
  3. 计算对周围萤火虫的吸引度
  4. 对于每个萤火虫而言,找到吸引度最高的萤火虫个体,并更新位置
  5. 使最亮的萤火虫随机移动位置
  6. 如果完成迭代或者达到精度则结束,否则转第2步

全文比较简洁,主要是一个简单介绍,若要具体研究,建议朋友们查阅论文。

你可能感兴趣的:(启发式算法)