Created
October 2, 2017 15:24
-
-
Save vladinator1000/d85e713051c97eb1b36e065c3c37e5a6 to your computer and use it in GitHub Desktop.
so QUESTION
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Hi, I'm trying to generate "Hello world!", but my results stop improving strings reach roughly about 70% similarity. Here's what I've done: | |
from difflib import SequenceMatcher | |
from numpy import std | |
from random import randint | |
import random | |
from pprint import pprint | |
GENES = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!." | |
TARGET = "Hello World!" | |
def randomCharFromString(string): | |
return string[randint(0, len(string) - 1)] | |
def randomStringFromString(string, length): | |
result = '' | |
for i in range(length - 1): | |
result += randomCharFromString(string) | |
return result | |
# Fitness | |
def asciiStringDistance(a, b): | |
distanceSum = 0 | |
for charA, charB in zip(a, b): | |
distanceSum += abs(ord(charA) - ord(charB)) | |
return distanceSum | |
# Two Tournaments, best of each become parents | |
def tournament(inputSet): | |
first = random.choice(tuple(inputSet)) | |
second = random.choice(tuple(inputSet)) | |
# Return tuple with bigger similarity ratio | |
if first[1] < second[1]: | |
return first | |
else: | |
return second | |
def mutateString(string, genes = GENES, probability = 0.05): | |
if random.random() < probability: | |
index = randint(0, len(string) - 1) | |
return string[:index] + randomCharFromString(genes) + string[index + 1:] | |
return string | |
# Crossover with probability, two strings returning tuple of tuples: | |
def crossover(parentOne, parentTwo, noCrossProbability = 0.05, fitnessFunction = asciiStringDistance): | |
if random.random() < noCrossProbability: | |
return (parentOne, parentTwo) | |
randomIndex = randint(0, len(parentOne[0]) - 1) | |
newStringOne = mutateString( | |
''.join((parentOne[0][:randomIndex], parentTwo[0][randomIndex:])), | |
) | |
newStringTwo = mutateString( | |
''.join((parentTwo[0][:randomIndex], parentOne[0][randomIndex:])), | |
GENES | |
) | |
return ( | |
(newStringOne, fitnessFunction(newStringOne, TARGET)), | |
(newStringTwo, fitnessFunction(newStringTwo, TARGET)), | |
) | |
def generatePopulation(old = set([]), currentGeneration = 0, howManyGenerations = 50, fitnessStandardDeviations = []): | |
new = set([]) | |
newDeviations = fitnessStandardDeviations | |
if currentGeneration < howManyGenerations: | |
while len(new) < len(old): | |
children = crossover(tournament(old), tournament(old)) | |
for child in children: | |
new.add(child) | |
ratios = list(map(lambda child: child[1], list(new))) | |
newDeviations.append(std(ratios)) | |
return generatePopulation(new, currentGeneration + 1, howManyGenerations, newDeviations) | |
return (old, newDeviations) | |
# Seed Population with tuples in this shape: (string, similarityRatio) | |
population = set([]) | |
for i in range(500): | |
string = randomStringFromString(GENES, len(TARGET)) | |
population.add( | |
(string, asciiStringDistance(string, TARGET)) | |
) | |
result = generatePopulation(population, howManyGenerations = 50) | |
pprint(result) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment