多源多点货车路径规划问题MSMP,蚁群算法

算法调研

现在的导航系统,仅有固定的a点到b点之间的单源导航,就算是增加途径点,本质上也是单源的路径规划算法。

但是针对货车场景,货车司机经常需要从多个仓库上货,中间又穿插着多个目标地点下货。针对该场景,传统的导航方式将无法完成任务。

适用于单个车辆的多仓库、多目标路径规划的两种有效算法:遗传算法和蚁群算法。

遗传算法(Genetic Algorithm, GA):

遗传算法是一种优化算法,灵感来自于生物进化的过程。

在单个车辆的多仓库、多目标路径规划中,遗传算法可以用于搜索最优的路径组合。

基本思想:

  • 创建一个初始种群,每个个体表示一种路径规划方案。
  • 通过选择、交叉和变异操作,不断优化种群中的个体。
  • 逐代迭代,直到找到最优解或达到停止条件。

适用性:

遗传算法适用于复杂的路径规划问题,可以处理多个仓库、多个目标点,以及不同的约束条件(如车辆容量、时间窗口等)。

蚁群算法(Ant Colony Optimization, ACO):

蚁群算法模拟了蚂蚁在寻找食物时的行为。

在单个车辆的多仓库、多目标路径规划中,蚁群算法可以用于搜索最短路径。

基本思想:

  • 创建一群虚拟蚂蚁,每只蚂蚁代表一种路径规划。
  • 蚂蚁根据信息素浓度选择路径,同时释放信息素。
  • 信息素浓度会影响其他蚂蚁的选择,从而逐步优化路径。

适用性:

蚁群算法适用于具有多个目标点的复杂环境,可以处理多仓库、多目标点的路径规划问题。

蚁群算法思路考虑

针对遗传算法构建python代码.需要注意的规则如下:

  • 必须保证货车先去仓库,再去目标地点;
  • 必须保证所有的货物容量和重量不会超出车辆容量和限重。
  • 输入为仓库坐标和目标坐标的二元列表的列表,例如[[仓库1,目标1,体积1,重量1],[仓库1,目标2,体积2,重量2],[仓库2,目标1,体积3,重量3],[仓库2,目标2,体积4,重量4],[仓库3,目标3,体积5,重量5]]

 伪代码如下:

初始化算法参数和信息素矩阵  
设置起始点坐标  
初始化仓库和目标的货物状态  
  
for 迭代次数 in 范围(最大迭代次数):  
    蚂蚁列表 = []  
      
    for 蚂蚁 in 范围(蚂蚁数量):  
        当前蚂蚁 = 初始化蚂蚁(起始点坐标)  
        当前蚂蚁的路径 = []  
        当前蚂蚁的装载状态 = 初始化装载状态  
          
        while 仍有未送达的货物:  
            下一个节点 = 当前蚂蚁选择下一个节点(根据信息素和启发式信息)  
            当前蚂蚁的路径.append(下一个节点)  
              
            if 下一个节点是仓库:  
                加载货物到当前蚂蚁(根据剩余容量)  
                更新当前蚂蚁的装载状态  
            elif 下一个节点是目标:  
                卸载货物从当前蚂蚁(根据目标需求量)  
                更新当前蚂蚁的装载状态  
                  
                if 所有货物已送达:  
                    break  
                  
        蚂蚁列表.append(当前蚂蚁)  
      
    评估所有蚂蚁的路径并计算总时间  
    更新信息素矩阵  
      
    if 所有货物已送达:  
        break  
  
输出最佳蚂蚁的路径和总时间

主文件如下:

import numpy as np
import function
import time
# 初始化算法参数
num_ants = 10            # 蚂蚁数量
max_iterations = 20     # 最大迭代次数
evaporation_rate = 0.3  # 信息素挥发率(上一轮的信息素在下一轮中的挥发比例)
max_volume = 50         # 最大容量
max_weight = 50         # 最大载重
start_point = np.array([0, 0])  # 设置起始点坐标
delt_time = 10
best_ant = []
best_time = []


node_list = [           # 节点坐标列表
    np.array([0, 0]),
    np.array([1, 4]),
    np.array([2, 4]),
    np.array([4, 6]),
    np.array([1, 8]),
    np.array([6, 10]),
    np.array([5, 12])
    ]

