用Python實(shí)現(xiàn)遺傳算法(GA)(一)

Clinton Sheppard的Genetic Algorithms with Python一書總結(jié)的筆記
git鏈接:
https://github.com/handcraftsman/GeneticAlgorithmsWithPython

1. 用遺傳算法guess password

import random
import datetime
geneSet = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!。"
target = "Hello World!"
def generate_parent(length):
    genes = []
    while len(genes) < length:
        sampleSize = min(length - len(genes), len(geneSet))
        genes.extend(random.sample(geneSet, sampleSize))
    return ''.join(genes)

隨機(jī)生成父母, random.sample(geneSet, sampleSize)在geneSet里隨機(jī)選sampleSize個(gè)不同的元素行施,組成字符串返回

def get_fitness(guess):
    return sum(1 for expected, actual in zip(target, guess) if expected ==actual)

計(jì)算和目標(biāo)相同的元素?cái)?shù)量确丢,作為適應(yīng)度返回

def mutate(parent):
    index = random.randrange(0, len(parent))
    childGenes = list(parent)
    newGene, alternate =random.sample(geneSet, 2)
    childGenes[index] = alternate if newGene == childGenes[index] else newGene
    return ''.join(childGenes)

變異,從parent里面隨機(jī)選一位變異奇钞,產(chǎn)生newGene和alternate兩個(gè)元素,是為了防止變異前和變異后相同

def display(guess):
    timeDiff = datetime.datetime.now() - startTime
    fitness = get_fitness(guess)
    print("{}\t{}\t{}\t".format(guess, fitness, timeDiff))
random.seed()
startTime = datetime.datetime.now()
bestParent = generate_parent(len(target))
bestFitness = get_fitness(bestParent)
display(bestParent)

while True:
    child = mutate(bestParent)
    childFitness = get_fitness(child)
    if bestFitness >= childFitness:
        continue
    display(child)
    if childFitness >= len(bestParent):
        break
    bestFitness = childFitness
    bestParent = child

2. 改進(jìn)一:從上面提取一個(gè)可重復(fù)使用的engine

為了讓這個(gè)GA engine不僅僅只解決這個(gè)項(xiàng)目漂坏,要單獨(dú)把初始值的產(chǎn)生景埃,變異媒至,遺傳算法的主要過程提取出來單獨(dú)放到一個(gè)py文件,命名為genetic.py

import random

def _generate_parent(length, geneSet):
    genes = []
    while len(genes) < length:
        sampleSize = min(length - len(genes), len(geneSet))
        genes.extend(random.sample(geneSet, sampleSize))
    return ''.join(genes)

def _mutate(parent, geneSet):
    index = random.randrange(0, len(parent))
    childGenes = list(parent)
    newGene, alternate =random.sample(geneSet, 2)
    childGenes[index] = alternate if newGene == childGenes[index] else newGene
    return ''.join(childGenes)

def get_best(get_fitness, targetLen, optimalFitness, geneSet, display):
    random.seed()
    bestParent = _generate_parent(targetLen, geneSet)
    bestFitness = get_fitness(bestParent)
    display(bestParent)
    if bestFitness >= optimalFitness:
        return bestParent

    while True:
        child = _mutate(bestParent, geneSet)
        childFitness = get_fitness(child)

        if bestFitness >= childFitness:
            continue
        display(child)
        if childFitness >= optimalFitness:
            return child
        bestFitness = childFitness
        bestParent = child

適應(yīng)度的計(jì)算谷徙,區(qū)間上下界以及主函數(shù)等放在另一個(gè)文件'guessword.py'

import datetime
import genetic


def get_fitness(genes, target):
    return sum(1 for expected, actual in zip(target, genes) if expected ==actual)

def display(genes, target, startTime):
    timeDiff = datetime.datetime.now() - startTime
    fitness = get_fitness(genes, target)
    print("{}\t{}\t{}\t".format(genes, fitness, timeDiff))

def test_Hello_World():
    target = "Hello World!"
    guess_password(target)

def guess_password(target):
    geneSet = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!."
    startTime = datetime.datetime.now()

    def fnGetFitness(genes):
        return get_fitness(genes, target)

    def fnDisplay(genes):
        display(genes, target, startTime)

    optimalFitness = len(target)
    genetic.get_best(fnGetFitness,len(target),optimalFitness,geneSet,fnDisplay)


if __name__ =='__main__':
    test_Hello_World()

3. 改進(jìn)二: Use unittest framework

在測(cè)試環(huán)境下工作拒啰,新建一個(gè)guessPasswordTests.py

import unittest

class GuessPasswordTests(unittest.TestCase):
    geneSet = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!."

    def test_Hello_World():
        target = "Hello World!"
        guess_password(target)

    def guess_password(self, target):

        optimalFitness = len(target)
        best = genetic.get_best(fnGetFitness, len(target), optimalFitness, self.geneset, fnDisplay)
        self.assertEqual(best, target)

if  __name__ == '__main__':
    unittest.main()

4.改進(jìn)三: 認(rèn)識(shí)染色體(Chromosome)

genetic.py定義一個(gè)染色體

class Chromosome:
    Genes = None
    Fitness = None

    def __init__(self, genes, fitness):
        self.Genes = genes
        self.Fitness = fitness

