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

需求

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

算法

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

# -*- 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()

你可能感兴趣的:(算法,python,笔记)