CP-SAT创建布尔变量报错:判断教师授课次数是否为0的解决方法
问题解决方法
错误根源
你遇到的TypeError是因为OR-Tools CP-SAT不支持嵌套的等式表达式:teacher_works_n_times == 0会返回一个BoundedLinearExpression对象,无法直接与布尔变量进行相等比较。同时你定义teacher_works_n_times的方式也有误,不能用model.NewIntVar(...).Sum(...)的链式调用。
修正步骤
- 正确计算教师授课次数总和:直接对
classes_by_teacher[t]中的变量求和,得到表示授课次数的线性表达式。 - 用双向约束关联布尔变量与数值条件:通过
OnlyEnforceIf方法,分别定义当布尔变量为真时总和为0,以及布尔变量为假时总和大于0的约束,确保两者完全等价。
修改后的完整代码
classes_by_teacher = {} for t in all_teachers: cur_classes = [] for d in all_days: for p in all_day_parts: for g in all_groups: for s in all_subjects: cur_classes.append(classes[(t, d, p, g, s)]) classes_by_teacher[t] = cur_classes teacher_i_doesnt_work = [] for t in all_teachers: # 直接计算授课次数总和,无需提前创建IntVar teacher_works_n_times = sum(classes_by_teacher[t]) teacher_doesnt_work = model.NewBoolVar(f"teacher {t} does not work") # 双向约束:布尔变量为真时,授课次数必须为0 model.Add(teacher_works_n_times == 0).OnlyEnforceIf(teacher_doesnt_work) # 反向约束:布尔变量为假时,授课次数必须大于0 model.Add(teacher_works_n_times > 0).OnlyEnforceIf(teacher_doesnt_work.Not()) teacher_i_doesnt_work.append(teacher_doesnt_work) model.Maximize(sum(teacher_i_doesnt_work))
额外说明
如果需要将teacher_works_n_times显式定义为IntVar(比如需要单独跟踪这个变量),可以这样写:
teacher_works_n_times = model.NewIntVar(0, 10000, f"How many times does {t} work") model.Add(teacher_works_n_times == sum(classes_by_teacher[t]))
之后再添加和布尔变量关联的双向约束即可。
内容的提问来源于stack exchange,提问作者mikecarti
相关产品推荐
相关产品推荐

