示例#1
0
    def set_gender(self, gender: int):
        """
        Set the gender of the individual as male (1) or female (0).
        """

        gender = lib.check_data("gender", gender, int, set_val=[0, 1])
        self._gender = gender
示例#2
0
    def set_offsprings(self, offsprings: list):
        """
        Allows to specify the offsprings of the individual.

        :param [Individual] offsprings : The offsprings of the individual.
        """

        for offspring in offsprings:
            _ = lib.check_data("offspring", offspring, Individual)
        self._offsprings = offsprings
示例#3
0
    def set_parents(self, parents: list):
        """
        Allows to specify the parents of the individual.

        :param [Individual] parents : The parents of the individual.
        """

        for parent in parents:
            _ = lib.check_data("parent", parent, Individual)
        self._parents = parents
示例#4
0
    def breed(self, mate, n=1, offspring_gender=None, offspring_id=None):
        """
        Given a mate Individual, a new offspring Individual is created.

        :param Individual mate : The partner with whom the offspring is generated.
        :param int, optional n : The number of offsprings that will be generated.
        :param [int], optional offspring_gender : The gender for the offsprings to be generated.
        :param str or [str], optional offspring_id : The ID(s) of the offspring(s).

        :return: Individual : A single Individual if n=1 or a list of Individual for n>1
        """

        # verify consistency of the parameters
        n = lib.check_data("n", n, int, min_val=1)

        if n == 1:
            if type(offspring_id) is str:
                tmp_id = offspring_id
            else:
                tmp_id = None
            offspring = Individual(ind_id=tmp_id, parents=[self, mate])

            if offspring_gender is not None:
                offspring.set_gender(offspring_gender)
            offspring.x_breed()

            # add the offspring to the list of each parent
            self._offsprings.append(offspring)
            mate._offsprings.append(offspring)
        else:
            offspring = []
            for idx in range(n):
                if offspring_id is not None and type(offspring_id) is list:
                    tmp_id = offspring_id[idx]
                else:
                    tmp_id = None

                if offspring_gender is None:
                    tmp_gender = None
                else:
                    tmp_gender = offspring_gender[idx]

                offspring.append(
                    self.breed(mate=mate,
                               offspring_gender=tmp_gender,
                               offspring_id=tmp_id))

        return offspring
示例#5
0
    def strand(self, idx: int) -> [[int]]:
        """
        Returns the selected strand for each segment of the chromosomes given a specific parent.

        :param int idx : identify the parent (0 or 1).

        :return: [[int]] : The selected strands for each segment of the chromosomes.
        """

        # evaluate consistency of the parameters
        idx = lib.check_data("parent idx", idx, int, set_val=[0, 1])

        parent = ["parent1", "parent2"]

        strand = []
        if self._strand:
            strand = self._strand[parent[idx]]

        return strand
示例#6
0
    def crossover(self, idx: int) -> [[int]]:
        """
        Returns the crossover points for a specific parent.

        :param int idx : select the parent (0 or 1).

        :return: [[int]] : The crossover points pertaining to the specified parent.
        """

        # evaluate consistency of the parameters
        idx = lib.check_data("parent idx", idx, int, set_val=[0, 1])

        parent = ["parent1", "parent2"]

        crs = []
        if self._crossover:
            crs = self._crossover[parent[idx]]

        return crs
示例#7
0
    def is_sibling(self, individual) -> bool:
        """
        Return True if the passed individual is a sibling, False otherwise.

        :param Individual individual : The individual to be verified as sibling.

        :return: bool : True if the individual is a sibling, False otherwise.
        """

        sibling = False
        if self.has_parents() and individual.has_parents(
        ):  # both individuals must have parents
            individual = lib.check_data(
                "individual", individual,
                Individual)  # check correctness of the parameter
            parent_ids = [self._parents[0].id,
                          self._parents[1].id]  # list of parent IDs

            # both parents are shared
            if individual.parents[0].id in parent_ids and individual.parents[
                    1].id in parent_ids:
                sibling = True

        return sibling
