Example #1
0
    def step(self):
        offspring = []
        while len(offspring) < self.offspring_size:
            # Selection
            parents = self.selection(self.population, self.selection_size)
            # Recombination
            if take_chances(self.p_recombination):
                progeny = self.recombination(*parents)
            else:
                progeny = [i.clone() for i in parents]
            # Mutation
            individuals_who_fit = min(
                len(progeny),
                self.offspring_size - len(offspring)
            )
            progeny = [
                self.mutation(individual, self.p_mutation)
                for individual in random.sample(progeny, individuals_who_fit)
                ]
            # Add progeny to the offspring
            offspring.extend(progeny)

        # Once offspring is generated, a replace step is performed
        self.replacement(self.population, offspring)

        # We store the best individual for further information
        if self.generation < len(self.best_individuals):
            self.best_individuals[self.generation] = self.population.best()
        else:
            self.best_individuals.append(self.population.best())
Example #2
0
    def __call__(self, individual, p):
        """ Changes the value of a random gene of the individual.

        The mutated chromosome is obtained by changing a random gene as seen in
        the next example:

        individual : aabbaaba
        alleles    : (a, b, c, d)
        change pos : 7
        -----------
        mutated    : aabdaabc

        :param individual: The individual to be mutated.
        :param p: The probability of mutation.
        """
        indexes = random.sample(
            range(len(individual)),
            min(self.n or len(individual), len(individual)),
        )
        clone = individual.clone()
        for i in indexes:
            if take_chances(probability=p):
                new_gene = self.alleles.get()
                while individual[i] == new_gene:
                    new_gene = self.alleles.get()
                clone[i] = new_gene
        return clone
Example #3
0
    def __call__(self, individual, p):
        """ Changes the value of a random gene of the individual.

        The mutated chromosome is obtained by changing a random gene as seen in
        the next example:

        individual : aabbaaba
        alleles    : (a, b, c, d)
        change pos : 7
        -----------
        mutated    : aabdaabc

        :param individual: The individual to be mutated.
        :param p: The probability of mutation.
        """
        clone = individual.clone()
        if take_chances(probability=p):
            # Set in a random position a different gene than before
            i = random.choice(range(len(individual)))
            new_gene = self.alleles.get()
            while individual[i] == new_gene:
                new_gene = self.alleles.get()
            # Set this gene in the cloned individual
            clone[i] = new_gene
            return clone
        else:
            return clone
Example #4
0
    def __call__(self, individual, p):
        """ Swaps the values of two positions of the list of values.

        When the individual is mutated, two random positions (pivots) are
        generated. Then, the values of those positions are swapped. For example:

        individual : 12345678
        pivot      : 3, 5
        -----------
        mutated    : 12365478

        :param individual: The individual to be mutated.
        :param p: The probability of mutation.
        :return: A new individual mutated with a probabiity of p or looking
            exactly to the one passed as parameter with a probability of 1-p.
        """
        clone = individual.clone()
        if take_chances(probability=p):
            # Get two random diferent indexes
            indexes = range(len(individual))
            i1, i2 = tuple(random.sample(indexes, 2))
            # Swap the genes in the cloned individual
            clone[i1], clone[i2] = clone[i2], clone[i1]
            return clone
        else:
            return clone
Example #5
0
    def __call__(self, individual, p):
        """ Returns the same instance of the individual mutated.

        :param individual: The individual to mutate.
        :param p: The probability for a gene to mutate.
        :return: The same instance maybe mutated).
        """
        for i, gene_value in enumerate(individual):
            if take_chances(probability=p):
                individual[i] = 1 - gene_value
        return individual
Example #6
0
    def __call__(self, individual, p):
        """ Returns the same instance of the individual mutated.

        :param individual: The individual to mutate.
        :param p: The probability for a gene to mutate.
        :return: The same instance maybe mutated).
        """
        for i, gene_value in enumerate(individual):
            if take_chances(probability=p):
                individual[i] = 1 - gene_value
        return individual
Example #7
0
    def random_derivation(self):
        """ Returns a tuple with the managed term according to limits and p.

        The minimum size of the returned tuple will be the lower limit
        specified in the init param "lower". After that, and with a maximum
        of "upper" terms, a new param will be added as long as random tests fall
        under the probability specified.
        """
        terms = [self.value for _ in range(self.lower)]
        while len(terms) < self.upper and take_chances(self.p):
            terms.append(self.value)
        return tuple(terms)
Example #8
0
    def random_derivation(self):
        """ Returns a tuple with the managed term according to limits and p.

        The minimum size of the returned tuple will be the lower limit
        specified in the init param "lower". After that, and with a maximum
        of "upper" terms, a new param will be added as long as random tests fall
        under the probability specified.
        """
        terms = [self.value for _ in range(self.lower)]
        while len(terms) < self.upper and take_chances(self.p):
            terms.append(self.value)
        return tuple(terms)
Example #9
0
    def __call__(self, parent1, parent2):
        """ Offspring is obtained generating a random mask.

        This mask determines which genes of each of the progenitors are used on
        each of the the genes. For example:

        parents     : aaaaaaaa, bbbbbbbb
        random mask : 00100110
        -----------
        children    : aabaabba, bbabbaab

        :param parent1: One of the individuals from which generate the progeny.
        :param parent2: The other.
        :return: A list of two individuals, each a child containing some
            characteristics from their parents.
        """
        child1, child2 = super().__call__(parent1, parent2)

        for i in range(len(parent1)):
            if take_chances(.5):
                child1[i], child2[i] = parent2[i], parent1[i]
        return child1, child2