Skip to content

Genomes

Provides Genome classes for the ATHENA project providing for alternative genome types with corresponding mapping and initialization approaches.

Genome

A GE genome.

Source code in src/athenage/grape/genomes.py
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
class Genome:
    """
    A GE genome.
    """
    def __init__(self, n_rules:int, codon_size:int):
        self.codon_size = codon_size
        self.init_codons(n_rules)

    def init_codons(self, n_rules:int) -> None:
        self.codons = []
        self.rule_match =[]
        self.next_read=0

    def add_codon(self,val:int, rule_used:int) -> None:
        self.codons.append(val)

    def finalize(self) -> None:
        pass

    def size(self) -> int:
        return len(self.codons)

    def add_tail(self, n_codons:int) -> None:
        for i in range(n_codons):
            self.codons.append(random.randrange(0,self.codon_size))

    def random_fill(self,genome_length:int) -> None:
        """ Fill genome with random codons """
        for i in range(genome_length):
            self.codons.append(random.randrange(0, self.codon_size))

    def consumed(self, rule_used:int) -> bool:
        "Returns True if all codons have been used"
        return True if self.next_read >= len(self.codons) else False

    def reset_map_index(self) -> None:
        """Reset the genome so that get_next_codon starts with first codon"""
        self.next_read = 0
        self.rule_match = []

    def get_next_codon(self, rule_used:int) -> int:
        """ Get next codon from genome for mapping. Store rule used requested for the codon.

        Args:
            rule_used: index of rule used in grammar

        Returns: 
            codon: codon value 
        """
        codon = self.codons[self.next_read]
        self.rule_match.append(rule_used)
        self.next_read += 1

        return codon

    def rule_used(self, codon_idx: int) -> int:
        """ Get rule used for the codon during mapping

        Args:
            codon_idx: index of codon to check 

        Returns: 
            int of the rule used in grammar
        """        
        return self.rule_match[codon_idx]

    def used_codons(self) -> int:
        return self.next_read

    def total_codons(self)-> int:
        return len(self.codons)

    def set_codon(self, codon_idx:int, value:int, invalid:bool) -> None:
        self.codons[codon_idx]=value

    def effective_cross_loc(self) -> list:
        """Return a list that contains the position for crossover"""
        return [random.randrange(1,self.next_read)]

    def all_cross_loc(self) -> list:
        """Return location for a cross over entire genome"""
        return [random.randrange(1,len(self.codons))]

    def crossover_onepoint(self, genome2:"Genome", pos1:list, pos2:list) -> tuple["Genome","Genome"]:
        """ cross over genomes and return new ones 
        Args:
            genome2:second geome to cross with this one
            pos1: codon position for cross on in the genome
            pos2: codon position for cross on second genome

        Returns:
            new_genome1: Genome
            new_genome2: Genome   
        """

        new_genome1 = copy.deepcopy(self)
        new_genome2 = copy.deepcopy(genome2)

        new_genome1.codons = self.codons[0:pos1[0]] + genome2.codons[pos2[0]:]
        new_genome2.codons = genome2.codons[0:pos2[0]] + self.codons[pos1[0]:]

        return new_genome1, new_genome2

    def crossover_twopoint(self, genome2:"Genome", pos1:list, pos2:list) -> tuple["Genome","Genome"]:
        """ cross over genomes and return new ones 
        Args:
            genome2:second geome to cross with this one
            pos1: codon positions designating start/end of slice for this genome
            pos2: codon positions designating start/end of slice for second genome

        Returns:
            new_genome1: Genome
            new_genome2: Genome   
        """

        new_genome1 = copy.deepcopy(self)
        new_genome2 = copy.deepcopy(genome2)

        new_genome1.codons = self.codons[0:pos1[0]] + genome2.codons[pos2[0]:pos2[1]+1] + self.codons[pos1[1]+1:]
        new_genome2.codons = genome2.codons[0:pos2[0]] + self.codons[pos1[0]:pos1[1]+1] + genome2.codons[pos2[1]+1:]

        return new_genome1, new_genome2