加入定義的染色體后其它function的變化

def _generate_parent(length, geneSet, get_fitness):
    genes = []
    while len(genes) < length:
        sampleSize = min(length - len(genes), len(geneSet))
        genes.extend(random.sample(geneSet, sampleSize))
    genes = ''.join(genes)
    fitness = get_fitness(genes)
    return Chromosome(genes, fitness)
def _mutate(parent, geneSet, get_fitness):
    index = random.randrange(0, len(parent.Genes))
    childGenes = list(parent.Genes)
    newGene, alternate = random.sample(geneSet, 2)
    childGenes[index] = alternate if newGene == childGenes[index] else newGene
    genes = ''.join(childGenes)
    fitness = get_fitness(genes)
    return Chromosome(genes, fitness)
def get_best(get_fitness, targetLen, optimalFitness, geneSet, display):
    random.seed()
    bestParent = _generate_parent(targetLen, geneSet, get_fitness)
    display(bestParent)
    if bestParent.Fitness >= optimalFitness:
        return bestParent
    while True:
        child = _mutate(bestParent, geneSet, get_fitness)
        if bestParent.Fitness >= child.Fitness:
            continue
        display(child)
        if child.Fitness >= optimalFitness:
            return child
        bestParent = child

5. 改進(jìn)四: 基準(zhǔn)測(cè)試(Benchmarking)

genetic.py添加Benchmarking來了解一個(gè)算法求解要多久,標(biāo)準(zhǔn)偏差是多少

import statistic
import time
class Benchmark:
    @staticmethod
    def run(function):
        timings = []
        stdout = sys.stdout
        for i in range(100):
            sys.stdout = None
            startTime = time.time()
            function()
            seconds = time.time() - startTime
            sys.stdout = stdout
            timings.append(seconds)
            mean = statistics.mean(timings)
            if i < 10 or i % 10 == 9:
                print("{} {:3.2f} {:3.2f}".format(
                    1 + i, mean,
                    statistics.stdev(timings, mean) if i > 1 else 0))

guessPasswordTests.py中添加相關(guān)function

import datetime
import random
import unittest
import genetic

def get_fitness(guess, target):
    return sum(1 for expected, actual in zip(target, guess)
               if expected == actual)

def display(candidate, startTime):
    timeDiff = datetime.datetime.now() - startTime
    print("{}\t{}\t{}".format(
        candidate.Genes, candidate.Fitness, timeDiff))

class GuessPasswordTests(unittest.TestCase):
    geneset = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!.,"

    def test_Hello_World(self):
        target = "Hello World!"
        self.guess_password(target)

    def test_For_I_am_fearfully_and_wonderfully_made(self):
        target = "For I am fearfully and wonderfully made."
        self.guess_password(target)

    def guess_password(self, target):
        startTime = datetime.datetime.now()

        def fnGetFitness(genes):
            return get_fitness(genes, target)

        def fnDisplay(candidate):
            display(candidate, startTime)

        optimalFitness = len(target)
        best = genetic.get_best(fnGetFitness, len(target), optimalFitness,
                                self.geneset, fnDisplay)
        self.assertEqual(best.Genes, target)

    def test_Random(self):
        length = 150
        target = ''.join(random.choice(self.geneset)
                         for _ in range(length))

        self.guess_password(target)

    def test_benchmark(self):
        genetic.Benchmark.run(self.test_Random)

if __name__ == '__main__':
    unittest.main()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末完慧,一起剝皮案震驚了整個(gè)濱河市谋旦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屈尼,老刑警劉巖册着,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異脾歧,居然都是意外死亡甲捏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門鞭执,熙熙樓的掌柜王于貴愁眉苦臉地迎上來司顿,“玉大人,你說我怎么就攤上這事蚕冬∶饣” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵囤热,是天一觀的道長(zhǎng)猎提。 經(jīng)常有香客問我,道長(zhǎng)旁蔼,這世上最難降的妖魔是什么锨苏? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮棺聊,結(jié)果婚禮上伞租,老公的妹妹穿的比我還像新娘。我一直安慰自己限佩,他們只是感情好葵诈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祟同,像睡著了一般作喘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晕城,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天泞坦,我揣著相機(jī)與錄音,去河邊找鬼砖顷。 笑死贰锁,一個(gè)胖子當(dāng)著我的面吹牛赃梧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播豌熄,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼授嘀,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了房轿?” 一聲冷哼從身側(cè)響起粤攒,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤所森,失蹤者是張志新(化名)和其女友劉穎囱持,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焕济,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纷妆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晴弃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掩幢。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖上鞠,靈堂內(nèi)的尸體忽然破棺而出际邻,到底是詐尸還是另有隱情,我是刑警寧澤芍阎,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布世曾,位于F島的核電站,受9級(jí)特大地震影響谴咸,放射性物質(zhì)發(fā)生泄漏轮听。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一岭佳、第九天 我趴在偏房一處隱蔽的房頂上張望血巍。 院中可真熱鬧,春花似錦珊随、人聲如沸述寡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鲫凶。三九已至,卻和暖如春京办,著一層夾襖步出監(jiān)牢的瞬間掀序,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工惭婿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留不恭,地道東北人叶雹。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像换吧,于是被迫代替她去往敵國(guó)和親折晦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容