Example #1
0
 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))
Example #2
0
 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))
Example #3
0
    def select_one(self, population: Population) -> Individual:
        """Return single individual from population.

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

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

        """
        candidates = self._preselection(population)
        cases = np.arange(len(population[0].error_vector))
        shuffle(cases)

        if isinstance(self.epsilon, np.ndarray):
            ep = np.apply_along_axis(median_absolute_deviation, 0,
                                     population.all_error_vectors())
        elif isinstance(self.epsilon, (float, int, np.int64, np.float64)):
            ep = self.epsilon

        while len(cases) > 0 and len(candidates) > 1:
            case = cases[0]
            errors_this_case = [i._error_vector[case] for i in candidates]
Example #4
0
    def step(self):
        """Perform one generation, or step, of the Simulated Annealing.

        The step method assumes an evaluated Population one Individual and
        produces a single candidate Individual. If the candidate individual
        passes the acceptance function, it becomes the Individual in the
        Population.

        """
        super().step()
        if self._get_temp() <= 0:
            return

        candidate = Individual(
            self.config.get_variation_op().produce(
                [self.population.best().genome],
                self.config.spawner
            ),
            self.config.signature
        )
        candidate.error_vector = self.config.evaluator.evaluate(candidate.program)

        acceptance_probability = self._acceptance(candidate.total_error)
        if np.random.random() < acceptance_probability:
            self.population = Population().add(candidate)
Example #5
0
File: search.py Project: erp12/Pysh
 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))
Example #6
0
    def step(self):
        """Perform one generation (step) of the genetic algorithm.

        The step method assumes an evaluated Population and performs parent
        selection and variation (producing children).

        """
        self.population = Population(
            [self._make_child() for _ in range(self.config.population_size)])
Example #7
0
    def _select_with_stream(self, population: Population, cases: CaseStream) -> Individual:
        candidates = one_individual_per_error_vector(population)

        ep = self.epsilon
        if isinstance(ep, bool) and ep:
            ep = self._epsilon_from_mad(population.all_error_vectors())

        for case in cases:
            if len(candidates) <= 1:
                break

            errors_this_case = [i.error_vector[case] for i in candidates]
            best_val_for_case = min(errors_this_case)
Example #8
0
def pop(atoms):
    i1 = Individual(Genome())
    i1.error_vector = np.array([0, 20, 0])  # 20

    i2 = Individual(Genome())
    i2.error_vector = np.array([3, 3, 3])  # 9

    i3 = Individual(Genome())
    i3.error_vector = np.array([1, 2, 3])  # 6

    i4 = Individual(Genome())
    i4.error_vector = np.array([4, 3, 5])  # 12

    return Population([i1, i2, i3, i4])
Example #9
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()
Example #10
0
def population(atoms, push_config):
    gn = Genome()
    sig = ProgramSignature(arity=0, output_stacks=[], push_config=push_config)
    i1 = Individual(gn, sig)
    i1.error_vector = np.array([0, 20, 0])  # 20

    i2 = Individual(gn, sig)
    i2.error_vector = np.array([3, 3, 3])  # 9

    i3 = Individual(gn, sig)
    i3.error_vector = np.array([1, 2, 3])  # 6

    i4 = Individual(gn, sig)
    i4.error_vector = np.array([4, 3, 5])  # 12

    return Population([i1, i2, i3, i4])
Example #11
0
    def select(self,
               population: Population,
               n: int = 1) -> Sequence[Individual]:
        """Return `n` individuals from the population.

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

        Returns
        -------
        Sequence[Individual]
            The selected Individuals.

        """
        return population.best_n(n)
Example #12
0
    def select(self, population: Population, n: int = 1) -> Sequence[Individual]:
        """Return `n` individuals from the population.

        Parameters
        ----------
        population
            A Population of Individuals.
        n : int
            The number of parents to select from the population. Default is 1.

        Returns
        -------
        Sequence[Individual]
            The selected Individuals.

        """
        super().select(population, n)
        return population.best_n(n)
Example #13
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
Example #14
0
 def test_empty_population_len(self):
     assert len(Population()) == 0
Example #15
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
Example #16
0
def partially_evaluated_pop(simple_individuals):
    simple_individuals[0].error_vector = np.array([1, 2, 3])
    simple_individuals[2].error_vector = np.array([0, 0, 0])
    return Population(simple_individuals)
Example #17
0
def evaluated_pop(simple_individuals):
    for i in simple_individuals:
        i.error_vector = np.arange(3)
    return Population(simple_individuals)
Example #18
0
def unevaluated_pop(simple_individuals):
    return Population(simple_individuals)
Example #19
0
 def test_genome_diversity_empty_pop(self):
     with pytest.raises(ZeroDivisionError):
         Population().genome_diversity()
Example #20
0
 def test_median_error_empty_pop(self):
     assert np.isnan(Population().median_error()).all()
Example #21
0
File: search.py Project: 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
Example #22
0
 def test_error_diversity_empty_pop(self):
     with pytest.raises(ValueError):
         Population().error_diversity()