优化算法——遗传算法

  • 与遗传算法的第一次接触

    • 遗传算法的基本概念
    • 基本定义
    • 遗传算法的基本流程
  • 遗传算法过程中的具体操作
    • 参数的编码

      • 二进制编码
      • Gray编码
      • 实数编码
      • 有序编码
    • 初始群体的设定
    • 适应度函数的计算
    • 遗传操作设计
      • 选择selection
      • 交叉crossover
      • 变异mutation
    • 控制参数的设定
  • 求解优化问题的实例
    • 问题描述
    • 问题分析
    • 算法设计
      • 个体编码
      • 适应值函数
      • 选择策略
      • 杂交算子
      • 变异算子
      • 参数设置
      • 初始化
      • 终止条件
    • 实验代码
    • 最终结果

与遗传算法的第一次接触

遗传算法是我进入研究生阶段接触的第一个智能算法,从刚开始接触,到后来具体去研究,再到后来利用遗传算法完成了水利水电的程序设计比赛,整个过程中对遗传算法有了更深刻的理解,在此基础上,便去学习和研究了粒子群算法,人工蜂群算法等等的群体智能算法。想利用这个时间,总结下我对于遗传算法的理解,主要还是些基本的知识点的理解。

遗传算法的基本概念

遗传算法(Genetic Algorithm, GA)是由Holland提出来的,是受遗传学中的自然选择和遗传机制启发发展起来的一种优化算法,它的基本思想是模拟生物和人类进化的方法求解复杂的优化问题。

基本定义

  1. 个体(individual):在遗传学中表示的是基因编码,在优化问题中指的是每一个解。
  2. 适应值(fitness):评价个体好坏的标准,在优化问题中指的是优化函数。
  3. 群体(population): 由个体组成的集合
  4. 遗传操作:遗传操作的主要目的是用于在当前的群体中产生新的群体,主要的操作包括:选择(selection)、交叉(crossover)、变异(mutation)。

遗传算法的基本流程

遗传算法的过程中主要包括这样几个要素:1、参数的编码。2、初始群体的设定。3、适应度函数的设计。4、遗传操作设计。5、控制参数的设定。

基本遗传算法的具体过程如下:

遗传算法过程中的具体操作

参数的编码

遗传算法中的参数编码的方式主要有:1、二进制编码。2、Gray编码。3、实数编码。4、有序编码。

二进制编码

二进制编码是最原始的编码方式,遗传算法最初是在二进制编码的方式下进行运算的。二进制编码也是遗传算法中使用最为直接的运算编码方式。二进制编码是指利用0和1对问题的解向量进行编码。例如,对于如下的优化问题:

maxf(x1,x2)=21.5+x1sin(4πx1)+x2sin(20πx2)

?3.0≤x1≤12.1;4.1≤x2≤5.8

其三维图像如下图所示:

在对这样的优化问题进行二进制编码的过程中,是将问题的可能解编码为二进制位串,例如问题的可能解为实数对(x1,x2),首先必须将x1和x2分别使用二进制位串表示,然后将他们的二进制位串组合在一起。对于每一个变量的二进制位串的长度取决于变量的定义域所要求的精度。



二进制位串的长度的计算方法如下:

假设aj≤xj≤bj,所要求的精度是小数点后t位。这要求将区间划分为至少(bj?aj)10t份。假设表示变量xj的位串的长度用lj表示,则lj可取为满足下列不等式的最小数m:

(bj?aj)10t≤2m?1

即有:

2lj?1?1<(bj?aj)10t≤2lj?1



对于上述的优化问题,假设精度为小数点后4位,则:

(12.1?(?3.0))×10000=151000

217?1<151000≤218?1

那么表示变量x1的二进制位串的长度为l1=18。

同理,对于变量x2:

(5.8?4.1)×10000=17000

214?1<17000≤215?1

表示变量x2的二进制位串的长度为l2?15。

此时,个体可以表示为:

其中,前18位表示的是x1,后15位表示的是x2。

Gray编码

这种编码方式在求解优化问题时,本人基本上没做过任何研究。

实数编码

在二进制编码的过程中存在这样的一个问题,即在计算适应值的时候需要将二进制编码转换成十进制的编码进行运算,这样,很显然会想到能否直接使用十进制编码直接进行运算,如上例中的(x1,x2)这样的编码方式。

有序编码

有序编码主要使用在TSP问题中,在本文中主要涉及二进制编码和实数编码

初始群体的设定

在解决了个体的编码问题后,需要解决的问题是如何利用个体表示群体。在上述中,我们知道,群体是个体的集合。假设初始群体的大小为N=20。对于二进制编码方式与实数编码方式产生20个初始解。如:

v1=(010001001011010000111110010100010)

对应的实数编码的方式则为:

v1=(1.052426,5.755330)

对于二进制编码则是随机初始化20组这样的初始解,每组初始解随机初始化33位的0?1编码。而对于实数编码方式,则是在区间上随机初始化20组初始解。

适应度函数的计算

适应度函数的目的是评价个体的好坏,如上面的优化问题中,即为最终的优化目标函数。对于二进制编码,则需要先将二进制编码转换成实数编码,再进行适应值函数的计算,对于实数编码方式,则直接进行适应值函数的计算。

遗传操作设计

遗传操作主要包括:选择(selection)、交叉(crossover)、变异(mutation),遗传操作的主要目的是从当前的群体中产生新的群体,这样便能使得产生新的更优的个体。

选择(selection)

选择操作的目的是选择出父体,用于参加交叉(crossover)和变异(mutation)操作。一般使用较多的方式是轮盘赌的选择策略(Roulette Wheel Selection)。根据每个个体的适应值,计算出相对适应值大小,即:

pi=fi∑fi

相对适应值又称为选择概率,将一个圆盘划分成N份,即群体的大小。每个扇面的面积与其选择概率成正比。轮盘如下图所示:

现在在[0,1]上产生一个随机数r,若:

p1+p2+?+pi?1<r≤p1+p2+?+pi

则选择第i个个体。

重复此操作N次,选择出N个父体。轮盘赌的算法过程如下所示:

交叉(crossover)

交叉操作也称为杂交,其目的是产生新的个体。

对于二进制编码方式,主要有单点杂交和多点杂交。单点杂交是指在二进制串中随机选择一位,交换两个父体中该位以后的二进制串,用以产生新的个体,操作如下图所示:

多点杂交是指在二进制串中选择某几位进行杂交,其中以两点杂交最为常见,其过程如下图所示:

具体的操作过程为:设定一个杂交的概率pc,对选择操作中产生的N个父体,每个父体产生一个[0,1]区间上的随机数rk,若rk<pc,则将第k个个体用于杂交,若选择出来的个体数目是奇数,则在父体集合中再随机挑选一个,以保证挑选出的是偶数个,之后进行两两杂交操作。

对于实数编码形式,可以将实数转换成二进制编码的形式进行杂交运算,但是这样同样存在效率的问题,在实数编码中,主要采用的是算术杂交方式,算术杂交分为:部分算术杂交和整体算术杂交。部分算术杂交是指在父体向量中选择一部分分量进行算术运算,而整体算术杂交是指全部的分量都进行算术运算。我们以整体算术杂交为例:先在[0,1]生成n个随机数a1,a2,?,an,经杂交算子后,所得到的两个后代为:

x′=(a1x1+(1?a1)y1,a2x2+(1?a2)y2,?,anxn+(1?an)yn)

y′=(a1y1+(1?a1)x1,a2y2+(1?a2)x2,?,anyn+(1?an)xn)

变异(mutation)

变异操作的目的是使得基因突变,在优化算法中,可以防止算法陷入局部最优,从而跳出局部最优,帮助算法找到全局最优解。

二进制编码时的变异算子非常简单,只是依一定的概率(称为变异概率)将所选个体的位取反。即若是1,则取0;若是0,则取1。

具体的操作为:设定一个变异概率pm,对杂交操作后的N个父体,对父体中的每一个位产生一个[0,1]区间上的随机数rk,j,若rk,j<pm,则该位变异。

