python 在ortools中计算IntVar列表中出现的次数

j5fpnvbx  于 2023-04-28  发布在  Python
关注(0)|答案(1)|浏览(169)

我在尝试解决一个员工调度问题。有一份24小时轮班工作的员工名单,一个月工作8天。我需要每天减少员工数量的分布,但我无法让它工作。因为每个员工的工作时间都是固定的,所以我不能把所有员工的工作时间加起来,得到平均值。我在理论上找到的解决方案是这样的:

days_six_employee_working = len([day for day in counts if day["count"] == 6])
days_seven_employee_working = len([day for day in counts if day["count"] == 7])
days_eigth_employee_working = len([day for day in counts if day["count"] == 8])
days_nine_employee_working = len([day for day in counts if day["count"] == 9])
days_ten_employee_working = len([day for day in counts if day["count"] == 10])
weighted_sum = days_six_employee_working**days_six_employee_working
+days_seven_employee_working**days_seven_employee_working
+days_eigth_employee_working**days_eigth_employee_working
+days_nine_employee_working**days_nine_employee_working
+days_ten_employee_working**days_ten_employee_working)

model.Maximize(weighted_sum)

但有两个问题:
1.我事先不知道计数列表(例如,我不知道[6,7,8,9,10]
1.我无法过滤日期:day["count"] == 6
顺便说一下,这是我每天计算员工数量的方法,如果有帮助的话:

working = []
for day in range(1, days_in_month+1):
    working.append(sum([employee.shifts[day] for employee in employees]))
for employee in employees:
    for day in range(1, days_in_month+1):
        employee.shifts[day] = model.NewBoolVar(f"emp_{employee.name}_day_{day}")

我肯定是新的cp-sat,所以请指出任何更好的所以

anhgbhbe

anhgbhbe1#

这就是我找到解决办法的方式。主要来源于:this post
1.用于最终计数的容器。因为我已经知道我想要过滤的数字,所以我从它构建了一个字典。

number_of_occurrences = {
    i: self.model.NewIntVar(0, 31, f"count_of_{i}_days")
    for i in range(
        self.settings["min_people_per_day"],
        self.settings["max_people_per_day"] + 1,
    )
}

1.获取列表中所有工作日的人数。我可能会在这里使用model.Add(x == sum(...)),但我没有。

working = []
for day in self._days_in_month:
    x = self.model.NewIntVar(
        0, len(self._assistant_list), f"number_of_asses_on_day_{day}"
    )
    self.model.AddAbsEquality(
        x, sum([ass.shifts[day] for ass in self._assistant_list])
    )
    working.append(x)

1.关键部分,过滤。我们创造一个临时的。变量名为is_equal。如果当前日期等于我们当前正在过滤的日期,则这将是正数。然后我们将其添加到count列表中,并在and中对该列表求和。因为sum将True取为1,False取为0,所以最后我们得到了主列表中出现次数的总和。

for key, val in self.number_of_occurrences.items():
    count = []
    for num in working:
        is_equal = self.model.NewBoolVar("is_equal")
        self.model.Add(num == key).OnlyEnforceIf(is_equal)
        self.model.Add(num != key).OnlyEnforceIf(is_equal.Not())
        count.append(is_equal)
    self.model.Add(val == sum(count))

相关问题