all_cross_loc()

Return location for a cross over entire genome

Source code in src/athenage/grape/genomes.py
83
84
85
def all_cross_loc(self) -> list:
    """Return location for a cross over entire genome"""
    return [random.randrange(1,len(self.codons))]

consumed(rule_used)

Returns True if all codons have been used

Source code in src/athenage/grape/genomes.py
35
36
37
def consumed(self, rule_used:int) -> bool:
    "Returns True if all codons have been used"
    return True if self.next_read >= len(self.codons) else False

crossover_onepoint(genome2, pos1, pos2)

cross over genomes and return new ones Args: genome2:second geome to cross with this one pos1: codon position for cross on in the genome pos2: codon position for cross on second genome

Returns:

Name Type Description
new_genome1 Genome

Genome

new_genome2 Genome

Genome

Source code in src/athenage/grape/genomes.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def crossover_onepoint(self, genome2:"Genome", pos1:list, pos2:list) -> tuple["Genome","Genome"]:
    """ cross over genomes and return new ones 
    Args:
        genome2:second geome to cross with this one
        pos1: codon position for cross on in the genome
        pos2: codon position for cross on second genome

    Returns:
        new_genome1: Genome
        new_genome2: Genome   
    """

    new_genome1 = copy.deepcopy(self)
    new_genome2 = copy.deepcopy(genome2)

    new_genome1.codons = self.codons[0:pos1[0]] + genome2.codons[pos2[0]:]
    new_genome2.codons = genome2.codons[0:pos2[0]] + self.codons[pos1[0]:]

    return new_genome1, new_genome2

crossover_twopoint(genome2, pos1, pos2)

cross over genomes and return new ones Args: genome2:second geome to cross with this one pos1: codon positions designating start/end of slice for this genome pos2: codon positions designating start/end of slice for second genome

Returns:

Name Type Description
new_genome1 Genome

Genome

new_genome2 Genome

Genome

Source code in src/athenage/grape/genomes.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
def crossover_twopoint(self, genome2:"Genome", pos1:list, pos2:list) -> tuple["Genome","Genome"]:
    """ cross over genomes and return new ones 
    Args:
        genome2:second geome to cross with this one
        pos1: codon positions designating start/end of slice for this genome
        pos2: codon positions designating start/end of slice for second genome

    Returns:
        new_genome1: Genome
        new_genome2: Genome   
    """

    new_genome1 = copy.deepcopy(self)
    new_genome2 = copy.deepcopy(genome2)

    new_genome1.codons = self.codons[0:pos1[0]] + genome2.codons[pos2[0]:pos2[1]+1] + self.codons[pos1[1]+1:]
    new_genome2.codons = genome2.codons[0:pos2[0]] + self.codons[pos1[0]:pos1[1]+1] + genome2.codons[pos2[1]+1:]

    return new_genome1, new_genome2

effective_cross_loc()

Return a list that contains the position for crossover

Source code in src/athenage/grape/genomes.py
79
80
81
def effective_cross_loc(self) -> list:
    """Return a list that contains the position for crossover"""
    return [random.randrange(1,self.next_read)]

get_next_codon(rule_used)

Get next codon from genome for mapping. Store rule used requested for the codon.

Parameters:

Name Type Description Default
rule_used int

index of rule used in grammar

required

Returns:

Name Type Description
codon int

codon value

Source code in src/athenage/grape/genomes.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def get_next_codon(self, rule_used:int) -> int:
    """ Get next codon from genome for mapping. Store rule used requested for the codon.

    Args:
        rule_used: index of rule used in grammar

    Returns: 
        codon: codon value 
    """
    codon = self.codons[self.next_read]
    self.rule_match.append(rule_used)
    self.next_read += 1

    return codon

random_fill(genome_length)

Fill genome with random codons

Source code in src/athenage/grape/genomes.py
30
31
32
33
def random_fill(self,genome_length:int) -> None:
    """ Fill genome with random codons """
    for i in range(genome_length):
        self.codons.append(random.randrange(0, self.codon_size))

