• 亲,这就是遗传算法


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

    背景

    当一些问题不存在确定性的最优解法,或者说最优解法的施展时间长的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
    每个城市的编号就是一个基因,城市的排列就是一个染色体(基因序列)。

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

    亲,这就是遗传算法。

    【版权所有@foreach_break】 【博客地址 http://www.cnblogs.com/foreach-break】 可以转载,但必须注明出处并保持博客超链接
  • 相关阅读:
    推荐2个Mac OS X上的JSON工具
    20个ios登陆界面
    IOS 真机调试和发布相关证书
    IOS学习路径
    Shell 语法和tips -- 持续更新
    Shell if 参数含义列表
    SimpleCursorAdapter 原理和实例
    Android Service VS AsyncTask VS Thread
    转:Intent 操作常用URI代码示例
    转:Android preference首选项框架
  • 原文地址:https://www.cnblogs.com/foreach-break/p/4471226.html
Copyright © 2020-2023  润新知