Exemplo n.º 1
0
    def crossover(self):
        new = []
        self.individuals = sorted(self.individuals,
                key = lambda ind: ind.score,
                reverse = True)

        for _ in range(self.size):
            p1 = self.select()
            p2 = self.select()
            g = Genome(10)
            g.crossover(p1, p2)
            new.append(g)

        self.individuals = new
Exemplo n.º 2
0
    def crossover(self):
        new = []
        self.individuals = sorted(self.individuals,
                                  key=lambda ind: ind.score,
                                  reverse=True)

        for _ in range(self.size):
            p1 = self.select()
            p2 = self.select()
            g = Genome(10)
            g.crossover(p1, p2)
            new.append(g)

        self.individuals = new
Exemplo n.º 3
0
class Organism(object):
    """ Wrapper class that provides fitness metrics. """
    def __init__(self, genome):
        self.genome = Genome(genome)
        self.policy = Network(self.genome)
        self.evals = list()

    def __cmp__(self, other):
        return cmp(self.fitness, other.fitness)

    def __str__(self):
        return '%.3f' % self.fitness

    def crossover(self, other):
        """ Return a new organism by recombining the parents. """
        return Organism(self.genome.crossover(other.genome))

    def mutate(self, frac=0.1, std=1.0, repl=0.25):
        """ Mutate the organism by mutating its genome. """
        self.genome.mutate(frac, std, repl)
        self.policy = Network(self.genome)

    def copy(self):
        """ Return a deep copy of this organism. """
        org = Organism(self.genome)
        org.evals = list(self.evals)
        return org

    @property
    def fitness(self):
        """ Average return. """
        try:
            return sum(self.evals, 0.) / len(self.evals)
        except ZeroDivisionError:
            return 0.
Exemplo n.º 4
0
class Organism(object):
  """ Wrapper class that provides fitness metrics. """
  def __init__(self, genome):
    self.genome = Genome(genome)
    self.policy = Network(self.genome)
    self.evals = list()

  def __cmp__(self, other):
    return cmp(self.fitness, other.fitness)

  def __str__(self):
    return '%.3f' % self.fitness

  def crossover(self, other):
    """ Return a new organism by recombining the parents. """
    return Organism(self.genome.crossover(other.genome))

  def mutate(self, frac=0.1, std=1.0, repl=0.25):
    """ Mutate the organism by mutating its genome. """
    self.genome.mutate(frac, std, repl)
    self.policy = Network(self.genome)

  def copy(self):
    """ Return a deep copy of this organism. """
    org = Organism(self.genome)
    org.evals = list(self.evals)
    return org

  @property
  def fitness(self):
    """ Average return. """
    try:
      return sum(self.evals, 0.) / len(self.evals)
    except ZeroDivisionError:
      return 0.
Exemplo n.º 5
0
class Player:
    def __init__(self):
        self.fitness = 0
        self.vision = []
        self.decision = []
        self.lifespan = 0
        self.max_lifespan = 500
        self.best_score = 0
        self.dead = False
        self.score = 0
        self.gen = 0
        self.genome_inputs = 8
        self.genome_outputs = 2
        self.brain = Genome(self.genome_inputs, self.genome_outputs)

    def reward(self, reward):
        self.score += reward
        self.max_lifespan += reward
        if self.score < 1:
            self.max_lifespan -= 1

    def update(self):
        self.lifespan += 1
        # self.score -= 0.02
        if self.lifespan > self.max_lifespan or self.score < -5:
            self.dead = True
            self.calculate_fitness()

    def look(self, inputs):
        self.vision = []
        self.vision = inputs

    def think(self):
        # choice_max = 0
        # max_index = 0
        self.decision = self.brain.feed_forward(self.vision)
        # for i in range(len(self.decision)):
        #     if self.decision[i] > choice_max:
        #         choice_max = self.decision[i]
        #         max_index = i
        return self.decision  # max_index

    def clone(self):
        clone = Player()
        clone.brain = self.brain.clone()
        clone.fitness = self.fitness
        clone.brain.generate_network()
        clone.gen = self.gen
        clone.best_score = self.score
        return clone

    def calculate_fitness(self):
        self.fitness = (self.score * self.score) + self.lifespan

    def crossover(self, parent2):
        child = Player()
        child.brain = self.brain.crossover(parent2.brain)
        child.brain.generate_network()
        return child
