任务目标是创建一个船舶调度程序,对 5 年内的船舶调度进行优化,其中每个月和每个年内需要满足以下约束条件:
- 每月都必须有一艘且仅有一艘船处于“本地巡逻”(state = ‘C’)状态。
- 每一年都必须有一艘且仅有一艘船进行为期四个月的“远程巡逻”(state = ‘A’),从 7 月到 10 月。
- 每艘船必须在 5 年内进行一次为期 4 个月的检查(state = ‘4’)。
- 每艘船必须在 5 年内进行一次为期 8 个月的休息(state = ‘8’)。
- 每艘船大约每 5 个月必须进行一次例行维护(state = ‘M’)。
- 每艘船在任何一个月内只能处于一种状态,但也可以没有状态(空闲/空缺,‘_’)。
目标函数制定:定义松弛变量来计算调度偏离 5 个月(‘M’)维护计划的次数(以及数量)。
解决方案:
- 将约束中左侧的表达式取绝对值。
- 使用 Pulp 的
pulp.lpSum()
函数将绝对值表达式求和。 - 将总和值与预期的值进行比较。
- 使用 Pulp 的
pulp.solve()
函数求解问题。
import pulp
# 创建模型
model = pulp.LpProblem("Scheduling", pulp.LpMinimize)
http://www.jshk.com.cn/mb/reg.asp?kefu=xiaoding;//爬虫IP免费获取;
# 创建变量
ship_list = ['ship1', 'ship2', 'ship3']
time_list = range(1, 61) # 5 年,每个月为一个时间单位
states = ['C', 'A', '4', '8', 'M', '_']
# 创建决策变量
x = pulp.LpVariable.dicts("x", (ship_list, time_list, states), cat='Binary')
# 添加约束
for ship in ship_list:
# 每月都必须有一艘且仅有一艘船处于“本地巡逻”(state = 'C')状态。
model += pulp.lpSum([x[ship][t]['C'] for t in time_list]) == 1
# 每一年都必须有一艘且仅有一艘船进行为期四个月的“远程巡逻”(state = 'A'),从 7 月到 10 月。
for year in range(1, 6):
model += pulp.lpSum([x[ship][t]['A'] for t in range(12 * (year - 1) + 7, 12 * (year - 1) + 11)]) == 1
# 每艘船必须在 5 年内进行一次为期 4 个月的检查(state = '4')。
model += pulp.lpSum([x[ship][t]['4'] for t in time_list]) == 1
# 每艘船必须在 5 年内进行一次为期 8 个月的休息(state = '8')。
model += pulp.lpSum([x[ship][t]['8'] for t in time_list]) == 1
# 每艘船大约每 5 个月必须进行一次例行维护(state = 'M')。
for t in range(0, 60, 5):
model += pulp.lpSum([x[ship][t]['M'] for t in range(t, t + 5)]) == 1
# 每艘船在任何一个月内只能处于一种状态,但也可以没有状态(空闲/空缺,'_')。
for t in time_list:
model += pulp.lpSum([x[ship][t][state] for state in states]) == 1
# 添加目标函数
model += pulp.lpSum([abs(pulp.lpSum([x[ship][t]['M'] for t in range(t, t + 5)]) - 1) for ship in ship_list for t in range(0, 60, 5)])
# 求解模型
model.solve()
# 打印结果
for ship in ship_list:
for t in time_list:
for state in states:
if x[ship][t][state].value() == 1:
print(f"{ship} is in {state} state at time {t}")
这个 Python 代码使用 Pulp 求解了船舶调度问题。代码首先创建了一个模型,然后创建了变量和约束。最后,它添加了目标函数并求解了模型。最后,它打印了结果。