def gga_chromosome(self, s=None, delta=None, alpha=None): """ :param s: :param delta: :param alpha: :return: The function creates the chromosomes of the population of a grid-based genetic algorithm if not given it uses the parameters that the object has itself. """ s = s if s is not None else self.s delta = delta if delta is not None else self.delta alpha = alpha if alpha is not None else self.alpha ga_tools.check(len(s) == len(delta) and len(delta) == len(alpha), "Delta, Alpha and S must have the same number of elements (equal to the number of dimensions") return s * delta + alpha
def blend(parents, prob, upper, lower, alpha=0.5): """ The following method applies a blend crossover to a matrix of chromosomes. parents is the chromosomes matrix to apply the function prob is the probability to apply the recombination upper and lower are the upper and lower bounds of the population alpha is the parameter used for blend recombination """ # Check the input var and shuffle the elements ga_tools.check(len(parents) > 0, "The population cannot be an empty matrix") # Shuffle the array to avoid any relation between the individuals parents = shuffle(parents) # In case the length of the parents is not 2*n we remove the last element if len(upper) % 2 != 0: upper = upper[:-1] lower = lower[:-1] # Iterate over the parents taking them two by two and store the generated children for i in range(0, len(parents), 2): # Recombine a pair of parents with probability prob if np.random.uniform(0, 1) <= prob: # Calculate the value of gamma gamma = (1. + 2. * alpha) * np.random.uniform(0, 1) - alpha # Generate the children and store them parents[i], parents[i + 1] = (1 - gamma) * parents[i] + gamma * parents[i + 1], \ ((1 - gamma) * parents[i + 1] + gamma * parents[i]).copy() # Fix the chromosomes values that are out of bounds. First create a mask # set the masked chromosome values to 0, create a matrix with the value of the # bounds where the mask is 1 (true) and zero in the rest, at the end add the new # matrix to the parents out = parents > upper parents[out] = 0 parents += out.astype(int) * upper out = parents < lower parents[out] = 0 parents += out.astype(int) * lower # Return the generated children return parents
def one_point_permutation(parents, prob): """ It recombines a pair of parents to generate their childrens. In order to do so it splits each parent in 2 halfs from the crossover point, then it combinates the halfs of each of them to generate two new children. Now the representation of each parent is a permutation of n elements, where n is len(parents[i]). """ # Check the input var and shuffle the elements ga_tools.check(len(parents) > 0, "The population cannot be an empty matrix") # Shuffle the array to avoid any relation between the individuals parents = shuffle(parents) def add_parent(new_parent, parent): """ Private auxiliary function to minimize the code. It appends to a given parents the values that it doesn't contain yet from the other parent's tail. """ return np.hstack((new_parent, [x for x in parent if x not in new_parent])) # Iterate over the parents taking them two by two and store the generated children for i in range(0, len(parents), 2): # Apply the crossover function with probability prob if np.random.uniform(0, 1) <= prob: # Get a random crossover point crossover_point = np.random.randint(len(parents[i])) # split parents in 2 parts in the crossover point parent_1 = np.hsplit(parents[i], [crossover_point]) parent_2 = np.hsplit(parents[i + 1], [crossover_point]) # recombine to generate their children parents[i] = add_parent(parent_1[0], np.hstack((parent_2[1], parent_2[0]))) parents[i + 1] = add_parent(parent_2[0], np.hstack((parent_1[1], parent_1[0]))) # Return the generated children as a np array return parents
def one_point_gga(parents_s, parents_alpha, prob=1): """ It recombines a pair of parents to generate their childrens. In order to do so it splits each parent in 2 halfs from the crossover point, then it combinates the halfs of each of them to generate two new children """ # Check the input var and shuffle the elements ga_tools.check(len(parents_s) > 0, "The population S cannot be an empty matrix") ga_tools.check(len(parents_s) > 0, "The population Alpha cannot be an empty matrix") # Iterate over the parents taking them two by two and store the generated children for i in range(0, len(parents_s), 2): # Apply the crossover function with probability prob if np.random.uniform(0, 1) <= prob: # Get the crossover point cp = np.random.randint(len(parents_s[i])) # Recombine to generate their children parents_s[i, cp:], parents_s[i + 1, cp:] = parents_s[i + 1, cp:], parents_s[i, cp:].copy() parents_alpha[i, cp:], parents_alpha[i + 1, cp:] = parents_alpha[i + 1, cp:], parents_alpha[i, cp:].copy() return parents_s, parents_alpha
def two_point(parents, prob): """ The following method recieves a pair of parents and the probability between [0,1] to apply the crossover function to them. It randomly sample 2 integers between 0 and the number of dimensions of the parents. Then the two sub-arrays generated (one for each parent) are swapped generating 2 children. """ # Check the input var and shuffle the elements ga_tools.check(len(parents) > 0, "The population cannot be an empty matrix") # Shuffle the array to avoid any relation between the individuals parents = shuffle(parents) # Iterate over the parents taking them two by two and store the generated children for i in range(0, len(parents), 2): # Apply the crossover function with probability prob if np.random.uniform(0, 1) <= prob: # Sample the 2 crossover points randomly cp1 = np.random.randint(len(parents[i])) cp2 = np.random.randint(len(parents[i])) # Avoid that cp1 and cp2 are equal while cp1 == cp2: cp2 = np.random.randint(len(parents[i])) # Swap if cp1 is bigger than cp2 (otherwise array slicing won't work) if cp1 > cp2: cp1, cp2 = cp2, cp1 # Recombine to generate their children parents[i, cp1:cp2], parents[i + 1, cp1:cp2] = parents[i + 1, cp1:cp2], parents[i, cp1:cp2].copy() return parents
def worst_parents(parents, fitness, children, minimize=True): """ Select the N worst fitness, where N is the number of children, out of the population and change them for the new generated children :param parents: current chromosomes :param fitness: fitness value of the chromosomes :param children: new generated chromosomes :param minimize: minimization problem or maximization (boolean) :return: return the new population """ # Test that the inputs are correct ga_tools.check( len(parents) > 0, "The population cannot be an empty matrix") ga_tools.check( len(parents) == len(fitness), "len(parents) and len(pa_fitness) are not the same") # find the worst parents and replace it with the children parents[ga_tools.n_sort(fitness, len(children), minimize)] = children # return the new chromosomes return parents
def elitist(parents, pa_fitness, children, ch_fitness, M, elitism=0.5, replacement=True, minimize=True): """ parents is the current chromosomes pa_fitness is parents fitness value children is the generated chromosomes ch_fitness is children fitness value M is the number of elements to select """ ga_tools.check(len(parents) > 0, "The parents cannot be an empty matrix") ga_tools.check( len(parents) + len(children) >= M, "Number of survival chromosomes cannot be higher than the number of parents and children" ) ga_tools.check( len(parents) == len(pa_fitness), "len(parents) and len(pa_fitness) are not the same") ga_tools.check( len(children) == len(ch_fitness), "len(children) and len(ch_fitness) are not the same") ga_tools.check(elitism >= 0 and elitism <= 1, "elitism must be between 0 and 1") # Gather the parents and children and its fitness chromosomes = np.vstack((parents, children)) fitness = np.hstack((pa_fitness, ch_fitness)) # Get the number of chromosomes to sample as elitist and the rest of chromosomes n_elitist = int(np.ceil(M * elitism)) n_rest = int(M - n_elitist) # Check that the fitness values are meaningful, if not assing equiprobability if np.sum(fitness) < 1e-15: fitness_prob = np.ones(fitness.shape) * (1.0 / len(fitness)) else: # Calculate its probabilites fitness_prob = ga_tools.wheel_prob(fitness, minimize) # Get the non elitist part of the chromosomes with a probability proportional # to the value of the fitness rest_chromosomes = chromosomes[np.random.choice(np.arange( 0, len(chromosomes)), n_rest, replace=replacement, p=fitness_prob)] # get the elitist chromosomes elitist_chromosomes = chromosomes[ga_tools.n_sort(fitness, n_elitist, minimize)] # print "rest", rest_chromosomes # print "elitist", elitist_chromosomes # Group the elitist and the rest of the chromosomes together final_chromosomes = np.vstack((rest_chromosomes, elitist_chromosomes)) # Shuffle the final matrix to avoid groups of elitist # shuffle = np.arange(len(final_chromosomes)) # np.random.shuffle(shuffle) # Return the shuffled array return final_chromosomes