示例#1
0
    def select_one(self, population: Population) -> Individual:
        """Return single individual from population.

        Parameters
        ----------
        population
            A Population of Individuals.

        Returns
        -------
        Individual
            The selected Individual.

        """
        return population.best()
示例#2
0
文件: search.py 项目: erp12/Pysh
class SearchAlgorithm(ABC):
    """Base class for all search algorithms.

    Parameters
    ----------
    config : SearchConfiguration
        The configuation of the search algorithm.

    Attributes
    ----------
    config : SearchConfiguration
        The configuation of the search algorithm.
    generation : int
        The current generation, or iteration, of the search.
    best_seen : Individual
        The best Individual, with respect to total error, seen so far.
    population : Population
        The current Population of individuals.

    """

    def __init__(self, config: SearchConfiguration):
        self.config = config
        self.generation = 0
        self.best_seen = None
        self.init_population()

    def init_population(self):
        """Initialize the population."""
        self.population = Population()
        for i in range(self.config.population_size):
            spawner = self.config.spawner
            genome = spawner.spawn_genome(self.config.initial_genome_size)
            self.population.add(Individual(genome))

    @abstractmethod
    def step(self) -> bool:
        """Perform one generation (step) of the search. Return if should continue.

        The step method should assume an evaluated Population, and must only
        perform parent selection and variation (producing children). The step
        method should modify the search algorithms population in-place, or
        assign a new Population to the population attribute.

        """
        pass

    def _full_step(self) -> bool:
        self.generation += 1
        self.population.evaluate(self.config.evaluator)

        best_this_gen = self.population.best()
        if self.best_seen is None or best_this_gen.total_error < self.best_seen.total_error:
            self.best_seen = best_this_gen
            if self.best_seen.total_error <= self.config.error_threshold:
                return False

        if self.config.verbosity_config.generation >= self.config.verbosity_config.log_level and \
           self.generation % self.config.verbosity_config.every_n_generations == 0:
            stat_logs = []
            stat_logs.append("GENERATION: {g}".format(
                g=self.generation
            ))
            stat_logs.append("ERRORS: best={b}, median={m}, diversity={e_d}".format(
                b=self.population.best().total_error,
                m=self.population.median_error(),
                e_d=self.population.error_diversity()
            ))
            # stat_logs.append("Population: size={p_s}, genome_diversity={g_d}".format(
            #     p_s=len(self.population),
            #     g_d=self.population.genome_diversity()
            # ))

            log(self.config.verbosity_config.generation, " | ".join(stat_logs))

        self.step()
        return True

    def _is_solved(self):
        return self.best_seen.total_error <= self.config.error_threshold

    def run(self):
        """Run the algorithm until termination."""
        while self._full_step():
            if self.generation >= self.config.max_generations:
                break

        verbose_solution = self.config.verbosity_config.solution_found
        if verbose_solution >= self.config.verbosity_config.log_level:
            if self._is_solved():
                log(verbose_solution, "Unsimplified solution found.")
            else:
                log(verbose_solution, "No unsimplified solution found.")

        # Simplify the best individual for a better generalization and interpreteation.
        simplifier = GenomeSimplifier(self.config.evaluator, self.config.verbosity_config)
        simp_genome, simp_error_vector = simplifier.simplify(
            self.best_seen.genome,
            self.best_seen.error_vector,
            self.config.simplification_steps
        )
        simplified_best = Individual(simp_genome)
        simplified_best.error_vector = simp_error_vector

        if verbose_solution >= self.config.verbosity_config.log_level:
            if self._is_solved():
                log(verbose_solution, "Simplified solution found.")
            else:
                log(verbose_solution, "No simplified solution found.")

        return simplified_best
