def mutation(self, old_pop, gen): new_pop = [] # three different mutation method for p in old_pop: mut_option = np.random.randint(1, 2) if mut_option == 1: # first mutation method: regular binary mutation bit_string, mutated = self.mutation_bin(p) elif mut_option == 2: # second mutation method: shuffle the indv phases order bit_string, mutated = self.mutation_shuffle(p) new_pop.append( nsga2_individual.IndividualEDNN(bit_string, self.n_phases, self.n_nodes)) new_pop[-1].id = "{}_{}".format(gen, len(new_pop) - 1) if mutated: new_pop[-1].mut_option = mut_option new_pop[-1].parents.append(p) else: for parent in p.parents: new_pop[-1].parents.append(parent) return new_pop
def crossover(self, parent1, parent2): p1_bit_string = np.concatenate( [np.array(i) for i in parent1.bit_string]) p2_bit_string = np.concatenate( [np.array(i) for i in parent2.bit_string]) common_bits = (p1_bit_string - p2_bit_string) == 0 child_base = np.zeros((len(p1_bit_string), ), dtype=np.int) child_base[common_bits] = p1_bit_string[common_bits] compl = np.array([np.sum(p1_bit_string), np.sum(p2_bit_string)]) - np.sum(child_base) compl_lb, compl_ub = np.amin(compl), np.amax(compl) # assuming create two offspring from two parents offspring = [] for i in range(2): # 1 blend of two parents if np.random.rand() < 1.5: child_bit_string = np.copy(child_base) idx, = np.where(common_bits == False) idx = np.random.permutation(idx) if compl_ub > compl_lb: idx = idx[:np.random.randint(compl_lb, compl_ub)] else: idx = idx[:compl_lb] child_bit_string[idx] = 1 child_bit_string = self.convert_to_bit_string(child_bit_string) # 2 swap phases else: child_bit_string = [] for j in range(self.n_phases): if np.random.rand() < 0.5: child_bit_string.append(parent1.bit_string[j]) else: child_bit_string.append(parent2.bit_string[j]) offspring.append( nsga2_individual.IndividualEDNN(child_bit_string, self.n_phases, self.n_nodes)) # fill in details offspring[-1].cr = 1 offspring[-1].parents.append(parent1) offspring[-1].parents.append(parent2) return offspring
def initialization(self): # two stages initialization config_archive = [] # initialize a empty unique config list # 1st stage: extract different unique phase configurations phase_length = int((self.n_nodes - 1) * self.n_nodes / 2 + 1) possible_phase_string = list( map(list, itertools.product([0, 1], repeat=phase_length))) # randomly shuffle the list np.random.shuffle(possible_phase_string) for phase_string in possible_phase_string: config_archive = self.update_config_archive( phase_string, config_archive, self.n_nodes) # terminate the loop if the desired number of unique phase configuration is reached if len(config_archive) >= self.pop_size * self.n_phases: break # 2nd stage: assemble these phase config together pop = [] idx = np.random.permutation(len(config_archive)) # check if found phase config is enough for creating initial population while len(idx) < self.pop_size * self.n_phases: idx = np.append(idx, np.random.permutation(len(config_archive))) idx = idx[:self.pop_size * self.n_phases] idx = idx.tolist() for i in range(0, len(idx), self.n_phases): bit_string, conn = [], [] for j in range(self.n_phases): conn.append(idx[i + j]) bit_string.append(config_archive[idx[i + j]].bit_string) pop.append( nsga2_individual.IndividualEDNN(bit_string, self.n_phases, self.n_nodes)) pop[-1].phase_connection = conn pop[-1].pt = 1 pop[-1].id = "{}_{}".format(0, len(pop) - 1) return pop, config_archive
def heuristic_recombination(self, pop, config_archive, pop_archive): if len(pop) < self.pop_size: max_trail = 20 # set the maximum trails to avoid infinite loop pop_bayesian = self.fill_nondominated_sort( pop_archive, int(len(pop_archive) / 2)) for i in range(len(pop), self.pop_size): trial = 1 while True: conn = self.sample_conn_from_bayesian(pop_bayesian) duplicate = False # assumes this conn is not duplicate # 1st check if conn exists in current population for p in pop: if p.phase_connection == conn: duplicate = True break # 2nd check if conn exists in population archive for member in pop_archive: if member.phase_connection == conn: duplicate = True break if (not duplicate) or (trial > max_trail): break # print(trial) trial += 1 if not duplicate: bit_string = [] for phase in range(len(conn)): # for c in conn: bit_string.append( config_archive[conn[phase]].bit_string) pop.append( nsga2_individual.IndividualEDNN( bit_string, self.n_phases, self.n_nodes)) pop[-1].phase_connection = conn trial = 0 pop[-1].cr = 0 return pop