2022深圳杯C题python解法

  2022深圳杯C题python解法_第1张图片

思路:

主要看第一大题,它是一个目标规划问题

现有资源是125车和150组电池,相当于含有275组可使用电池,用完了之后就需要充电了,每次充电需要三个小时,需要考虑的问题是直接派出新车还是对该车换电池,在换完电池后,需要对电池进行充电,

通过一个动态规划过程自定义函数作为目标函数,用群智能搜索算法进行求解即可。

理清第一问其中的思路,其它小题都是在第一小问的基础上进行的。

已知条件:

1、P点到D点:里程10 km,双向单车(轨)专用道,车距不小于200 m

注意:需要考虑车身的长度。
假设车身为5米,约有96台车能同时行驶。
在理想状态下,相当于每隔12秒可进行发一趟车。

2、车辆:125辆,速率60 km/h, 每车额定装配6个电池组,初始位于换电站空载状态,且每个车载电池组的SoC(荷电状态)都是100%,拉一趟物料,不充电的情况下,耗时22分钟


3、电池:900组,单个电池组独立计量,车载6个电池组一致消耗电量,空载车辆每行驶3分钟每个电池组的SoC都减少1%,载货车辆每行驶2分钟每个电池组的SoC都减少1%,车载电池组的SoC位于区间[10%,25%]时方可更换,备更换电池组的SoC为100%,900/6=150,相当于有150个备用电池。

4、耗时:每更换一个电池组耗时20秒,每个电池组更换下来后充电、检测进入备用状态总耗时3小时,装卸货每次各需要1分钟

耗电5%+3.33%=8.33%
约9趟--75%
约10趟--83.33%
拉货9趟(9.5趟)后或10趟(10.5趟)后电量处于[10%,25%]时,可更换电池(这个点很关键)


对于动态规划,首先推荐还是群智能优化算法,自定义动态规划目标函数,限定待求参数(也就是充电站位置)的上下限,这里话是【0,10】,必须给定参数的上下限,其后根据群智能优化法搜索到局部较优的结果。

第一问代码:


import numpy as np
 
from itertools import product
 
class Lorry:
 
def __init__(self, station1, station2):
 
# station1: P->D 换电站位置, station2:D->P 换电站位置
 
self.bet = 100 # 当前电池电量
 
self.p = 20 - station2 # 当前位置
 
self.t = 0 # 当前时间
 
self.station1 = station1
 
self.station2 = station2
 
self.n_charge = 0 # 充电次数
 
def __str__(self):
 
return "Lorry is at position {}, with battery {}, at time {}".format(self.p, self.bet, self.t)
 
def move(self, dt):
 
# 0(P)___10(D)___20(P')
 
# dt时间后的演化结果
 
if 0 <= self.p < 10 or np.isclose(self.p, 0):
 
# P->D
 
self.bet -= 1/2 * dt # 电池消耗
 
elif 10 <= self.p < 20 or np.isclose(self.p, 10):
 
# D->P
 
self.bet -= 1/3 * dt # 电池消耗
 
if self.bet < 0 or np.isclose(self.bet, 0):
 
raise Exception("Lorry is out of battery")
 
self.t = self.t + dt # 时间变化
 
self.p = (self.p + dt * 1) % 20 # 位置变化
 
if np.isclose(self.p, 10) or np.isclose(self.p, 0):
 
# 装卸货时间
 
self.t += 1
 
self.recharge()
 
def recharge(self):
 
if (np.isclose(self.p, self.station1) or np.isclose(self.p, 20 - self.station2)) and 10 <= self.bet <= 12.6:
 
# 逐渐降低阈值,测试是否存在可行解
 
self.bet = 100
 
# print("Lorry is recharged at time {}".format(self.t))
 
# gap.append(self.t)
 
# print(self)
 
self.t += 2
 
self.n_charge += 1
 
# for (sta1, sta2) in product(np.arange(0, 10, 1), np.arange(0, 10, 1)):
 
for sta1 in np.arange(0.1, 10, 0.1):
 
sta2 = sta1
 
lorry = Lorry(sta1, sta2)
 
try:
 
for T in range(1000*60*10):
 
lorry.move(dt=0.1)
 
print('({:.1f}, {:.1f}) worked with charge {:d} times'.format(sta1, sta2, lorry.n_charge))
 
except Exception as e:
 
print((sta1, sta2), e, end='\r')
 
# # gap = []
 
# (sta1, sta2) = (5, 5)
 
# lorry = Lorry(sta1, sta2)
 
# for T in range(1000*60*10):
 
# lorry.move(dt=0.1)
 
# # print(lorry.n_charge)
 
# # gap = [gap[i] - gap[i-1] for i in range(1, len(gap))]
 
