Пример #1
0
 def set_params(self,
                solution_size=3,
                q0=0.1,
                alpha=0.9,
                beta=0.9,
                rho=0.05):
     # this is the same as __init__
     self.__rho = rho
     self.__solution_size = solution_size
     new_sets_steps = list(
         permutations(list(range(1, self.__solution_size + 1)) * 2))
     new_ants = []
     for x in new_sets_steps:
         a = Ant(self.__solution_size)
         a.add_to_solution(x)
         new_ants.append(a)
     p = list(
         filter(lambda a: self.fitness_function(a) == MIN_FITNESS,
                new_ants))
     new_sets_steps = [ant.last() for ant in p]
     self.__steps = [list(step) for step in new_sets_steps]
     self.__beta = beta
     self.__alpha = alpha
     self.__q0 = q0
     self.__best_ant = None
     self.__colony_size = 0
     self.__colony = []
     self.__pheromone_matrices = []
     # generate these matrices
     for _ in range(self.__solution_size * 2):
         self.__pheromone_matrices.append(
             [[1 for _ in range(self.__solution_size + 1)]
              for _ in range(self.__solution_size + 1)])
Пример #2
0
    def random_ants(self, world, count, even=False):
        """Returns a list of :class:`Ant`\s distributed to the nodes of the 
        world in a random fashion.

        Note that this does not ensure at least one :class:`Ant` begins at each
        node unless there are exactly as many :class:`Ant`\s as there are
        nodes. This method is used to create the :class:`Ant`\s before solving
        if *ant_count* is **not** ``0``.

        :param World world: the :class:`World` in which to create the ants.
        :param int count: the number of :class:`Ant`\s to create
        :param bool even: ``True`` if :func:`random.random` should avoid 
                          choosing the same starting node multiple times
                          (default is ``False``)
        :return: the :class:`Ant`\s initialized to nodes in the :class:`World`
        :rtype: list
        """
        ants = []
        if even:
            starts = world.nodes
            n = len(starts)
            # Since the caller wants an even distribution, use a round-robin
            # method until the number of ants left to create is less than the
            # number of nodes.
            if count > n:
                for i in range(self.ant_count // n):
                    ants.extend([
                        Ant(self.alpha, self.beta).initialize(world,
                                                              start=starts[j])
                        for j in range(n)
                    ])
            # Now (without choosing the same node twice) choose the reamining
            # starts randomly.
            ants.extend([
                Ant(self.alpha,
                    self.beta).initialize(world,
                                          start=starts.pop(
                                              random.randrange(n - i)))
                for i in range(count % n)
            ])
        else:
            start = 0
            # Just pick random nodes.
            ants.extend([
                Ant(self.alpha, self.beta).initialize(world, start=start)
                for i in range(count)
            ])
        return ants
Пример #3
0
    def epoch(self):
        if self.__graph.settings['dynamic'] and random(
        ) < self.__graph.settings['changeProb']:
            x, y = np.random.choice(self.__graph.nodes, size=2, replace=False)
            self.__graph[x][y] = self.__graph[y][x] = randint(
                self.__graph.settings['minCost'],
                self.__graph.settings['maxCost'])

        ants = [
            Ant(self.__graph) for _ in range(self.__graph.settings['noAnts'])
        ]
        for _ in range(len(self.__graph) - 1):
            for ant in ants:
                ant.addMove()

        pheromons = [self.__graph.settings['Q'] / ant.fitness for ant in ants]

        for i in range(len(self.__graph)):
            for j in range(len(self.__graph)):
                self.__graph.trace[i][j] *= (1 - self.__graph.settings['decay']
                                             )  # intensitatea urmei de feromon

        for index, ant in enumerate(ants):
            for i in range(len(ant.path) - 1):
                x = ant.path[i]
                y = ant.path[i + 1]
                self.__graph.trace[x][y] = pheromons[index]

        # furnica cu cel mai bun fitness
        return min([(ant.fitness, ant) for ant in ants],
                   key=lambda pair: pair[0])[1]
Пример #4
0
    def __init__(self, team_size, initializer, evaluation):
        self.__team_size = team_size

        self.__taboo = []
        self.__solution = []
        self.__loader = None
        self.__initial_states = []
        self.__evaluation = sys.maxsize
        self.__evaluation_criterion = evaluation
        self.__ants = [Ant(initializer) for _ in range(team_size)]
Пример #5
0
 def execute(self, graph: Graphic):
     best_cost = float('inf')
     best_solution = []
     for it in range(self.__iterations):
         ants = [Ant(self, graph) for i in range(self.__ant_count)]
         for ant in ants:
             for i in range(graph.rank - 1):
                 self.__select_next(ant)
             ant.total_cost += graph.matrix[ant.tabu[-1]][ant.tabu[0]]
             if ant.total_cost < best_cost:
                 best_cost = ant.total_cost
                 best_solution = [] + ant.tabu
             self.__update_pheromone_delta(ant)
         self.__update_pheromone(graph, ants)
     return best_solution, best_cost
Пример #6
0
    def run(self):
        start_time_total = time.time()
        # maximum number of iterations
        start_iteration = 0
        for iter in range(self.max_iter):
            # initialize ants
            ants = list(Ant(self.graph) for x in range(self.ants_num))
            for k in range(self.ants_num):
                # visiting all customers
                while not ants[k].index_to_visit_empty():
                    next_index = self.select_next_index(ants[k])
                    # check if the condition is satisfied after joining the position, if not, select again
                    if not ants[k].check_condition(next_index):
                        next_index = self.select_next_index(ants[k])
                        if not ants[k].check_condition(next_index):
                            next_index = 0
                    # update ant path
                    ants[k].move_to_next_index(next_index)
                    self.graph.local_update_pheromone(ants[k].current_index, next_index)
                # return to position 0
                ants[k].move_to_next_index(0)
                self.graph.local_update_pheromone(ants[k].current_index, 0)
            # calculate the routes length of all ants
            paths_distance = np.array([ant.total_travel_distance for ant in ants])
            # save the current best path
            best_index = np.argmin(paths_distance)
            if self.best_path is None or paths_distance[best_index] < self.best_path_distance:
                self.best_path = ants[int(best_index)].travel_path
                self.best_path_distance = paths_distance[best_index]
                self.best_vehicle_num = self.best_path.count(0) - 1
                start_iteration = iter

                print('[iteration %d]: found better path, distance: %f' % (iter, self.best_path_distance))

            # update pheromone table
            self.graph.global_update_pheromone(self.best_path, self.best_path_distance)
            given_iteration = 250
            if iter - start_iteration > given_iteration:
                print('Cannot find better solution after %d iteration' % given_iteration)
                break

        print('Final best path dist is %f, number of vehicle is %d' % (self.best_path_distance, self.best_vehicle_num))
        print('Running time: %0.3f seconds' % (time.time() - start_time_total))

        print_graph(self.graph, self.best_path, self.best_path_distance, self.best_vehicle_num)
Пример #7
0
    def round_robin_ants(self, world, count):
        """Returns a list of :class:`Ant`\s distributed to the nodes of the 
        world in a round-robin fashion.

        Note that this does not ensure at least one :class:`Ant` begins at each
        node unless there are exactly as many :class:`Ant`\s as there are
        nodes. However, if *ant_count* is ``0`` then *ant_count* is set to the
        number of nodes in the :class:`World` and this method is used to create
        the :class:`Ant`\s before solving.

        :param World world: the :class:`World` in which to create the
                            :class:`Ant`\s
        :param int count: the number of :class:`Ant`\s to create
        :return: the :class:`Ant`\s initialized to nodes in the :class:`World`
        :rtype: list
        """
        starts = world.nodes
        n = len(starts)
        return [
            Ant(self.alpha, self.beta).initialize(world, start=starts[i % n])
            for i in range(count)
        ]
Пример #8
0
 def epoch(self, colony_size):
     self.__colony_size = colony_size
     # create the colony
     self.__colony = [
         Ant(self.__solution_size) for _ in range(self.__colony_size)
     ]
     for ant in self.__colony:
         ant.add_to_solution(deepcopy(choice(self.__steps)))
     # put the ants in random order
     for _ in range(self.__solution_size):
         for ant in self.__colony:
             self.add_move_to_ant(ant)
     # update the pheromone matrices
     for ant in self.__colony:
         self.update_pheromone_matrix(ant)
     # update the best ant
     if self.__best_ant:
         self.__best_ant = min(min(self.__colony,
                                   key=self.fitness_function),
                               self.__best_ant,
                               key=self.fitness_function)
     else:
         self.__best_ant = min(self.__colony, key=self.fitness_function)
Пример #9
0
    def acs_vehicle(new_graph, vehicle_num, ants_num, q0, beta, global_path_queue, path_found_queue, stop_event):
        # vehicle_num is set to one less than the current best_path
        print('[acs_vehicle]: start, vehicle_num %d' % vehicle_num)
        global_best_path = None
        global_best_distance = None

        # Initialize path and distance using nearest_neighbor_heuristic algorithm
        current_path, current_path_distance, _ = new_graph.nearest_neighbor(max_vehicle_num=vehicle_num)

        # Find the unvisited nodes in the current path
        current_index_to_visit = list(range(new_graph.node_num))
        for ind in set(current_path):
            current_index_to_visit.remove(ind)

        ants_pool = ThreadPoolExecutor(ants_num)
        ants_thread = []
        ants = []
        IN = np.zeros(new_graph.node_num)
        while True:
            print('[acs_vehicle]: new iteration')

            if stop_event.is_set():
                print('[acs_vehicle]: receive stop event')
                return

            for k in range(ants_num):
                ant = Ant(new_graph, 0)
                thread = ants_pool.submit(MultipleAntColonySystem.new_active_ant, ant, vehicle_num, False, IN, q0,
                                          beta, stop_event)

                ants_thread.append(thread)
                ants.append(ant)

            # Here you can use the result method and wait for the thread to finish
            for thread in ants_thread:
                thread.result()

            for ant in ants:

                if stop_event.is_set():
                    print('[acs_vehicle]: receive stop event')
                    return

                IN[ant.index_to_visit] = IN[ant.index_to_visit] + 1

                # The path found by the ant is compared with the current_path, can you use the vehicle_num
                # vehicles to access more nodes
                if len(ant.index_to_visit) < len(current_index_to_visit):
                    current_path = copy.deepcopy(ant.travel_path)
                    current_index_to_visit = copy.deepcopy(ant.index_to_visit)
                    current_path_distance = ant.total_travel_distance
                    # And set IN to 0
                    IN = np.zeros(new_graph.node_num)

                    # If this path is easy, it will be sent to macs_vrptw
                    if ant.index_to_visit_empty():
                        print('[acs_vehicle]: found a feasible path, send path info to macs')
                        path_found_queue.put(Path(ant.travel_path, ant.total_travel_distance))

            # Update the pheromone in new_graph, global
            new_graph.global_update_pheromone(current_path, current_path_distance)

            if not global_path_queue.empty():
                info = global_path_queue.get()
                while not global_path_queue.empty():
                    info = global_path_queue.get()
                print('[acs_vehicle]: receive global path info')
                global_best_path, global_best_distance, global_used_vehicle_num = info.get_path_info()

            new_graph.global_update_pheromone(global_best_path, global_best_distance)

            ants_thread.clear()
            for ant in ants:
                ant.clear()
                del ant
            ants.clear()
Пример #10
0
    def acs_time(new_graph, vehicle_num, ants_num, q0, beta, global_path_queue, path_found_queue, stop_event):
        # You can use vehicle_num vehicles at most, that is, the path contains the most vehicle_num + 1
        # depots to find the shortest path, vehicle_num is set to be consistent with the current best_path
        print('[acs_time]: start, vehicle_num %d' % vehicle_num)
        # initialize the pheromone matrix
        global_best_path = None
        global_best_distance = None
        ants_pool = ThreadPoolExecutor(ants_num)
        ants_thread = []
        ants = []
        while True:
            print('[acs_time]: new iteration')

            if stop_event.is_set():
                print('[acs_time]: receive stop event')
                return

            for k in range(ants_num):
                ant = Ant(new_graph, 0)
                thread = ants_pool.submit(MultipleAntColonySystem.new_active_ant, ant, vehicle_num, True,
                                          np.zeros(new_graph.node_num), q0, beta, stop_event)
                ants_thread.append(thread)
                ants.append(ant)

            # Here you can use the result method and wait for the thread to finish
            for thread in ants_thread:
                thread.result()

            ant_best_travel_distance = None
            ant_best_path = None
            # Determine whether the path found by the ant is feasible and better than the global path
            for ant in ants:

                if stop_event.is_set():
                    print('[acs_time]: receive stop event')
                    return

                # Get the current best path
                if not global_path_queue.empty():
                    info = global_path_queue.get()
                    while not global_path_queue.empty():
                        info = global_path_queue.get()
                    print('[acs_time]: receive global path info')
                    global_best_path, global_best_distance, global_used_vehicle_num = info.get_path_info()

                # The shortest path calculated by the ant
                if ant.index_to_visit_empty() and (
                        ant_best_travel_distance is None or ant.total_travel_distance < ant_best_travel_distance):
                    ant_best_travel_distance = ant.total_travel_distance
                    ant_best_path = ant.travel_path

            # Perform global update of pheromone here
            new_graph.global_update_pheromone(global_best_path, global_best_distance)

            # Send the calculated current best path to macs
            if ant_best_travel_distance is not None and ant_best_travel_distance < global_best_distance:
                print('[acs_time]: ants\' local search found a improved feasible path, send path info to macs')
                path_found_queue.put(Path(ant_best_path, ant_best_travel_distance))

            ants_thread.clear()
            for ant in ants:
                ant.clear()
                del ant
            ants.clear()