Package Bio :: Package GA :: Module Organism
[hide private]
[frames] | no frames]

Source Code for Module Bio.GA.Organism

  1  # This code is part of the Biopython distribution and governed by its 
  2  # license.  Please see the LICENSE file that should have been included 
  3  # as part of this package. 
  4  # 
  5   
  6  """Deal with an Organism in a Genetic Algorithm population.""" 
  7  # standard modules 
  8  import sys  # for Python 3 hack 
  9  import random 
 10  import array 
 11   
 12  # Sequence objects from Biopython 
 13  from Bio.Seq import MutableSeq 
 14   
 15   
16 -def function_population(new_genome, num_organisms, fitness_calculator):
17 """Generate a population given a function to create genomes. 18 19 Arguments: 20 - new_genome - A function or callable object that will return 21 a genome that can be used for a new organism. This new genome 22 should be a MutableSeq object with a specified alphabet. 23 - num_organisms - The number of individuals we want in the population. 24 - fitness_calculator -- A function that will calculate the fitness 25 of the organism when given the organisms genome. 26 27 """ 28 all_orgs = [] 29 30 for org_num in range(num_organisms): 31 cur_genome = new_genome() 32 all_orgs.append(Organism(cur_genome, fitness_calculator)) 33 34 return all_orgs
35 36
37 -def random_population(genome_alphabet, genome_size, num_organisms, 38 fitness_calculator):
39 """Generate a population of individuals with randomly set genomes. 40 41 Arguments: 42 - genome_alphabet -- An Alphabet object describing all of the 43 possible letters that could potentially be in the genome of an 44 organism. 45 - genome_size -- The size of each organisms genome. 46 - num_organism -- The number of organisms we want in the population. 47 - fitness_calculator -- A function that will calculate the fitness 48 of the organism when given the organisms genome. 49 50 """ 51 all_orgs = [] 52 53 # a random number generator to get letters for the genome 54 letter_rand = random.Random() 55 56 # figure out what type of characters are in the alphabet 57 if isinstance(genome_alphabet.letters[0], str): 58 if sys.version_info[0] == 3: 59 alphabet_type = "u" # Use unicode string on Python 3 60 else: 61 alphabet_type = "c" # Use byte string on Python 2 62 elif isinstance(genome_alphabet.letters[0], int): 63 alphabet_type = "i" 64 elif isinstance(genome_alphabet.letters[0], float): 65 alphabet_type = "d" 66 else: 67 raise ValueError( 68 "Alphabet type is unsupported: %s" % genome_alphabet.letters) 69 70 for org_num in range(num_organisms): 71 new_genome = MutableSeq(array.array(alphabet_type), genome_alphabet) 72 73 # generate the genome randomly 74 for gene_num in range(genome_size): 75 new_gene = letter_rand.choice(genome_alphabet.letters) 76 new_genome.append(new_gene) 77 78 # add the new organism with this genome 79 all_orgs.append(Organism(new_genome, fitness_calculator)) 80 81 return all_orgs
82 83
84 -class Organism(object):
85 """Represent a single individual in a population. 86 87 Attributes: 88 - genome -- The genome of the organism. This is a Bio.MutableSeq 89 object that has the sequence of the genome, and the alphabet 90 describing all elements that can be a part of the genome. 91 - fitness -- The calculate fitness of the organism. This fitness is 92 based on the last time it was calculated using the fitness_calculator. 93 So... the fitness could potentially be out of date with the real genome 94 if you are not careful to recalculate it after changes with 95 recalculate_fitness() 96 97 """ 98
99 - def __init__(self, genome, fitness_calculator, start_fitness=None):
100 """Initialize an organism. 101 102 Arguments: 103 - genome -- A MutableSeq object representing the sequence of the 104 genome. 105 - fitness_calculator -- A function that will calculate the fitness 106 of the organism when given the organisms genome. 107 - start_fitness - the starting fitness corresponding with the 108 given genome. If not supplied, the fitness will be calculated 109 using fitness_calculator. 110 111 """ 112 assert isinstance(genome, MutableSeq), "Genome must be a MutableSeq" 113 114 self.genome = genome 115 self._fitness_calc = fitness_calculator 116 117 # calculate the fitness of the genome 118 if start_fitness is None: 119 self.fitness = self._fitness_calc(self.genome) 120 else: 121 self.fitness = start_fitness
122
123 - def __str__(self):
124 """Provide a string output for debugging.""" 125 return "Genome: %s; Fitness %s" % (str(self.genome), self.fitness)
126
127 - def __eq__(self, other):
128 """Compare organisms by their genomes (as strings of letters).""" 129 # See Bio/Seq.py and the comments there about shifting to 130 # using simple string equality. Previously Seq objects used 131 # object equality, while MutableSeq objects used alphabet 132 # aware string equality. 133 return str(self.genome) == str(other.genome)
134
135 - def __ne__(self, other):
136 """Compare organisms by their genomes (as strings of letters).""" 137 return str(self.genome) != str(other.genome)
138
139 - def __lt__(self, other):
140 """Compare organisms by their genomes (as strings of letters).""" 141 return str(self.genome) < str(other.genome)
142
143 - def __le__(self, other):
144 """Compare organisms by their genomes (as strings of letters).""" 145 return str(self.genome) <= str(other.genome)
146
147 - def __gt__(self, other):
148 """Compare organisms by their genomes (as strings of letters).""" 149 return str(self.genome) > str(other.genome)
150
151 - def __ge__(self, other):
152 """Compare organisms by their genomes (as strings of letters).""" 153 return str(self.genome) >= str(other.genome)
154
155 - def copy(self):
156 """Return a copy of the organism. 157 158 This makes it easy to duplicate an organism before changing it. 159 """ 160 copy_genome = self.genome[:] 161 return Organism(copy_genome, self._fitness_calc, self.fitness)
162
163 - def recalculate_fitness(self):
164 """Calculate and reset the fitness of the current genome. 165 166 This should be called after the genome is updated to ensure that 167 fitness always stays in sync with the current genome. 168 """ 169 self.fitness = self._fitness_calc(self.genome)
170