蚁群算法一个VRP小实现

仍然是参考https://blog.csdn.net/baiyuxuan123123/article/details/114818224这个文章,编码做了一下这个题:

有一配送中心,负责将货物配送到指定的各个配送点。每个配送点有一定的货物需求量,用货物重量表示。
配送中心有若干辆车,每辆车有一定的载重量和里程限制,车的载重和行驶里程不可超过指定的值。
一辆车可负责一个或多个点的配送任务,且每个配送点只被服务一次。
在某一时刻,所有负责配送的车同时从配送中心出发,分别完成各自的配送任务后,再回到配送中心。
根据以上条件,设计一个最优配送方案。对于每个方案,应给出每辆车负责的配送点及其先后顺序。

为衡量方案之间的优劣,我们给出如下三个指标:
配送总时间t:从配送开始 到最后一辆车返回物流中心所经历的时间
车辆总里程s:所有配送车辆的里程之和
车辆总数n:用于配送的车辆数量
在实际应用中,我们为这三个指标分别分配一个权重 wt  ws  和 wn  用如下公式作为每个方案的得分:得分越高,方案越优。
score = − ( wt ⋅ t + ws ⋅ s + wn ⋅ n ) 


import random
import pickle
from collections import namedtuple
import numpy as np
from scipy.spatial.distance import pdist, squareform
import matplotlib.pyplot as plt


# ***** begin 配置信息 *****
# **** 题目数据配置
generate_new_flag = True
max_car_no = 10
min_car_no = 8    # 如果car_no设置得较小,可能会鉴权失败多次,效率差   不能设置得大于 cargo_site_total
cargo_site_total = 20
site_location_range = tuple(range(-100, 101, 5))
car_carrying_range = tuple(range(180, 221, 10))
car_speed_range = tuple(range(20, 41, 10))
move_cargo_second = 2    # 简化处理的每次装卸货时间, 也可以使用与货物重量相关的变量
max_cargo_weight = 100
max_car_distance = 1200

time_weight = 0.4
distance_weight = 0.3
cargo_no_weight = 1 - time_weight - distance_weight

# **** 算法配置
max_iter = 1000
algorithm_GA = False
algorithm_ACO = True


# *** GA配置
population_size = 100
mutate_max_try_times = 20
select_ratio = 0.5

# *** aco 配置
ant_no = 10
pheromone_factor_alpha = 1      # 信息素启发式因子
visible_factor_beta = 2          # 能见度启发式因子
volatil_factor = 0.5         # 信息素挥发速度
pheromone_cons = 100         # 信息素强度

# **** 画图配置
plot_flag = False      # windows下运行 可设为True
# ***** end 配置信息 *****


# 其他定义
cargo_site_info = namedtuple("cargo_site_info", ("site_location_x", "site_location_y", "cargo_weight"))
car_info = namedtuple("car_info", ("speed", "volume"))


# 正常情况 应该把Utils写成一个文件或文件夹  而不是一个类..
class Utils:
    @staticmethod
    def pickle_dump(data, write_file):
        pickle_file = open(write_file, 'wb')
        pickle.dump(data, pickle_file)
        pickle_file.close()
        return None

    @staticmethod
    def pickle_load(read_file):
        pickle_file = open(read_file, 'rb')
        result = pickle.load(pickle_file)
        pickle_file.close()
        return result


class QuestionDataHandle:
    def __init__(self):
        pass

    def get_data(self, generate_new=False, pick_file='vrp_question.pick'):
        if not generate_new:
            try:
                print("will get data by file!")
                # 目前的实现 配置信息不能在导出后有变化。  如需优化 需要将题目数据配置信息 同时导出导入
                return Utils.pickle_load(pick_file)
            except Exception as e:
                print("!! Attention !! can not load from vrp_question.pick. will generate new! \n")
                # 报错后,继续用新生成的数据 当然 这里也可以报错后 退出处理
        return self.generate_data_process(pick_file)

    def generate_data_process(self, pick_file):
        cargo_sites, cargo_site_info_dict, car_info_dict = self.generate_data()
        Utils.pickle_dump((cargo_sites, cargo_site_info_dict, car_info_dict), pick_file)
        return cargo_sites, cargo_site_info_dict, car_info_dict

    def generate_data(self):
        cargo_sites = list(range(1, cargo_site_total + 1))  # cargo_site 从1开始, 0留给这里唯一的配送中心
        car_info_dict = {car_no: car_info(random.choice(car_speed_range),
                                          random.choice(car_carrying_range))
                         for car_no in range(1, max_car_no + 1)}
        return cargo_sites, self.get_cargo_site_info(cargo_sites), car_info_dict

    def get_cargo_site_info(self, cargo_sites):
        while True:
            cargo_site_info_dict = {site_no: cargo_site_info(random.choice(site_location_range),
                                                             random.choice(site_location_range),
                                                             random.randint(0, max_cargo_weight))
                                    for site_no in cargo_sites}
            # 补充起点和终点的site_location信息,计算距离时会用到。最后一个weight用不到
            cargo_site_info_dict[0] = cargo_site_info(0, 0, 0)
            # 偶尔有生成的货物点 xy坐标都一样的情况,此时重新再生成
            site_location_list = [(info.site_location_x, info.site_location_y)
                                  for info in cargo_site_info_dict.values()]
            if len(set(site_location_list)) == len(site_location_list):
                return cargo_site_info_dict


class VRPData:
    def __init__(self, cargo_sites, cargo_site_info_dict, car_info_dict):
        self.cargo_sites = cargo_sites
        self.cargo_site_info_dict = cargo_site_info_dict
        self.car_info_dict = car_info_dict
        self.site_location = [(info.site_location_x, info.site_location_y)
                              for key, info in sorted(self.cargo_site_info_dict.items(), key=lambda x: x[0])]

    def get_a_possible_try(self, cargo_site_list=None):
        if not cargo_site_list:
            cargo_site_list = random.sample(self.cargo_sites, car
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值