【问题标题】:Problems with the solver configuration for two planning entity classes两个规划实体类的求解器配置问题
【发布时间】:2016-07-03 03:22:39
【问题描述】:

我正在解决一个与 optaplanner 中的护士排班示例接近的问题。

员工被分配到护士名册中的轮班,但主要区别在于还有持续 20 分钟的技能要求(分配)。如果员工被分配到涵盖给定技能要求时间的班次,则可以将其分配给技能要求。假设我们在 12:00 到 12:20 之间对 Skill1 有技能要求,并且员工在 08:00 到 16:00 的轮班时间被分配,那么只有当他具有该技能时,他才能被分配到该技能要求。

我有 2 个规划实体类。示例中的默认轮班分配,我已经实现了另外 2 个类 SkillRequirement 类,它们将在给定的时间范围内保持一项技能要求(这将是一个计划事实),第二个计划实体类将在 Employee 和SkillRequirement 类,其名称为 EmployeeSkillRequirement。

到现在为止,我认为我所做的一切都很好,我注释了 EmployeeSkillRequirement 类为@PlanningEntity 和具有适当值范围的计划变量,在计划解决方案中,我添加了技能要求列表(这是事实,也进入流口水工作记忆)和技能要求的员工列表,这是计划实体并使用@PlanningEntitySolutionProperty 正确注释

我很难配置求解器,我尝试了许多不同的求解器配置,我在文档中读到,当有更多规划实体和/或规划变量时,应该在你告诉的地方使用移动选择器的联合OptaPlanner 规划实体类和规划变量的名称,因为默认找不到。

似乎没有一个工作,我一直得到这个异常

Exception in thread "main" java.lang.IllegalArgumentException: Unmarshalling of solverConfigResource (org/optaplanner/examples/nurserostering/solver/nurseRosteringSolverConfig.xml) fails.

这是我一直在尝试使用的配置:

配置 1:

在此配置中,默认移动选择器用于 在本地搜索和移动中规划实体移位分配类 选择器 为计划实体类添加 “EmployeeSkillRequirement”和一切都组合在一个 并且构造启发式被替换为结合在一个联合中的移动选择器。

<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!--<environmentMode>FAST_ASSERT</environmentMode> -->
<solutionClass>org.optaplanner.examples.nurserostering.domain.NurseRoster
</solutionClass>
<entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</entityClass>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
<scoreDirectorFactory>
    <scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
    <scoreDrl>org/optaplanner/examples/nurserostering/solver/nurseRosteringScoreRules.drl
    </scoreDrl>
</scoreDirectorFactory>

<termination>
    <!-- Official benchmark secondsSpentLimit allowed on: - ge0ffrey's main 
        pc: sprint 11, medium 700, long 42000 -->
    <secondsSpentLimit>700</secondsSpentLimit>
    <!--<bestScoreLimit>-0hard/-999999soft</bestScoreLimit> -->
</termination>
<constructionHeuristic>
    <queuedEntityPlacer>
        <unionMoveSelector>
            <changeMoveSelector>
                <entitySelector>
                    <entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                    </entityClass>
                </entitySelector>
                <valueSelector>
                    <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                    </downcastEntityClass>
                    <variableName>employee</variableName>
                </valueSelector>
            </changeMoveSelector>
            <swapMoveSelector>
                <entitySelector>
                    <entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                    </entityClass>
                </entitySelector>
                <valueSelector>
                    <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                    </downcastEntityClass>
                    <variableName>employee</variableName>
                </valueSelector>
            </swapMoveSelector>
            <changeMoveSelector>
                <entitySelector>
                    <entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                    </entityClass>
                </entitySelector>
                <valueSelector>
                    <variableName>employee</variableName>
                </valueSelector>
            </changeMoveSelector>
            <swapMoveSelector>
                <entitySelector>
                    <entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                    </entityClass>
                </entitySelector>
                <valueSelector>
                    <variableName>employee</variableName>
                </valueSelector>
            </swapMoveSelector>
        </unionMoveSelector>
    </queuedEntityPlacer>
</constructionHeuristic>
<localSearch>
    <unionMoveSelector>

        <!-- Move Selectors for ShiftAssignment this was the default configuration 
            from the example -->
        <moveListFactory>
            <cacheType>PHASE</cacheType>
            <moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.EmployeeChangeMoveFactory
            </moveListFactoryClass>
        </moveListFactory>
        <moveListFactory>
            <cacheType>PHASE</cacheType>
            <moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.ShiftAssignmentSwapMoveFactory
            </moveListFactoryClass>
        </moveListFactory>
        <moveListFactory>
            <cacheType>STEP</cacheType>
            <moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.ShiftAssignmentPillarPartSwapMoveFactory
            </moveListFactoryClass>
        </moveListFactory>


        <!-- The move selectors for the second plannig entity class EmployeeSkillRequirement -->
        <changeMoveSelector>
            <entitySelector>
                <entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                </entityClass>
            </entitySelector>
            <valueSelector>
                <variableName>employee</variableName>
            </valueSelector>
        </changeMoveSelector>
        <swapMoveSelector>
            <entitySelector>
                <entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                </entityClass>
            </entitySelector>
            <valueSelector>
                <variableName>employee</variableName>
            </valueSelector>
        </swapMoveSelector>
    </unionMoveSelector>
    <acceptor>
        <entityTabuSize>7</entityTabuSize>
    </acceptor>
    <forager>
        <acceptedCountLimit>800</acceptedCountLimit>
    </forager>
