Java 用Choco(CSP)模拟网球比赛

Java 用Choco(CSP)模拟网球比赛,java,constraints,constraint-programming,choco,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"

我试图用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在第2场比赛的时隙为3和4:

0 0 0 2 2 0 0 0 0 0 0 0 
我尝试定义约束
n值
,该约束应该是强制的,即数组中的不同值不超过
n
,但是如果我像您上面看到的那样使用它,问题只会呈现一个解决方案(什么?!)

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

  • 如果确实指定了球场,则球员所在的每一排球场必须有连续的号码
  • 对于每一行,我只能有0和法院编号[1-n法院]
  • 列应该配对以创建一对玩家之间的匹配
  • 同一场地在同一时间段内不能进行多次配对(意味着同一场地内不能同时进行多场比赛)
这就是我所能想到的限制,但我相信还有更多的限制


我希望有任何建议能帮助我继续这样做,因为现在我觉得自己完全不知所措,而且网上几乎没有关于Choco的信息可以帮助我澄清这一点。

我会先用数学写下你想要的东西

不确定这是否有用,但这是我的实现,作为一个数学规划问题来解决它。它不使用约束编程,但事情看起来可能与您在Choco中所做的类似:

我试图最大化一个玩家的最小游戏数,这样我们就不会有人玩零游戏。你可以想到很多变化,比如不总是和同一个人比赛等等

结果如下:


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

我会先用数学写下你想要什么

不确定这是否有用,但这是我的实现,作为一个数学规划问题来解决它。它不使用约束编程,但事情看起来可能与您在Choco中所做的类似:

我试图最大化一个玩家的最小游戏数,这样我们就不会有人玩零游戏。你可以想到很多变化,比如不总是和同一个人比赛等等

结果如下:


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

这是一个很大的帮助。虽然我在试图弄清楚一些变量和方程的用途时遇到了一些困难。你是如何实施的?你能告诉我怎么用巧克力做吗?再次,非常感谢你,你在这个答案上做了很多工作,这确实很有帮助。然而,为什么有些球员要打多场比赛?或者那只是代表了所有可能的组合?我对巧克力知之甚少。多重匹配是我的发明。我的目标是安排尽可能多的比赛(准确地说,就是尽量减少比赛次数)。这很容易被更无聊的东西所取代,比如要求每个人(或相关的东西)只进行一场比赛的限制。我可以让它按照你的意愿工作,也可以限制每个球员只进行一场比赛吗?(这样一来,循环赛和单淘汰赛都可以进行)。我想问一下“Twoslots1”和“Twoslots2”方程。它们的用途是什么?为什么有两个呢?并不是说在我最初的问题中,
matchDuration
是一个变量,因此比赛不应该在
matchDuration
时段的
2个时段内进行。实际上不可能最大化每个玩家的比赛数量,同时将相同的事情固定到一个。(至少对我来说没什么意义)。Twoslots1映射在比赛开始(由g表示)和两个对应的x(x表示有人比赛时)之间。Twoslots2说比赛不能从t和t+1开始。我假设每场比赛都需要连续两个阶段(见结果)。这是一个很大的帮助。虽然我在试图弄清楚一些变量和方程的用途时遇到了一些困难。你是如何实施的?你能告诉我怎么用巧克力做吗?再次,非常感谢你,你在这个答案上做了很多工作,这确实很有帮助。然而,为什么有些球员要打多场比赛?或者那只是代表了所有可能的组合?我对巧克力知之甚少。多重匹配是我的发明。我的目标是安排尽可能多的比赛(准确地说,就是尽量减少比赛次数)。这很容易被更无聊的东西所取代,比如要求每个人(或相关的东西)只进行一场比赛的限制。我可以让它按照你的意愿工作,也可以限制每个球员只进行一场比赛吗?(这样一来,循环赛和单淘汰赛都可以进行)。我想问一下“Twoslots1”和“Twoslo”的情况
0 0 0 2 2 0 0 0 0 0 0 0