我正在使用 python 解决一个优化问题,我必须优化一家理论医院的时间表。这个时间表有 3 列代表不同的剧院,每行 9 个时段代表每天的时段数。
每个时间段都被一个手术占用,描述每个手术的值之一是它是否需要麻醉师,而问题的限制之一是在任何一个手术中都不能有超过两个需要的麻醉师。所有手术室的给定时间段。
因为我的时间表是这样表示的:
剧院1 | 剧场2 | 剧场2 |
---|---|---|
插槽 1 | 插槽 1 | 插槽 1 |
插槽 2 | 插槽 2 | 插槽 2 |
插槽3 | 插槽3 | 插槽3 |
插槽 4 | 插槽 4 | 插槽 4 |
插槽 5 | 插槽 5 | 插槽 5 |
插槽 6 | 插槽 6 | 插槽 6 |
插槽7 | 插槽7 | 插槽7 |
插槽8 | 插槽8 | 插槽8 |
插槽 9 | 插槽 9 | 插槽 9 |
我创建了这个函数来检查 3 个剧院的一个槽位的手术情况,如果所需的数量超过 2 的限制,则返回 false,如果所需的数量在限制之内,则返回 true。
def AnaesthetistsWithinLimit(timetable, anaesthetistLimit):
# Index of column, theatre, max 3
for i in range(len(timetable)):
# Index of row, slot, max 9
for j in range(len(timetable[0])):
comparisonArray = [timetable[0][j], timetable[1][j], timetable[2][j]]
anaesthetistCount = 0
for y in comparisonArray:
if y["requires_anaesthetist"] == "Yes":
anaesthetistCount += 1
if anaesthetistCount > anaesthetistLimit:
print("Constraint breached:")
print(" " + str(anaesthetistCount) + " anaesthetists were required")
print(" limit is " + str(anaesthetistLimit) + " anaesthetists.")
return False
return True
为了生成解决方案,我使用一种方法来创建随机分类的槽位,从包含所有可能的手术及其详细信息的 csv 文件中获取,这些信息包含在外科手术数据中。
def RandomiseTimetable(timetable, surgeryData):
for x in range(3):
column = []
for y in range(9):
randomIndex = random.randint(0, len(surgeryData) - 1)
randomRow = surgeryData.iloc[randomIndex]
column.append({
"surgery": randomRow["surgery"],
"name": randomRow["name"],
"requires_anaesthetist": randomRow["requires_anaesthetist"],
})
timetable.append(column)
return timetable
随机化时间表是有效的,正如我在编辑器中看到的那样,表格随着每次运行而变化,但是当我尝试测试此约束并生成新的解决方案直到满意为止时,它要么不会生成新的解决方案根本没有或继续生成,迫使我手动停止它。
这里我想检查当前所需的数量是否在限制范围内,如果不在限制范围内,则生成新的解决方案。然后,一旦为真,它应该逃脱 while 循环,并继续执行适应度函数。
while AnaesthetistsWithinLimit(timetable, 2) != True:
timetable = RandomiseTimetable(timetable, surgeryData)
FitnessFunction(timetable, True)
但是,如此处所示,它只是继续运行限制检查器,并且从未真正生成新的解决方案。
Constraint breached:
3 anaesthetists were required
limit is 2 anaesthetists.
Constraint breached:
3 anaesthetists were required
limit is 2 anaesthetists.
Constraint breached:
3 anaesthetists were required
limit is 2 anaesthetists.
Constraint breached:
3 anaesthetists were required
limit is 2 anaesthetists.
Constraint breached:
3 anaesthetists were required
limit is 2 anaesthetists.
Constraint breached:
3 anaesthetists were required
limit is 2 anaesthetists.
...
我看不出我错过了什么。如果检测到违规,麻醉师检查器将返回 false,否则返回 true。因此,当此测试返回 false 时,生成一个新的解决方案。据我了解,python 通过引用传递列表,因此该函数应该使用在其下面的行中生成的时间表。
我可能误解了什么?
我认为问题在于您不断在
timetable
内向 RandomiseTimetable()
添加更多列,但您只查看 comparisonArray
中 AnaesthetistsWithinLimit()
中的前三列。因此,您的 timetable
确实发生了变化,但您只查看在第一次迭代中已经拥有的未更改的列。
我会尝试在
RandomiseTimetable()
中初始化一个新的空时间表,然后您可以在其中附加新列:
def RandomiseTimetable(surgeryData):
timetable = []
for x in range(3):
...
timetable.append(column)
return timetable
条件
y["requires_anaesthetist"] == "Yes"
仅覆盖三行之一,因为 y 的类型为 ["", "", ""]
在您的代码中,您可以使用 count 并将所述条件更改为
anaesthetistCount = y.count("Yes")
if anaesthetistCount > anaesthetistLimit:
...