# 初始化仓库和目标的货物状态 [仓库节点id, 目标节点id, 体积, 重量]
warehouse_targets = [
    [1, 2, 5, 10],
    [2, 3, 8, 15],
    [3, 4, 6, 12],
    [4, 5, 7, 8],
    [5, 6, 9, 7],
    [1, 4, 5, 8],
    [2, 5, 7, 10],
    [3, 6, 4, 6]
]

# 初始化信息素矩阵启发式信息矩阵
num_points = len(node_list)                             # 仓库和目标地点总数
pheromone_matrix = np.ones((num_points, num_points))    # 信息素矩阵
heuristic_matrix = function.calculate_inverse_distance_matrix(node_list)# 启发式信息矩阵

# 初始化蚂蚁列表
ants = [function.Ant(start_point, node_list) for _ in range(num_ants)]

# 主循环
for iteration in range(max_iterations):
    # 重新初始化蚂蚁列表
    ants = [function.Ant(start_point, node_list) for _ in range(num_ants)]
    # 评估路径总时间
    total_time = 0
    count = 0
    for ant in ants:
        count = count + 1
        # 初始化货物送达状态
        delivered = {i: False for i in range(len(warehouse_targets))}
        # 蚂蚁送货
        while not all(delivered.values()):
            print("#####################")
            #time.sleep(0.5)
            # 蚂蚁选择下一个节点
            next_node = ant.select_next_node(pheromone_matrix, heuristic_matrix, node_list, warehouse_targets, delivered)
           
            # 更新当前蚂蚁的位置
            ant.current_point = node_list[next_node]
            
            action = ""
            # 如果下一个节点是仓库
            if any((next_node == wt[0]).all() for wt in warehouse_targets):
                # 加载货物到当前蚂蚁
                for index, wt in enumerate(warehouse_targets):
                    # 若为仓库,且(仓库货物不在车辆上且没有抵达)则上货
                    if (next_node == wt[0]).all() and index not in ant.current_cargo and delivered[index] == False:
                        if ant.load_weight + wt[3] <= max_weight and ant.load_volume + wt[2] <= max_volume:
                            print(wt, "上货")
                            ant.load_weight += wt[3]
                            ant.load_volume += wt[2]
                            ant.current_cargo.append(index)
                            action = action + "上货" + str(index) + "号货物"

            # 如果下一个节点是目标地点
            if any((next_node == wt[1]).all() for wt in warehouse_targets):
                # 卸载货物从当前蚂蚁
                for index, wt in enumerate(warehouse_targets):
                    if next_node == wt[1] and index in ant.current_cargo:
                        print(wt, "卸货")
                        ant.load_weight -= wt[3]
                        ant.load_volume -= wt[2]
                        ant.current_cargo.remove(index)
                        delivered[index] = True
                        action = action + "卸货" + str(index) + "号货物"
                        if all(delivered.values()):
                            print("货物抵达情况:", delivered)
                            break
            # 更新路径
            ant.path.append([next_node, action])
            # 如果所有货物已送达,退出循环
            if all(delivered.values()):
                print("货物抵达情况:", delivered)
                break
            ant.print_status()
            print("货物抵达情况:", delivered)
            
        # 计算蚂蚁的路径总时间
        ant_time = function.get_cost(ant, delt_time, node_list)
        total_time += ant_time
    
    # 输出最佳蚂蚁的路径和总时间
    best_ant_temp, best_time_temp = function.get_best_ant(ants, delt_time, node_list)
    best_ant.append([best_ant_temp, best_time_temp])
    
    # 更新信息素
    delta_pheromone = np.zeros((num_points, num_points))
    for ant in ants:
        ant_cost = function.get_cost(ant, delt_time, node_list)
        # 精英算法,只有足够优异的蚂蚁有资格留下信息素
        if ant_cost > 130:
            continue
        for i in range(len(ant.path) - 1):
            delta_pheromone[ant.path[i][0]][ant.path[i + 1][0]] += 200 / total_time
    pheromone_matrix = (1 - evaporation_rate) * pheromone_matrix + delta_pheromone
    
# 输出最佳蚂蚁的路径和总时间
Best_ant = sorted(best_ant, key=lambda x: x[1])
best_path = Best_ant[0][0].path
print("Best Path:", best_path)
print("Total Time:", Best_ant[0][1])

次文件function.py如下:

import numpy as np

