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

Source Code for Module Bio.GA.Organism

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