|
GeneticAlgorithm
0.5 (beta)
A python framework for rapid GA prototyping
|
00001 import copy 00002 import random 00003 from Core import * 00004 00005 ## @class SelectLethals 00006 # @brief Select the individuals to replace based on the population.maximize flag and the population.genSize property 00007 # 00008 # Select as many individuals as indicated by population.genSize to be replaced during the next crossover operation 00009 class SelectLethals(GeneticOperator): 00010 ## @fn select(self, population) 00011 # @brief Select the individuals to replace based on the population.maximize flag and the population.genSize property 00012 def select(self, population): 00013 # Get the population size 00014 n = len(population.individuals) 00015 # Get the amount of offspring to produce (2*m = len(mating_pool)) 00016 m = getattr(population, 'genSize', n) 00017 # Get a fitness vector out of the individual vector 00018 fitness = [individual.fitness for individual in population.individuals] 00019 indices = range(n) 00020 sortedFitness = sorted(zip(fitness, indices), key=lambda x: x[0]) 00021 # Select the m worse individuals in the generation to be replaced 00022 if population.maximize: 00023 L = sortedFitness[:m] 00024 else: 00025 L = sortedFitness[-m:] 00026 # Update the lethals vector 00027 population.lethals = [l[1] for l in L] 00028 # Select individuals for replacement only during the iterate phase of runGA 00029 iterate = select 00030 00031 ## @class KTournament 00032 # @brief A selection operator that implements the k-tournament algorithm 00033 class KTournament(GeneticOperator): 00034 ## @fn __init__(self, k=2, **kwargs) 00035 # @brief The genetic operator constructor 00036 # @param k The number of individuals that will participate in every tournament 00037 def __init__(self, k=2, **kwargs): 00038 super(KTournament, self).__init__(**kwargs) 00039 self.k = k 00040 00041 ## @fn selectBest(self, candidates, population) 00042 # @brief Given a list of candidates and a population, decide which cantidae is the best 00043 # @param candidates A list of indexes that point to the tournament candiadates 00044 # @param population A Core.Population object that contains the contender individuals 00045 # @return The index of the best individual among the candidates 00046 def selectBest(self, contenders, population): 00047 sortedContenders = sorted([(population.individuals[i].fitness,i) for i in contenders], key=lambda x: x[0]) 00048 if population.maximize: 00049 return sortedContenders[-1][1] 00050 else: 00051 return sortedContenders[0][1] 00052 00053 ## @fn select(self, population) 00054 # @brief Perform the k-tournament selection 00055 # 00056 # The k-tournament selection algorithm consists on creating tournaments in which k random individuals participate. The best individual is selected for each tournament, and is selected to belong to the mating pool. 00057 # M torunaments are performed, where M is equal to population.genSize (or n if this property is not found) 00058 def select(self, population): 00059 # Number of individuals 00060 n = len(population.individuals) 00061 # Get the amount of offspring to produce (2*m = len(mating_pool)) 00062 m = getattr(population, 'genSize', n) 00063 # Compute the contenders for each torunament 00064 tournaments = [ [random.randrange(n) for contender in xrange(self.k) ] for tournament in xrange(2*m) ] 00065 # Put the tournament winners on the mating pool 00066 population.matingPool = [self.selectBest(contenders, population) for contenders in tournaments ] 00067 # Make iterate function call select instead 00068 iterate = select 00069 00070 ## @class SUSSelection 00071 # @brief This operator performs stochastic uniform selection over the population, updating the field matingPool 00072 # 00073 # This class performs SUS for both maximization or minimization, the mating pool is simply a list of indices that point to the parents. If minimization is desired, the population.maximize flag must be set to False. 00074 # If population.genSize exists, the mating pool will be twice that number (to produce the same number of offspring); If this parameter does not exist, the mating pool will have twice the length of population.individuals 00075 class SUSSelection(GeneticOperator): 00076 def select(self, population): 00077 # Number of individuals 00078 n = len(population.individuals) 00079 # Fitness vector 00080 fit = [ind.fitness for ind in population.individuals] 00081 # Adjust the pdf for minimization 00082 if not population.maximize: 00083 pdf = [0.0]*n 00084 M = max(fit) + (1.0) 00085 for i in xrange(n): 00086 pdf[i] = M - fit[i] 00087 else: 00088 pdf = fit 00089 # Normalization factor 00090 F = reduce(lambda x, y: x+y, pdf) 00091 # Cumulative distribution function 00092 cdf = [pdf[0]/F] *n 00093 # Probability distribution function 00094 for i in xrange(1, n): 00095 cdf[i] = cdf[i-1] + pdf[i]/F 00096 # Get the amount of offspring to produce (2*m = len(mating_pool)) 00097 m = getattr(population, 'genSize', n) 00098 # Distance between ticks in SUS -> 1/2*m := 0.5/m 00099 delta = 0.5/m 00100 # Initialize the mating pool 00101 matingPool = [ 0 ] * (2*m) 00102 # SUS implements a roulette with 2*m equidistant ticks, this variable stores the position of the current tick (as a probability) 00103 currentTick = delta * random.random() 00104 # Generate 2*m parent pointers 00105 for i in xrange(2*m): 00106 # Find the first entry on the cdf that is greater than or equal to the current tick 00107 for slicePointer in xrange(n): 00108 if cdf[slicePointer] > currentTick: 00109 break 00110 # The ith element on the maitingPool is slice pointer 00111 matingPool[i] = slicePointer 00112 currentTick += delta 00113 while currentTick > 1.0: 00114 currentTick -= 1.0 00115 random.shuffle(matingPool) 00116 population.matingPool = matingPool 00117 iterate = select