合并两个 Forall 和 Sum 约束

问题描述

我正在寻找一种将这两个约束合并在一起的方法,并且觉得有一种方法可以利用 IF 语句将它们合并在一起。我的尝试如下,但我似乎无法获得正确执行的约束。有人可以提供帮助,因为我相信有一种简单的方法可以加入它们,从而使模型更有效地执行。


%Constraint 4 - Coaches must have 3 or less Juniors

constraint forall (coach in Coaches where coach != Unallocated) 
                    (sum(coachee in Coachees where   Coachee_Grade[coachee]=Junior) (Matched_Coach[coachee,coach]=1) <= 3);
                                                                                                  
%Constraint 5 - Coaches must have 4 or less Seniors

constraint forall (coach in Coaches where coach != Unallocated) 
                    (sum(coachee in Coachees where Coachee_Grade[coachee]=Senior) (Matched_Coach[coachee,coach]=1) <= 4);

%Constraint 4 + Constraint 5 - Coaches must have 4 or less Seniors,3 or less Juniors     
      
constraint forall (coachee in Coachees,coach in Coaches where coach != Unallocated) 
                    (if Coachee_Grade[coachee]=Junior then (Matched_Coach[coachee,coach]=1) <= 3) 
               else (Matched_Coach[coachee,coach]=1) <= 4) endif);

解决方法

如果每位教练在指导初级或高级水平的学生,我建议对他们进行明确记录。这将简化总和约束,并可能允许您指定首先解决此问题的搜索策略,这可能会有所帮助。


array[COACHES] of var bool: coaches_juniors;
% Ensure coaches that teach senior will never teach juniors
constraint forall(coach in COACHES where not coaches_juniors[coach],coachee in Coachees where Coachee_Grade[coachee]=Junior) (
  not Matched_Coach[coachee,coach]
)

% Constrain coaches to teach at most 4 students or 3 when junior
constraint forall (coach in Coaches where coach != Unallocated) (
  sum(coachee in Coachees)(Matched_Coach[coachee,coach]=1) + coaches_juniors[coach] <= 4
);

这应该捕获提到的约束。


此外,您可能会考虑模型的观点。您已为变量选择了布尔矩阵,但在 CP 中通常值得在更高级别描述您的模型。 (这看起来很像整数规划模型)。您可能想尝试使用以下方法描述它:

  • 为包含受训者的每个教练设置的变量。 (可能是 4 个数组而不是集合,如果您需要更多控制并知道如何消除对称性)。
  • 或者为每个学生分配一个教练的整数变量。

听起来像 Chuffed 或 OR-Tools 这样的 LCG 求解器很适合您的模型,因此使用这种更高级别的视图可能会给您带来更好的结果。

请注意,MiniZinc 旨在将高级模型转换为目标求解器。一般最好使用高级MiniZinc,让求解器库选择最好的问题编码。