基于蒙特卡洛模拟求解城市货运配送路径(python+arcgis)

本文介绍了如何利用Python的networkx库处理地理数据,构建道路网络模型,计算最短路径,以及运用蒙特卡洛模拟和遗传算法进行配送路线优化。作者分享了如何通过编程实现节点、边的添加,以及如何通过算法求解配送中心到多个配送点的最短配送路径问题。
摘要由CSDN通过智能技术生成

该环节需要基于python的networkx库进行。实验中所用到的excel文件内容如图8所示。Python中的部分操作内容可以参考如下链接:

[4] https://zhuanlan.zhihu.com/p/164470586

图8

通过以下代码可以构建复杂网络,节点为道路端点,连边为道路。

#节点经纬度字典
dict_loc=dict(zip(df_node['节点ID'],list(zip(df_node['经度'],df_node['纬度']))))
# 创建空的交通网络
G = nx.Graph()

# 添加节点到交通网络
for index, row in df_node.iterrows():
    node_id = row['节点ID']
    longitude = row['经度']
    latitude = row['纬度']
    G.add_node(node_id, pos=(longitude, latitude))

# 添加边到交通网络
for index, row in df_edge.iterrows():
    road_id = row['道路ID']
    start_node = row['节点1']
    end_node = row['节点2']
    road_length = row['长度']
    G.add_edge(start_node, end_node, road_id=road_id, length=road_length)

4**、最短路径计算**


以下代码以节点“19814”与节点“30073”为例展示了最短路径的计算方式,批量计算可以通过For循环实现。另外,由于实际计算中所需的POI(如配送中心)并不一定是道路的端点,此时可以通过一些判断准则,选取合适的道路端点代表POI(如选取距离POI最近的端点)。

# 计算最短路径
start_node = 19814
end_node = 30073
shortest_path = nx.shortest_path(G, source=start_node, target=end_node, weight='length')
shortest_distance = nx.shortest_path_length(G, source=start_node, target=end_node, weight='length')
# 打印最短路径和最短距离
print(f"最短路径: {shortest_path}")
print(f"最短距离: {shortest_distance}")

5**、蒙特卡洛模拟**


此处主要参考蒙特卡洛模拟的思想,进行多次随机实验。如存在配送中心A与100个配送点,每次配送需要运送5个配送点,需要计算最短的配送距离。所以每次模型都要从100个配送点中随机抽取5个点。假设5个配送点分别为a、b、c、d、e,前往各个配送点的配送顺序将决定整体的配送距离。以下代码展示了利用穷举法进行相关实验所构建的相关函数。

#计算节点之间的最短路径
def cal_path(start,end):
    distance = nx.shortest_path_length(G, source=start, target=end, weight='length')
    return distance
#蒙特卡洛模拟
def monte_carlo_sim(data,num_samples,num_sim):
    list_sample=[]
    for _ in range(num_sim):
        sample = random.sample(data, num_samples)
        sample_key = tuple(sorted(sample)) 
        list_sample.append(sample_key)
       return list_sample
#生成列表元素的全排列
def all_permutations(lst):
    # 使用permutations函数生成所有排列
    perm_list = list(permutations(lst))
    return perm_list
#列表最小元素位置
def min_position(lst):
    min_value = min(lst)
    min_position = lst.index(min_value)
    return min_position
#对于每条配送路径选取最优路径
#穷举法
def select_path_all(start,list_data):
    #蒙特卡洛模拟每次抽取的一个送货目的地列表进行全排列
    list_choose=all_permutations(list_data)
    list_result=[]
    for i in list_choose:
        #首先计算起点到第一个点的距离
        length_all=cal_path(start,i[0])
        #计算剩余节点间的距离
        for j in range(0,len(i)-1):
            distance=cal_path(i[j],i[j+1])
            length_all=length_all+distance
        #返程
        length_end= cal_path(i[-1],start)  
        length_all=length_all+length_end
        list_result.append(length_all)
    index=min_position(list_result)
    list_out=list(list_choose[index])
    list_out.insert(0,start)
    list_out.append(start)
    return list_out,list_result

穷举法存在计算时间较长的问题,可以结合一些智能算法进行优化求解,如遗传算法等。主要针对“select_path_all”函数代码进行改进。以下代码使用精英策略的遗传算法进行求解。

#对于每条配送路径选取最优路径
#遗传算法
def calculate_total_distance(graph, path):
    total_distance = 0
    #计算某条路径的总长度
    for i in range(len(path) - 1):
        total_distance += graph[path[i]][path[i+1]]['weight']
    return total_distance

def generate_random_route(graph, start):
    nodes = list(graph.nodes())
    nodes.remove(start)
    random.shuffle(nodes)
    return [start] + nodes + [start]

def crossover(parent1, parent2):
    crossover_point = random.randint(1, len(parent1) - 2)
    child = parent1[:crossover_point]
    for node in parent2:
        if node not in child:
            child.append(node)
    child.append(child[0])
    return child

def mutate(route):
    mutation_point1 = random.randint(1, len(route) - 2)
    mutation_point2 = random.randint(1, len(route) - 2)
    route[mutation_point1], route[mutation_point2] = route[mutation_point2], route[mutation_point1]

def genetic_algorithm(graph, start, population_size, generations):
    #随机生成路径,含起始点,生成种群大小
    population = [generate_random_route(graph, start) for _ in range(population_size)]
    for _ in range(generations):
        population = sorted(population, key=lambda x: calculate_total_distance(graph, x))    
        new_population = [population[0]]  # Elitism: keep the best route from the previous generation
        while len(new_population) < population_size:
            parent1, parent2 = random.sample(population, 2)
            child = crossover(parent1, parent2)
            if random.random() < 0.1:  # Mutation rate
                mutate(child)
            new_population.append(child)
        population = new_population
    return population[0], calculate_total_distance(graph, population[0])
def pair_elements(lst):
    #生成节点之间两两的组合,用于创建网络
    return list(combinations(lst, 2))

def GA_sim(list_path,start,population_size,generations): 
    #构建路径图
    G_cal=nx.Graph()
    nodes=start+list_path
    pairs = pair_elements(nodes)
    for i in pairs:
        length_edge=cal_path(i[0],i[1])
        #weight与函数遗传算法中计算距离保持一致
        G_cal.add_edge(i[0],i[1],weight=length_edge)      
    optimal,result=genetic_algorithm(G_cal, start[0], population_size, generations)
    return optimal,result

下面代码为路径求解及文件导出过程,最后将得到各起点(start/配送中心)到多种终点(end/配送点)组合的配送距离结果。

#循环求解配送中心到各个配送点组合的最短距离
for i in list_start:
    df_out=pd.DataFrame([])
    list_out=[]
    # for i in list_choose_path:
    list_monte_path=monte_carlo_sim(list_end,10,1000)
    for j in tqdm(list_monte_path, desc="Processing paths"):
        _,result=GA_sim(list(j),start,1000,100)
        list_out.append(result)
    file_name=str(i)+'.csv'
    df_out.to_csv(file_name)

6**、结语**

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

img
  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值