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)
Example #2
0
    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])
Example #3
0
    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])
Example #4
0
    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
Example #6
0
 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))
Example #7
0
    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)