亲,这就是遗传算法

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

背景

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

比如说旅行商问题:

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

城市的分布可能会像下面这样:
这里写图片描述

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

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

为什么呢?

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

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

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

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

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

遗传算法

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

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

也许不能得到一个最优的解,但旅行商恐怕不得不接受一个差不多的解:
这里写图片描述

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

遗传算法,是一种进化算法,进化大家都明白。
那么生命的变化在于基因的变化,什么是基因呢,我们不关注真正的生物基因,毕竟这里不是讨论生殖问题:
这里写图片描述

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

    /**
     * 基因
     */
    private class Gene {
        /**
         * 编码
         */
        int value;
        /**
         * 等位基因(编码的值)
         */
        Integer Allele;
    }

    public interface IChromosome {
        public Genes[];
    }

好,有了这个表达基础,就可以很好的描述进化过程了。
为了简化问题,突出本质,我们简化种群(population)的描述:
这里写图片描述

这张图告诉我们

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

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

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

这里写图片描述

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

让我们继续认识进化。

选择

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

交叉

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

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

下面将进入少儿不宜环节:
这里写图片描述

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

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

变异

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

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

旅行商

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

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

那么,在经过若干次进化之后,优质染色体就可以被挑选出来,旅行商也就得到了一个接近最短的旅行路线:
这里写图片描述

亲,这就是遗传算法。

 

posted @ 2015-04-27 18:32  foreach_break  阅读(1006)  评论(1编辑  收藏  举报