def mutateWeight(self): rand = random.uniform(0, 1) if rand < RANDOM_WEIGHT_PROB: self.weight = random.uniform(-1, 1) elif rand < PERTRUBE_WEIGHT_PROB: self.weight += random.gauss(0, 1) * WEIGHT_MUTATION_POWER self.weight = max(min(self.weight, WEIGHT_CAP), -WEIGHT_CAP)
def __init__(self, in_node, out_node, weight=None, disable_chance=0.0): assert in_node.depth < out_node.depth, f'in {in_node} has depth {in_node.depth}, out {out_node} has depth {out_node.depth}' self.innovation = self.getInnovation(in_node, out_node) if self.innovation is None: self.innovation = self.addInnovation(in_node, out_node) self.in_ = in_node self.out = out_node self.weight = random.uniform(-1, 1) if weight is None else weight self.enabled = random.uniform(0, 1) >= disable_chance
def crossover(cls, genome1, genome2): child = cls([genome1, genome2]) child.nodes = copy(genome1.nodes) for innovation, connection in genome1.connections.items(): disable_prob = 0.0 weight = None if innovation in genome2.connections: # matching case if not connection.enabled or not genome2.connections[ innovation].enabled: disable_prob = DISABLE_PROB_IF_PARENT_DISABLED # TODO: Parameterizing this might improve performance if random.uniform(0, 1) < 0.5: weight = connection.weight else: weight = genome2.connections[innovation].weight else: # excess or disjoint case disable_prob = 0.0 if connection.enabled else 1.0 weight = connection.weight child._addConnection( ConnectionGene(connection.in_, connection.out, weight, disable_prob)) return child
def reproduce(self, generation): baby_genome = None if random.uniform(0, 1) < PERCENT_NO_CROSSOVER: parent = self._select_org_for_reproduction() baby_genome = parent.genome.clone() baby_genome.verify() baby_genome.mutate() else: parent1 = self._select_org_for_reproduction() parent2 = self._select_org_for_reproduction() parent1.genome.verify() parent2.genome.verify() if parent1.fitness > parent2.fitness: baby_genome = Genome.crossover(parent1.genome, parent2.genome) else: baby_genome = Genome.crossover(parent2.genome, parent1.genome) baby_genome.verify() if parent1 is parent2 or random.uniform(0, 1) > MATE_ONLY_PROB: baby_genome.mutate() return Organism(generation, baby_genome)
def _mutate_any(self): if not self.connections: self.addConnectionMutation() if random.uniform(0, 1) < MUTATE_WEIGHTS_PROB: self.weightsMutation() if random.uniform(0, 1) < MUTATE_ADD_LINK_PROB: self.addConnectionMutation() if random.uniform(0, 1) < MUTATE_ADD_NODE_PROB: self.addNodeMutation() if random.uniform(0, 1) < MUTATE_DELETE_LINK_PROB: self.deleteConnectionMutation() if random.uniform(0, 1) < MUTATE_TOGGLE_ENABLE_PROB: self.toggleEnableMutation() if random.uniform(0, 1) < MUTATE_RENABLE_PROB: self.renenableMutation()
def _select_org_for_reproduction(self): orgs = len(self.organisms) favoured_ind = int(orgs - sqrt(orgs**2 - random.uniform(0, orgs**2))) return self.organisms[favoured_ind]