Exemplo n.º 6
0
def crossover(agents):
    next_generation = []
    agents = sorted(agents, key=lambda x: x.get_fitness())
    # random.shuffle(agents)
    s = int((1-SELECT_PERC)*POPULATION)
    for _ in range(s):
        p1 = random.choice(agents)
        p2 = random.choice(agents)
        next_generation += Genome.crossover(p1, p2)
    return next_generation
Exemplo n.º 7
0
def test_crossover():
    a = Genome()
    for i in range(3):
        a.add_node(Node(NodeType.inp, i + 1))
    a.add_node(Node(NodeType.out, 4))
    a.add_node(Node(NodeType.hidden, 5))
    a.add_connection(Connection(1, 4, 1.0, True, 1))
    a.add_connection(Connection(2, 4, 1.0, False, 2))
    a.add_connection(Connection(3, 4, 1.0, True, 3))
    a.add_connection(Connection(2, 5, 1.0, True, 4))
    a.add_connection(Connection(5, 4, 1.0, True, 5))
    a.add_connection(Connection(1, 5, 1.0, True, 8))
    a.conn_innovation = 9
    a.node_innovation = 6

    b = Genome()
    for i in range(3):
        b.add_node(Node(NodeType.inp, i + 1))
    b.add_node(Node(NodeType.out, 4))
    b.add_node(Node(NodeType.hidden, 5))
    b.add_node(Node(NodeType.hidden, 6))
    b.add_connection(Connection(1, 4, 1.0, True, 1))
    b.add_connection(Connection(2, 4, 1.0, False, 2))
    b.add_connection(Connection(3, 4, 1.0, True, 3))
    b.add_connection(Connection(2, 5, 1.0, True, 4))
    b.add_connection(Connection(5, 4, 1.0, False, 5))
    b.add_connection(Connection(5, 6, 1.0, True, 6))
    b.add_connection(Connection(6, 4, 1.0, True, 7))
    b.add_connection(Connection(3, 5, 1.0, True, 9))
    b.add_connection(Connection(1, 6, 1.0, True, 10))
    a.conn_innovation = 11
    a.node_innovation = 7

    c = Genome.crossover(b, a)

    a.render("render/crossover_a.gv")
    b.render("render/crossover_b.gv")
    c.render("render/crossover_c.gv")