示例#8
0
    def chromosomes_reproduction(chromosomes1: [[str]],
                                 chromosomes2: [[str]],
                                 div_snp="|") -> dict:
        """
        Generate the chromosomes of an offspring given the chromosomes of the parents.

        :param [[str]] chromosomes1 : The chromosomes of the first parent.
        :param [[str]] chromosomes2 : The chromosomes of the second parent.
        :param str, optional div_snp : The separator of the strands.

        :return: A dictionary containing the chromosomes of the offspring (chromosomes) the crossover points from each
            parent (crossover["parent1"], crossover["parent2"]) and the selected segments (strand["parent1"],
            strand["parent2"]).
        """

        output = {}

        n_chr = len(chromosomes1)  # number of chromosomes
        if not n_chr == len(chromosomes2):
            msg = "Individuals have different number of chromosomes (Found {} and {}).".format(
                n_chr, len(chromosomes2))
            raise ValueError(msg)

        offspring_chromosome = [
            []
        ] * n_chr  # initialize the sequence of the chromosomes
        offspring_crossover = {
            "parent1": [[0, 0, 0]] * n_chr,
            "parent2": [[0, 0, 0]] * n_chr
        }
        offspring_strand = {
            "parent1": [[0, 0, 0]] * n_chr,
            "parent2": [[0, 0, 0]] * n_chr
        }
        for idx_chromosome in range(len(offspring_chromosome)):

            # the considered chromosome (from each parent)
            chr1 = chromosomes1[idx_chromosome]
            chr2 = chromosomes2[idx_chromosome]

            chr_length = len(chr1)
            if not (chr_length == len(chr2)):
                msg = "Individuals have different chromosome length (Found {} and {} for index {}).".format(
                    chr_length, len(chr2), idx_chromosome)
                raise ValueError(msg)

            # evaluate consistency of the length
            chr_length = lib.check_data(
                "chromosome length (idx = {})".format(idx_chromosome),
                chr_length,
                int,
                min_val=4)

            # define the homologue chromosomes for parent1
            chr1_homo1 = []
            chr1_homo2 = []
            for val in chr1:
                chr1_homo1.append(val.split(div_snp)[0])
                chr1_homo2.append(val.split(div_snp)[1])

            # define the homologue chromosomes for parent2
            chr2_homo1 = []
            chr2_homo2 = []
            for val in chr2:
                chr2_homo1.append(val.split(div_snp)[0])
                chr2_homo2.append(val.split(div_snp)[1])

            # first segment: [0, chr1_rec_pts[0])
            # second segment: [chr1_rec_pts[0], chr1_rec_pts[1])
            # third segment: [chr1_rec_pts[1], chr1_rec_pts[2])
            # third segment: [chr1_rec_pts[2], end]
            #
            # range(1, chr_length) generate random values between 1 and chr_length-1
            chr1_rec_pts = sorted(random.sample(range(1, chr_length), 3))
            chr2_rec_pts = sorted(random.sample(range(1, chr_length), 3))

            offspring_crossover["parent1"][idx_chromosome] = chr1_rec_pts
            offspring_crossover["parent2"][idx_chromosome] = chr2_rec_pts

            # split the homologue chromosomes according to recombination points
            chr1_homo1 = [
                chr1_homo1[i:j]
                for i, j in zip([0] + chr1_rec_pts, chr1_rec_pts + [None])
            ]
            chr1_homo2 = [
                chr1_homo2[i:j]
                for i, j in zip([0] + chr1_rec_pts, chr1_rec_pts + [None])
            ]
            chr2_homo1 = [
                chr2_homo1[i:j]
                for i, j in zip([0] + chr2_rec_pts, chr2_rec_pts + [None])
            ]
            chr2_homo2 = [
                chr2_homo2[i:j]
                for i, j in zip([0] + chr2_rec_pts, chr2_rec_pts + [None])
            ]

            chrs1_homos = [chr1_homo1,
                           chr1_homo2]  # merge the two strands of parent 1
            chrs2_homos = [chr2_homo1,
                           chr2_homo2]  # merge the two strands of parent 2

            # choose one homologue randomly from each segment
            chr1_segs = random.choices([0, 1], k=4)
            chr2_segs = random.choices([0, 1], k=4)

            offspring_strand["parent1"][idx_chromosome] = chr1_segs
            offspring_strand["parent2"][idx_chromosome] = chr2_segs

            # assemble the selected segments together to form gametes
            chr1_gamete = []
            chr2_gamete = []
            for i in range(4):
                chr1_gamete = chr1_gamete + chrs1_homos[chr1_segs[i]][i]
                chr2_gamete = chr2_gamete + chrs2_homos[chr2_segs[i]][i]

            # join the gametes to form the offspring chromosome
            single_chr = []
            for i in range(len(chr1_gamete)):
                offspring_gt = str(chr1_gamete[i]) + div_snp + str(
                    chr2_gamete[i])
                single_chr.append(offspring_gt)

            offspring_chromosome[idx_chromosome] = single_chr

        output["chromosomes"] = offspring_chromosome
        output["crossover"] = offspring_crossover
        output["strand"] = offspring_strand

        return output