aegis_sim.submodels.reproduction.reproduction
1from aegis_sim.dataclasses.genomes import Genomes 2from aegis_sim.submodels.reproduction.pairing import pairing 3from aegis_sim.submodels.reproduction.recombination import recombination, recombination_via_pairs 4 5 6class Reproducer: 7 """ 8 GUI 9 Individuals are fertile starting with [[MATURATION_AGE]] (can be 0) until [[REPRODUCTION_ENDPOINT]] (if 0, no REPRODUCTION_ENDPOINT occurs). 10 Reproduction can be sexual (with diploid genomes) or asexual (with diploid or haploid genomes). 11 When reproduction is sexual, recombination occurs in gametes at a rate of [[RECOMBINATION_RATE]] 12 and gametes will inherit mutations at an age-independent rate 13 which can be parameterized (genetics-independent) or set to evolve (genetics-dependent). 14 Mutations cause the offspring genome bit states to flip from 0-to-1 or 1-to-0. 15 The ratio of 0-to-1 and 1-to-0 can be modified using the [[MUTATION_RATIO]]. 16 17 If the population is oviparous, [[INCUBATION_PERIOD]] should be set to -1, 1 or greater. 18 When it is set to -1, all laid eggs hatch only once all living individuals die. 19 When it is set to 0 or greater, eggs hatch after that specified time. 20 Thus, when 0, individuals do not go through an egg stage during their life cycle. 21 """ 22 23 # TODO INCUBATION_PERIOD set to -1 or 1 or greater is stupid 24 # TODO INCUBATION_PERIOD is not really a part of this submodel, but it is in the documentation. it should be though. 25 26 # TODO probably better to split mutation logic into another domain and cluster together with genetic architecture stuff 27 28 def __init__(self, RECOMBINATION_RATE, REPRODUCTION_MODE, mutator): 29 self.RECOMBINATION_RATE = RECOMBINATION_RATE 30 self.REPRODUCTION_MODE = REPRODUCTION_MODE 31 self.mutator = mutator 32 33 def generate_offspring_genomes(self, genomes, muta_prob, ages, parental_sexes, 34 ancestry=None, parent_positions=None, 35 max_search_radius=0): 36 """Generate offspring genomes from parental input. 37 38 Asexual: each parent yields one offspring (same chromatids as parent). 39 Sexual: pairing pairs males and females. When `parent_positions` is given 40 (LATTICE_MODE), pairing is lattice-aware — see matingmanager. When None, 41 classical well-mixed pairing. 42 43 Returns `(genomes, ancestry, mother_slots)`. `mother_slots` is the slot 44 indices of the paired mothers (into the parental_genomes array). For 45 sexual, callers use this to look up mother positions for offspring 46 placement on the lattice. For asexual, mother_slots is None — the 47 caller already knows the parent->offspring mapping via `who`. 48 """ 49 mother_slots = None 50 if self.REPRODUCTION_MODE == "sexual": 51 if ancestry is not None: 52 genomes, ancestry = recombination_via_pairs(genomes, self.RECOMBINATION_RATE, ancestry=ancestry) 53 genomes, ages, muta_prob, ancestry, mother_slots = pairing( 54 Genomes(genomes), parental_sexes, ages, muta_prob, 55 ancestry=ancestry, 56 parent_positions=parent_positions, 57 max_search_radius=max_search_radius, 58 ) 59 else: 60 genomes = recombination_via_pairs(genomes, self.RECOMBINATION_RATE) 61 genomes, ages, muta_prob, mother_slots = pairing( 62 Genomes(genomes), parental_sexes, ages, muta_prob, 63 parent_positions=parent_positions, 64 max_search_radius=max_search_radius, 65 ) 66 67 # Mutation flips genome bits — ancestry labels are not mutated 68 genomes = self.mutator._mutate(genomes, muta_prob, ages) 69 genomes = Genomes(genomes) 70 return genomes, ancestry, mother_slots
7class Reproducer: 8 """ 9 GUI 10 Individuals are fertile starting with [[MATURATION_AGE]] (can be 0) until [[REPRODUCTION_ENDPOINT]] (if 0, no REPRODUCTION_ENDPOINT occurs). 11 Reproduction can be sexual (with diploid genomes) or asexual (with diploid or haploid genomes). 12 When reproduction is sexual, recombination occurs in gametes at a rate of [[RECOMBINATION_RATE]] 13 and gametes will inherit mutations at an age-independent rate 14 which can be parameterized (genetics-independent) or set to evolve (genetics-dependent). 15 Mutations cause the offspring genome bit states to flip from 0-to-1 or 1-to-0. 16 The ratio of 0-to-1 and 1-to-0 can be modified using the [[MUTATION_RATIO]]. 17 18 If the population is oviparous, [[INCUBATION_PERIOD]] should be set to -1, 1 or greater. 19 When it is set to -1, all laid eggs hatch only once all living individuals die. 20 When it is set to 0 or greater, eggs hatch after that specified time. 21 Thus, when 0, individuals do not go through an egg stage during their life cycle. 22 """ 23 24 # TODO INCUBATION_PERIOD set to -1 or 1 or greater is stupid 25 # TODO INCUBATION_PERIOD is not really a part of this submodel, but it is in the documentation. it should be though. 26 27 # TODO probably better to split mutation logic into another domain and cluster together with genetic architecture stuff 28 29 def __init__(self, RECOMBINATION_RATE, REPRODUCTION_MODE, mutator): 30 self.RECOMBINATION_RATE = RECOMBINATION_RATE 31 self.REPRODUCTION_MODE = REPRODUCTION_MODE 32 self.mutator = mutator 33 34 def generate_offspring_genomes(self, genomes, muta_prob, ages, parental_sexes, 35 ancestry=None, parent_positions=None, 36 max_search_radius=0): 37 """Generate offspring genomes from parental input. 38 39 Asexual: each parent yields one offspring (same chromatids as parent). 40 Sexual: pairing pairs males and females. When `parent_positions` is given 41 (LATTICE_MODE), pairing is lattice-aware — see matingmanager. When None, 42 classical well-mixed pairing. 43 44 Returns `(genomes, ancestry, mother_slots)`. `mother_slots` is the slot 45 indices of the paired mothers (into the parental_genomes array). For 46 sexual, callers use this to look up mother positions for offspring 47 placement on the lattice. For asexual, mother_slots is None — the 48 caller already knows the parent->offspring mapping via `who`. 49 """ 50 mother_slots = None 51 if self.REPRODUCTION_MODE == "sexual": 52 if ancestry is not None: 53 genomes, ancestry = recombination_via_pairs(genomes, self.RECOMBINATION_RATE, ancestry=ancestry) 54 genomes, ages, muta_prob, ancestry, mother_slots = pairing( 55 Genomes(genomes), parental_sexes, ages, muta_prob, 56 ancestry=ancestry, 57 parent_positions=parent_positions, 58 max_search_radius=max_search_radius, 59 ) 60 else: 61 genomes = recombination_via_pairs(genomes, self.RECOMBINATION_RATE) 62 genomes, ages, muta_prob, mother_slots = pairing( 63 Genomes(genomes), parental_sexes, ages, muta_prob, 64 parent_positions=parent_positions, 65 max_search_radius=max_search_radius, 66 ) 67 68 # Mutation flips genome bits — ancestry labels are not mutated 69 genomes = self.mutator._mutate(genomes, muta_prob, ages) 70 genomes = Genomes(genomes) 71 return genomes, ancestry, mother_slots
GUI Individuals are fertile starting with [[MATURATION_AGE]] (can be 0) until [[REPRODUCTION_ENDPOINT]] (if 0, no REPRODUCTION_ENDPOINT occurs). Reproduction can be sexual (with diploid genomes) or asexual (with diploid or haploid genomes). When reproduction is sexual, recombination occurs in gametes at a rate of [[RECOMBINATION_RATE]] and gametes will inherit mutations at an age-independent rate which can be parameterized (genetics-independent) or set to evolve (genetics-dependent). Mutations cause the offspring genome bit states to flip from 0-to-1 or 1-to-0. The ratio of 0-to-1 and 1-to-0 can be modified using the [[MUTATION_RATIO]].
If the population is oviparous, [[INCUBATION_PERIOD]] should be set to -1, 1 or greater. When it is set to -1, all laid eggs hatch only once all living individuals die. When it is set to 0 or greater, eggs hatch after that specified time. Thus, when 0, individuals do not go through an egg stage during their life cycle.
34 def generate_offspring_genomes(self, genomes, muta_prob, ages, parental_sexes, 35 ancestry=None, parent_positions=None, 36 max_search_radius=0): 37 """Generate offspring genomes from parental input. 38 39 Asexual: each parent yields one offspring (same chromatids as parent). 40 Sexual: pairing pairs males and females. When `parent_positions` is given 41 (LATTICE_MODE), pairing is lattice-aware — see matingmanager. When None, 42 classical well-mixed pairing. 43 44 Returns `(genomes, ancestry, mother_slots)`. `mother_slots` is the slot 45 indices of the paired mothers (into the parental_genomes array). For 46 sexual, callers use this to look up mother positions for offspring 47 placement on the lattice. For asexual, mother_slots is None — the 48 caller already knows the parent->offspring mapping via `who`. 49 """ 50 mother_slots = None 51 if self.REPRODUCTION_MODE == "sexual": 52 if ancestry is not None: 53 genomes, ancestry = recombination_via_pairs(genomes, self.RECOMBINATION_RATE, ancestry=ancestry) 54 genomes, ages, muta_prob, ancestry, mother_slots = pairing( 55 Genomes(genomes), parental_sexes, ages, muta_prob, 56 ancestry=ancestry, 57 parent_positions=parent_positions, 58 max_search_radius=max_search_radius, 59 ) 60 else: 61 genomes = recombination_via_pairs(genomes, self.RECOMBINATION_RATE) 62 genomes, ages, muta_prob, mother_slots = pairing( 63 Genomes(genomes), parental_sexes, ages, muta_prob, 64 parent_positions=parent_positions, 65 max_search_radius=max_search_radius, 66 ) 67 68 # Mutation flips genome bits — ancestry labels are not mutated 69 genomes = self.mutator._mutate(genomes, muta_prob, ages) 70 genomes = Genomes(genomes) 71 return genomes, ancestry, mother_slots
Generate offspring genomes from parental input.
Asexual: each parent yields one offspring (same chromatids as parent).
Sexual: pairing pairs males and females. When parent_positions is given
(LATTICE_MODE), pairing is lattice-aware — see matingmanager. When None,
classical well-mixed pairing.
Returns (genomes, ancestry, mother_slots). mother_slots is the slot
indices of the paired mothers (into the parental_genomes array). For
sexual, callers use this to look up mother positions for offspring
placement on the lattice. For asexual, mother_slots is None — the
caller already knows the parent->offspring mapping via who.