Exemple #1
0
    def evaluate_population(self,
                            pop,
                            game_ids=None):  # TODO: Not used, remove?
        """
        Evaluate the population on a set of games and create blueprints of the final positions afterwards.

        :param pop: Population object
        :param game_ids: List of game-ids
        """
        if game_ids: self.set_games(game_ids)

        if len(self.games) > 20:
            raise Exception(
                "It is not advised to evaluate a whole population on more than 20 games at once"
            )

        # Create the environment which is responsible for evaluating the genomes
        multi_env = get_multi_env(pop=pop, game_config=self.game_config)

        # Initialize the evaluation-pool
        pool = mp.Pool(mp.cpu_count())
        manager = mp.Manager()
        return_dict = manager.dict()

        # Fetch the dictionary of genomes
        genomes = list(iteritems(pop.population))

        # Progress bar during evaluation
        pbar = tqdm(total=len(genomes), desc="parallel training")

        def cb(*_):
            """Update progressbar after finishing a single genome's evaluation."""
            pbar.update()

        # Evaluate the genomes
        for genome in genomes:
            pool.apply_async(func=multi_env.eval_genome,
                             args=(genome, return_dict),
                             callback=cb)
        pool.close()  # Close the pool
        pool.join()  # Postpone continuation until everything is finished
        pbar.close()  # Close the progressbar

        # Create blueprint of final result
        game_objects = [get_game(g, cfg=self.game_config) for g in self.games]
        create_blueprints(final_observations=return_dict,
                          games=game_objects,
                          gen=pop.generation,
                          save_path=get_subfolder(
                              f'population/storage/{pop.folder_name}/{pop}/',
                              'images'))
    def trace_genomes(self, pop: Population, given_genome: Genome = None):
        """
        Create blueprints that contain the walking-traces for all the requested mazes.

        :param pop: Population object
        :param given_genome: Single genomes for which the trace must be made
        """
        multi_env = get_multi_env(pop=pop, game_config=self.game_config)
        if len(self.games) > 20:
            raise Exception(
                "It is not advised to evaluate on more than 20 at once")

        multi_env.set_games(self.games)

        # Initialize the evaluation-pool
        pool = mp.Pool(mp.cpu_count())
        manager = mp.Manager()
        return_dict = manager.dict()

        # Fetch the dictionary of genomes
        genomes = [(given_genome.key, given_genome)] if given_genome else list(
            iteritems(pop.population))

        # Progress bar during evaluation
        pbar = tqdm(total=len(genomes), desc="parallel evaluating")

        def cb(*_):
            """Update progressbar after finishing a single genome's evaluation."""
            pbar.update()

        # Evaluate the genomes
        for genome in genomes:
            pool.apply_async(func=multi_env.trace_genome,
                             args=(genome, return_dict),
                             callback=cb)
        pool.close()  # Close the pool
        pool.join()  # Postpone continuation until everything is finished

        # Create blueprint of final result
        game_objects = [get_game(g, cfg=self.game_config) for g in self.games]
        create_traces(
            traces=return_dict,
            games=game_objects,
            gen=pop.generation,
            save_path=get_subfolder(
                f'population/storage/{pop.folder_name}/{pop}/', 'images'),
            save_name=f'trace_{given_genome.key}' if given_genome else 'trace',
        )
    def visualize(self, genome, game_id: int):
        """
        Visualize the performance of a single genome.
        
        :param genome: Tuple (genome_id, genome_class)
        :param game_id: ID of the game that will be used for evaluation
        """
        # Create the requested game
        game: Game = get_game(game_id, cfg=self.game_config)
        game.player.set_active_sensors(
            set(genome.get_used_connections().keys()))

        # Create space in which game will be played
        window = pyglet.window.Window(
            game.game_config.x_axis * game.game_config.p2m,
            game.game_config.y_axis * game.game_config.p2m,
            "Robot Simulator - Game {id:03d}".format(id=game_id),
            resizable=False,
            visible=True)
        window.set_location(100, 100)
        pyglet.gl.glClearColor(1, 1, 1, 1)

        # Setup the requested game
        self.state = game.reset()[D_SENSOR_LIST]
        self.finished = False

        # Make the network used during visualization
        net = self.make_net(
            genome=genome,
            genome_config=self.pop_config.genome,
            game_config=self.game_config,
            bs=1,
            initial_read=self.state,
        )

        # Create the visualize-environment
        space = pymunk.Space()
        options = DrawOptions()

        # Draw static objects - walls
        for wall in game.walls:
            wall_shape = pymunk.Segment(space.static_body,
                                        a=wall.x * game.game_config.p2m,
                                        b=wall.y * game.game_config.p2m,
                                        radius=0.05 *
                                        game.game_config.p2m)  # 5cm walls
            wall_shape.color = (0, 0, 0)
            space.add(wall_shape)

        # Draw static objects - target
        target_body = pymunk.Body(body_type=pymunk.Body.KINEMATIC)
        target_body.position = game.target * game.game_config.p2m
        target_shape = pymunk.Circle(body=target_body,
                                     radius=game.bot_config.radius *
                                     game.game_config.p2m)
        target_shape.sensor = True
        target_shape.color = (0, 128, 0)
        space.add(target_body, target_shape)

        # Init player²
        m = pymunk.moment_for_circle(mass=2,
                                     inner_radius=0,
                                     outer_radius=game.bot_config.radius *
                                     game.game_config.p2m)
        player_body = pymunk.Body(mass=1, moment=m)
        player_body.position = game.player.pos * game.game_config.p2m
        player_body.angle = game.player.angle
        player_shape = pymunk.Circle(body=player_body,
                                     radius=game.bot_config.radius *
                                     game.game_config.p2m)
        player_shape.color = (255, 0, 0)
        space.add(player_body, player_shape)
        label = pyglet.text.Label(
            f'{self.time}',  # TODO: Creates error in WeakMethod after run (during termination)
            font_size=16,
            color=(100, 100, 100, 100),
            x=window.width - 20,
            y=window.height - 20,
            anchor_x='center',
            anchor_y='center')

        # Draw the robot's sensors
        def draw_sensors():
            [
                space.remove(s) for s in space.shapes
                if s.sensor and type(s) == pymunk.Segment
            ]
            for key in game.player.active_sensors:
                s = game.player.sensors[key]
                if type(s) == ProximitySensor:
                    line = pymunk.Segment(space.static_body,
                                          a=s.start_pos * game.game_config.p2m,
                                          b=s.end_pos * game.game_config.p2m,
                                          radius=0.5)
                    line.sensor = True
                    touch = ((s.start_pos - s.end_pos).get_length() <
                             game.bot_config.ray_distance - 0.05)
                    line.color = (100, 100, 100) if touch else (
                        200, 200, 200)  # Brighten up ray if it makes contact
                    space.add(line)

        @window.event
        def on_draw():
            window.clear()
            draw_sensors()
            label.draw()
            space.debug_draw(options=options)

        def update_method(_):  # Input dt ignored
            dt = 1 / game.game_config.fps
            self.time += dt
            label.text = str(int(self.time))

            # Stop when target is reached
            if not self.finished:
                # Query the game for the next action
                action = self.query_net(net, [self.state])
                if self.debug:
                    print("Passed time:", round(dt, 3))
                    print("Location: x={}, y={}".format(
                        round(player_body.position.x / game.game_config.p2m,
                              2),
                        round(player_body.position.y / game.game_config.p2m,
                              2)))
                    print("Action: lw={l}, rw={r}".format(
                        l=round(action[0][0], 3), r=round(action[0][1], 3)))
                    print("Observation:", [round(s, 3) for s in self.state])

                # Progress game by one step
                obs = game.step_dt(dt=dt, l=action[0][0], r=action[0][1])
                self.finished = obs[D_DONE]
                self.state = obs[D_SENSOR_LIST]

                # Update space's player coordinates and angle
                player_body.position = game.player.pos * game.game_config.p2m
                player_body.angle = game.player.angle
            space.step(dt)

        # Run the game
        pyglet.clock.schedule_interval(
            update_method, 1.0 / (game.game_config.fps * self.speedup))
        pyglet.app.run()
    # Set the title for the plot
    plt.title("Heatmap - Game {id:05d}".format(id=game.id))

    # Create the colorbar
    cax = divider.append_axes('right', size='5%', pad=0.05)
    norm = mpl.colors.Normalize(vmin=0, vmax=max_dist)
    data = np.ones((256, 3))
    data[:, 1] = np.linspace(0.33, 1, 256)
    data[:, 2] = 0
    mpl.colorbar.ColorbarBase(cax,
                              cmap=clr.ListedColormap(data),
                              norm=norm,
                              orientation='vertical')

    # Save the figure
    plt.savefig(f'environment/visualizations/heatmap_game{game.id:05d}')