def calculate_inverse_distance_matrix(node_list):  
    """  
    计算节点列表中每个点到其他所有点之间距离的倒数,并返回一个距离倒数矩阵。  
  
    参数:  
    node_list (list of np.ndarray): 包含节点坐标的列表,每个节点坐标是一个 NumPy 数组。  
  
    返回:  
    np.ndarray: 距离倒数矩阵,大小为 (len(node_list), len(node_list))。  
    """  
    # 初始化距离矩阵  
    num_nodes = len(node_list)  
    distance_matrix = np.zeros((num_nodes, num_nodes))  
  
    # 计算距离并存储倒数  
    for i in range(num_nodes):  
        for j in range(i+1, num_nodes):  # 只计算i到j,避免重复计算  
            distance = calculate_distance(node_list[i], node_list[j])  # 计算两点间距离  
            if distance > 0:  # 避免除以0的情况  
                distance_inverse = 1.0 / distance  
                distance_matrix[i, j] = distance_inverse  
                distance_matrix[j, i] = distance_inverse  # 距离矩阵对称  
  
    return distance_matrix 
    
# 计算两点之间的距离时间 后续需要用导航API替代
def calculate_distance(point1, point2):
    return np.linalg.norm(point1 - point2)
    
# 定义蚂蚁类
class Ant:
    def __init__(self, start_point, node_list):
        self.current_point = start_point    # 当前位置
        self.path = [[0,"出发!"]]       # 已经过的路径与操作
        self.current_cargo = []             # 装载的货物id
        self.load_volume = 0                # 已有容量
        self.load_weight = 0                # 已有重量
    def select_next_node(self, pheromone_matrix, heuristic_matrix, node_list, warehouse_targets, delivered):  
        """  
        根据信息素和启发式信息选择下一个节点  
          
        :param pheromone_matrix: 信息素矩阵  
        :param heuristic_matrix: 启发式信息矩阵(如距离的倒数)  
        :return: 选择的下一个节点的索引  
        """  
        
        # 获取当前节点在notelist中的索引  
        current_node_index = next((i for i, arr in enumerate(node_list) if np.array_equal(arr, self.current_point)), None)
        # 计算选择下一个节点的概率  
        probabilities = []  
        for i, node_index in enumerate(range(len(pheromone_matrix))): 
            # 需要上货
            need_to_load = False
            # 需要卸货
            need_to_down = False
            
            for j, wt in enumerate(warehouse_targets):
                # 若为仓库
                if node_index == wt[0] and j not in self.current_cargo and delivered[j] == False:
                    print(node_index, "是仓库,需要上货", j, "号货物")
                    need_to_load = True
                if node_index == wt[1] and j in self.current_cargo:
                    print(node_index, "是目标,需要卸货", j, "号货物")
                    need_to_down = True
            if need_to_down == False and need_to_load == False:
                probabilities.append(0.0)
                continue

            
            if pheromone_matrix[current_node_index, node_index] == 0:  
                # 跳过信息素为0的节点  
                probabilities.append(0.0)  
            else:  
                # 计算选择概率,通常使用信息素和启发式信息的某种组合  
                # 这里简化地假设为信息素和启发式信息的乘积  
                prob = pheromone_matrix[current_node_index, node_index] * heuristic_matrix[current_node_index, node_index]  
                probabilities.append(prob)  
          
        # 归一化概率  
        probabilities = [p / sum(probabilities) for p in probabilities]    
        # 根据概率随机选择下一个节点  
        next_node_index = np.random.choice(range(len(probabilities)), p=probabilities)
        
        return next_node_index
    def print_status(self):
        print("当前位置:", self.current_point)
        print("当前载重:", self.load_weight)
        print("当前体积:", self.load_volume)
        print("装载的货物ID列表", self.current_cargo)
        print("经过路径:", self.path)

# 获取当前蚂蚁的代价
def get_cost(ant, delt_time, node_list):
    ant_time = 0
    for i in range(len(ant.path) - 1):
            # 模拟时间:简单地取两点之间的距离作为时间
            distance = calculate_distance(node_list[ant.path[i][0]], node_list[ant.path[i+1][0]])
            #计算 运货时间 and 上下货时间
            ant_time += distance + delt_time
    return ant_time

# 获取最佳蚂蚁   
def get_best_ant(ants, delt_time, node_list):
    min_cost = 999
    best_ant = None
    for ant in ants:
        ant_time = get_cost(ant, delt_time, node_list)
        if ant_time < min_cost:
            min_cost = ant_time
            best_ant = ant
        print("ant.time = ", ant_time)
    return best_ant, min_cost
    
# 更新信息素矩阵
def refresh_pheromone_matrix(ants, pheromone_matrix):
    return 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千天夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值