reset_map_index()

Reset the genome so that get_next_codon starts with first codon

Source code in src/athenage/grape/genomes.py
39
40
41
42
def reset_map_index(self) -> None:
    """Reset the genome so that get_next_codon starts with first codon"""
    self.next_read = 0
    self.rule_match = []

rule_used(codon_idx)

Get rule used for the codon during mapping

Parameters:

Name Type Description Default
codon_idx int

index of codon to check

required

Returns:

Type Description
int

int of the rule used in grammar

Source code in src/athenage/grape/genomes.py
59
60
61
62
63
64
65
66
67
68
def rule_used(self, codon_idx: int) -> int:
    """ Get rule used for the codon during mapping

    Args:
        codon_idx: index of codon to check 

    Returns: 
        int of the rule used in grammar
    """        
    return self.rule_match[codon_idx]

LeapGenome

Bases: Genome

A GE genome.

Source code in src/athenage/grape/genomes.py
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
class LeapGenome(Genome):
    """
    A GE genome.
    """
    def __init__(self, n_rules:int, codon_size:int):
        super().__init__(n_rules, codon_size)

    def init_codons(self, n_rules:int) -> None:
        super().init_codons(n_rules)
        self.frame_size = n_rules
        self.codons.extend(self.new_frame())
        self.last_frame = 0

    def new_frame(self)  -> list:
        """ Return new frame initialized to be empty """
        return [-1 for i in range(self.frame_size)]

    def add_codon(self,val:int, rule_used:int)  -> None:
        codon_idx = self.last_frame * self.frame_size + rule_used
        if self.codons[codon_idx] != -1:
            # fill unused codons with random values
            self.codons[-self.frame_size:] = [random.randrange(0,self.codon_size) if x == -1 else x for x in self.codons[-self.frame_size:]]
            self.codons.extend(self.new_frame())
            self.last_frame += 1
            codon_idx += self.frame_size

        self.codons[codon_idx] = val

    def finalize(self)  -> None:
        """Convert any unset codons to hold random values"""
        self.codons[-self.frame_size:] = [random.randrange(0,self.codon_size) if x == -1 else x for x in self.codons[-self.frame_size:]]

    def add_tail(self, n_codons:int)  -> None:
        """Convert n_codons to complete frames"""
        n_codons = n_codons + self.frame_size - (n_codons % self.frame_size)
        for i in range(n_codons):
            self.codons.append(random.randrange(0,self.codon_size))

    def random_fill(self,genome_length:int) -> None:
        """ Fill genome with frames containing random codons"""
        genome_length = genome_length + (genome_length % self.frame_size)
        for i in range(genome_length):
            self.codons.append(random.randrange(0, self.codon_size))

    def consumed(self,rule_used:int) -> bool:
        "Returns True if all codons have been used"
        if ((self.last_frame * self.frame_size + self.frame_size > len(self.codons)) or
        (self.consumed_codons[rule_used] and ((self.last_frame+1) * self.frame_size + self.frame_size > len(self.codons)))):
            return True
        else:
            return False

    def reset_map_index(self) -> None:
        """Reset the genome so that get_next_codon starts with first frame"""
        self.last_frame = 0
        self.consumed_codons = [False for i in range(self.frame_size)]

    def get_next_codon(self, rule_used:int) -> int:
        """ Get next codon from genome for mapping

        Args:
            rule_used: index of rule used in grammar

        Returns: 
            codon: codon value or False if no next codon
        """
        if(self.consumed_codons[rule_used]):
            self.last_frame += 1
            self.consumed_codons = [False for i in range(self.frame_size)]

        self.consumed_codons[rule_used] = True
        codon_idx = self.last_frame * self.frame_size + rule_used
        return self.codons[codon_idx]

    def used_codons(self) -> int:
        return self.last_frame * self.frame_size

    def effective_cross_loc(self) -> list:
        """Return a list that contains the frame for crossover"""
        return [random.randrange(1,self.last_frame)]

    def all_cross_loc(self) -> list:
        """Return location for a cross over entire genome"""
        return [random.randrange(1,len(self.codons)//self.frame_size-1)]

    def crossover_onepoint(self, genome2:"LeapGenome", pos1:list, pos2:list) -> tuple["LeapGenome","LeapGenome"]:
        """ cross over genomes and return new ones 
        Args:
            genome2: LeapGenome to cross with
            pos1: contains frame to cross for this genome
            pso2: contains frame to cross at second genome

        Returns;
            new_genome1: LeapGenome
            new_genome2: LeapGenome    
        """
        new_genome1 = copy.deepcopy(self)
        new_genome2 = copy.deepcopy(genome2)

        pt1 = pos1[0] * self.frame_size
        pt2 = pos2[0] * self.frame_size

        new_genome1.codons = self.codons[0:pt1] + genome2.codons[pt2:]
        new_genome2.codons = genome2.codons[0:pt2] + self.codons[pt1:]

        return new_genome1, new_genome2

add_tail(n_codons)

Convert n_codons to complete frames

Source code in src/athenage/grape/genomes.py
159
160
161
162
163
def add_tail(self, n_codons:int)  -> None:
    """Convert n_codons to complete frames"""
    n_codons = n_codons + self.frame_size - (n_codons % self.frame_size)
    for i in range(n_codons):
        self.codons.append(random.randrange(0,self.codon_size))

all_cross_loc()

Return location for a cross over entire genome

Source code in src/athenage/grape/genomes.py
208
209
210
def all_cross_loc(self) -> list:
    """Return location for a cross over entire genome"""
    return [random.randrange(1,len(self.codons)//self.frame_size-1)]

consumed(rule_used)

Returns True if all codons have been used

Source code in src/athenage/grape/genomes.py
171
172
173
174
175
176
177
def consumed(self,rule_used:int) -> bool:
    "Returns True if all codons have been used"
    if ((self.last_frame * self.frame_size + self.frame_size > len(self.codons)) or
    (self.consumed_codons[rule_used] and ((self.last_frame+1) * self.frame_size + self.frame_size > len(self.codons)))):
        return True
    else:
        return False

crossover_onepoint(genome2, pos1, pos2)

cross over genomes and return new ones Args: genome2: LeapGenome to cross with pos1: contains frame to cross for this genome pso2: contains frame to cross at second genome

Returns; new_genome1: LeapGenome new_genome2: LeapGenome

Source code in src/athenage/grape/genomes.py
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
def crossover_onepoint(self, genome2:"LeapGenome", pos1:list, pos2:list) -> tuple["LeapGenome","LeapGenome"]:
    """ cross over genomes and return new ones 
    Args:
        genome2: LeapGenome to cross with
        pos1: contains frame to cross for this genome
        pso2: contains frame to cross at second genome

    Returns;
        new_genome1: LeapGenome
        new_genome2: LeapGenome    
    """
    new_genome1 = copy.deepcopy(self)
    new_genome2 = copy.deepcopy(genome2)

    pt1 = pos1[0] * self.frame_size
    pt2 = pos2[0] * self.frame_size

    new_genome1.codons = self.codons[0:pt1] + genome2.codons[pt2:]
    new_genome2.codons = genome2.codons[0:pt2] + self.codons[pt1:]

    return new_genome1, new_genome2

effective_cross_loc()

Return a list that contains the frame for crossover

Source code in src/athenage/grape/genomes.py
204
205
206
def effective_cross_loc(self) -> list:
    """Return a list that contains the frame for crossover"""
    return [random.randrange(1,self.last_frame)]

finalize()

Convert any unset codons to hold random values

Source code in src/athenage/grape/genomes.py
155
156
157
def finalize(self)  -> None:
    """Convert any unset codons to hold random values"""
    self.codons[-self.frame_size:] = [random.randrange(0,self.codon_size) if x == -1 else x for x in self.codons[-self.frame_size:]]

get_next_codon(rule_used)

Get next codon from genome for mapping

Parameters:

Name Type Description Default
rule_used int

index of rule used in grammar

required

Returns:

Name Type Description
codon int

codon value or False if no next codon

Source code in src/athenage/grape/genomes.py
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
def get_next_codon(self, rule_used:int) -> int:
    """ Get next codon from genome for mapping

    Args:
        rule_used: index of rule used in grammar

    Returns: 
        codon: codon value or False if no next codon
    """
    if(self.consumed_codons[rule_used]):
        self.last_frame += 1
        self.consumed_codons = [False for i in range(self.frame_size)]

    self.consumed_codons[rule_used] = True
    codon_idx = self.last_frame * self.frame_size + rule_used
    return self.codons[codon_idx]

new_frame()

Return new frame initialized to be empty

Source code in src/athenage/grape/genomes.py
140
141
142
def new_frame(self)  -> list:
    """ Return new frame initialized to be empty """
    return [-1 for i in range(self.frame_size)]

random_fill(genome_length)

Fill genome with frames containing random codons

Source code in src/athenage/grape/genomes.py
165
166
167
168
169
def random_fill(self,genome_length:int) -> None:
    """ Fill genome with frames containing random codons"""
    genome_length = genome_length + (genome_length % self.frame_size)
    for i in range(genome_length):
        self.codons.append(random.randrange(0, self.codon_size))

reset_map_index()

Reset the genome so that get_next_codon starts with first frame

Source code in src/athenage/grape/genomes.py
179
180
181
182
def reset_map_index(self) -> None:
    """Reset the genome so that get_next_codon starts with first frame"""
    self.last_frame = 0
    self.consumed_codons = [False for i in range(self.frame_size)]

MCGEGenome

Bases: Genome

A GE genome.

Source code in src/athenage/grape/genomes.py
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
class MCGEGenome(Genome):
    """
    A GE genome.
    """
    def __init__(self, n_rules, codon_size):
        super().__init__(n_rules, codon_size)

    def init_codons(self, n_rules) -> None:
        self.codons = [ [] for i in range(n_rules)]
        self.consumed_codons = [ 0 for i in range(n_rules)]

    def add_codon(self,val:int, rule_used:int) -> None:
        self.codons[rule_used].append(val)


    def size(self) -> int:
        """Returns average size of a chromosome"""
        total = 0
        for chr in self.codons:
            total += len(chr)
        return total // len(self.codons) + 1

    def add_tail(self, n_codons:int) -> None:
        """ Add tail to each chrom"""
        for chr in self.codons:
            for i in range(n_codons):
                chr.append(random.randrange(0,self.codon_size)) 

    def random_fill(self,genome_length:int) -> None:
        """ Fill genome with chromosomes that equal genome length"""
        chrom_length = genome_length // len(self.codons) + 1
        for i in range(len(self.codons)):
            for j in range(chrom_length):
                self.codons[i].append(random.randrange(0, self.codon_size))

    def consumed(self,rule_used:int) -> bool:
        "Returns True if all codons have been used"
        return True if self.consumed_codons[rule_used] >= len(self.codons[rule_used]) else False

    def reset_map_index(self) -> None:
        """Reset the genome so that get_next_codon starts with first frame"""
        self.consumed_codons = [ 0 for i in range(len(self.codons))]

    def get_next_codon(self, rule_used:int) -> int:
        """ Get next codon from genome for mapping

        Args:
            rule_used: index of rule used in grammar

        Returns: 
            codon: codon value or False if no next codon
        """
        codon = self.codons[rule_used][self.consumed_codons[rule_used]]
        self.consumed_codons[rule_used] += 1
        return codon

    def used_codons(self) -> int:
        return sum(self.consumed_codons)

    def total_codons(self)-> int:
        total = 0
        for chr in self.codons:
            total += len(chr)
        return total

    def set_codon(self, codon_idx:int, value:int, invalid:bool) -> None:
        """ Sets specified codon. Calculates chromosome and position for codon to match index passed

        Args:
            codon_idx: overall codon position to alter
            value: new codon value
            invalid: when True use all codons to calculate position

        Returns:
            None
        """
        if invalid:
            for chrnum in range(len(self.codons)):
                if codon_idx >= len(self.codons[chrnum]):
                    codon_idx -= (len(self.codons[chrnum])+1)
                else:
                    self.codons[chrnum][codon_idx] = value
        else:
            for chrnum in range(len(self.consumed_codons)):
                if codon_idx >= self.consumed_codons[chrnum]:
                    codon_idx -= (self.consumed_codons[chrnum]+1)
                else:
                    self.codons[chrnum][codon_idx] = value
                    break

    def effective_cross_loc(self) -> list:
        """Return a list that contains the frame for crossover"""
        positions = []
        for chr_idx in range(len(self.codons)):
            positions.append(random.randrange(0,self.consumed_codons[chr_idx]))
        return positions

    def all_cross_loc(self) -> list:
        """Return location for a cross over entire genome"""
        positions = []
        for chr_idx in range(self.codons):
            positions.append(random.randrange(1,len(self.codons[chr_idx])))
        return positions

    def crossover_onepoint(self, genome2:"MCGEGenome", pos1:list, pos2:list) -> tuple["MCGEGenome","MCGEGenome"]:
        """ cross over genomes and return new ones 
        Args:
            genome2: MCGEGenome to cross with
            pos1: contains [chrom,position] to cross for this genome
            pso2: contains [chrom,position]  to cross at second genome

        Returns;
            new_genome1: MCGEGenome created after crossover
            new_genome2: MCGEGenome created after crossover
        """
        new_genome1 = copy.deepcopy(self)
        new_genome2 = copy.deepcopy(genome2)

        #select chromosome for crossover
        chr_idx = random.randrange(0,len(self.codons))

        new_genome1.codons[chr_idx] = self.codons[chr_idx][0:pos1[chr_idx]] + genome2.codons[chr_idx][pos2[chr_idx]:]
        new_genome2.codons[chr_idx]  = genome2.codons[chr_idx][0:pos2[chr_idx]] + self.codons[chr_idx][pos1[chr_idx]:]
        return new_genome1, new_genome2

add_tail(n_codons)

Add tail to each chrom

Source code in src/athenage/grape/genomes.py
257
258
259
260
261
def add_tail(self, n_codons:int) -> None:
    """ Add tail to each chrom"""
    for chr in self.codons:
        for i in range(n_codons):
            chr.append(random.randrange(0,self.codon_size)) 

all_cross_loc()

Return location for a cross over entire genome

Source code in src/athenage/grape/genomes.py
332
333
334
335
336
337
def all_cross_loc(self) -> list:
    """Return location for a cross over entire genome"""
    positions = []
    for chr_idx in range(self.codons):
        positions.append(random.randrange(1,len(self.codons[chr_idx])))
    return positions

consumed(rule_used)

Returns True if all codons have been used

Source code in src/athenage/grape/genomes.py
270
271
272
def consumed(self,rule_used:int) -> bool:
    "Returns True if all codons have been used"
    return True if self.consumed_codons[rule_used] >= len(self.codons[rule_used]) else False

crossover_onepoint(genome2, pos1, pos2)

cross over genomes and return new ones Args: genome2: MCGEGenome to cross with pos1: contains [chrom,position] to cross for this genome pso2: contains [chrom,position] to cross at second genome

Returns; new_genome1: MCGEGenome created after crossover new_genome2: MCGEGenome created after crossover

Source code in src/athenage/grape/genomes.py
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
def crossover_onepoint(self, genome2:"MCGEGenome", pos1:list, pos2:list) -> tuple["MCGEGenome","MCGEGenome"]:
    """ cross over genomes and return new ones 
    Args:
        genome2: MCGEGenome to cross with
        pos1: contains [chrom,position] to cross for this genome
        pso2: contains [chrom,position]  to cross at second genome

    Returns;
        new_genome1: MCGEGenome created after crossover
        new_genome2: MCGEGenome created after crossover
    """
    new_genome1 = copy.deepcopy(self)
    new_genome2 = copy.deepcopy(genome2)

    #select chromosome for crossover
    chr_idx = random.randrange(0,len(self.codons))

    new_genome1.codons[chr_idx] = self.codons[chr_idx][0:pos1[chr_idx]] + genome2.codons[chr_idx][pos2[chr_idx]:]
    new_genome2.codons[chr_idx]  = genome2.codons[chr_idx][0:pos2[chr_idx]] + self.codons[chr_idx][pos1[chr_idx]:]
    return new_genome1, new_genome2

effective_cross_loc()

Return a list that contains the frame for crossover

Source code in src/athenage/grape/genomes.py
325
326
327
328
329
330
def effective_cross_loc(self) -> list:
    """Return a list that contains the frame for crossover"""
    positions = []
    for chr_idx in range(len(self.codons)):
        positions.append(random.randrange(0,self.consumed_codons[chr_idx]))
    return positions

get_next_codon(rule_used)

Get next codon from genome for mapping

Parameters:

Name Type Description Default
rule_used int

index of rule used in grammar

required

Returns:

Name Type Description
codon int

codon value or False if no next codon

Source code in src/athenage/grape/genomes.py
278
279
280
281
282
283
284
285
286
287
288
289
def get_next_codon(self, rule_used:int) -> int:
    """ Get next codon from genome for mapping

    Args:
        rule_used: index of rule used in grammar

    Returns: 
        codon: codon value or False if no next codon
    """
    codon = self.codons[rule_used][self.consumed_codons[rule_used]]
    self.consumed_codons[rule_used] += 1
    return codon

random_fill(genome_length)

Fill genome with chromosomes that equal genome length

Source code in src/athenage/grape/genomes.py
263
264
265
266
267
268
def random_fill(self,genome_length:int) -> None:
    """ Fill genome with chromosomes that equal genome length"""
    chrom_length = genome_length // len(self.codons) + 1
    for i in range(len(self.codons)):
        for j in range(chrom_length):
            self.codons[i].append(random.randrange(0, self.codon_size))

reset_map_index()

Reset the genome so that get_next_codon starts with first frame

Source code in src/athenage/grape/genomes.py
274
275
276
def reset_map_index(self) -> None:
    """Reset the genome so that get_next_codon starts with first frame"""
    self.consumed_codons = [ 0 for i in range(len(self.codons))]

set_codon(codon_idx, value, invalid)

Sets specified codon. Calculates chromosome and position for codon to match index passed

Parameters:

Name Type Description Default
codon_idx int

overall codon position to alter

required
value int

new codon value

required
invalid bool

when True use all codons to calculate position

required

Returns:

Type Description
None

None

Source code in src/athenage/grape/genomes.py
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
def set_codon(self, codon_idx:int, value:int, invalid:bool) -> None:
    """ Sets specified codon. Calculates chromosome and position for codon to match index passed

    Args:
        codon_idx: overall codon position to alter
        value: new codon value
        invalid: when True use all codons to calculate position

    Returns:
        None
    """
    if invalid:
        for chrnum in range(len(self.codons)):
            if codon_idx >= len(self.codons[chrnum]):
                codon_idx -= (len(self.codons[chrnum])+1)
            else:
                self.codons[chrnum][codon_idx] = value
    else:
        for chrnum in range(len(self.consumed_codons)):
            if codon_idx >= self.consumed_codons[chrnum]:
                codon_idx -= (self.consumed_codons[chrnum]+1)
            else:
                self.codons[chrnum][codon_idx] = value
                break

size()

Returns average size of a chromosome

Source code in src/athenage/grape/genomes.py
250
251
252
253
254
255
def size(self) -> int:
    """Returns average size of a chromosome"""
    total = 0
    for chr in self.codons:
        total += len(chr)
    return total // len(self.codons) + 1