建模:有效地选择模型子集



我想使用Optaplanner建模和解决的问题是为一个运动队(这里是足球)创建一个花名册。也就是说:从所有可用的球员中,根据几个标准选择11个。我使用硬/中/软分数来定义有效的解决方案,例如,一个硬性标准规定只有一名守门员必须出现在名单上。球员被选中的顺序无关紧要。

我现在的PlanningEntity:

@PlanningEntity
public class Roster
{
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member1;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member2;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member3;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member4;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member5;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member6;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member7;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member8;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member9;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member10;
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member11;
    public List<RosterMember> getMembers()
    {
        return Lists.newArrayList(member1, member2, member3, member4, member5, member6, member7, member8, member9, member10, member11);
    }
}

对于分数计算,我只使用getMembers,即我不关心玩家是否被分配到member1member2。求解器主要使用默认配置,并配置为在100秒后超时,或者在10秒后没有改进。

在一些样本数据集上玩了这个之后,我注意到求解器在大多数情况下没有找到最佳解决方案(但至少是有效的),例如,没有选择最佳守门员(这通常很容易看到,因为没有很多可用的,应该选择一个)。

我怀疑这与我如何建模PlanningEntity有关:因为所有花名册成员都可以单独设置,这似乎使解决方案空间不必要地大。如前所述,将成员分配给哪个字段并不重要。重要的是是否(或者更确切地说,谁)被分配了,谁没有。所以我基本上需要选择一个玩家子集,同时满足一些约束和优化标准。

然而,简单地将List of RosterMember注释为@PlanningVariable似乎不起作用。我在例子中也找不到类似的情况。我想这应该是一个简单的建模例子?

到目前为止,我能想到的唯一想法是明确地建模一些(硬)约束,例如,将范围限制为goalkeeper的规划变量之一,而将所有其他的限制为non-goalkeeper(甚至可能进一步)。根据文档(4.3.5.2.3.),这应该尽量避免。

编辑:我只有一个花名册实例。我假设不同团队的花名册不相关,并计划依次为每个团队运行求解器。

编辑2:根据建议,我现在有了这个而不是以前的Roster:

@PlanningEntity
public class RosterAssignment
{
    @PlanningVariable(valueRangeProviderRefs = {"candidates"})
    private RosterMember member;
}

在创建初始未解决的解决方案时,我添加了11个空RosterAssignments。然而,在开始解决方案创建后,求解器似乎无法改进任何东西:

(DefaultConstructionHeuristicPhase.java:158) Construction Heuristic phase (0) ended: step total (11), time spent (111), best score (-1hard/-2medium/1275soft).
(DefaultLocalSearchPhase.java:152) Local Search phase (1) ended: step total (375104), time spent (10111), best score (-1hard/-2medium/1275soft).
(DefaultSolver.java:238)       Solving ended: time spent (10129), best score (-1hard/-2medium/1275soft), average calculate count per second (75545), environment mode (REPRODUCIBLE).

参见Tennis的例子:对于每个Day实例,有4个TeamAssignment实例,而不是Day本身的4个规划变量。

虽然搜索空间是相同的,但默认移动(changeMove和swapMove)工作得更好,因为您将在TeamAssignment "day1-spot1"和TeamAssignment "day2-spot3"之间进行交换。

最新更新