Exemplo n.º 8
0
    def get_new_population(self, adjusted_species_sizes, remaining_species,
                           species_set, generation_tracker, backprop_mutation):
        """
        Creates the dictionary of the new genomes for the next generation population
        :param: genetation_tracker:
        :param adjusted_species_sizes:
        :param remaining_species:
        :param species_set:
        :param new_population:
        :return:
        """
        new_population = {}

        for species_size, species in zip(adjusted_species_sizes,
                                         remaining_species):

            assert (species_size > 0)

            # List of old species members
            old_species_members = list(species.members.values())
            # Reset the members for the current species
            species.members = {}
            # Save the species in the species set object
            species_set.species[species.key] = species

            # Sort the members into the descending fitness
            old_species_members.sort(reverse=True, key=lambda x: x.fitness)

            # Double check that it is descending
            if len(old_species_members) > 1:
                assert (old_species_members[0].fitness >=
                        old_species_members[1].fitness)

            # If we have specified a number of genomes to carry over, carry them over to the new population
            num_genomes_without_crossover = int(
                round(species_size *
                      self.config.chance_for_mutation_without_crossover))
            if num_genomes_without_crossover > 0:

                for member in old_species_members[:
                                                  num_genomes_without_crossover]:

                    # Check if we should carry over a member un-mutated or not
                    if not self.config.keep_unmutated_top_percentage:
                        child = copy.deepcopy(member)

                        child.mutate(
                            reproduction_instance=self,
                            innovation_tracker=self.innovation_tracker,
                            config=self.config,
                            backprop_mutation=backprop_mutation)

                        if not child.check_connection_enabled_amount(
                        ) and not child.check_num_paths(
                                only_add_enabled_connections=True):
                            raise Exception(
                                'This child has no enabled connections')

                        new_population[child.key] = child
                        self.ancestors[child.key] = ()
                        # new_population[member.key] = member
                        species_size -= 1
                        assert (species_size >= 0)
                    else:
                        # Else we just add the current member to the new population
                        new_population[member.key] = member
                        species_size -= 1
                        assert (species_size >= 0)

            # If there are no more genomes for the current species, then restart the loop for the next species
            if species_size <= 0:
                continue

            # Only use the survival threshold fraction to use as parents for the next generation.
            reproduction_cutoff = int(
                math.ceil(
                    (1 - self.config.chance_for_mutation_without_crossover) *
                    len(old_species_members)))

            # Need at least two parents no matter what the previous result
            reproduction_cutoff = max(reproduction_cutoff, 2)
            old_species_members = old_species_members[:reproduction_cutoff]

            # Randomly choose parents and choose whilst there can still be additional genomes for the given species
            while species_size > 0:
                species_size -= 1

                # TODO: If you don't allow them to mate with themselves then it's a problem because if the species previous
                # TODO: size is 1, then how can you do with or without crossover?
                parent_1 = copy.deepcopy(random.choice(old_species_members))
                parent_2 = copy.deepcopy(random.choice(old_species_members))

                # Has to be a deep copy otherwise the connections which are crossed over are also modified if mutation
                # occurs on the child.
                parent_1 = copy.deepcopy(parent_1)
                parent_2 = copy.deepcopy(parent_2)

                self.genome_indexer += 1
                genome_id = self.genome_indexer

                child = Genome(key=genome_id)
                # TODO: Save the parent_1 and parent_2 mutation history as well as what connections they had
                # Create the genome from the parents
                num_connections_enabled = child.crossover(genome_1=parent_1,
                                                          genome_2=parent_2,
                                                          config=self.config)

                # If there are no connections enabled we forget about this child and don't add it to the existing
                # population
                if num_connections_enabled:
                    child.mutate(reproduction_instance=self,
                                 innovation_tracker=self.innovation_tracker,
                                 config=self.config,
                                 generation_tracker=generation_tracker,
                                 backprop_mutation=backprop_mutation)

                    if not child.check_connection_enabled_amount(
                    ) and not child.check_num_paths(
                            only_add_enabled_connections=True):
                        raise Exception(
                            'This child has no enabled connections')

                    new_population[child.key] = child
                    self.ancestors[child.key] = (parent_1.key, parent_2.key)
                else:
                    # Else if the crossover resulted in an invalid genome.
                    assert num_connections_enabled == 0
                    species_size += 1
                    self.genome_indexer -= 1

        return new_population
