Google OR-工具-查找最佳的小组作业

问题描述

我正在使用ortools(在Python中)将学生分配给小组。每个学生都有三种不同技能的水平。通过示例程序,我可以创建小组,并确保每个小组中至少有一个学生的每种技能都有一定的水平:

for p in all_people:
    for g in all_groups:
        allocation[(p,g)] = model.NewBoolVar('shift_p%ig%i' % (p,g))


# Setup Constraints

# Each person is assigned to exactly one group.
for p in all_people:
    model.Add(sum(allocation[(p,g)] for g in all_groups) == 1)

# Each group has at enough people but not too many.
for g in all_groups:
    model.Add(sum(allocation[(p,g)] for p in all_people) >= min_size)
    model.Add(sum(allocation[(p,g)] for p in all_people) <= max_size)


# Each group has at least one person with good skills
for g in all_groups:
    for s in all_skills:
        model.Add(sum(skills_enough[p][s] *  allocation[(p,g)] for p in all_people  ) > 0)

这可以很好地解决约束满足问题。

我现在想做的是添加一个优化约束,该约束试图使每个组中的技能水平尽可能地提高。我尝试了几种不同的配置,但是无法提供一些功能

  • 我无法找出一种方法使ORTools在生成器中使用最小值,即进行min(student_info[p][s] * allocation[(p,g)] for p in all_people)以获得g组中的最小值,因为没有min()等效项sum()
  • 我也无法将其设置为最小化平方和,因为将乘法项相加会生成TypeError: Not an integer linear expression:。公平地说,它不再是线性的。示例代码
model.Minimize(
sum(
    sum(
        (
            sum(student_info[p][s] * allocation[(p,g)] for p in all_people) *
            sum(student_info[p][s] * allocation[(p,g)] for p in all_people)
         ) for s in all_skills
    ) for g in all_groups
) )

一种优化与线性求解器模型匹配的组的方法与设置现有问题的方法一样有帮助。

解决方法

对于min()和max(),您需要使用AddMinEquality和AddMaxEquality。

请注意,这些变量包含一个变量数组,因此您需要根据自己的情况创建中间变量。

请参见this doc