[置顶] 亲,这就是遗传算法

本文试图通过几幅简明的图来介绍遗传算法。

背景

当一些问题不存在确定性的最优解法,或者说最优解法的施展时间长的1-B,那我们就得开始考虑点其他路子了。

比如说旅行商问题:

旅行商要去很多城市卖货,为了节省时间,它一个城市只去一次,最后还得返回原城市,因为他老婆不允许他离开太久。 
它怎么走比较合算?

城市的分布可能会像下面这样: 
《[置顶] 亲,这就是遗传算法》

旅行商会想就是把所有城市路线做个排列(一半),然后看看哪条路线最短就按哪条路线来。

好吧,如果旅行商要去的城市只有3-5个还好说,如果旅行商生意太好,可能要去几十个城市,那这个方法行不通。

为什么呢?

O(1)<O(logN)<O(N)<O(N2)<O(N!)

如果你熟悉时间复杂度,一定明白我在说什么,不信,自己试试34的阶乘算出来是个什么,亲,如果钱包有那么多钱那该多好。

好在,达尔文总结出了自然界的一个不知确否的道理,就是生物通过优胜劣汰的自然选择过程,来完成进化。

这个过程,看起来像是一堆随机不确定的微小变化中,让确定而显著的优势变化延续下来。

谁强,谁就更有话语权,资源就该属于这种强强的亲,而弱弱的主因为无法抗拒灾难和考验,最终就被淹没在进化的过程中。

遗传算法

既然生命都可以进化,现存的生物都是摸爬滚打、出生入死过来的,那么解决点计算问题还有什么复杂的。

于是,我们想着用可以量化的数学的方式去表达这种进化过程,然后让计算机来模拟自然选择和种群的演化,看看会有什么样的优质个体(解)出现。

也许不能得到一个最优的解,但旅行商恐怕不得不接受一个差不多的解: 
《[置顶] 亲,这就是遗传算法》

好吧,那我们来认识一下所谓的遗传算法(genetic algorithms)。

遗传算法,是一种进化算法,进化大家都明白。 
那么生命的变化在于基因的变化,什么是基因呢,我们不关注真正的生物基因,毕竟这里不是讨论生殖问题: 
《[置顶] 亲,这就是遗传算法》

如果把基因(gene)当做一个经过编码的元素,用一个数组或者列表来存储一组基因,这组基因就是染色体(chromosome)

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 基因
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Gene</span> {</span>
        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 编码
         */</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> value;
        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 等位基因(编码的值)
         */</span>
        Integer Allele;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">IChromosome</span> {</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Genes[];
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

好,有了这个表达基础,就可以很好的描述进化过程了。 
为了简化问题,突出本质,我们简化种群(population)的描述: 
《[置顶] 亲,这就是遗传算法》

这张图告诉我们

种群包含了若干个个体(染色体),一次又一次的进化,让种群规模变大,个体数目变多,优质个体也越来越多。

那么我们的解可能就蕴藏其中呢?

这幅图没有告诉我们关于进化的细节信息,显然,我们需要了解进化到底是什么东东。

《[置顶] 亲,这就是遗传算法》

你可能觉得我骗了你,但事实上,进化只有三维,就是选择(select)、交叉(crossover)和变异(mutate)。

让我们继续认识进化。

选择

选择就是选择,为什么选择,因为要优胜劣汰: 
《[置顶] 亲,这就是遗传算法》 
个体们在种群内部,不能闲着,都得上学打工养老婆,所以它们需要通过各种考试和考核。 
通过考核的加薪升职,否则就扫地出门。 
上面的图可以告诉我们,选择是针对种群的操作,选择的目的是为了确保下一代种群的质量更佳。

交叉

那么,个体之间又如何出现了差异?这要从个体的爸爸妈妈说起,现在不是都搞什么优质基因人工D孕吗,好吧,个体的差异就是因为繁殖而出现的。

人家都会说,哇,这孩子长得跟花儿似的! 
其实,可能是这孩子他妈妈很漂亮,优秀的基因得以传递。 
也有人会说,哦哟,这孩子眼睛跟他爹一样乌黑乌黑的,说明他爹可能是个码农,而且孩子不幸遗传了他爹的这些个…

下面将进入少儿不宜环节: 
《[置顶] 亲,这就是遗传算法》

至于激情的细节如何,本篇不打算讨论交叉的具体算法,但要说明它的意思:

交叉就是对两组父个体进行基因交叉,从而形成1个或者1组新的基因序列或染色体。 
交叉可以随机,但尽量要避免无意义的交叉。 
交叉的目的是在个体中增加大幅度的变化,并集成父母的优质基因。 
交叉是遗传算法最重要的一步操作。

变异

也许孩子是个富二代,也许孩子是个官二代,但有可能就是一个普通的孩子,令人遗憾的是,他比较喜欢他爸,他幼稚的心灵觉得他爸挺牛X的,所以他觉得码农挺牛X的。

不同的,这孩子喜欢汇编,囧~ 
这是他的个性,谁也阻止不了,人家会说,这孩子一点都不像他妈妈。 
那么这种个性,虽然不全是,但基因方面的原因可能是: 
《[置顶] 亲,这就是遗传算法》 
变异其实没有交叉重要,而且可能产生极坏的变异。 
但变异是一种对交叉的补充和完善,也是一种有风险的创新。

旅行商

现在我们回到旅行商问题,如果对城市进行编号,比如123...N,那么一条路线就是这样:

3,10,2,1,...,20,3 
每个城市的编号就是一个基因,城市的排列就是一个染色体(基因序列)。

那么,在经过若干次进化之后,优质染色体就可以被挑选出来,旅行商也就得到了一个接近最短的旅行路线: 
《[置顶] 亲,这就是遗传算法》

亲,这就是遗传算法。

    原文作者:遗传算法
    原文地址: https://blog.csdn.net/dl0914791011/article/details/45621101
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