###################################################################### #### chromosome.py ###################################################################### import random import copy class Nucleotide(object): def __init__(self, value = None): self.value = value def __str__(self): return "Nucleotide(" + str(self.value) + ")" def flip(self): return NotImplemented class Chromosome(object): """ Chromosome is intended to be subclassed and have logic implemented there - iter and getitem are provided for convenience """ def __init__(self): print("Do not use this implementation - subclass this and implement logic") @classmethod def new_from_parent(cls, parent): x = copy.deepcopy(parent) x.mutate() return x def __iter__(self): for n in self.raw_data: yield n def __getitem__(self, key): return "".join(item.value for item in self.raw_data[key]) @property def encoded_data(self): return NotImplemented def fitness(self): return NotImplemented def mutate(self, amount = None): if amount is None: amount = self.mutability for nucleotide in self.raw_data: if random.random() < amount: nucleotide.flip() ###################################################################### #### simple_implementation.py ###################################################################### #!/usr/bin/env python3 import random import math from chromosome import Nucleotide, Chromosome #from organism import Organism class NumberNucleotide(Nucleotide): def __init__(self, value = None): if value is None: value = random.randint(0,9) self.value = value def flip(self): delta = random.choice([-1,1]) self.value += delta if self.value < 0: self.value = 0 self.value %= 10 class NumberChromosome(Chromosome): def __init__(self, length, mutability): self.raw_data = [NumberNucleotide() for i in range(length)] self.mutability = mutability @property def encoded_data(self): return int("".join([str(j.value) for j in self.raw_data])) def fitness(self): return self.encoded_data def main(): # generations = [] length = 1000 keep = 500 convergeance = 20 conv_ctr = 0 orgs = [NumberChromosome(length = 10, mutability = 0.1) for i in range(length)] while True: orgs.sort(key = lambda org: org.fitness(), reverse = True) if orgs[keep-1].fitness() == orgs[0].fitness(): conv_ctr += 1 else: conv_ctr = 0 if conv_ctr == convergeance: print("Converged") exit() print(orgs[0].fitness(), orgs[0].encoded_data) orgs = orgs[:keep] for i in range(length - keep): orgs.append(NumberChromosome.new_from_parent(orgs[random.randint(0, keep-1)])) if __name__ == "__main__": main()