对于实数编码方式,可以采用均匀变异和非均匀变异方式,在均匀变异中,假设x=(x1,x2,?,xn)是要变异的个体,随机产生一个随机整数k∈[1,n],产生新的后代x=(x1,x2,?,x′k,?,xn),其中x′k是[lk,uk]中服从均匀分布的一个随机数。

另一种是非均匀变异,,假设x=(x1,x2,?,xn)是要变异的个体,随机产生一个随机整数k∈[1,n],产生新的后代x=(x1,x2,?,x′k,?,xn),其中:

x′k={xk+Δ(t,uk?xk)xk?Δ(t,xk?lk) if Random(2)=0 if Random(2)=1

这里t是当前演化代数,函数Δ(t,y)返回[0,y]中的一个值,并且Δ(t,y)随t的增加而趋于0的概率增大。函数Δ(t,y)具体形式为:

Δ(t,y)=y?(1?r(1?t/T)b)

或者

Δ(t,y)=y?r?(1?tT)b

其中,r是[0,1]上的一个随机数,T表示最大演化代数。b是确定非均匀度的一个参数,通常取2~5。

控制参数的设定

控制参数主要包括种群的规模N,演化代数T,杂交概率pc,变异概率pm等等。



在实现遗传算法时,一个常用的方法是将到当前代为止演化的最好个体单独存放起来,在遗传算法结束后,将演化过程中发现的最好个体作为问题的最优解或近似最优解。


求解优化问题的实例

问题描述

minf(x1,x2,?,xn)=?20?exp???0.21n∑i=1nx2i???????√???exp(1n∑i=1ncos(2π?xi))+20+e

其中,

?30≤xi≤30,i=1,2,?,n;e=2.71828

问题分析

这是一道不带约束条件的函数优化的问题,既可以采用二进制编码方式,也可以采用十进制的编码方式,在本题的解决过程中,采用十进制的编码方式。首先通过Matlab得到的函数图像大致如下,从图像中可以观察到当n=2时,我们可以在(0,0)附近取得函数的最小值。

算法设计

基于以上的分析,当n=2时,以下分别从个体的编码、适应值函数、选择策略、杂交算子、变异算子、参数设置、初始化以及终止条件这八个方面对程序的设计作简要的描述:

个体编码

采用实数向量编码,每一个个体是一实数对(x1,x2)。

适应值函数

该优化问题是一个极小化问题,可对目标函数作简单变换,同时考虑到在选择策略时选择的是轮盘赌的选择策略,轮盘赌的选择策略有一个要求就是个体的适应值要为正数,因此,可以作如下的变换:F=30?f(x1,x2),这里的30是取的一个上界。这样,既保证了变换后的适应值函数式中为正,而且我们可以将极小化问题转换成一个极大值问题考虑。

选择策略

采用轮盘赌的选择策略,因为在计算适应值时已经作了处理,即适应值始终为正,这样就可以使用轮盘赌的选择策略。轮盘赌的选择策略是一种基于适应值比例的选择策略,适应值越大被选择到下一代的概率也会越大。

杂交算子

采用整体算术杂交,即给定两个父体,产生一个随机数,经杂交后得到两个后代个体,v1=(x1,x2),v2=(y1,y2),产生一个随机数α∈[0,1],经杂交后得到两个后代个体:v′1=(αx1+(1?α)y1,αx2+(1?α)y2),v′2=(αy1+(1?α)x1,αy2+(1?α)x2)。

变异算子

采用非均匀变异,即对于要变异的个体x=(x1,x2),随机产生整数k∈{1,2},例如k=1,然后产生后代x′=(x′1,x2),其中

x′1={x1+Δ(t,u1?x1)x1?Δ(t,x1?l1) if Random(2)=0 if Random(2)=1

参数设置

  • 种群规模N=100
  • 个体长度Size=2
  • 演化代数T=3000
  • 杂交概率pc=0.7
  • 变异概率pm=0.1
  • 函数上界Upp=30.0

初始化

在区间内随机初始化种群的个体,并置个体的适应值,适应值之和以及相对适应值比例为0。

终止条件

采用代数作为终止条件,当算法运行到指定的最大代数时,程序停止。

实验代码

#include<iostream>
#include<time.h>
#include<stdlib.h>
#include<cmath>
#include<fstream>

using namespace std;

const int COLONY_SIZE=100;  //个体数目
const int Size=2;//个体的长度
const int Generation=3000;//代数
const double OVER=0.7;//杂交的概率
const double MUTATE=0.1;//变异的概率
const double UPPER=30.0;//函数的上界

struct Indival
{
    double code[Size];
    double fitness;
    double cfitness;
    double rfitness;
}Group[COLONY_SIZE];

Indival newGroup[COLONY_SIZE];

Indival bestChrom;//记录最好的个体

int GenNum=0;

double random(double, double);
void initiate();
void calvalue();
void select();
void crossOver();
void xOver(int,int);
void mutate();
double delta(int,double,double,double);
void sort();

/*****************主函数***************/
int main()
{
    ofstream output;
    srand((unsigned)time(NULL));
    initiate();
    calvalue();
    output.open("data.txt");
    while(GenNum<=Generation)
    {
        GenNum++;
        select();
        crossOver();
        mutate();
        calvalue();
        sort();
        if (bestChrom.fitness<Group[0].fitness)
        {
            bestChrom.code[0]=Group[0].code[0];
            bestChrom.code[1]=Group[0].code[1];
            bestChrom.fitness=Group[0].fitness;
        }
//      output<<"gen: "<<GenNum<<"最优解为:"<<endl;
//      output<<"x1: "<<bestChrom.code[0]<<"  x2: "<<bestChrom.code[1]<<"   函数值为: "<<(30-bestChrom.fitness)<<endl;
        output<<GenNum<<"   "<<(30-bestChrom.fitness)<<endl;
    }
    output.close();
    cout<<"运行结束!"<<endl;//提示运行结束
    return 0;
}

/******************************函数的实现*****************************************/

double random(double start, double end){//随机产生区间内的随机数
    return start+(end-start)*rand()/(RAND_MAX + 1.0);
}

void initiate()//初始化
{
    for(int i=0;i<COLONY_SIZE;i++)
    {
        Group[i].code[0]=random(-30,30);
        Group[i].code[1]=random(-30,30);
        Group[i].fitness=0;//适应值
        Group[i].cfitness=0;//相对适应值比例之和
        Group[i].rfitness=0;//相对适应值比例
    }
}

void calvalue()//计算适应值
{
    double x1,x2;
    double sum=0;
    double part1,part2;//将函数分成几个部分
    for(int i=0;i<COLONY_SIZE;i++)
    {
        x1=Group[i].code[0];
        x2=Group[i].code[1];
        part1=-0.2*sqrt((x1*x1+x2*x2)/Size);
        part2=(cos(2*3.1415926*x1)+cos(2*3.1415926*x2))/Size;
        Group[i].fitness=UPPER-(-20*exp(part1)-exp(part2)+20+2.71828);//适应值
        sum+=Group[i].fitness;//计算适应值之和
    }
    for(int mem=0;mem<COLONY_SIZE;mem++)//轮盘赌选择机制里所要求的几个参数
    {
        Group[mem].rfitness=Group[mem].fitness/sum;//适应值的比例
    }
    Group[0].cfitness=Group[0].rfitness;
    for(mem=1;mem<COLONY_SIZE;mem++)
    {
        Group[mem].cfitness=Group[mem-1].cfitness+Group[mem].rfitness;//模拟轮盘
    }

}
void select()
{
    double p;
    for(int i=0;i<COLONY_SIZE;i++)//挑选出N个个体
    {
        p=random(0,1);//随机产生0到1之间的随机数
        if(p<Group[0].cfitness)
            newGroup[i]=Group[0];
        else
        {
            for(int j=1;j<COLONY_SIZE;j++)//往轮盘后走
            {
                if(p>=Group[j-1].cfitness&&p<Group[j].cfitness)
                {
                    newGroup[i]=Group[j];
                    break;
                }
            }
        }
    }
    for(i=0;i<COLONY_SIZE;i++)//从newGroup复制到Group中
        Group[i]=newGroup[i];
}
void crossOver()
{
    int mem,one;
    int first=0;//记录杂交的数目
    double x;
    for(mem=0;mem<COLONY_SIZE;mem++)
    {
        x=random(0,1);
        if(x<OVER)
        {
            ++first;
            if(first%2==0)//若为偶数
                xOver(one,mem);
            else
                one=mem;
        }
    }
}
void xOver(int one,int two)
{
    double point;
    point=random(0,1);
    Group[one].code[0]=Group[one].code[0]*point+Group[two].code[0]*(1-point);
    Group[one].code[1]=Group[one].code[1]*point+Group[two].code[1]*(1-point);
    Group[two].code[0]=Group[one].code[0]*(1-point)+Group[two].code[0]*point;
    Group[two].code[1]=Group[one].code[1]*(1-point)+Group[two].code[1]*point;
}
void mutate()
{
    double x;
    for(int i=0;i<COLONY_SIZE;i++)
    {
        for(int j=0;j<Size;j++)
        {
            x=random(0,1);
            if (x<MUTATE)
            {
                Group[i].code[j]=delta(GenNum,Group[i].code[0],30,-30);
            }
        }
    }
}

double delta(int t,double x,double u,double l)
{
    double temp1;
    double temp2;
    double y;
    double r=random(0,1);
    temp1=pow((1-t/Generation),4);
    temp2=pow(r,temp1);
    int a=(int)random(0,2);
    if(a==0)
    {
        y=u-x;
        return (x+y*(1-temp2));
    }else
    {
        y=x-l;
        return (x-y*(1-temp2));
    }
}

void sort()//排序
{
    Indival temp;
    for(int i=0;i<COLONY_SIZE-1;i++)
    {
        for(int j=i+1;j<COLONY_SIZE;j++)
        {
            if(Group[i].fitness<Group[j].fitness)
            {
                temp=Group[i];
                Group[i]=Group[j];
                Group[j]=temp;
            }
        }
    }
}

最终结果

我在这里简单介绍了遗传算法,遗传算法是一个研究较多的算法,还有利用遗传算法求解组合优化问题,带约束的优化问题,还有一些遗传算法的理论知识,如模式定理,积木块假设,在这里就不一一列举了,希望我的博文对你的学习有帮助,也欢迎转载,谢谢,有不到位的地方还请指出。

时间: 2024-11-10 17:24:37

优化算法——遗传算法的相关文章

现代优化算法 之 遗传算法

之前两篇转载的文章: 遗传算法入门到掌握(一).遗传算法入门到掌握(二) 对遗传算法的数学推导讲解得非常详细,同时我也附带了一份遗传算法的C语言实现,这篇文章将要运用遗传算法对一个多项式求最小值,要求在(-8,8)间寻找使表达式达到最小的x,误差为0.001. 但是那篇文章仅仅讲解了关于本例的遗传算法的规则,并没有详细的算法过程. 这篇文章简介一下遗传算法的具体算法过程,并且用MATLAB实现遗传算法的代码,该算法将解决模拟退火一文中的例题. 遗传算法简介 遗传算法(Genetic Algori

细菌觅食优化算法:理论基础,分析,以及应用(未完)

原作者:Swagatam Das,Arijit Biswas,Sambarta Dasgupta,和Ajith Abraham  [摘 要]细菌觅食优化算法(Bacterial foraging optimization algorithm[BFOA])已经被分布式优化和控制的同行们当作一种全局性的优化算法接受.BFOA是由大肠杆菌的群体觅食行为所启发而总结出来 的.BFOA已经吸引了足够多的研究者的注意,由于它出现在解决真实世界中一些应用领域上优化问题的高效性.E.coli 的群体策略的生物基

智能优化算法对TSP问题的求解研究

要求: TSP 算法(Traveling Salesman Problem)是指给定 n 个城市和各个城市之间的距离,要 求确定一条经过各个城市当且仅当一次的最短路径,它是一种典型的优化组合问题,其最优 解得求解代价是指数级的.TSP 问题代表一类优化组合问题,在实际工程中有很多应用,如 计算机联网.电子地图.交通诱导等,具有重要的研究价值.遗传算法和禁忌搜所算法都是 是一种智能优化算法,具有全局的优化性能.通用性强.这种算法一般具有严密的理论依据, 理论上可以在一定的时间内找到最优解或近似最优

粒子群优化算法(PSO)

1. 概念 粒子群优化算法(PSO:Particle swarm optimization) 是一种进化计算技术(evolutionary computation). 源于对鸟群捕食的行为研究.粒子群优化算法的基本思想:是通过群体中个体之间的协作和信息共享来寻找最优解. PSO的优势:在于简单容易实现并且没有许多参数的调节.目前已被广泛应用于函数优化.神经网络训练.模糊系统控制以及其他遗传算法的应用领域. 2. 算法 2.1 问题抽象 鸟被抽象为没有质量和体积的微粒(点),并延伸到N维空间,粒子

粒子群优化算法简介

好好学数学. 一.问题来源 经朋友介绍,接了一份工作,就是做PSO及其优化,恰好我导师也研究这个,刚开学也有接触,那我就接了.......赚点生活费. 欢迎大家和我联系做算法类项目,QQ:791909235,Tel:13137910179. 二.背景介绍 2.1 人工生命 人工生命:研究具有某些生命基本特征的人 工系统.包括两方面的内容: 1.研究如何利用计算技术研究生物现象: 2. 研究如何利用生物技术研究计算问题. 我们关注的是第二点.已有很多源于生物现象的计算技巧,例如神经网络和遗传算法.

几种常见的优化算法

我们每个人都会在我们的生活或者工作中遇到各种各样的最优化问题,比如每个企业和个人都要考虑的一个问题"在一定成本下,如何使利润最大化"等.最优化方法是一种数学方法,它是研究在给定约束之下如何寻求某些因素(的量),以使某一(或某些)指标达到最优的一些学科的总称.随着学习的深入,博主越来越发现最优化方法的重要性,学习和工作中遇到的大多问题都可以建模成一种最优化模型进行求解,比如我们现在学习的机器学习算法,大部分的机器学习算法的本质都是建立优化模型,通过最优化方法对目标函数(或损失函数)进行优

粒子群优化算法PSO及matlab实现

算法学习自:MATLAB与机器学习教学视频 1.粒子群优化算法概述 粒子群优化(PSO, particle swarm optimization)算法是计算智能领域,除了蚁群算法,鱼群算法之外的一种群体智能的优化算法,该算法最早由Kennedy和Eberhart在1995年提出的,该算法源自对鸟类捕食问题的研究. • PSO算法首先在可行解空间中初始化一群粒子,每个粒子都代表极值优化问题的一个潜在最优解,用位置.速度和适应度值三项指标表示该粒子特征. • 粒子在解空间中运动,通过跟踪个体极值Pb

机器学习几种常见优化算法介绍

机器学习几种常见优化算法介绍 https://blog.csdn.net/class_brick/article/details/78949145 1. 梯度下降法(Gradient Descent) 2. 牛顿法和拟牛顿法(Newton's method & Quasi-Newton Methods) 3. 共轭梯度法(Conjugate Gradient) 4. 启发式优化方法 5. 解决约束优化问题--拉格朗日乘数法 我们每个人都会在我们的生活或者工作中遇到各种各样的最优化问题,比如每个企

机器学习常见的优化算法

1.梯度下降法 梯度下降法是最早最简单的,也是最为常用的最优化算法.梯度下降法实现简单,当目标函数是凸函数时,梯度下降法的解是全局解.一般情况下,其解不保证是全局最优解,梯度下降法的速度未必是最快的.梯度下降法的优化思想是用当前位置负梯度方向作为搜索方向,因为该方向为当前位置的最快下降方向,所以也被称为"最速下降法".最速下降法越接近目标值,步长越小,前进越慢. 在机器学习中,基于基本的梯度下降法发展了两种梯度下降方法,分别为随即梯度下降法和批量梯度下降法. 批量梯度下降:最小化所有训