linux小组分享会_遗传算法

遗传算法初步

维基百科:

https://zh.wikipedia.org/wiki/%E9%81%97%E4%BC%A0%E7%AE%97%E6%B3%95

遗传算法(英语:genetic algorithm (GA) )是计算数学中用于解决最佳化的搜索算法,是进化算法的一种。进化算法最初是借鉴了进化生物学中的一些现象而发展起来的,这些现象包括遗传突变自然选择以及杂交等。

遗传算法通常实现方式为一种计算机模拟。对于一个最优化问题,一定数量的候选解(称为个体)可抽象表示为染色体,使种群向更好的解进化。传统上,解用二进制表示(即0和1的串),但也可以用其他表示方法。进化从完全随机个体的种群开始,之后一代一代发生。在每一代中评价整个种群的适应度,从当前种群中随机地选择多个个体(基于它们的适应度),通过自然选择和突变产生新的生命种群,该种群在算法的下一次迭代中成为当前种群。

遗传算法的机理

在遗传算法里,优化问题的解被称为个体,它表示为一个变量序列,叫做染色体或者基因。染色体一般被表达为简单的字符串或数字串,不过也有其他的依赖于特殊问题的表示方法适用,这一过程称为编码。首先,算法随机生成一定数量的个体,有时候操作者也可以干预这个随机产生过程,以提高初始种群的质量。在每一代中,都会评价每一个体,并通过计算适应度函数得到适应度数值。按照适应度排序种群个体,适应度高的在前面。这里的“高”是相对于初始的种群的低适应度而言。

下一步是产生下一代个体并组成种群。这个过程是通过选择和繁殖完成,其中繁殖包括交配(crossover,在算法研究领域中我们称之为交叉操作)和突变(mutation)。选择则是根据新个体的适应度进行,但同时不意味着完全以适应度高低为导向,因为单纯选择适应度高的个体将可能导致算法快速收敛到局部最优解而非全局最优解,我们称之为早熟。作为折中,遗传算法依据原则:适应度越高,被选择的机会越高,而适应度低的,被选择的机会就低。初始的数据可以通过这样的选择过程组成一个相对优化的群体。之后,被选择的个体进入交配过程。一般的遗传算法都有一个交配概率(又称为交叉概率),范围一般是0.6~1,这个交配概率反映两个被选中的个体进行交配的概率。例如,交配概率为0.8,则80%的“夫妻”会生育后代。每两个个体通过交配产生两个新个体,代替原来的“老”个体,而不交配的个体则保持不变。交配父母的染色体相互交换,从而产生两个新的染色体,第一个个体前半段是父亲的染色体,后半段是母亲的,第二个个体则正好相反。不过这里的半段并不是真正的一半,这个位置叫做交配点,也是随机产生的,可以是染色体的任意位置。再下一步是突变,通过突变产生新的“子”个体。一般遗传算法都有一个固定的突变常数(又称为变异概率),通常是0.1或者更小,这代表变异发生的概率。根据这个概率,新个体的染色体随机的突变,通常就是改变染色体的一个字节(0变到1,或者1变到0)。

经过这一系列的过程(选择、交配和突变),产生的新一代个体不同于初始的一代,并一代一代向增加整体适应度的方向发展,因为总是更常选择最好的个体产生下一代,而适应度低的个体逐渐被淘汰掉。这样的过程不断的重复:评价每个个体,计算适应度,两两交配,然后突变,产生第三代。周而复始,直到终止条件满足为止。一般终止条件有以下几种:

  • 进化次数限制;
  • 计算耗费的资源限制(例如计算时间、计算占用的内存等);
  • 一个个体已经满足最优值的条件,即最优值已经找到;
  • 适应度已经达到饱和,继续进化不会产生适应度更好的个体;
  • 人为干预;
  • 以及以上两种或更多种的组合。

算法

选择初始生命种群
循环

评价种群中的个体适应度
以比例原则(分数高的挑中概率也较高)选择产生下一个种群(轮盘法(roulette
wheel selection)、竞争法(tournament selection)及等级轮盘法(Rank
Based Wheel Selection))。不仅仅挑分数最高的的原因是这么做可能收敛到局部的最佳点,而非整体的。
改变该种群(交叉和变异)
直到停止循环的条件满足

个人理解:

所谓遗传算法,是一种随机化算法,像这类随机化算法是从平时生活中总结出来的,而遗传算法就是从生物的遗传之中总结出来的,其思想与生物遗产类似,具体代码可以根据不同问题进行改变。

