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

Timefold中链式规划变量实体的PlanningPin配置问题咨询

链式规划变量下的实体固定(Pin)配置调整

核心问题分析

使用@PlanningPin固定链式实体时,默认会锁定该实体的前后链节点关系,导致求解器无法在固定工单的前后添加新工单。这是因为默认的Pin逻辑会把实体的所有规划变量(包括链式的previous/next关联)都标记为不可修改。

调整方案

1. 自定义Pin过滤器(替代默认注解行为)

移除WorkOrder类上的@PlanningPin注解,自定义过滤器仅固定技术人员分配和开始时间,放开链式邻接的修改权限:

public class WorkOrderPinFilter implements EntityPinFilter<WorkOrder> {
    @Override
    public boolean isPin(ScoreDirector<YourSolution> scoreDirector, WorkOrder workOrder) {
        return workOrder.isPinned();
    }

    @Override
    public boolean isPin(ScoreDirector<YourSolution> scoreDirector, WorkOrder workOrder, String variableName) {
        // 仅固定技术人员和开始时间变量,允许修改链式的previous/next节点
        return workOrder.isPinned() && 
               (variableName.equals("technician") || variableName.equals("startTime"));
    }
}

在求解器配置中注册该过滤器:

<solver>
    <!-- 其他配置项 -->
    <entityPinFilterClass>com.yourpackage.WorkOrderPinFilter</entityPinFilterClass>
</solver>

2. 调整移动选择器(允许修改固定实体的邻接链)

默认移动选择器会跳过与固定实体相关的链式操作,需明确允许修改固定实体的前后链:

<solver>
    <constructionHeuristic>
        <forager>
            <acceptedCountLimit>1000</acceptedCountLimit>
        </forager>
    </constructionHeuristic>
    <localSearch>
        <moveSelector>
            <chainMoveSelector>
                <!-- 允许针对固定实体的邻接链执行移动操作 -->
                <ignoreEntityPins>false</ignoreEntityPins>
                <subChainChangeMoveSelector/>
                <subChainSwapMoveSelector/>
                <tailChainSwapMoveSelector/>
            </chainMoveSelector>
        </moveSelector>
        <!-- 其他局部搜索配置 -->
    </localSearch>
</solver>

其中ignoreEntityPins=false是核心配置,它让求解器不忽略与固定实体相关的链式移动,支持在固定工单前后插入新工单。

3. 添加硬约束(确保固定属性不被篡改)

为了防止固定实体的技术人员和开始时间被意外修改,在约束流中添加硬约束:

Constraint fixedWorkOrderTechnician(ConstraintFactory factory) {
    return factory.from(WorkOrder.class)
            .filter(WorkOrder::isPinned)
            .penalize("固定工单的技术人员不可变更", 
                      HardSoftScore.ONE_HARD,
                      workOrder -> !workOrder.getTechnician().equals(workOrder.getOriginalTechnician()))
            .asConstraint();
}

Constraint fixedWorkOrderStartTime(ConstraintFactory factory) {
    return factory.from(WorkOrder.class)
            .filter(WorkOrder::isPinned)
            .penalize("固定工单的开始时间不可变更", 
                      HardSoftScore.ONE_HARD,
                      workOrder -> !workOrder.getStartTime().equals(workOrder.getOriginalStartTime()))
            .asConstraint();
}

需要在WorkOrder类中新增originalTechnician和originalStartTime字段,在标记工单为pinned时保存原始值。

效果验证

配置完成后,求解器会实现:

  • 保持固定WorkOrder的技术人员和开始时间不变
  • 允许在该WorkOrder的前后链中插入、调整其他WorkOrder,分配给同一位技术人员

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:27:10