# # gap = np.array(gap)
 
# # print(gap.min())
 
# n_lorry = 75

第二问代码

import numpy as np
from itertools import product
 
 
class Lorry:
    def __init__(self, station1, station2):
        # station1: P->D 换电站位置, station2:D->P 换电站位置
        self.bet = 100  # 当前电池电量
        self.p = 20 - station2  # 当前位置
        self.t = 0  # 当前时间
        self.station1 = station1
        self.station2 = station2
        self.n_charge = 0  # 充电次数
        self.n_mission = 0  # 运货次数
 
    def __str__(self):
        return "Lorry is at position {:.1f}, charged {:d} times,\n complete mission {:d} times in {:.1f} minutes".format(self.p, self.n_charge, self.n_mission, self.t)
 
    def move(self, dt):
        # 0(P)___10(D)___20(P')
        # dt时间后的演化结果
        if 0 <= self.p < 10 or np.isclose(self.p, 0):
            # P->D
            self.bet -= 1/2 * dt  # 电池消耗
        elif 10 <= self.p < 20 or np.isclose(self.p, 10):
            # D->P
            self.bet -= 1/3 * dt  # 电池消耗
        if self.bet < 0 or np.isclose(self.bet, 0):
            raise Exception("Lorry is out of battery")
        self.t = self.t + dt  # 时间变化
        self.p = (self.p + dt * 1) % 20  # 位置变化
        if np.isclose(self.p, 0):
            # 装卸货时间
            self.t += 1
        elif np.isclose(self.p, 10):
            self.t += 1
            self.n_mission += 1
        self.recharge()
 
    def recharge(self):
        # 逐渐降低阈值,测试是否存在可行解
        if np.isclose(self.p, self.station1) and 10 <= self.bet <= 12.6:
            # 满载到达换电站
            self.bet = 100
            self.t += 2
            self.n_charge += 1
        elif np.isclose(self.p, 20 - self.station2) and 10 <= self.bet <= 12.6:
            # 空载到达换电站
            self.bet = 100
            self.t += 2/3  # 只考虑换电为2, 考虑换电为2/3
            self.n_charge += 1
 
 
lorry = Lorry(7.0, 2.0)
print("选址位于(7.0, 2.0)")
while lorry.t < (1000*60 - 0.1):
    lorry.move(dt=0.1)
print(lorry)
 
lorry = Lorry(5.0, 5.0)
print("选址位于(5.0, 5.0)")
while lorry.t < (1000*60 - 0.1):
    lorry.move(dt=0.1)
print(lorry)
 
lorry = Lorry(3.0, 8.0)
print("选址位于(3.0, 8.0)")
while lorry.t < (1000*60 - 0.1):
    lorry.move(dt=0.1)
print(lorry)
 
# for (sta1, sta2) in product(np.arange(0, 10, 1), np.arange(0, 10, 1)):
# # for sta1 in np.arange(0.1, 10, 0.1):
# #     sta2 = sta1
#     lorry = Lorry(sta1, sta2)
#     try:
#         for T in range(1000*60*10):
#             lorry.move(dt=0.1)
#         print('({:.1f}, {:.1f}) worked with charge {:d} times'.format(sta1, sta2, lorry.n_charge))
#     except Exception as e:
#         print((sta1, sta2), e, end='\r')
 
# # gap = []
# (sta1, sta2) = (5, 5)
# lorry = Lorry(sta1, sta2)
# for T in range(1000*60*10):
#     lorry.move(dt=0.1)
# # print(lorry.n_charge)
# # gap = [gap[i] - gap[i-1] for i in range(1, len(gap))]
# # gap = np.array(gap)
# # print(gap.min())

2022深圳杯C题python解法_第2张图片

具体换车换电流程为:

初始时, 有75辆车运行, 50辆满电的车备用.

将所有车按1-75进行编号, 初始时, 以0.2km间隔发车, 则最后一辆车与第一辆车有约为5km的间隔.

在满载的状态下, 若如果路过换电站时, 电量在10%至12.6%, 只选择换电, 不选择换车.

在空载的状态下, 若如果路过换电站时, 电量在10%至12.6%, 按照如下状态进行换车换电:

第一轮位于空载状态下路过换电站, 对1-50车进行换车操作, 50-75号车进行换电操作, 则75号与1号车间隔缩小(但仍远大于0.2km), 50号与51号车间隔变大.

第二轮位于空载状态下路过换电站, 对51-75, 1-25车进行换车操作, 25-75号车进行换电操作

第三轮位于空载状态下路过换电站, 对25,-75车进行换车操作, 1-25号车进行换电操作

三轮操作为一个循环, 间距回到原来的状态.

你可能感兴趣的:(python,开发语言)