Source code for desdeo_emo.recombination.SinglePointCrossoverMutation

import numpy as np
from random import shuffle

[docs]class SinglePoint_Xover: """Simple single point crossover and mutation. Parameters ---------- ProC : float, optional [description], by default 1 DisC : float, optional [description], by default 30 """ def __init__(self, ProC: float = 1, DisC: float = 30): """[summary] """ self.ProC = ProC self.DisC = DisC
[docs] def crossover(self, ind_0, ind_1): """ Single point crossover. Args: ind_0: individual_0 ind_1: individual_1 Ret: new_0, new_1: the individuals generatd after crossover. """ assert(len(ind_0) == len(ind_1)) point = np.random.randint(len(ind_0)) # new_0, new_1 = np.zeros(len(ind_0)), np.zeros(len(ind_0)) new_0 = np.hstack((ind_0[:point], ind_1[point:])) new_1 = np.hstack((ind_1[:point], ind_0[point:])) assert(len(new_0) == len(ind_0)) return new_0, new_1
[docs] def mutation(self, indi): """ Simple mutation. Arg: indi: individual to mutation. """ point = np.random.randint(len(indi)) indi[point] = 1 - indi[point] return indi
[docs] def do(self, pop: np.ndarray, mating_pop_ids: list = None) -> np.ndarray: """Consecutive members of mating_pop_ids are crossed over in pairs. Example: if mating_pop_ids = [0, 2, 3, 6, 5] then the individuals are crossover as: [0, 2], [3, 6], [5, 0]. Note: if the number of elements is odd, the last individual is crossed over with the first one. Parameters ---------- pop : np.ndarray Array of all individuals mating_pop_ids : list, optional Indices of population members to mate, by default None, which shuffles and mates whole population Returns ------- np.ndarray The offspring produced as a result of crossover. """ pop_size, num_var = pop.shape if mating_pop_ids is None: shuffled_ids = list(range(pop_size)) shuffle(shuffled_ids) else: shuffled_ids = mating_pop_ids mating_pop = pop[shuffled_ids] mate_size = len(shuffled_ids) if len(shuffled_ids) % 2 == 1: # Maybe it should be pop_size-1? mating_pop = np.vstack((mating_pop, mating_pop[0])) mate_size = mate_size + 1 # The rest closely follows the matlab code. offspring = np.zeros_like(mating_pop) # empty_like() more efficient? for i in range(0, mate_size, 2): offspring[i], offspring[i + 1] = self.crossover(mating_pop[i],mating_pop[i+1]) offspring = offspring.round() return offspring
[docs]class SinglePoint_Mutation: """Simple single point crossover and mutation. Parameters ---------- ProC : float, optional [description], by default 1 DisC : float, optional [description], by default 30 """ def __init__(self, ProC: float = 1, DisC: float = 30): """[summary] """ self.ProC = ProC self.DisC = DisC
[docs] def mutation(self, indi): """ Simple mutation. Arg: indi: individual to mutation. """ point = np.random.randint(len(indi)) indi[point] = 1 - indi[point] return indi
[docs] def do(self, offspring: np.ndarray): """Consecutive members of mating_pop_ids are crossed over in pairs. Example: if mating_pop_ids = [0, 2, 3, 6, 5] then the individuals are crossover as: [0, 2], [3, 6], [5, 0]. Note: if the number of elements is odd, the last individual is crossed over with the first one. Parameters ---------- pop : np.ndarray Array of all individuals mating_pop_ids : list, optional Indices of population members to mate, by default None, which shuffles and mates whole population Returns ------- np.ndarray The offspring produced as a result of crossover. """ offspring_size, num_var = offspring.shape k = np.random.randint(0,num_var, offspring_size) for i in range(offspring_size): offspring[i,k[i]] = 1 - offspring[i,k[i]] return offspring