</localSearch>

配置 2:

其次,我查看了文档,发现这个提示说,如果每个计划实体类有两个不同的构造启发式部分,则处理多个计划实体类会更容易 http://docs.jboss.org/optaplanner/release/6.3.0.Final/optaplanner-docs/html_single/index.html#allocateEntityFromQueueMultipleEntityClasses 所以我也尝试了这个配置。

<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!--<environmentMode>FAST_ASSERT</environmentMode> -->
<solutionClass>org.optaplanner.examples.nurserostering.domain.NurseRoster
</solutionClass>
<entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</entityClass>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
<scoreDirectorFactory>
    <scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
    <scoreDrl>org/optaplanner/examples/nurserostering/solver/nurseRosteringScoreRules.drl
    </scoreDrl>
</scoreDirectorFactory>

<termination>
    <!-- Official benchmark secondsSpentLimit allowed on: - ge0ffrey's main 
        pc: sprint 11, medium 700, long 42000 -->
    <secondsSpentLimit>700</secondsSpentLimit>
    <!--<bestScoreLimit>-0hard/-999999soft</bestScoreLimit> -->
</termination>
<constructionHeuristic>
    <queuedEntityPlacer>
        <unionMoveSelector>
            <changeMoveSelector>
                <entitySelector>
                    <entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                    </entityClass>
                </entitySelector>
                <valueSelector>
                    <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                    </downcastEntityClass>
                    <variableName>employee</variableName>
                </valueSelector>
            </changeMoveSelector>
            <swapMoveSelector>
                <entitySelector>
                    <entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                    </entityClass>
                </entitySelector>
                <valueSelector>
                    <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                    </downcastEntityClass>
                    <variableName>employee</variableName>
                </valueSelector>
            </swapMoveSelector>
        </unionMoveSelector>
    </queuedEntityPlacer>
</constructionHeuristic>
<constructionHeuristic>
    <queuedEntityPlacer>
        <unionMoveSelector>
            <changeMoveSelector>
                <entitySelector>
                    <entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                    </entityClass>
                </entitySelector>
                <valueSelector>
                    <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                    </downcastEntityClass>
                    <variableName>employee</variableName>
                </valueSelector>
            </changeMoveSelector>
            <swapMoveSelector>
                <entitySelector>
                    <entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                    </entityClass>
                </entitySelector>
                <valueSelector>
                    <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                    </downcastEntityClass>
                    <variableName>employee</variableName>
                </valueSelector>
            </swapMoveSelector>
        </unionMoveSelector>
    </queuedEntityPlacer>
</constructionHeuristic>
<localSearch>
    <unionMoveSelector>

        <!-- Move Selectors for ShiftAssignment this was the default configuration 
            from the example -->
        <moveListFactory>
            <cacheType>PHASE</cacheType>
            <moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.EmployeeChangeMoveFactory
            </moveListFactoryClass>
        </moveListFactory>
        <moveListFactory>
            <cacheType>PHASE</cacheType>
            <moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.ShiftAssignmentSwapMoveFactory
            </moveListFactoryClass>
        </moveListFactory>
        <moveListFactory>
            <cacheType>STEP</cacheType>
            <moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.ShiftAssignmentPillarPartSwapMoveFactory
            </moveListFactoryClass>
        </moveListFactory>
        <!-- besides this default configuration from optaplaner i also tried this here

        <changeMoveSelector>
            <entitySelector>
                <entityClass>org.optaplanner.examples.nurserostering.domain.
                </entityClass>
            </entitySelector>
            <valueSelector>
                <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                </downcastEntityClass>
                <variableName>employee</variableName>
            </valueSelector>
        </changeMoveSelector>
        <swapMoveSelector>
            <entitySelector>
                <entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                </entityClass>
            </entitySelector>
            <valueSelector>
                <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
                </downcastEntityClass>
                <variableName>employee</variableName>
            </valueSelector>
        </swapMoveSelector>-->


        <!-- The move selectors for the second plannig entity class EmployeeSkillRequirement -->
        <changeMoveSelector>
            <entitySelector>
                <entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                </entityClass>
            </entitySelector>
            <valueSelector>
                <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                </downcastEntityClass>
                <variableName>employee</variableName>
            </valueSelector>
        </changeMoveSelector>
        <swapMoveSelector>
            <entitySelector>
                <entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                </entityClass>
            </entitySelector>
            <valueSelector>
                <downcastEntityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
                </downcastEntityClass>
                <variableName>employee</variableName>
            </valueSelector>
        </swapMoveSelector>
    </unionMoveSelector>
    <acceptor>
        <entityTabuSize>7</entityTabuSize>
    </acceptor>
    <forager>
        <acceptedCountLimit>800</acceptedCountLimit>
    </forager>
