You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OptaPlanner陷入局部最优违反硬约束问题求助

会议调度OptaPlanner局部最优问题的解决建议

1. 提升构造启发式的初始解质量

当前使用的FIRST_FIT构造启发式会按顺序给会议分配第一个可行的时间/参会者,但如果第一天的初始分配直接违反硬约束,后续局部搜索极易陷入局部最优。建议:

  • 替换为FIRST_FIT_DECREASING:优先处理优先级更高的会议(如参会人数多、时间要求严格的会议),减少初始解的硬约束违反次数
  • 启用构造启发式的贪心优化,在constructionHeuristic节点下添加如下配置,让构造阶段多尝试候选解,避免初始点落入劣质区域:
    <constructionHeuristic>
        <constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
        <forager>
            <acceptedCountLimit>100</acceptedCountLimit>
        </forager>
    </constructionHeuristic>
    

2. 优化局部搜索的邻域配置

你的局部搜索仅配置了接受器,未定义邻域选择器,OptaPlanner默认邻域可能仅调整单个变量(如仅修改参会者,不切换会议时间),导致无法跳出第一天的分配。建议:

  • 显式配置复合邻域,同时覆盖两个规划变量的调整逻辑:
    <localSearch>
        <acceptor>
            <acceptorType>LATE_ACCEPTANCE</acceptorType>
            <lateAcceptanceSize>400</lateAcceptanceSize> <!-- 增大窗口,提升跳出局部最优的概率 -->
        </acceptor>
        <forager>
            <acceptedCountLimit>1</acceptedCountLimit>
            <finalistPodiumType>HIGHEST_SCORE</finalistPodiumType>
        </forager>
        <moveSelector>
            <unionMoveSelector>
                <!-- 调整会议时间的邻域 -->
                <changeMoveSelector>
                    <planningVariableName>meetingTime</planningVariableName>
                </changeMoveSelector>
                <!-- 调整参会者的邻域 -->
                <changeMoveSelector>
                    <planningVariableName>attendee</planningVariableName>
                </changeMoveSelector>
            </unionMoveSelector>
        </moveSelector>
    </localSearch>
    
  • 增大lateAcceptanceSize:默认值过小会导致算法快速收敛到局部最优,建议设置为300-500,让算法有机会接受暂时较差的解,探索更优区域

3. 启用多阶段求解流程

单阶段求解易被初始解限制,多阶段可先修复硬约束,再优化中等约束:

  • 第一阶段:聚焦硬约束修复(暂时将中等约束权重设为0),先得到无硬约束违反的可行解
  • 第二阶段:恢复完整约束权重,在可行解基础上优化参会者负载均衡
    <solver>
        <!-- 第一阶段:修复硬约束 -->
        <phase>
            <constructionHeuristic>
                <constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
            </constructionHeuristic>
        </phase>
        <phase>
            <localSearch>
                <acceptor>
                    <acceptorType>LATE_ACCEPTANCE</acceptorType>
                    <lateAcceptanceSize>500</lateAcceptanceSize>
                </acceptor>
                <moveSelector>
                    <changeMoveSelector>
                        <planningVariableName>meetingTime</planningVariableName>
                    </changeMoveSelector>
                </moveSelector>
                <!-- 临时禁用中等约束 -->
                <scoreDirectorFactory>
                    <scoreDefinitionType>HARD_MEDIUM_SOFT</scoreDefinitionType>
                    <constraintProviderClass>your.package.YourConstraintProvider</constraintProviderClass>
                    <constraintConfiguration>
                        <constraintId>attendeeLoadBalance</constraintId>
                        <weight>0</weight>
                    </constraintConfiguration>
                </scoreDirectorFactory>
            </localSearch>
        </phase>
        <!-- 第二阶段:优化中等约束 -->
        <phase>
            <localSearch>
                <acceptor>
                    <acceptorType>LATE_ACCEPTANCE</acceptorType>
                    <lateAcceptanceSize>400</lateAcceptanceSize>
                </acceptor>
                <moveSelector>
                    <unionMoveSelector>
                        <changeMoveSelector>
                            <planningVariableName>meetingTime</planningVariableName>
                        </changeMoveSelector>
                        <changeMoveSelector>
                            <planningVariableName>attendee</planningVariableName>
                        </changeMoveSelector>
                    </unionMoveSelector>
                </moveSelector>
                <!-- 恢复正常约束权重 -->
                <scoreDirectorFactory>
                    <scoreDefinitionType>HARD_MEDIUM_SOFT</scoreDefinitionType>
                    <constraintProviderClass>your.package.YourConstraintProvider</constraintProviderClass>
                </scoreDirectorFactory>
            </localSearch>
        </phase>
    </solver>
    

4. 约束逻辑调试

  • 检查硬约束实现:确认“参会者时间可用”的约束逻辑无漏洞,比如是否正确判断参会者在会议时段的空闲状态,是否遗漏边界场景
  • 启用分数计算日志:在求解器配置中添加<scoreDirectorFactory><enableScoreCalculationLogging>true</enableScoreCalculationLogging></scoreDirectorFactory>,观察每次移动的分数变化,确认将会议时间调整至第二天时,硬约束分数是否符合预期,排除错误分数计算的影响

5. 其他细节调整

  • 优化终止条件:延长思考时间至120秒,同时设置无改进自动终止,避免无效计算:
    <termination>
        <secondsSpentLimit>120</secondsSpentLimit>
        <unimprovedSecondsSpentLimit>30</unimprovedSecondsSpentLimit>
    </termination>
    
  • 尝试Tabu Search进阶配置:若使用Tabu,显式设置禁忌对象为会议时间,避免算法持续停留在第一天:
    <localSearch>
        <acceptor>
            <acceptorType>TABU</acceptorType>
            <tabuSize>20</tabuSize>
            <tabuOrder>1</tabuOrder>
        </acceptor>
        <moveSelector>
            <changeMoveSelector>
                <planningVariableName>meetingTime</planningVariableName>
                <selectedCountLimit>10</selectedCountLimit>
            </changeMoveSelector>
        </moveSelector>
    </localSearch>
    

内容的提问来源于stack exchange,提问作者Zhetao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 23:55:20