Exemplo n.º 9
0
class Player:

    size_x = 100
    size_y = 50
    genome_inputs = 4
    genome_outputs = 2  # Up or down?

    def __init__(self, game):
        self.game = game
        self.top = game.top
        self.middle = game.middle
        self.bottom = game.bottom
        self.position_x = 0.075 * game.width
        self.position_y = game.middle
        self.speed_x = 0
        self.speed_y = 0
        self.color = (255, 255, 255)
        self.speed = 10
        self.dead = False
        self.next_lane = None
        self.fitness = 0
        self.unadjusted_fitness = 0
        self.lifespan = 0
        self.best_score = 0
        self.replay = False
        self.score = 0
        self.gen = 0
        self.vision = [0 for _ in range(self.genome_inputs)]
        self.decision = [0 for _ in range(self.genome_outputs)]
        self.brain = Genome(self.genome_inputs, self.genome_outputs)

    def draw(self):
        arcade.draw_rectangle_filled(self.position_x, self.position_y,
                                     self.size_x, self.size_y, self.color)

    def update(self):
        self.increment_counters()

        if self.next_lane == None:
            if self.speed_y > 0:
                if self.position_y == self.bottom:
                    self.next_lane = self.middle
                elif self.position_y == self.middle:
                    self.next_lane = self.top
            elif self.speed_y < 0:
                if self.position_y == self.top:
                    self.next_lane = self.middle
                elif self.position_y == self.middle:
                    self.next_lane = self.bottom
        else:
            if self.speed_y > 0:
                if (self.next_lane == self.middle
                        and self.position_y >= self.middle):
                    self.next_lane = None
                    self.position_y = self.middle
                    self.speed_y = 0
                elif (self.next_lane == self.top
                      and self.position_y >= self.top):
                    self.next_lane = None
                    self.position_y = self.top
                    self.speed_y = 0
                else:
                    self.position_y += self.speed_y
            if self.speed_y < 0:
                if (self.next_lane == self.middle
                        and self.position_y <= self.middle):
                    self.next_lane = None
                    self.position_y = self.middle
                    self.speed_y = 0
                elif (self.next_lane == self.bottom
                      and self.position_y <= self.bottom):
                    self.next_lane = None
                    self.position_y = self.bottom
                    self.speed_y = 0
                else:
                    self.position_y += self.speed_y

        for enemy in self.game.enemy_list:
            if enemy.collided(self):
                self.dead = True
                break

    def move(self, direction):
        if self.next_lane == None:
            if direction == 'up':
                self.speed_y = self.speed
            elif direction == 'down':
                self.speed_y = -self.speed

    def clone(self):
        clone = Player(self.game)
        clone.brain = self.brain.clone()
        clone.fitness = self.fitness
        clone.unadjusted_fitness = self.unadjusted_fitness
        clone.brain.generate_network()
        clone.gen = self.gen
        clone.best_score = self.best_score
        clone.color = self.color

        return clone

    def calculate_fitness(self):
        self.unadjusted_fitness = self.score * self.score
        self.fitness = self.unadjusted_fitness

    def crossover(self, parent_2):
        child = Player(self.game)
        child.color = self.color
        child.brain = self.brain.crossover(parent_2.brain)
        child.brain.generate_network()

        return child

    def look(self):
        if len(self.game.enemy_list) > 0:
            dist_min_bot = 1e6
            dist_min_mid = 1e6
            dist_min_top = 1e6

            for enemy in self.game.enemy_list:
                dist = enemy.position_x - self.position_x
                if dist <= 0:
                    continue
                if enemy.position_y == self.bottom:
                    if dist < dist_min_bot:
                        dist_min_bot = dist
                if enemy.position_y == self.middle:
                    if dist < dist_min_mid:
                        dist_min_mid = dist
                if enemy.position_y == self.top:
                    if dist < dist_min_top:
                        dist_min_top = dist

            self.vision[0] = (dist_min_bot /
                              self.game.width if dist_min_bot != 1e6 else 1)
            self.vision[1] = (dist_min_mid /
                              self.game.width if dist_min_mid != 1e6 else 1)
            self.vision[2] = (dist_min_top /
                              self.game.width if dist_min_top != 1e6 else 1)

        else:
            self.vision[0] = 1
            self.vision[1] = 1
            self.vision[2] = 1
        self.vision[3] = self.position_y / self.game.height

    def think(self):
        decision = self.brain.feed_forward(self.vision)

        action_certainty = max(decision)
        action_taken = decision.index(action_certainty)

        if action_taken == 0:
            self.move('up')
        elif action_taken == 1:
            self.move('down')

    def increment_counters(self):
        self.lifespan += 1

        if self.lifespan % 5 == 0:
            self.score += 1