经典例题:旅行商问题(TSP)

假设有一个旅行商人要拜访N个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,

而且最后要回到原来出发的城市。

路径的选择目标是要求得的路径路程为所有路径之中的最小值。

算法介绍:

根据达尔文的进化论,我们可以总结出遗传算法的一般步骤:

达尔文进化论:

1.评估每条染色体所对应个体的适应度。

2.遵照适应度越高,选择概率越大的原则,从种群中选择两个个体作为父方和母方。

3.抽取父母双方的染色体,进行交叉,产生子代。

4.对子代的染色体进行变异。

5.重复2,3,4步骤,直到新种群的产生。

遗传算法步骤:

1.  初始化   t←0进化代数计数器;T是最大进化代数;随机生成M个个体作为初始群体    P(t);

2.  个体评价 计算P(t)中各个个体的适应度值;

3.  选择运算 将选择算子作用于群体;

4.  交叉运算 将交叉算子作用于群体;

5.  变异运算 将变异算子作用于群体,并通过以上运算得到下一代群体P(t + 1);

6.  终止条件判断  t≦T:t← t+1 转到步骤2;

t>T:终止 输出解。 、

▲Procedures  GA:   伪代码

begin

initialize P(0);

t = 0;             //t是进化的代数,一代、二代、三代...

while(t <= T) do

for i = 1 to M  do     //M是初始种群的个体数

Evaluate fitness of P(t);  //计算P(t)中各个个体的适应度

end for

for i = 1 to M  do

Select operation to P(t);  //将选择算子作用于群体

end for

for i = 1 to M/2  do

Crossover operation to P(t); //将交叉算子作用于群体

end for

for i = 1 to M  do

Mutation operation to P(t);  //将变异算子作用于群体

end for

for i = 1 to M  do

P(t+1) = P(t);      //得到下一代群体P(t + 1)

end for

t = t + 1;      //终止条件判断  t≦T:t← t+1 转到步骤2

end while

end

这里的一些专业术语会在下面的程序中具体介绍到。

下面来看代码,其中有较详细注释:

/*************************************************************************
	> File Name: yichuan.cpp
	> Author:chudongfang
	> Mail:[email protected]
	> Created Time: 2016年06月19日 星期日 23时50分57秒
************************************************************************/
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include <algorithm>
#define INF (1ll<<60)-1

#define city_num    10//城市的数目
#define unit_num    100//种群中个体的数目
#define probability 60//变异概率
#define genmax      100//最大产生代数
#define group_num   100//产生种群数量

using namespace std;
typedef long long ll;

typedef struct individual //一个个体
{
	int path[city_num];//个体的路径
    int lenth;         //路径的长度
}INDI;

typedef struct unit//一个种群
{
    INDI group[unit_num]; //数组存储个体
    INDI best;            //最优个体
    int  best_gen;        //最优个体所在的代数
    int  cur_gen;         //种群当前的代数
}UNIT;

//1.初始化t←0进化代数计数器;genmax是最大进化代数;随机生成unit_num个个体作为初始群体P(t);
void init();

//2.个体评价
void assess();

//3.选择运算 将选择算子作用于群体
void choose(int gen);

//4.交叉运算 将交叉算子作用于群体,保留较优个体,淘汰较差个体
void cross();

//5.变异运算 将变异算子作用于群体,并通过以上运算得到下一代群体p(t+1)
void mutation();

//总调用函数,决定一个种群的进化
void sovel();

//子模块
INDI  cross_once(int father,int mother);
void mutation_one(int x);

//打印,供测试用
void print();

//城市距离表,邻接矩阵方式储存无向图
int length_table[10][10] =
{
    {0,1,1272,2567,1653,2097,1425,1177,3947,1},
    {1,0,1,2511,1633,2077,1369,1157,3961,1518},
    {1272,1,0,1,380,1490,821,856,3660,385},
   	{2567,2511,1,0,1,2335,1562,2165,3995,933},
   	{1653,1633,380,1,0,1,1041,1135,3870,456},
   	{2097,2077,1490,2335,1,0,1,920,2170,1920},
   	{1425,1369,821,1562,1041,1,0,1,4290,626},
   	{1177,1157,856,2165,1135,920,1,0,1,1290},
   	{3947,3961,3660,3995,3870,2170,4290,1,0,1},
   	{1,1518,385,993,456,1920,626,1290,1,0}
};

//创建一个种群
UNIT  Group;

//储存每个种群进化的结果
INDI  bestsovel[105];