if __name__ == '__main__':
    os.chdir("../..")
    cfg = Config()
    # for g_id in [0]:
    for g_id in tqdm(range(1, 11)):
        # Load the game
        g = get_game(g_id, cfg=cfg)

        # Create visualizations
        game_blueprint(g)
        # path_heatmap(g)
Exemple #5
0
    def eval_genome(
        self,
        genome,
        return_dict=None,
    ):
        """
        Evaluate a single genome in a pre-defined game-environment.
        
        :param genome: Tuple (genome_id, genome_class)
        :param return_dict: Dictionary used to return observations corresponding the genome
        """
        # Split up genome by id and genome itself
        genome_id, genome = genome
        used_connections = set(genome.get_used_connections().keys())

        # Initialize the games on which the genome is tested
        games = [get_game(g, cfg=self.game_config) for g in self.games]
        for g in games:
            g.player.set_active_sensors(used_connections)  # Set active-sensors

        # Ask for each of the games the starting-state
        states = [g.reset()[D_SENSOR_LIST] for g in games]

        # Finished-state for each of the games is set to false
        finished = [False] * self.batch_size

        # Create the network used to query on, initialize it with the first-game's readings (good approximation)
        net = self.make_net(
            genome=genome,
            genome_config=self.pop_config.genome,
            game_config=self.game_config,
            bs=self.batch_size,
            initial_read=states[0],
        )

        # Start iterating the environments
        step_num = 0
        while True:
            # Check if maximum iterations is reached
            if step_num == self.max_steps: break

            # Determine the actions made by the agent for each of the states
            actions = self.query_net(net, states)

            # Check if each game received an action
            assert len(actions) == len(games)

            for i, (g, a, f) in enumerate(zip(games, actions, finished)):
                # Ignore if game has finished
                if not f:
                    # Proceed the game with one step, based on the predicted action
                    obs = g.step(l=a[0], r=a[1])
                    finished[i] = obs[D_DONE]

                    # Update the candidate's current state
                    states[i] = obs[D_SENSOR_LIST]

            # Stop if agent reached target in all the games
            if all(finished): break
            step_num += 1

        # Return the final observations
        if return_dict is not None:
            return_dict[genome_id] = [g.close() for g in games]
Exemple #6
0
 def get_game_params(self):
     """Return list of all game-parameters currently in self.games."""
     return [
         get_game(i, cfg=self.game_config).game_params() for i in self.games
     ]