Drools optaplanner规则不起作用

时间:2014-11-03 12:42:22

标签: java drools rule-engine rule optaplanner

我正在构建一个管理团队的简单应用程序。我的问题是我不能让约束/规则适用于我的规则。我的结果是在一轮中独特的球员组合,但不适用于所有轮次。

如何才能使我的规则正确,以便我获得所有轮次的独特玩家组合以及如何在规则中循环轮次而不是为每轮做一个规则集,除了($ round.getId()之外基本相同+1,$ round.getId + 2等)

规则:所有轮次都应重复使用uniqueMatchingX,而不是将其编码。

我有以下域对象:

播放器    排行 匹配(@PlanningEntity)    ID    2x一名球员(@PlanningVariable)    回合 回合    ID 比赛(@PlanningSolution)    比赛列表    球员名单    轮次列表

在解决方案中,我填充了事实(6名玩家排名不同,2轮,6轮比赛3轮) 在匹配中我不会填充玩家,因为这将由optaplanner完成。

我已经定义了以下规则:   硬约束       你不能对抗自己       你不能对抗同一个对手(在任何一轮)   软约束       您必须与接近排名的玩家对战

我已按如下方式实施这些规则:

// ############################################################################
// Hard constraints
// ############################################################################

rule "uniqueMatching1"
    when
       $m : Match($player1 : player1, $player2 : player2, $round1 : round)
       Match(player1 == $player1, eval(round.getId() == $round1.getId()))
       or Match(player1 == $player2, eval(round.getId() == $round1.getId()))
    then
        scoreHolder.addHardConstraintMatch(kcontext,  -1);
end

rule "uniqueMatching2"
    when
       $m : Match($player1 : player1, $player2 : player2, $round1 : round)
       Match(player2 == $player1, eval(round.getId() == $round1.getId()))
       or Match(player2 == $player2, eval(round.getId() == $round1.getId()))
    then
        scoreHolder.addHardConstraintMatch(kcontext,  -1);
end

rule "uniqueMatching1Round2"
    when
       $m : Match($player1 : player1, $player2 : player2, $round1 : round)
       Match(player1 == $player1, eval(round.getId() == $round1.getId()+1))
       or Match(player1 == $player2, eval(round.getId() == $round1.getId()+1))
    then
        scoreHolder.addHardConstraintMatch(kcontext,  -1);
end

rule "uniqueMatching2Round2"
    when
       $m : Match($player1 : player1, $player2 : player2, $round1 : round)
       Match(player2 == $player1, eval(round.getId() == $round1.getId()+1))
       or Match(player2 == $player2, eval(round.getId() == $round1.getId()+1))
    then
        scoreHolder.addHardConstraintMatch(kcontext,  -1);
end

rule "uniquePlayers"
    when
       Match(player1 == player2)
    then
        scoreHolder.addHardConstraintMatch(kcontext,  -1);
end

// ############################################################################
// Soft constraints
// ############################################################################

rule "minimumPointDifference"
    when
       $m : Match($player1 : player1, $player2 : player2, $round1 : round)
       Match(player1!=null, player2!=null,$player1!=null, $player2!=null)
    then
       scoreHolder.addSoftConstraintMatch(kcontext,  $player1.scoreGap($player2));
end

1 个答案:

答案 0 :(得分:1)

显然你正在尝试计划瑞士系统锦标赛。但是,除uniquePlayers之外,您的规则相当错误。

表格的条件

when
   $m : Match($player1 : player1, $player2 : player2, $round1 : round)
   Match(player2 == $player1, eval(round.getId() == $round1.getId()))
   or Match(player2 == $player2, eval(round.getId() == $round1.getId()))

根本没用。对于6名玩家和3轮,此规则将激活超过一千次。主要是由于使用or和缺少括号。此外,您不需要使用eval()。也许Round.equals(Object o)应该仅基于round id的比较,或者使用round id(int)作为Match的属性,而不是对某个Round对象的引用。

以下是一些可以作为起点的规则。 (我无视国际象棋锦标赛的额外怪癖,玩家必须拥有白人与黑人的公平份额。)

rule "no rematch" // If we have A:B, we don't consider B:A at all.
when
    $m : Match($player1 : player1, $player2 : player2)
    $m1: Match(player1 == $player2, player2 == $player1)
then
   // hard constraint on $m1
end

我也无视动态发展,即由于第一轮中的动作选择而导致的比赛事实的变化,需要知道第二轮的计划。

rule "only one match" 
// If we have A:B in round n, it won't happen again
// Need an indiaction what has actually been played in rounds 1..n.
when
    $m : Match($player1 : player1, $player2 : player2, $round : round)
    $m1: Match(player1 == $player1, player2 == $player2, round > $round)
then
    // hard constraint on $m1
end

规则uniquePlayers没问题,但我不认为minimumPointDifference正在做任何有用的事情,因为它会激发很多次。