//在这里创建了多个种群,这样使得解更具有准确性。
int main(int argc,char *argv[])
{
    //时间种子产生随机数
	srand(time(0));

    //对产生的种群进行一一求解
    for(int i=0;i<group_num;i++)
    {
        sovel();
        bestsovel[i]=Group.best;
    }

    //输出每个种群的最优个体(解)
    for(int i=0;i<group_num;i++)
        printf("%dth=%d\n",i,bestsovel[i].lenth);

    //排序,并输出所有种群的最优解
    INDI t;
    for(int i=0;i<group_num;i++)
    {
        for(int j=i;j<group_num;j++)
        {
            if(bestsovel[i].lenth>bestsovel[j].lenth)
            {
                t=bestsovel[i];
                bestsovel[i]=bestsovel[j];
                bestsovel[j]=t;
            }
        }
    }

    printf("最优解:");
    for(int i=0;i<city_num;i++)
        printf("%4d",bestsovel[0].path[i]);

    printf("\n最优值:%d",bestsovel[0].lenth);

    return 0;
}

//对一个种群进行求解。
void sovel()
{
    init();
    for(int  i=1;i<=genmax;i++) //种群繁杂代数
    {
        Group.cur_gen=i;
        assess();               //评估
        choose(Group.cur_gen);  //找最优个体
        cross();                //交叉,优胜劣汰,保留较优个体,淘汰较差个体
        mutation();             //变异
    }
}

void init()
{
    Group.best.lenth=0x3f3f3f3f;//初始化一个很大的值,便于下面比较
    Group.best_gen=0;//记录产生最好结果的代数
    Group.cur_gen=0;//当前代数为0

    //把每一个个体随机初始化
    for(int i=0;i<unit_num;i++)//unit_num个个体
    {
        bool  flag[city_num]={0};//用来标记其是否已经储存过
        for(int j=0;j<city_num;j++)
        {
            int t=rand()%city_num;
            //保证每个数字不重复
            while(flag[t])
                t=rand()%city_num;

            flag[t]=true;
            Group.group[i].path[j]=t;
        }
    }
}

//个体评价
void assess()
{
    //计算出每个个体的适应度值,即其路径长度
    for(int k=0;k<unit_num;k++)
    {
        int rel=0;
        for(int i=1;i<city_num;i++)//根据其经过的节点,计算其路径
            rel+=length_table[Group.group[k].path[i-1]][Group.group[k].path[i]];

        rel+=length_table[Group.group[k].path[city_num-1]][Group.group[k].path[0]];
        Group.group[k].lenth=rel;
    }
}

//先进行排序,然后选择出最优解
void choose(int gen)
{
    //进行排序
    INDI t;
    for(int i=0;i<unit_num;i++)
    {
        for(int j=i;j<unit_num;j++)
        {
            if(Group.group[i].lenth>Group.group[j].lenth)
            {
                t             =Group.group[i];
                Group.group[i]=Group.group[j];
                Group.group[j]=t;
            }
        }
    }

    //选出这个种群的最优个体,并储存
    if(Group.best.lenth>Group.group[0].lenth)
    {
        Group.best.lenth=Group.group[0].lenth;
        for(int i=0;i<city_num;i++)
            Group.best.path[i]=Group.group[0].path[i];
        Group.best_gen        =gen;
    }
}

//对一个种群中的个体,按一定方式进行交叉运算,并淘汰掉一部分,保存较优个体
void cross()
{
    for(int i=unit_num/2;i<unit_num;i++)//很容易看出,这里淘汰了后部分个体
        Group.group[i]=cross_once(i-unit_num/2,i-unit_num/2+1);
}

//交叉两个个体
INDI  cross_once(int father,int mother)
{
    INDI son;
    int t;
    int pos=0;
    int l=rand()%city_num;//随机生成两个数
    int r=rand()%city_num;
    if(l>r)
    {
        t=l;
        l=r;
        r=t;
    }

    bool flag[city_num]={0};

    for(int i=l;i<=r;i++)
        flag[Group.group[father].path[i]]=true;

    for(int i=0;i<l;i++)
    {
        while(flag[Group.group[mother].path[pos]])
            pos++;
        son.path[i]=Group.group[mother].path[pos++];
    }

    //父亲的一段全部放在儿子中
    for(int i=l;i<=r;i++)
        son.path[i]=Group.group[father].path[i];

    //母亲的在不与父亲的一段重复的情况下,把其元素放在儿子中
    for(int i=r+1;i<city_num;i++)
    {
        while(flag[Group.group[mother].path[pos]])
            pos++;
        son.path[i]=Group.group[mother].path[pos++];
    }

    return son;
}