示例#3
0
class SearchAlgorithm(ABC):
    """Base class for all search algorithms.

    Parameters
    ----------
    config : SearchConfiguration
        The configuation of the search algorithm.

    Attributes
    ----------
    config : SearchConfiguration
        The configuration of the search algorithm.
    generation : int
        The current generation, or iteration, of the search.
    best_seen : Individual
        The best Individual, with respect to total error, seen so far.
    population : Population
        The current Population of individuals.

    """
    def __init__(self, config: SearchConfiguration):
        self.config = config
        self._p_context = config.parallel_context
        self.generation = 0
        self.best_seen = None
        self.population = None
        self.init_population()

    def init_population(self):
        """Initialize the population."""
        spawner = self.config.spawner
        init_gn_size = self.config.initial_genome_size
        pop_size = self.config.population_size
        signature = self.config.signature
        self.population = Population()
        if self._p_context is not None:
            gen_func = partial(_spawn_individual, self._p_context.ns.spawner,
                               init_gn_size, signature)
            for indiv in self._p_context.pool.imap_unordered(
                    gen_func, range(pop_size)):
                self.population.add(indiv)
        else:
            for i in range(pop_size):
                self.population.add(
                    _spawn_individual(spawner, init_gn_size, signature))

    @tap
    @abstractmethod
    def step(self) -> bool:
        """Perform one generation (step) of the search.

        The step method should assume an evaluated Population, and must only
        perform parent selection and variation (producing children). The step
        method should modify the search algorithms population in-place, or
        assign a new Population to the population attribute.

        """
        pass

    def _full_step(self) -> bool:
        self.generation += 1
        if self._p_context is not None:
            self.population.p_evaluate(self._p_context.ns.evaluator,
                                       self._p_context.pool)
        else:
            self.population.evaluate(self.config.evaluator)

        best_this_gen = self.population.best()
        if self.best_seen is None or best_this_gen.total_error < self.best_seen.total_error:
            self.best_seen = best_this_gen
            if self.best_seen.total_error <= self.config.error_threshold:
                return False

        self.step()
        return True

    def is_solved(self) -> bool:
        """Return ``True`` if the search algorithm has found a solution or ``False`` otherwise."""
        return self.best_seen.total_error <= self.config.error_threshold

    @tap
    def run(self) -> Individual:
        """Run the algorithm until termination."""
        while self._full_step():
            if self.generation >= self.config.max_generations:
                break

        # Simplify the best individual for a better generalization and interpretation.
        simplifier = GenomeSimplifier(self.config.evaluator,
                                      self.config.signature)
        simp_genome, simp_error_vector = simplifier.simplify(
            self.best_seen.genome, self.best_seen.error_vector,
            self.config.simplification_steps)
        simplified_best = Individual(simp_genome, self.config.signature)
        simplified_best.error_vector = simp_error_vector
        self.best_seen = simplified_best
        return self.best_seen
示例#4
0
class SearchAlgorithm(ABC):
    """Base class for all search algorithms.

    Parameters
    ----------
    config : SearchConfiguration
        The configuation of the search algorithm.

    Attributes
    ----------
    config : SearchConfiguration
        The configuation of the search algorithm.
    generation : int
        The current generation, or iteration, of the search.
    best_seen : Individual
        The best Individual, with respect to total error, seen so far.
    population : Population
        The current Population of individuals.

    """
    def __init__(self, config: SearchConfiguration):
        self.config = config
        self.generation = 0
        self.best_seen = None
        self.init_population()

    def init_population(self):
        """Initialize the population."""
        self.population = Population()
        for i in range(self.config.population_size):
            spawner = self.config.spawner
            genome = spawner.spawn_genome(self.config.initial_genome_size)
            self.population.add(Individual(genome))

    @abstractmethod
    def step(self) -> bool:
        """Perform one generation (step) of the search. Return if should continue.

        The step method should assume an evaluated Population, and must only
        perform parent selection and variation (producing children). The step
        method should modify the search algorithms population in-place, or
        assign a new Population to the population attribute.

        """
        pass

    def _full_step(self) -> bool:
        self.generation += 1
        self.population.evaluate(self.config.evaluator)

        best_this_gen = self.population.best()
        if self.best_seen is None or best_this_gen.total_error < self.best_seen.total_error:
            self.best_seen = best_this_gen
            if self.best_seen.total_error <= self.config.error_threshold:
                return False

        if self.config.verbosity_config.generation and \
           self.generation % self.config.verbosity_config.every_n_generations == 0:
            stat_logs = []
            stat_logs.append("GENERATION: {g}".format(g=self.generation))
            stat_logs.append(
                "ERRORS: best={b}, median={m}, diversity={e_d}".format(
                    b=self.population.best().total_error,
                    m=self.population.median_error(),
                    e_d=self.population.error_diversity()))
            # stat_logs.append("Population: size={p_s}, genome_diversity={g_d}".format(
            #     p_s=len(self.population),
            #     g_d=self.population.genome_diversity()
            # ))
            self.config.verbosity_config.generation(" | ".join(stat_logs))

        self.step()
        return True

    def _is_solved(self):
        return self.best_seen.total_error <= self.config.error_threshold

    def run(self):
        """Run the algorithm until termination."""
        while self._full_step():
            if self.generation >= self.config.max_generations:
                break

        verbose_solution = self.config.verbosity_config.solution_found
        if verbose_solution:
            if self._is_solved():
                verbose_solution("Unsimplified solution found.")
            else:
                verbose_solution("No unsimplified solution found.")

        # Simplify the best individual for a better generalization and interpreteation.
        simplifier = GenomeSimplifier(self.config.evaluator,
                                      self.config.verbosity_config)
        simp_genome, simp_error_vector = simplifier.simplify(
            self.best_seen.genome, self.best_seen.error_vector,
            self.config.simplification_steps)
        simplified_best = Individual(simp_genome)
        simplified_best.error_vector = simp_error_vector

        if verbose_solution:
            if self._is_solved():
                verbose_solution("Simplified solution found.")
            else:
                verbose_solution("No simplified solution found.")

        return simplified_best