Optaplanner中双changeMoveSelector笛卡尔积移动配置报错及实现问询
OptaPlanner笛卡尔积移动选择器配置报错及解决方法
问题描述
使用OptaPlanner 8.25版本,尝试通过cartesianProductMoveSelector实现两个规划变量(previousStandstill和startModifier)的笛卡尔积移动,配置代码如下:
<?xml version="1.0" encoding="UTF-8"?> <solver> <solutionClass>com.company.MySolution</solutionClass> <entityClass>com.company.Standstill</entityClass> <entityClass>com.company.PlanningVisit</entityClass> <environmentMode>REPRODUCIBLE</environmentMode> <randomSeed>50</randomSeed> <environmentMode>FULL_ASSERT</environmentMode> <scoreDirectorFactory> <constraintProviderClass>com.company.MyConstraintProvider </constraintProviderClass> <initializingScoreTrend>ONLY_DOWN</initializingScoreTrend> </scoreDirectorFactory> <termination> <minutesSpentLimit>1800</minutesSpentLimit> </termination> <customPhase> <customPhaseCommandClass>com.company.phase.MySolutionInit</customPhaseCommandClass> </customPhase> <constructionHeuristic> <changeMoveSelector> </changeMoveSelector> <constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType> </constructionHeuristic> <localSearch> <termination> <minutesSpentLimit>300</minutesSpentLimit> </termination> <unionMoveSelector> <moveListFactory> <variableName>previousStandstill</variableName> <moveListFactoryClass>com.company.moves.RideChangeMoveFactory</moveListFactoryClass> </moveListFactory> <cartesianProductMoveSelector> <changeMoveSelector> <entitySelector id="cartesianProductEntitySelector"/> <valueSelector> <variableName>previousStandstill</variableName> </valueSelector> </changeMoveSelector> <changeMoveSelector> <entitySelector mimicSelectorRef="cartesianProductEntitySelector"/> <valueSelector> <variableName>startModifier</variableName> </valueSelector> </changeMoveSelector> </cartesianProductMoveSelector> <swapMoveSelector> <variableName>previousStandstill</variableName> </swapMoveSelector> <subChainChangeMoveSelector> <subChainSelector> <valueSelector variableName="previousStandstill"> </valueSelector> </subChainSelector> <valueSelector variableName="previousStandstill"> </valueSelector> <selectReversingMoveToo>true</selectReversingMoveToo> </subChainChangeMoveSelector> <subChainSwapMoveSelector> <subChainSelector> <valueSelector variableName="previousStandstill"> </valueSelector> </subChainSelector> <secondarySubChainSelector> <valueSelector variableName="previousStandstill"> </valueSelector> </secondarySubChainSelector> <selectReversingMoveToo>true</selectReversingMoveToo> </subChainSwapMoveSelector> <tailChainSwapMoveSelector> <valueSelector variableName="previousStandstill"> </valueSelector> </tailChainSwapMoveSelector> </unionMoveSelector> <acceptor> <entityTabuSize>12</entityTabuSize> </acceptor> <forager> <acceptedCountLimit>3000</acceptedCountLimit> </forager> </localSearch> </solver>
运行时抛出异常:
Multiple EntityMimicRecorders (usually EntitySelectors) have the same id (cartesianProductEntitySelector).
解决方案
报错原因是手动指定的entitySelector ID在全局范围内重复(可能配置中其他隐式生成的选择器也使用了该ID)。正确的配置方式不需要手动给第一个entitySelector设置ID,OptaPlanner会自动在cartesianProductMoveSelector内部关联两个changeMoveSelector的实体选择器,确保操作的是同一个实体。
修正后的cartesianProductMoveSelector配置如下:
<cartesianProductMoveSelector> <changeMoveSelector> <!-- 无需手动指定id,OptaPlanner自动处理内部关联 --> <valueSelector> <variableName>previousStandstill</variableName> </valueSelector> </changeMoveSelector> <changeMoveSelector> <!-- 使用mimicSelectorRef="cartesianProductEntitySelector" 自动关联第一个changeMoveSelector的entitySelector --> <entitySelector mimicSelectorRef="cartesianProductEntitySelector"/> <valueSelector> <variableName>startModifier</variableName> </valueSelector> </changeMoveSelector> </cartesianProductMoveSelector>
说明
- 第一个
changeMoveSelector中的entitySelector可以省略,OptaPlanner会默认选择所有规划实体;若需指定实体范围,可添加entitySelector但不要手动设置id。 - 第二个
changeMoveSelector的entitySelector通过mimicSelectorRef="cartesianProductEntitySelector"自动关联第一个changeMoveSelector的实体选择器,确保笛卡尔积操作针对同一个实体的两个不同规划变量。
内容的提问来源于stack exchange,提问作者Luka Bradeško
相关产品推荐
相关产品推荐

