ORtools 安排学生 类 有冲突的时间表
ORtools scheduling students to classes with conflicting schedules
在我的问题中,我有学生每个人都需要分配给一个 class。每个学生和每个 class 都有一个时间表,如果一个学生被分配到一个 class,时间表不能冲突。
举个小例子,假设有五个时间块。如果学生的日程安排在第三个时间段已满,但所有其他时间段均空闲,则他们的日程安排将类似于 [0,0,1,0,0]
。类似地,如果 class 发生在第一次和第二次时间块上,它的时间表将看起来像 [1,1,0,0,0]
。因为这个学生的日程与这个class的日程不冲突,所以可以把这个学生分配到这个class。但是,如果学生的日程安排是 [1,0,0,0,0]
,则无法将他们分配到 class。
使用 google 的 ortools,约束看起来很简单:每个学生只有一个 class,如果我们有 2 个学生时间表 S 和 3 个 class 时间表 C:
S = {0:[0,0,1,0,0],1:[0,1,0,1,0]}
C = {0:[1,1,0,0,0],1:[0,0,1,0,1],2:[1,0,0,0,0]}
然后学生 [i]
只有在 np.dot(np.asarray(S[s]),np.asarray(C[c]))==0
才能分配给 class [j]
,即时间表的点积为零。
实施后一个约束对我没有用。我尝试了以下方法:
num_students = 2
num_classes = 3
all_students = range(num_students)
all_classes = range(num_classes)
S = {0:[0,0,1,0,0],1:[0,1,0,1,0]}
C = {0:[1,1,0,0,0],1:[0,0,1,0,1],2:[1,0,0,0,0]}
# Creates the model.
model = cp_model.CpModel()
# Creates scheduling variables.
# shifts[(c, s)]: student c is assigned to class s.
# 1 if true, 0 if not
sched = {}
for s in all_students:
for c in all_classes:
sched[(c,s)] = model.NewBoolVar('shift_c%is%i' % (c, s))
# Each class is assigned to exactly one student in the schedule period.
for s in all_students:
model.Add(sum(sched[(c, s)] for c in all_classes) == 1)
# The schedules cannot conflict
for c in all_classes:
for s in all_students:
model.AddBoolOr([(sched[(c,s)] and np.dot(np.asarray(S[s]),np.asarray(C[c]))==0),
sched[(c,s)].Not()])
但是,当我 运行 这样做时,出现以下错误:
<ipython-input-41-9aad6f1c8113> in main()
55 for s in all_students:
56 model.AddBoolOr([(sched[(c,s)] and np.dot(np.asarray(S[s]),np.asarray(C[c]))==0),
---> 57 sched[(c,s)].Not()])
58
59
/anaconda3/lib/python3.6/site-packages/ortools/sat/python/cp_model.py in AddBoolOr(self, literals)
1162 model_ct = self.__model.constraints[ct.Index()]
1163 model_ct.bool_or.literals.extend(
-> 1164 [self.GetOrMakeBooleanIndex(x) for x in literals])
1165 return ct
1166
/anaconda3/lib/python3.6/site-packages/ortools/sat/python/cp_model.py in <listcomp>(.0)
1162 model_ct = self.__model.constraints[ct.Index()]
1163 model_ct.bool_or.literals.extend(
-> 1164 [self.GetOrMakeBooleanIndex(x) for x in literals])
1165 return ct
1166
/anaconda3/lib/python3.6/site-packages/ortools/sat/python/cp_model.py in GetOrMakeBooleanIndex(self, arg)
1408 else:
1409 raise TypeError('NotSupported: model.GetOrMakeBooleanIndex(' +
-> 1410 str(arg) + ')')
1411
1412 def GetIntervalIndex(self, arg):
TypeError: NotSupported: model.GetOrMakeBooleanIndex(True)
这只是重新格式化 AddBoolOr 语句的问题,还是我遗漏了更大的东西?
感谢任何帮助!
- 您不能将
min, max, or, and
用于 ortools 创建的变量。
- AddBoolOr 只需要 BoolVars。
针对您的问题,您可以执行以下操作之一:
- 固定值
if np.dot(np.asarray(S[s]),np.asarray(C[c])) != 0:
model.Add(sched[(c,s)] == 0)
- 不创建布尔值如果 np.dot(np.asarray(S[s]),np.asarray(C[c]))!=0
在我的问题中,我有学生每个人都需要分配给一个 class。每个学生和每个 class 都有一个时间表,如果一个学生被分配到一个 class,时间表不能冲突。
举个小例子,假设有五个时间块。如果学生的日程安排在第三个时间段已满,但所有其他时间段均空闲,则他们的日程安排将类似于 [0,0,1,0,0]
。类似地,如果 class 发生在第一次和第二次时间块上,它的时间表将看起来像 [1,1,0,0,0]
。因为这个学生的日程与这个class的日程不冲突,所以可以把这个学生分配到这个class。但是,如果学生的日程安排是 [1,0,0,0,0]
,则无法将他们分配到 class。
使用 google 的 ortools,约束看起来很简单:每个学生只有一个 class,如果我们有 2 个学生时间表 S 和 3 个 class 时间表 C:
S = {0:[0,0,1,0,0],1:[0,1,0,1,0]}
C = {0:[1,1,0,0,0],1:[0,0,1,0,1],2:[1,0,0,0,0]}
然后学生 [i]
只有在 np.dot(np.asarray(S[s]),np.asarray(C[c]))==0
才能分配给 class [j]
,即时间表的点积为零。
实施后一个约束对我没有用。我尝试了以下方法:
num_students = 2
num_classes = 3
all_students = range(num_students)
all_classes = range(num_classes)
S = {0:[0,0,1,0,0],1:[0,1,0,1,0]}
C = {0:[1,1,0,0,0],1:[0,0,1,0,1],2:[1,0,0,0,0]}
# Creates the model.
model = cp_model.CpModel()
# Creates scheduling variables.
# shifts[(c, s)]: student c is assigned to class s.
# 1 if true, 0 if not
sched = {}
for s in all_students:
for c in all_classes:
sched[(c,s)] = model.NewBoolVar('shift_c%is%i' % (c, s))
# Each class is assigned to exactly one student in the schedule period.
for s in all_students:
model.Add(sum(sched[(c, s)] for c in all_classes) == 1)
# The schedules cannot conflict
for c in all_classes:
for s in all_students:
model.AddBoolOr([(sched[(c,s)] and np.dot(np.asarray(S[s]),np.asarray(C[c]))==0),
sched[(c,s)].Not()])
但是,当我 运行 这样做时,出现以下错误:
<ipython-input-41-9aad6f1c8113> in main()
55 for s in all_students:
56 model.AddBoolOr([(sched[(c,s)] and np.dot(np.asarray(S[s]),np.asarray(C[c]))==0),
---> 57 sched[(c,s)].Not()])
58
59
/anaconda3/lib/python3.6/site-packages/ortools/sat/python/cp_model.py in AddBoolOr(self, literals)
1162 model_ct = self.__model.constraints[ct.Index()]
1163 model_ct.bool_or.literals.extend(
-> 1164 [self.GetOrMakeBooleanIndex(x) for x in literals])
1165 return ct
1166
/anaconda3/lib/python3.6/site-packages/ortools/sat/python/cp_model.py in <listcomp>(.0)
1162 model_ct = self.__model.constraints[ct.Index()]
1163 model_ct.bool_or.literals.extend(
-> 1164 [self.GetOrMakeBooleanIndex(x) for x in literals])
1165 return ct
1166
/anaconda3/lib/python3.6/site-packages/ortools/sat/python/cp_model.py in GetOrMakeBooleanIndex(self, arg)
1408 else:
1409 raise TypeError('NotSupported: model.GetOrMakeBooleanIndex(' +
-> 1410 str(arg) + ')')
1411
1412 def GetIntervalIndex(self, arg):
TypeError: NotSupported: model.GetOrMakeBooleanIndex(True)
这只是重新格式化 AddBoolOr 语句的问题,还是我遗漏了更大的东西?
感谢任何帮助!
- 您不能将
min, max, or, and
用于 ortools 创建的变量。 - AddBoolOr 只需要 BoolVars。
针对您的问题,您可以执行以下操作之一:
- 固定值
if np.dot(np.asarray(S[s]),np.asarray(C[c])) != 0:
model.Add(sched[(c,s)] == 0)
- 不创建布尔值如果 np.dot(np.asarray(S[s]),np.asarray(C[c]))!=0