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(\ 63 "Alphabet type is unsupported: %s" % genome_alphabet.letters) 64 65 for org_num in range(num_organisms): 66 new_genome = MutableSeq(array.array(alphabet_type), genome_alphabet) 67 68 # generate the genome randomly 69 for gene_num in range(genome_size): 70 new_gene = letter_rand.choice(genome_alphabet.letters) 71 new_genome.append(new_gene) 72 73 # add the new organism with this genome 74 all_orgs.append(Organism(new_genome, fitness_calculator)) 75 76 return all_orgs
77
78 -class Organism:
79 """Represent a single individual in a population. 80 81 Attributes: 82 83 o genome -- The genome of the organism. This is a Bio.MutableSeq 84 object that has the sequence of the genome, and the alphabet 85 describing all elements that can be a part of the genome. 86 87 o fitness -- The calculate fitness of the organism. This fitness is 88 based on the last time it was calculated using the fitness_calculator. 89 So... the fitness could potentially be out of date with the real genome 90 if you are not careful to recalculate it after changes with 91 recalculate_fitness() 92 """
93 - def __init__(self, genome, fitness_calculator, start_fitness = None):
94 """Initialize an organism 95 96 Arguments: 97 98 o genome -- A MutableSeq object representing the sequence of the 99 genome. 100 101 o fitness_calculator -- A funtion that will calculate the fitness 102 of the organism when given the organisms genome. 103 104 o start_fitness - the starting fitness corresponding with the 105 given genome. If not supplied, the fitness will be calculated 106 using fitness_calculator. 107 """ 108 assert isinstance(genome, MutableSeq), "Genome must be a MutableSeq" 109 110 self.genome = genome 111 self._fitness_calc = fitness_calculator 112 113 # calculate the fitness of the genome 114 if start_fitness is None: 115 self.fitness = self._fitness_calc(self.genome) 116 else: 117 self.fitness = start_fitness
118
119 - def __str__(self):
120 """Provide a string output for debugging. 121 """ 122 return "Genome: %s; Fitness %s" % (self.genome.data, self.fitness)
123
124 - def __cmp__(self, other):
125 """Define comparisons for organisms. 126 127 Compare organisms by their genomes (as strings of letters). 128 """ 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 cmp(str(self.genome), str(other.genome))
134
135 - def copy(self):
136 """Return a copy of the organism. 137 138 This makes it easy to duplicate an organism before changing it. 139 """ 140 copy_genome = self.genome[:] 141 return Organism(copy_genome, self._fitness_calc, self.fitness)
142
143 - def recalculate_fitness(self):
144 """Calculate and reset the fitness of the current genome 145 146 This should be called after the genome is updated to ensure that 147 fitness always stays in sync with the current genome. 148 """ 149 self.fitness = self._fitness_calc(self.genome)
150