我正在使用Python解决一个优化问题,我必须优化一个理论医院的时间表.本时间表有3栏代表不同的剧院,每行9个时段代表每天的时段数.

每个时间段都被一个手术占用,描述每个手术的一个值是它是否需要麻醉师,而这个问题的一个限制是,在所有手术室的任何给定时间段内,你不能有超过两个的需要.

因为我的时间表是这样表示的:

Theatre 1 Theatre 2 Theatre 2
Slot 1 Slot 1 Slot 1
Slot 2 Slot 2 Slot 2
Slot 3 Slot 3 Slot 3
Slot 4 Slot 4 Slot 4
Slot 5 Slot 5 Slot 5
Slot 6 Slot 6 Slot 6
Slot 7 Slot 7 Slot 7
Slot 8 Slot 8 Slot 8
Slot 9 Slot 9 Slot 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文件中提取,该文件包含在surgeryData中.

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通过引用传递列表,所以函数应该使用它下面一行生成的时间表.

我可能误解了什么?

推荐答案

我认为问题是你不断地在RandomiseTimetable()内向timetable附加更多的列,但你只看到comparisonArray中的前三列.因此,您的timetable确实发生了变化,但您只看到了在第一次迭代中已经存在的未改变的列.

我会try 在RandomiseTimetable()中初始化一个新的空时间表,然后你可以在该时间表中添加新的列:

def RandomiseTimetable(surgeryData):
    timetable = []
    for x in range(3):
        ...
        timetable.append(column)   
    return timetable

Python相关问答推荐

在函数内部使用eval(),将函数的输入作为字符串的一部分

比较两个二元组列表,NP.isin

Python多处理:当我在一个巨大的pandas数据框架上启动许多进程时,程序就会陷入困境

Python daskValue错误:无法识别的区块管理器dask -必须是以下之一:[]

发生异常:TclMessage命令名称无效.!listbox"

pyscript中的压痕问题

迭代嵌套字典的值

如何根据一列的值有条件地 Select 前N个组,然后按两列分组?

将标签移动到matplotlib饼图中楔形块的开始处

基于另一列的GROUP-BY聚合将列添加到Polars LazyFrame

如何获得3D点的平移和旋转,给定的点已经旋转?

有没有办法在不先将文件写入内存的情况下做到这一点?

如何重新组织我的Pandas DataFrame,使列名成为列值?

我可以不带视频系统的pygame,只用于游戏手柄输入吗?''

如何使用大量常量优化代码?

如何获取包含`try`外部堆栈的`__traceback__`属性的异常

Polars表达式无法访问中间列创建表达式

如何通过特定导入在类中执行Python代码

对当前的鼹鼠进行编码,并且我的按键获得了注册

将Pandas DataFrame中的列名的长文本打断/换行为_STRING输出?