当前位置: 首页 > 知识库问答 >
问题:

solver.solve()返回看似随机的解和分数,而不是最好的

晏树
2023-03-14

我所拥有的

在Java8上使用OptaPlanner 7.45.0.final。

我的行为

对于小型数据集,该计划似乎很好地工作,因为在这些数据集中有许多好的解决方案。然而,当我转移到更大的数据集时,返回良好的最终时间表就比较困难了。会有像-60硬/-390060中/-1280457软这样的分数,看起来真的很糟糕。而且,如果我增加可用的时间,分数有时会变得更糟!

我尝试过的事情

我尝试通过合并硬值和中值简化为hardsoftscore,但行为是相同的。

我尝试调用SolverConfig.SetEnvironmentMode(environmentMode.non_intrusive_full_assert);(是的,我正在以编程方式创建SolverConfig,但行为没有改变。

相关代码段

@PlanningEntity
public final class CrewAssignment
{
    private Long crewMemberId;
    @PlanningVariable(valueRangeProviderRefs = {"crewMemberId"})
    public Long getCrewMemberId() { return crewMemberId; }
    public void setCrewMemberId(Long value) { crewMemberId = value; }

    @Override
    protected CrewAssignment clone()
    {
        CrewAssignment newAssignment = new CrewAssignment(getActivities());
        newAssignment.setCrewMemberId(crewMemberId);

        return newAssignment;
    }
}

解决方案的子集:

@PlanningSolution(solutionCloner = CrewSchedSolutionCloner.class)
public final class CrewSchedSolution
{
    private final List<Long> crewMemberIds;
    @ValueRangeProvider(id="crewMemberId")
    @ProblemFactCollectionProperty
    public List<Long> getCrewMemberIds() { return crewMemberIds; }

    // assignments
    private List<CrewAssignment> crewAssignments = new ArrayList<>();
    @PlanningEntityCollectionProperty
    public List<CrewAssignment> getCrewAssignments() { return crewAssignments; }

    HardSoftScore score;
    @PlanningScore
    public HardSoftScore getScore() { return score; }
    public void setScore(HardSoftScore value) { score = value; }

    public CrewSchedSolution cloneSolution()
    {
        List<CrewAssignment> newCrewAssignments = new ArrayList<>(crewAssignments);
        for (int i = 0; i < newCrewAssignments.size(); i++)
        {
            CrewAssignment existingAssignment = newCrewAssignments.get(i);
            CrewAssignment newAssignment = existingAssignment.clone();
            newCrewAssignments.set(i, newAssignment);
        }
        return new CrewSchedSolution(/* Various additional data */,
            crewMemberIds,
            newCrewAssignments, score);
    }
}

solutioncloner:

public final class CrewSchedSolutionCloner
    implements SolutionCloner<CrewSchedSolution>
{
    @Override
    public CrewSchedSolution cloneSolution(CrewSchedSolution originalSolution)
    {
        return originalSolution.cloneSolution();
    }
}

摘要

共有1个答案

莫宁
2023-03-14

如果我增加可用的时间,分数有时会变得更糟!这是不可能的(如果它在第二次运行中得到更多的步骤,这是它应该得到的,并且它是一个可复制的运行,这是事实)。

debug日志显示它正在运行更多的“ls step”行吗?如果发生了,则可能存在分数损坏,但如果它们运行的时间足够长(比没有运行的时间长得多,因为它们更慢),则NON_INTRUSIVE_FULL_ASSERT或FULL_ASSERT将检测到这一点。

通常情况下,optaplanner的运行是100%可重复性的,给定相同数量的步骤(~相同数量的时间给予或采取几个步骤)。如果是这种情况,请检查debug日志。模拟退火是不可复制的,但默认情况下是关闭的。

OptaPlanner基准测试是您最好的朋友。特别是BEST_SCORE图和分数计算速度数。再运行4次,这样您就可以看到如果给更多时间,BEST_SCORE图是如何表现的。此外,subsinglecount可能是一个有趣的东西,可以在这里打开,看看优化对一个好的随机种子有多敏感(不应该)。

 类似资料:
  • 问题内容: 当他每次运行程序时都不断获得相同的数字时,我试图向Java解释随机数生成器。我为同一件事创建了自己的简单版本,每次运行该程序时,我也得到了与他得到的确切数字相同的数字。 我究竟做错了什么? 100个数字中的最后五个数字是: 问题答案: 您已经为随机数生成器提供了恒定的值。它是确定性的,因此每次运行都会生成相同的值。 我不确定您为什么选择使用作为种子,但是种子值与生成的值范围无关(这是由

  • 问题内容: 我有以下方法。方法rnd返回两个边界之间的单个随机整数: 如何修改此值,以使返回的数字mod2 = 0? 谢谢 问题答案: 如果您可以获得范围内的随机数,那么您要做的就是获得范围内的随机数并将其乘以2以得到范围内的随机偶数

  • 我寻找如何在堆栈溢出的Java中进行IP查找,但答案与我已经在做的匹配,并没有解决我的问题。 问题:此代码与预期的一些IP广告,而不是与其他一些。 例如,对于IP 157.55.39.29,输出为: 根据Linux命令,此结果似乎是正确的: 返回: 此IP地址的完全限定域名,如果安全检查不允许此操作,则返回IP地址的文本表示形式。 但我很确定这不是安全检查的问题...或者我不明白出了什么问题。 你

  • 我试图让2支球队互相比赛。当我说团队1.玩(团队2)时,我称之为;当 i 生成的数字小于 0.5 时,team2 应获胜,如果大于 0.5,则团队 1 应获胜。当团队 1 获胜时,它会正确显示为尼克斯,但当团队 2 获胜时,它会显示内存地址。我怎么能让它正确地说网是赢的,而不是team@78987neu73

  • 问题内容: 不知道为什么将其链接为骗子。 问题是不同的。答案是不同的。不知道要更改什么。如果有人看到我想念的东西,请告诉我… 使用这两个查询,我得到的结果数量不同。在分析了几个小时之后,我需要扔掉毛巾,承认我无法发现重要性的差异。由于我的方法库已空荡荡,因此我需要帮助。 LINQ SQL 第一个问题是上述两个陈述是否确实相等,或者我是否缺少某些内容。第二个问题是我所缺少的(如果有的话)或如何解决它

  • 如果我的代码返回,但可以为空。转换它以返回是否有好处。它是否会为空而不是空的实例增加任何好处?