Source code for desdeo_emo.recombination.SimulatedBinaryCrossover

import numpy as np
from random import shuffle
#from numba import njit


[docs]class SBX_xover: """Simulated binary crossover. 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 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): beta = np.zeros(num_var) miu = np.random.rand(num_var) beta[miu <= 0.5] = (2 * miu[miu <= 0.5]) ** (1 / (self.DisC + 1)) beta[miu > 0.5] = (2 - 2 * miu[miu > 0.5]) ** (-1 / (self.DisC + 1)) beta = beta * ((-1) ** np.random.randint(0, high=2, size=num_var)) beta[np.random.rand(num_var) > self.ProC] = 1 # It was in matlab code avg = (mating_pop[i] + mating_pop[i + 1]) / 2 diff = (mating_pop[i] - mating_pop[i + 1]) / 2 offspring[i] = avg + beta * diff offspring[i + 1] = avg - beta * diff return offspring
# TODO: Make sure the following works correctly, then replace the code above. """@njit def create_offsprings(pop:np.ndarray, mate_size:int,ProC: float=1, DisC: float=30): pop_size, num_var = pop.shape beta = np.zeros(num_var) offspring = np.zeros_like(pop) for i in range(0, mate_size, 2): beta[:] = 0 miu = np.random.rand(num_var) beta[miu <= 0.5] = (2 * miu[miu <= 0.5]) ** (1 / (DisC + 1)) beta[miu > 0.5] = (2 - 2 * miu[miu > 0.5]) ** (-1 / (DisC + 1)) beta = beta * ((-1) ** np.random.randint(0, high=2, size=num_var)) beta[np.random.rand(num_var) > ProC] = 1 # It was in matlab code avg = (pop[i] + pop[i + 1]) / 2 diff = (pop[i] - pop[i + 1]) / 2 offspring[i] = avg + beta * diff offspring[i + 1] = avg - beta * diff return offspring"""