Python笔记之按订单重量与去向进行拼车运输算法

需求

在TMS模块,对同去向不同客户之间的订单进行拼车以节省运输成本。

算法

使用Python的interval、itertools 进行拼车。

python 复制代码
# -*- codeing = utf-8 -*-
# @File : TMS拼车2.py
# @Author : 一起种梧桐吧
# @Version : Python 3.10.0
# @Software : PyCharm
# @Time : 2023年7月31日
# @Purpose : TMS运输管理系统同路线客户拼车

from interval import Interval
from itertools import combinations

XL = ["东", "西", "南", "北"]
KH = {"客户01": ["东", 100],
	  "客户02": ["东", 150],
	  "客户03": ["东", 190],
	  "客户04": ["东", 250],
	  "客户05": ["南", 160],
	  "客户06": ["南", 170],
	  "客户07": ["南", 200]}
ZZ = {"客户01": {"dd01": 12550, "dd02": 300},
	  "客户02": {"dd03": 11020, "dd04": 11000, "dd05": 1180, },
	  "客户03": {"dd06": 11050, "dd07": 1220, "dd08": 110, },
	  "客户04": {"dd09": 6350, "dd10": 5280},
	  "客户05": {"dd11": 3050, "dd12": 3180},
	  "客户06": {"dd13": 3520, "dd14": 3180},
	  "客户07": {"dd15": 5390, "dd16": 3210}}
CL = {"X": 11500, "D": 13500}


def load_1shop1order(shop: str, zzl_min: float, zzl_max: float):
	'''
	单门店-单订单装车
	:param zzl_min: 最小载重量
	:param zzl_max: 最大载重量
	:return: 满足条件的订单ID
	'''
	zzl_interval = Interval(zzl_min, zzl_max)
	for item in sorted(ZZ[shop].items(), key=lambda x: x[1], reverse=True):
		if item[1] in zzl_interval:
			return item[0], item[1]
		elif item[1] < zzl_min:
			return None
		else:
			continue
	else:
		return None


def load_1shop2order(shop: str, zzl_min: float, zzl_max: float):
	'''
	单门店-多订单装车
	:param zzl_min: 最小载重量
	:param zzl_max: 最大载重量
	:return: 满足条件的订单ID
	'''
	zzl_interval = Interval(zzl_min, zzl_max)
	dct_order = ZZ[shop]
	if sum(dct_order.values()) in zzl_interval:
		return tuple(dct_order.keys()), sum(dct_order.values())
	elif sum(dct_order.values()) <= zzl_min:
		return None
	else:
		lst_order = []
		for key, value in dct_order.items():
			if value <= zzl_max:
				lst_order.append(key)
		lst_comb = []
		for i in range(1, len(lst_order) + 1):
			lst_comb.extend(combinations(lst_order, i))
		dct_comb = {}
		for order_comb in lst_comb:
			zl_order_comb = 0
			for order in order_comb:
				zl_order_comb += dct_order[order]
			if zl_order_comb in zzl_interval:
				dct_comb.update({order_comb: zl_order_comb})
		for item in sorted(dct_comb.items(), key=lambda x: x[1], reverse=True):
			if item[1] in zzl_interval:
				return item[0], item[1]
			elif item[1] < zzl_min:
				return None
			else:
				continue
		else:
			return None