Exemplo n.º 10
0
class Player:
    MAX_ROTATION = 25
    IMGS = [pygame.transform.scale2x(pygame.image.load(
        os.path.join("imgs", "bird" + str(x) + ".png"))) for x in range(1, 4)]
    ROT_VEL = 20
    ANIMATION_TIME = 5
    genome_inputs = 3 # Flappy-Bird Vision! If you change vision parameter in look(), change here too!
    genome_outputs = 1 # To jump or not to jump!

    def __init__(self, x, y):
        self.dead = False
        self.x = x
        self.y = y
        self.tilt = 0
        self.tick_count = 0
        self.vel = 0
        self.height = self.y
        self.img_count = 0
        self.img = self.IMGS[0]
        self.fitness = 1
        self.unadjusted_fitness = 0
        self.lifespan = 0
        self.best_score = 0
        #self.replay = False
        self.score = 1
        #self.gen = 0
        self.vision = [0 for _ in range(self.genome_inputs)]
        self.decision = 0
        self.brain = Genome(self.genome_inputs, self.genome_outputs)

    def draw(self, win):
        self.img_count += 1

        if self.img_count <= self.ANIMATION_TIME:
            self.img = self.IMGS[0]
        elif self.img_count <= self.ANIMATION_TIME*2:
            self.img = self.IMGS[1]
        elif self.img_count <= self.ANIMATION_TIME*3:
            self.img = self.IMGS[2]
        elif self.img_count <= self.ANIMATION_TIME*4:
            self.img = self.IMGS[1]
        elif self.img_count == self.ANIMATION_TIME*4 + 1:
            self.img = self.IMGS[0]
            self.img_count = 0

        if self.tilt <= -80:
            self.img = self.IMGS[1]
            self.img_count = self.ANIMATION_TIME*2

        self.blitRotateCenter(win, self.img, (self.x, self.y), self.tilt)

    def blitRotateCenter(self, surf, image, topleft, angle):
       	rotated_image = pygame.transform.rotate(image, angle)
        new_rect = rotated_image.get_rect(
        	center=image.get_rect(topleft=topleft).center)
        surf.blit(rotated_image, new_rect.topleft)

    def get_mask(self):
        return pygame.mask.from_surface(self.img)

    def jump(self):
        self.vel = -10.5
        self.tick_count = 0
        self.height = self.y

    def move(self):
        self.tick_count += 1
        displacement = self.vel*(self.tick_count) + 0.5 * \
            (3)*(self.tick_count)**2  

        if displacement >= 16:
            displacement = (displacement/abs(displacement)) * 16

        if displacement < 0:
            displacement -= 2

        self.y = self.y + displacement

        if displacement < 0 or self.y < self.height + 50:
            if self.tilt < self.MAX_ROTATION:
                self.tilt = self.MAX_ROTATION
        else:
            if self.tilt > -90:
                self.tilt -= self.ROT_VEL

    def clone(self):
        clone = Player(230, randint(200,400))
        clone.brain = self.brain.clone()
        clone.fitness = self.fitness
        clone.unadjusted_fitness = self.unadjusted_fitness
        clone.brain.generate_network()
        clone.best_score = self.best_score

        return clone

    def calculate_fitness(self):
        self.unadjusted_fitness = self.score*self.score
        self.fitness = self.unadjusted_fitness

    def crossover(self, parent_2):
        child = Player(230, randint(200,400))
        child.brain = self.brain.crossover(parent_2.brain)
        child.brain.generate_network()
        
        return child

    def look(self, pipes, pipe_ind):
        self.vision[0] = self.y
        self.vision[1] = abs(self.y - pipes[pipe_ind].height)
        self.vision[2] = abs(self.y - pipes[pipe_ind].bottom)

    def think_and_act(self):
        decision = self.brain.feed_forward(self.vision)[0]

        if decision > 0:
            self.jump()

    #def increment_counters(self):
    #    self.lifespan += 1
#
     #   if self.lifespan % 5 == 0:
      #      self.score += 1

    def increment_score_by(self, number):
        self.score += number