tyler569 icon

EvolutionBase

tyler569 | PRO | 01/30/17 09:08:23 PM UTC | 0 ⭐ | 1051 👁️ | Never ⏰ | []
Python |

3.15 KB

|

None

|

0 👍

/

0 👎

 
######################################################################
####            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()

Comments