Created
May 16, 2019 15:43
-
-
Save bakirillov/88ec29005b4569cd02f5c0d9a83186df to your computer and use it in GitHub Desktop.
Yes, I wrote a code to win an internet argument. Look how bored I was.
This file contains 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
import numpy as np | |
from tqdm import tqdm | |
class GenAlgWithoutPopulationRestriction(): | |
def __init__( | |
self, N_init=10, target_string="ESCHO SPORIT SO MNOY BUDESH LOLKA SASAII", | |
temperature=1, pm=0.5, pmating=0.6 | |
): | |
self.alphabet = [a for a in "ABCDEFGHIJKLMNOPQRSTUVWXYZ "] | |
self.ts = [a for a in target_string] | |
self.population = [self.generate_random() for a in np.arange(N_init)] | |
self.p_mutation = pm | |
self.temperature = temperature | |
self.p_mating = pmating | |
def generate_random(self): | |
return(np.random.choice(self.alphabet, len(self.ts))) | |
def fitness(self, s): | |
return(np.sum([1 if a == b else 0 for a,b in zip(s, self.ts)])) | |
def crossover(self, s1, s2): | |
mid = int(len(s1)/2) | |
s3 = list(s1[0:mid])+list(s2[mid:]) | |
s4 = list(s2[0:mid])+list(s1[mid:]) | |
return([s3, s4]) | |
def mutate(self, s1): | |
s2 = s1[:] | |
s2[np.random.choice(np.arange(len(s1)))] = np.random.choice(self.alphabet) | |
return(s2) | |
def softmax(self, d): | |
e = np.exp(np.array(d)/self.temperature) | |
return(e/np.sum(e)) | |
def mate(self, ffs): | |
pdist = self.softmax(ffs) | |
inds = np.random.choice(np.arange(len(self.population)), 2, p=pdist) | |
return(self.population[inds[0]], self.population[inds[1]]) | |
def mating_selection(self, n_epochs=100): | |
for a in tqdm(list(range(n_epochs))): | |
if np.random.choice([True, False], p=[self.p_mutation, 1-self.p_mutation]): | |
chosen = np.random.choice(np.arange(len(self.population))) | |
self.population[chosen] = self.mutate(self.population[chosen]) | |
if np.random.choice([True, False], p=[self.p_mating, 1-self.p_mating]): | |
ffs = [self.fitness(a) for a in self.population] | |
m1,m2 = self.mate(ffs) | |
self.population.extend(self.crossover(m1, m2)) | |
def plot_top(self, n): | |
ordered = list(reversed(list(sorted(self.population, key=self.fitness)))) | |
return(["".join(a) for a in ordered[0:n]]) | |
g = GenAlgWithoutPopulationRestriction() | |
g.mating_selection(10000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment