def ordered_crossover(self, parent_a: Chromosome, parent_b: Chromosome) -> (Chromosome, Chromosome): seq = random.sample(range(0, len(parent_a.order_city) - 1), k=2) seq.sort() i, j = seq cities_a = parent_a.order_city[1:] items_a = parent_a.pick_items cities_b = parent_b.order_city[1:] items_b = parent_b.pick_items b_without_a = [ x for x in parent_b.order_city[j:] + parent_b.order_city[1:j] if x not in cities_a[i:j] ] a_without_b = [ x for x in parent_a.order_city[j:] + parent_a.order_city[1:j] if x not in cities_b[i:j] ] for p in range(j, len(cities_a) + i - 1): cities_a[p % len(cities_a)] = b_without_a[p - j] cities_b[p % len(cities_b)] = a_without_b[p - j] cities_b.insert(0, parent_b.order_city[0]) cities_a.insert(0, parent_a.order_city[0]) return Chromosome(cities_a, items_a), Chromosome(cities_b, items_b)
def swap_mutation(self, parent: Chromosome, rate: float) -> None: """ This method implements the swap mutation algorithm """ selected_for_swap = random.choices(parent.order_city[1:], k=2) index0 = parent.order_city.index(selected_for_swap[0]) index1 = parent.order_city.index(selected_for_swap[1]) parent.order_city[index0] = selected_for_swap[1] parent.order_city[index1] = selected_for_swap[0] for x in range(len(parent.pick_items)): if random.random() < rate: parent.pick_items[x] = random.choice([False, True])
def partial_shuffle_mutation(self, parent: Chromosome, rate: float) -> None: """ This method implements the partial shuffle mutation algorithm """ for i in range(1, len(parent.order_city)): if random.random() < rate: j = random.randint(1, len(parent.order_city) - 1) city_i = parent.order_city[i] parent.order_city[i] = parent.order_city[j] parent.order_city[j] = city_i for x in range(len(parent.pick_items)): if random.random() < rate: parent.pick_items[x] = random.choice([False, True])
def edge_crossover_single(parent_a: Chromosome, parent_b: Chromosome) -> Chromosome: """ This method implements the edge crossover algorithm """ cities_a = parent_a.order_city cities_b = parent_b.order_city edge_map = defaultdict(list) for c in cities_a: edge_map.setdefault(c, []) edge_map[cities_a[0]].append(cities_a[-1]) edge_map[cities_b[0]].append(cities_b[-1]) edge_map[cities_a[-1]].append(cities_a[0]) edge_map[cities_b[-1]].append(cities_b[0]) for i, c in enumerate(cities_a[0:-2]): edge_map[c].append(cities_a[i + 1]) edge_map[cities_a[i + 1]].append(c) for i, c in enumerate(cities_b[0:-2]): edge_map[c].append(cities_b[i + 1]) edge_map[cities_b[i + 1]].append(c) current_city = cities_a[0] new_cities = [current_city] while len(edge_map.keys()) > 1: current_city_edge_list = edge_map.pop(current_city) if not current_city_edge_list: next_city = random.choice(list(edge_map.keys())) else: minx = sys.maxsize for city in current_city_edge_list: edge_map[city].remove(current_city) if len(edge_map[city]) < minx: minx = len(edge_map[city]) next_city = city elif len(edge_map[city]) == minx: next_city = random.choice([city, next_city]) current_city = next_city new_cities.append(current_city) new_items = [] items_a = parent_a.pick_items items_b = parent_b.pick_items for i in range(len(items_a)): if random.randrange(1) == 1: new_items.append(items_a[i]) else: new_items.append(items_b[i]) # print(new_cities) return Chromosome(new_cities, new_items)
def reverse_sequence_mutation(self, parent: Chromosome, rate: float) -> None: seq = random.sample(range(1, len(parent.order_city)), k=2) seq.sort() i, j = seq order_city = parent.order_city[:i] + parent.order_city[ i:j][::-1] + parent.order_city[j:] pick_items = parent.pick_items[:i] + parent.pick_items[ i:j][::-1] + parent.pick_items[j:] for x in range(len(pick_items)): if random.random() >= rate: pick_items[x] = random.choice([False, True]) parent.order_city = order_city parent.pick_items = pick_items
def generate_initial_population(self) -> None: for _ in range(self.population_size): order_city = self.problem.cities[1:] random.shuffle(order_city) order_city.insert(0, self.problem.cities[0]) pick_items = random.choices([False, True], weights=[0.9, 0.1], k=self.problem.number_of_cities) self.population.append(Chromosome(order_city, pick_items))
def ordered_crossover(self, parent_a: Chromosome, parent_b: Chromosome) -> (Chromosome, Chromosome): """ This method implements the ordered crossover algorithm """ seq = random.sample(range(0, len(parent_a.order_city) - 1), k=2) seq.sort() i, j = seq seq = random.sample(range(0, len(parent_a.pick_items) - 1), k=2) seq.sort() p, q = seq cities_a = parent_a.order_city[1:] items_a = parent_a.pick_items cities_b = parent_b.order_city[1:] items_b = parent_b.pick_items b_without_a = [ x for x in parent_b.order_city[j:] + parent_b.order_city[1:j] if x not in cities_a[i:j] ] a_without_b = [ x for x in parent_a.order_city[j:] + parent_a.order_city[1:j] if x not in cities_b[i:j] ] b_i_a = parent_b.pick_items[q:] + parent_b.pick_items[:q] a_i_b = parent_a.pick_items[q:] + parent_a.pick_items[:q] for x in range(j, len(cities_a) + i - 1): cities_a[x % len(cities_a)] = b_without_a[x - j] cities_b[x % len(cities_b)] = a_without_b[x - j] for x in range(q, len(items_a) + p - 1): items_a[x % len(items_a)] = b_i_a[x - q] items_b[x % len(items_b)] = a_i_b[x - q] cities_b.insert(0, parent_b.order_city[0]) cities_a.insert(0, parent_a.order_city[0]) return Chromosome(cities_a, items_a), Chromosome(cities_b, items_b)