使用Choco(CSP)模拟网球对决

时间:2016-03-02 20:55:47

标签: java constraints constraint-programming choco

我正在尝试用Choco模拟一个问题,以便在网球赛事(或任何运动)中获得可能的对决组合。

我试图这样做的方式我有以下几点:

// Set of timeslots when the event is held (i.e. 10am-10pm)
int nTimeslots = 12;

// Courts available: court #1, #2 and #3
int nCourts = 3;

String[] players = { "Novak", "Andy", "Roger", "Stan", "Rafel", "Kei", "Tomas", "David" };
int nPlayers = players.length;

// Timeslots when each player cannot play for whatever reason
int[][] unavailability = {
    { 0, 1, 5 },
    { 8, 10, 11 },
    { 1, 2, 11 },
    { 0, 1 },
    { 2, 3, 4, 5, 6 },
    { 3, 4, 9, 10, 11 },
    { 4, 5 },
    { 2, 3 }
};

// Number of timeslots each match will occupy
int matchDuration = 2;

// This will hold the final combinations
// rows -> players, columns -> timeslots, matches[i][j] -> court where the player plays at that timeslot (0 means the player does not play at that time)
IntVar[][] matches;

我的主要问题是,通过这种设置,我无法想出一种定义问题的方法。我花了好几天都没有成功。我似乎有类似的问题,但应该合并的不同元素的数量较少,通常为1或2,但在我的问题中有3个:玩家,时间段和法院。

在花了很多时间之后,我无法得到更多:

for (int player = 0; player < nPlayers; player++) {
    for (int timeslot = 0; timeslot < nTimeslots; timeslot++) {
        for (int playerUnavailbleTimeslot : unavailability[player]) {
            if (playerUnavailbleTimeslot != timeslot) {
                solver.post(IntConstraintFactory.arithm(matches[player][playerUnavailbleTimeslot], ">=", 0));
            } else {
                for (int i = 0; i < matchDuration; i++)
                    if (playerUnavailbleTimeslot - i >= 0)
                        solver.post(IntConstraintFactory.arithm(matches[player][playerUnavailbleTimeslot - i], "=", 0));
            }
        }
    }
}

IntVar matchesSum = VariableFactory.enumerated("Matches sum", 1 * matchDuration, nCourts * matchDuration, solver);
for (int player = 0; player < nPlayers; player++) {
    solver.post(IntConstraintFactory.sum(matches[player], matchesSum));
    //solver.post(IntConstraintFactory.nvalues(matches[player], VariableFactory.fixed(2, solver)));
}

第一个双循环只强制0播放器不可用的时间段(加上基于匹配持续时间值的范围),如果可用则大于或等于。这样,最终矩阵开始看起来像这样:

0 0 ? ? ? 0 ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? 0 0 0 0 ?
.........................

然后我确保比每个玩家的时间段中的值之和在最低数字乘以匹配持续时间的法院和具有最高数字的法院乘以匹配持续时间之间。这是我想到的约束之一,所以每一行都是这样的,例如,玩家0在时间段3和4的法庭2中扮演:

0 0 0 2 2 0 0 0 0 0 0 0 

我尝试定义了应该强制执行的约束nvalues,不超过n个不同的值符合数组,但是如果我使用它就像你可以看到上面的问题只是呈现一个解决方案(什么?!)。

但是我需要定义更多的约束,我甚至不知道如何开始:

  • 对于每一行,如果确实指派了法院,则球员所在的球场必须有连续的数字
  • 对于每一行,我只能有0和法院号码[1 - nCourts]
  • 列应配对以创建一对玩家之间的匹配。
  • 同一个法院不能在同一时段范围内配对不止一次(意味着同时在法庭上不能超过一场比赛)

就限制而言,这是我所能想到的,但我相信还有更多。

我希望有任何建议可以帮助我继续这样做,因为现在我觉得绝对无能为力,并且几乎没有关于Choco在线的信息,以帮助我清除这一点。

1 个答案:

答案 0 :(得分:2)

我首先要写下你想要的数学。

不确定这是否有用,但这是我的实现,将其解决为数学编程问题。它没有使用Constraint Programming,但事情看起来与你在Choco中所做的相似:

enter image description here

我尝试最大限度地提高玩家的最低游戏数量,因此我们不会让某人玩零游戏。人们可以想到许多变化,例如不要一直与同一个人玩等等。

结果如下:

enter image description here

表中的数字是法院编号(-1表示不允许)。在这个时间表中,每个人都会玩三次。