</localSearch>

我也尝试了一些与这些类似的其他配置,仍然没有运气。

我该如何解决这个问题并使其正常工作?

编辑:

Exception in thread "main" java.lang.IllegalArgumentException: Unmarshalling of solverConfigResource (org/optaplanner/examples/nurserostering/solver/nurseRosteringSolverConfig.xml) fails.
at org.optaplanner.core.impl.solver.XStreamXmlSolverFactory.configure(XStreamXmlSolverFactory.java:114)
at org.optaplanner.core.api.solver.SolverFactory.createFromXmlResource(SolverFactory.java:66)
at org.optaplanner.examples.nurserostering.app.NurseRosteringApp.createSolver(NurseRosteringApp.java:50)
at org.optaplanner.examples.common.app.CommonApp.createSolutionBusiness(CommonApp.java:90)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:77)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:73)
at org.optaplanner.examples.nurserostering.app.NurseRosteringApp.main(NurseRosteringApp.java:38)
Caused by: " com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field   org.optaplanner.core.config.heuristic.selector.move.generic.SwapMoveSelectorConfig.valueSelector
---- Debugging information ----
field               : valueSelector
class               :      org.optaplanner.core.config.heuristic.selector.move.generic.SwapMoveSelect    orConfig
required-type       :     org.optaplanner.core.config.heuristic.selector.move.generic.SwapMoveSelect    orConfig
converter-type      :    com.thoughtworks.xstream.converters.reflection.ReflectionConverter
line number         : 98
class[1]            :       org.optaplanner.core.config.heuristic.selector.move.composite.UnionMoveSel    ectorConfig
class[2]            :    org.optaplanner.core.config.localsearch.LocalSearchPhaseConfig
class[3]            : org.optaplanner.core.config.solver.SolverConfig
version             : 1.4.7
-------------------------------
at org.optaplanner.core.impl.solver.XStreamXmlSolverFactory.configure(XStreamXmlSolverFactory.java:114)
at org.optaplanner.core.api.solver.SolverFactory.createFromXmlResource(SolverFactory.java:66)
at org.optaplanner.examples.nurserostering.app.NurseRosteringApp.createSolver(NurseRosteringApp.java:50)
at org.optaplanner.examples.common.app.CommonApp.createSolutionBusiness(CommonApp.java:90)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:77)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:73)
at org.optaplanner.examples.nurserostering.app.NurseRosteringApp.main(NurseRosteringApp.java:38)

【问题讨论】:

  • 非法参数异常的原因是什么? XStream 异常消息应该清楚地指出没有解析的内容。我怀疑您在此处编写的两个配置可能会有所不同。我们打算迟早提供 XSD 架构。
  • 关于配置 1:swapMoveSelector 嵌套在 constructionHeuristic 中没有意义。请参阅文档的this section

标签: optaplanner


【解决方案1】:

一个常见的错误是在无法正确解析的类名属性中添加空格。这在解析过程中失败:

<solutionClass>org.optaplanner.examples.nurserostering.domain.NurseRoster
</solutionClass>

但这成功地被解析了:

<solutionClass>org.optaplanner.examples.nurserostering.domain.NurseRoster</solutionClass>

【讨论】:

  • 这就像一个魅力。谢谢。我还按照你的建议从构造启发式中删除了 swapMoveSelector。现在我收到另一个错误,我将其发布为编辑。
  • 最好为新问题创建一个新问题,否则阅读时间太长(并且对于其他有相同问题的用户来说也很长才能识别它)。话虽如此,这是另一个 Xstream 解组错误。如果您检查错误消息,它基本上说您在&lt;swapMoveSelector&gt; 元素中有一个&lt;valueSelector&gt; 元素,但是如果您查看SwapMoveSelectorConfig,您会注意到那里没有这样的字段。
  • 哦,是的:要查找 XML 元素的 java 类,只需在其名称中添加后缀 Config
  • 它再次像魅力一样工作,一切正常!我发布了关于您的提案的另一个问题,并在那里回答了它以帮助社区。这是链接:stackoverflow.com/questions/36090831/…。再次感谢您的帮助!
  • 也许您应该考虑修剪该值并删除所有新行或标签
猜你喜欢
  • 2022-08-12
  • 2023-01-20
  • 1970-01-01
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 2013-06-23
  • 2011-07-27
  • 1970-01-01
相关资源
最近更新 更多