Skip to content

Instantly share code, notes, and snippets.

@handcraftsman
Created June 26, 2016 20:23
Show Gist options
  • Save handcraftsman/965905be74ad3972c7965a53382f1c14 to your computer and use it in GitHub Desktop.
Save handcraftsman/965905be74ad3972c7965a53382f1c14 to your computer and use it in GitHub Desktop.
Hello World! genetic algorithm in python
# File: genetic.py
# from chapter 1 of _Genetic Algorithms with Python_, an ebook
# available for purchase at http://leanpub.com/genetic_algorithms_with_python
#
# Author: Clinton Sheppard <[email protected]>
# Repository: https://drive.google.com/open?id=0B2tHXnhOFnVkRU95SC12alNkU2M
# Copyright (c) 2016 Clinton Sheppard
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.
import random
import statistics
import time
import sys
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
class Chromosome:
Genes = None
Fitness = None
def __init__(self, genes, fitness):
self.Genes = genes
self.Fitness = fitness
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("{0} {1:3.2f} {2:3.2f}".format(
1 + i, mean,
statistics.stdev(timings, mean)
if i > 1 else 0))
# File: guessPasswordTests.py
# from chapter 1 of _Genetic Algorithms with Python_, an ebook
# available for purchase at http://leanpub.com/genetic_algorithms_with_python
#
# Author: Clinton Sheppard <[email protected]>
# Repository: https://drive.google.com/open?id=0B2tHXnhOFnVkRU95SC12alNkU2M
# Copyright (c) 2016 Clinton Sheppard
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.
import datetime
import genetic
import unittest
import random
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("{0}\t{1}\t{2}".format(
candidate.Genes, candidate.Fitness, str(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(lambda: self.test_Random())
if __name__ == '__main__':
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment