Google Optimization Tools是否支持软约束?

时间:2018-03-22 19:39:40

标签: optimization constraints optaplanner constraint-programming

我想知道是否有人熟悉Google Optimization工具可以解决这个问题。我正在查看Google examples员工安排和N-queens。这两个例子似乎都让优化器仅在硬约束下运行(例如必须如此),但似乎无法解决(这是首选但不是必需的)。是否支持软约束?或者是目前唯一的软约束实现optaplanner

我不反对optaplanner。它只需要花费更多的精力来学习足够的java和" drools"使用的语法。

2 个答案:

答案 0 :(得分:2)

软约束的实现

正如Erwin所指出的,为了实现软约束,我们需要在模型中添加松弛变量并将它们放在目标函数中。为此,我们为我们的问题中的每个软约束变量添加了两个决策变量。这些决策变量代表了我们感兴趣的变量的松弛。然后我们可以使用以下公式来创建我们的软约束:

x1 + x1_surplus - x1_deficit = goal

x1是我们的决策变量,x1_surplusx1_deficit分别是我们的正面和负面松弛变量,目标是我们决定变量{{1 }}

一旦我们有了这个约束,我们必须添加一个最小化总百分比偏差的目标,如下所示:

x1

注意:

我们使用百分比偏差,因为我们经常处理以不同单位测量的变量(例如,下面示例中的千克与磅)。如果我们不使用百分比偏差,我们的变量中的松弛效应将是不平衡的。

Google OR Tools中的示例

以下是Google OR Tools中的基本工作示例。在这里,我们制作了两种产品,A和B,并且我们想要生产一定数量的产品。我们还有与制作这些产品相关的成本,以及我们希望在制作产品时花费的金额(在这种情况下为+/- 10000)。

minimize:
    (1/goal) * x1_surplus + (1/goal) * x1_deficit

答案 1 :(得分:0)

在OptaPlanner中,您不再需要使用drools语法。您可以使用新的增量ConstraintStreams。 ConstraintStreams快速且可扩展。

下面是一个示例,用于说明如何在您询问的NQueens问题上使用它们:

protected Constraint horizontalConflict(ConstraintFactory factory) {
    // Select a queen
    return factory.from(Queen.class)
            // Select a different queen on the same row
            .join(Queen.class,
                    equal(Queen::getRowIndex),
                    lessThan(Queen::getId))
            // Tell OptaPlanner not to put 2 queens on the same row
            .penalize("Horizontal conflict", HardSoftScore.ONE_HARD);
}

// For reference, the model:
@PlanningEntity
class Queen {
     long id;
     int columnIndex;
     @PlanningVariable
     int rowIndex;
     ... // getters/setters
}

类似地,您询问员工名册:

protected Constraint skillLacking(ConstraintFactory factory) {
    // Select a shift
    return factory.from(Shift.class)
            // The shift's employee doesn't have the required skill
            .filter(shift -> !shift.getEmployee().getSkillSet()
                    .contains(shift.getRequiredSkill())
            // Tell OptaPlanner to avoid that
            .penalize("Skill lacking", HardSoftScore.ONE_SOFT,
                    // Lose one soft point per minute of the shift
                    shift -> shift.getDurationInMinutes());
}

// For reference, the model:
@PlanningEntity
class Shift {
     Skill requiredSkill;
     LocalDateTime start;
     LocalDateTime end;
     @PlanningVariable
     Employee employee;
     ... // getters/setters
}
class Employee {
     String name;
     Set<Skill> skillSet;
     ... // getters/setters
}