def load(truck=CL):
	'''
	根据卡车装载量进行自动装载
	:param truck: 卡车信息
	:return: 满足条件的订单ID
	'''
	zzl_min = truck["X"]
	zzl_max = truck["D"]
	zzl_interval = Interval(zzl_min, zzl_max)
	dct_order = {}
	for item in ZZ.values():
		dct_order.update(item)
	# step_01:尝试单店单订单装载
	lst_order1 = []
	for shop in ZZ.keys():
		res = load_1shop1order(shop, zzl_min, zzl_max)
		if res:
			lst_order1.append(res)
	# print(lst_order1)
	dct_order_load1 = {}
	for item_comb in lst_order1:
		if item_comb:
			dct_order_load1.update({item_comb[0]: item_comb[1]})
	if dct_order_load1:
		for key, value in sorted(dct_order_load1.items(), key=lambda x: x[1], reverse=True):
			# return key, value
			print("step_01", key, value)
	# step_02:尝试单店多订单装载
	lst_order2 = []
	for shop in ZZ.keys():
		res = load_1shop2order(shop, zzl_min, zzl_max)
		if res:
			lst_order2.append(res)
	# print(lst_order2)
	dct_order_load2 = {}
	for item_comb in lst_order2:
		if item_comb:
			dct_order_load2.update({item_comb[0]: item_comb[1]})
	if dct_order_load2:
		for key, value in sorted(dct_order_load2.items(), key=lambda x: x[1], reverse=True):
			# return key, value
			print("step_02", key, value)
	# step_03:尝试2店拼订单装载(由远及近)
	dct_shop_03 = {}
	zzl_interval_03 = Interval(zzl_min * 0.5, zzl_max * 0.75)
	for shop in ZZ.keys():
		zzl_shop = sum(ZZ[shop].values())
		if zzl_shop in zzl_interval_03:
			dct_shop_03[shop] = zzl_shop
	for key03, value03 in sorted(dct_shop_03.items(), key=lambda x: x[1], reverse=True):
		zzl_interval_new_03 = Interval(value03 * 0.33, value03) & Interval(zzl_min - value03, zzl_max - value03)
		if not zzl_interval_new_03:
			continue
		[qx03, yj03] = KH[key03]
		lst_shop_03_02 = []
		for shop03_02, qxyj03_02 in KH.items():
			if (qxyj03_02[0] == qx03) & (yj03 - qxyj03_02[1] in Interval(0, 50, lower_closed=False)):
				lst_shop_03_02.append(shop03_02)
		if not lst_shop_03_02:
			continue
		else:
			lst_order03 = []
			for shop02 in lst_shop_03_02:
				res = load_1shop2order(shop02, zzl_interval_new_03.lower_bound, zzl_interval_new_03.upper_bound)
				if res:
					lst_order03.append(res)
			if not res:
				continue
			dct_order_load03 = {}
			for item_comb in lst_order03:
				if item_comb:
					dct_order_load03.update({item_comb[0]: item_comb[1]})
			if dct_order_load03:
				for key03_02, value03_02 in sorted(dct_order_load03.items(), key=lambda x: x[1], reverse=True):
					lst_order_shop = list(ZZ[key03].keys())
					for order in key03_02:
						lst_order_shop.append(order)
					# return key, value
					print("step_03", tuple(lst_order_shop), value03_02 + value03)
	# step_04:尝试2店拼订单装载(由近到远)
	dct_shop_04 = {}
	zzl_interval_04 = Interval(zzl_min * 0.25, zzl_max * 0.5)
	for shop in ZZ.keys():
		zzl_shop = sum(ZZ[shop].values())
		if zzl_shop in zzl_interval_04:
			dct_shop_04[shop] = zzl_shop
	for key04, value04 in sorted(dct_shop_04.items(), key=lambda x: x[1], reverse=True):
		# print(Interval(value * 0.33, value), Interval(zzl_min - value, zzl_max - value))
		zzl_interval_new_04 = Interval(value04, value04 * 3) & Interval(zzl_min - value04, zzl_max - value04)
		if not zzl_interval_new_04:
			continue
		[qx04, yj04] = KH[key04]
		lst_shop_04 = []
		for shop04_02, qxyj04_02 in KH.items():
			if (qxyj04_02[0] == qx04) & (qxyj04_02[1] - yj04 in Interval(0, 50, lower_closed=False)):
				lst_shop_04.append(shop04_02)
		if not lst_shop_04:
			continue
		else:
			lst_order04 = []
			for shop04_02 in lst_shop_04:
				res = load_1shop2order(shop04_02, zzl_interval_new_04.lower_bound, zzl_interval_new_04.upper_bound)
				if res:
					lst_order04.append(res)
			# print(lst_order04)
			dct_order_load04 = {}
			for item_comb in lst_order04:
				if item_comb:
					dct_order_load04.update({item_comb[0]: item_comb[1]})
			if dct_order_load04:
				for key04_02, value04_02 in sorted(dct_order_load04.items(), key=lambda x: x[1], reverse=True):
					lst_order_shop = list(ZZ[key04].keys())
					for order in key04_02:
						lst_order_shop.append(order)
					# return key, value
					print("step_04", tuple(lst_order_shop), value04_02 + value04)


if __name__ == "__main__":
	load()
相关推荐
是main不是漫3 小时前
【双指针——移动零】数组划分类题目的入门基石
c++·算法
Nuanyt3 小时前
Agent 学习笔记(下篇三):上线工程、进阶选择与操作界面(Stage 7 / 7.5 / 8 + 延伸路线)
笔记·python·学习·memory·aiagent·harness
吴卫斌3 小时前
定投ETF实战指南(四):行业/主题ETF——定投的“进攻端“
开发语言·python·股票·量化
2601_967987373 小时前
Python——入门级(定义功能def函数)
python·函数·可变参数·默认参数·关键字参数
深圳市快瞳科技有限公司4 小时前
野外鸟类AI识别落地实录:输入适配、结构化输出、去重聚合与置信度分流的工程实践
算法·计算机视觉·鸟类识别·鸟类ai识别·野外鸟类观测·林业调查
叼烟扛炮4 小时前
Linux 学习笔记(四十一):TCP 并发演进——从单进程到多线程服务器
linux·运维·服务器·网络·笔记·学习·tcp/ip
叼烟扛炮5 小时前
Linux 学习笔记(四十三):网络编程进阶——自定义协议解决 TCP 粘包与守护进程
linux·开发语言·网络·笔记·tcp/ip
songyuc5 小时前
【Manskill3】TableSceneBuilder学习笔记
pytorch·笔记·学习
专注仿真6 小时前
梯度提升类(XFBoost)算法详解与代码实例
开发语言·人工智能·python·算法·大模型训练·控制算法
小豆庄6 小时前
视频遮罩追踪退场后ID撞号的排查—多目标场景下的失效
opencv·算法·bug·视频·python3.11