//对一个种群的全部个体都进行变异运算
void mutation()
{
    for(int i=0;i<unit_num;i++)
    {
        mutation_one(i);
    }
}

//对一个个体的变异运算
void mutation_one(int x)
{
    int pro=rand()%100;
    if(pro>probability)
        return ;
    //随机生成两个数
    int first =rand()%city_num;
    int second=rand()%city_num;

    while(first==second)
        second=rand()%city_num;

    //进行交换
    int t;
    t=Group.group[x].path[first];
    Group.group[x].path[first]=Group.group[x].path[second];
    Group.group[x].path[second]=t;
}

void print()
{
    for(int i=0;i<unit_num;i++)
    {
        for(int j=0;j<city_num;j++)
        {
            printf("%4d",Group.group[i].path[j]);
        }
        printf("\n");
    }
    printf("\n\n\n");
}

运行结果:

0th=10

1th=10

2th=10

3th=10

4th=10

5th=10

6th=10

7th=10

8th=10

9th=10

10th=10

11th=10

12th=10

13th=10

14th=10

15th=10

16th=10

17th=10

18th=10

19th=10

20th=10

21th=10

22th=10

23th=10

24th=10

25th=10

26th=10

27th=10

28th=10

29th=10

30th=1811

31th=10

32th=10

33th=10

34th=10

35th=10

36th=10

37th=10

38th=10

39th=10

40th=10

41th=10

42th=10

43th=10

44th=10

45th=10

46th=10

47th=10

48th=10

49th=10

50th=10

51th=10

52th=10

53th=10

54th=10

55th=10

56th=10

57th=10

58th=10

59th=10

60th=10

61th=10

62th=10

63th=10

64th=10

65th=10

66th=1969

67th=1811

68th=10

69th=10

70th=10

71th=10

72th=10

73th=10

74th=10

75th=1969

76th=10

77th=10

78th=10

79th=10

80th=10

81th=10

82th=10

83th=10

84th=10

85th=10

86th=10

87th=10

88th=10

89th=10

90th=10

91th=10

92th=10

93th=10

94th=10

95th=10

96th=10

97th=10

98th=10

99th=10

最优解:   6   5   4   3   2   1   0   9   8   7

最优值:10

real 0m0.585s

user 0m0.580s

sys 0m0.004s

参数分析:

在这里,以下参数越大其结果越精确,不过其耗时也相应变大,所以这里要充分衡量其参数大小,以便于在耗时较少的情况下的到更优的解。

#define unit_num    100//种群中个体的数目
#define probability 60//变异概率
#define genmax      100//最大产生代数
#define group_num   100//产生种群数量

简单总结一下遗传算法,遗传算法是一个根据生物进化的过程中总结出来的,其与生物进化相似,优胜劣汰,遗传变异。其大概就分为:初始化、个体评估、选择、交叉、变异这几个过程,可以根据具体不同的问题,编不同的程序,但大致思想一样。

以上内容不足之处请多多指教!

转载请注明出处:http://write.blog.csdn.net/postedit/51720607

时间: 2024-11-09 15:14:22

linux小组分享会_遗传算法的相关文章

Linux电源管理(1)_整体架构(转自蜗窝科技,www.wowotech.net)

Linux电源管理(1)_整体架构(转自蜗窝科技,www.wowotech.net) 1. 前言 在这个世界中,任何系统的运转都需要能量.如树木依靠光能生长,如马儿依靠食物奔跑,如计算机系统依靠电能运行.而 能量的获取是有成本的,因此如果能在保证系统运转的基础上,尽量节省对能量的消耗,就会大大提升该系统的生存竞争力.这方面,大自然已经做的很好了,如植 物的落叶,如动物的冬眠,等等.而在计算机的世界里(这里以运行Linux OS的嵌入式系统为例),称作电源管理(Power Management).

Linux网络设备驱动(一) _驱动模型

Linux素来以其强大的网络功能著名,同时, 设备'>网络设备也作为三大设备之一, 成为Linux驱动学习中必不可少的设备类型, 此外, 由于历史原因, Linux并没有强制对设备'>网络设备贯彻其"一切皆文件"的思想, 设备'>网络设备不以/dev下的设备文件为接口,用户程序通过socket作为访问硬件的接口.本文以Linux3.14.0内核为例, 讨论Linux中的网络驱动模型 Linux的设备'>网络设备并不使用文件作为用户程序访问设备'>网络设备的

