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

时间:2016-08-11 21:23:56

标签: optimization modeling optaplanner constraint-satisfaction

我想用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).

1 个答案:

答案 0 :(得分:1)

请参阅网球示例:对于每个Day实例,TeamAssignment本身有4个Day个实例,而不是4个计划变量。

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