llinux 基础命令 及个人Linux文件分享

llinux 基础命令 及个人Linux文件分享 一, root用户名 @ 分隔符 kingle 主机名 ~当前所在目录 # root权限 $ 没分配权限用户 二, 书写格式:空格 [命令参数] 空格 路径 三,linux 目录结构 root --- 启动Linux时使用的一些核心文件.如操作系统内核.引导程序Grub等. home --- 存储普通用户的个人文件 ftp --- 用户所有服务 httpd samba user1 user2 bin --- 系统启动时需要的执行文件(二进制) s

springboot视频教程下载_java知识分享网_免费资源下载【www.51dali.cn】

springboot视频教程下载_java知识分享网_免费资源下载-牛逼的springboot教程来源[51dali资料分享网]下载地址:http://www.51dali.cn/javajiaocheng/61.html基本看完本套视频教程即可学会springboot课程介绍:1.搭建Spring Boot2.SpringBoot之集成MySql数据库 3.SpringBoot之集成MyBatis 4.Spring Boot整合Quartz定时器 5 Spring Boot整合Redis缓存

迅为4412开发板Linux驱动教程——总线_设备_驱动注册流程详解

视频下载地址: 驱动注册:http://pan.baidu.com/s/1i34HcDB 设备注册:http://pan.baidu.com/s/1kTlGkcR 总线_设备_驱动注册流程详解 ? 注册流程图 ? 设备一般都需要先注册,才能注册驱动 – 现在越来越多的热拔插设备,反过来了.先注册驱动,设备来了再注册 设备 ? 本节使用的命令 – 查看总线的命令#ls /sys/bus/ – 查看设备号的命令#cat /proc/devices ? 设备都有主设备号和次设备号,否则255个设备号不

Linux大牛分享的7道经典面试题和秒收 offer 的技巧

笔者其实没有想到去面试,只是在智联上更新了一下简历,就陆陆续续接到很多猎头的邮件和电话,闲话少说,下面就分享给大家Linuxer的面试经历: 首先,猎头或者公司人资会把公司的介绍及岗位要求发到你邮箱(或者QQ.微信),下面这份是猎头发给我的岗位说明,为了职业道德操守,公司的介绍和面试通知信息我就不贴出来了,我就把岗位要求贴出来: 职位描述: 1. 负责应用服务器的安装.配置.优化与维护: 2. 负责应用系统的日志信息备份.管理.维护与分析: 3. 负责应用系统的日常监测于维护.故障处理.性能分析

[51CTO]Linux入门到精通视频教程_企业级Linux运维视频教程_附课程配套资料[百度云盘]

通过本套实战课程的全程学习,能力跨越一个台阶,选择和努力决定薪资,向高级运维工程师迈进,通过本课程的学习,大家可以从懵懂到熟悉,从熟悉到熟练,能够在企业中熟练运用,同时在学习的过程中有任何不明白的地方,都可以向我咨询,我会积极帮助大家解决问题. 此视频资源由51CTO发布,微夏博客收集整理于网络,仅供学习交流,请于下载24小时内删除.如有侵权可联系微夏博客删除处理. 请支持原版!课程官方链接:http://edu.51cto.com/course/2157.html 课程目录: (微夏博客分享的

Linux该如何学习呢?Linux学习分享!

从目前情况来说,Linux系统是应用最为广泛的服务器操作系统,随着普及性的增高,越来越多的人想要学习Linux,不过学习并不是一件容易的事情,讲究合适的方法和技巧.那么Linux应该怎么学习?为大家分享一下学习技巧. 1.想要学习好Linux就要将它当成兴趣,兴趣才是最好的老师.良好的兴趣才是学习成功好的开始,想要学习好首先就要足够喜欢它.我们要了解市场上Linux的发展势头,了解Linux的相关情况,相信学习好Linux一定要是非常不错的选择. 2.学习合适的Linux发行版本,在开始学习Li

linux进程D状态_转

Linux进程状态:S (TASK_INTERRUPTIBLE),可中断的睡眠状态. 处于这个状态的进程因为等待某某事件的发生(比如等待socket连接.等待信号量),而被挂起.这些进程的task_struct结构被放入对应事件的等待队列中.当这些事件发生时(由外部中断触发.或由其他进程触发),对应的等待队列中的一个或多个进程将被唤醒. 通过ps命令我们会看到,一般情况下,进程列表中的绝大多数进程都处于TASK_INTERRUPTIBLE状态(除非机器的负载很高).毕竟CPU就这么一两个,进程动