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

如何在Optaplanner中停用无需调度的规划实体以缩减搜索空间?

在OptaPlanner中实现非激活任务的规划变量忽略逻辑

要实现当任务active = False时,算法不处理其开始时间和持续时长这两个规划变量、缩小搜索空间,可通过以下几种方式实现:

1. 基于条件的规划变量值域限制

给目标规划变量添加条件式值域,仅当任务处于激活状态时提供有效取值范围;非激活时返回空值域或固定无效值(如null),让算法无法为其生成有效赋值。

代码示例:

// 任务实体类中的开始时间规划变量
@PlanningVariable(nullable = true, valueRangeProviderRefs = {"taskTimeRange"})
public LocalDateTime getStartTime() {
    return startTime;
}

// 任务实体类中的持续时长规划变量
@PlanningVariable(nullable = true, valueRangeProviderRefs = {"taskDurationRange"})
public Duration getDuration() {
    return duration;
}

// 开始时间的值域提供者,仅激活任务返回有效范围
@ValueRangeProvider(id = "taskTimeRange")
public ValueRange<LocalDateTime> getTimeRange() {
    if (this.active) {
        // 返回规划窗口内的有效时间范围
        return ValueRangeFactory.createLocalDateTimeRange(planningStart, planningEnd);
    } else {
        // 非激活任务返回仅包含null的值域,避免算法赋值
        return ValueRangeFactory.createSingleton(null);
    }
}

// 持续时长的值域提供者,仅激活任务返回有效范围
@ValueRangeProvider(id = "taskDurationRange")
public ValueRange<Duration> getDurationRange() {
    if (this.active) {
        // 返回允许的时长范围(如1小时到8小时)
        return ValueRangeFactory.createDurationRange(Duration.ofHours(1), Duration.ofHours(8));
    } else {
        return ValueRangeFactory.createSingleton(null);
    }
}

2. 自定义移动选择器过滤非激活任务

在求解器配置中,通过自定义移动过滤器,让算法仅对激活状态的任务生成修改开始时间和时长的移动操作,彻底排除非激活任务的变量变更搜索。

配置示例(XML):

<solver>
    <constructionHeuristic>
        <moveSelector>
            <filterClass>com.yourpackage.ActiveTaskMoveFilter</filterClass>
            <changeMoveSelector>
                <planningVariableName>startTime</planningVariableName>
            </changeMoveSelector>
            <changeMoveSelector>
                <planningVariableName>duration</planningVariableName>
            </changeMoveSelector>
        </moveSelector>
    </constructionHeuristic>
    <localSearch>
        <!-- 同样给局部搜索的移动选择器添加过滤器 -->
        <moveSelector>
            <filterClass>com.yourpackage.ActiveTaskMoveFilter</filterClass>
            <changeMoveSelector>
                <planningVariableName>startTime</planningVariableName>
            </changeMoveSelector>
            <changeMoveSelector>
                <planningVariableName>duration</planningVariableName>
            </changeMoveSelector>
        </moveSelector>
    </localSearch>
</solver>

过滤器实现类:

public class ActiveTaskMoveFilter implements MoveFilter<TaskScheduleSolution> {
    @Override
    public boolean accept(ScoreDirector<TaskScheduleSolution> scoreDirector, Move<TaskScheduleSolution> move) {
        // 仅允许修改激活任务的规划变量
        if (move instanceof ChangeMove) {
            ChangeMove<TaskScheduleSolution> changeMove = (ChangeMove<TaskScheduleSolution>) move;
            Task task = (Task) changeMove.getEntity();
            return task.isActive();
        }
        // 其他类型的移动(如交换)也可按需过滤
        return false;
    }
}

3. 约束规则中忽略非激活任务

配合上述两种方法,在分数计算的约束规则中仅对激活任务进行校验,避免非激活任务的变量状态影响分数结果。

Drools规则示例:

package com.yourpackage.constraints;

import com.yourpackage.Task;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;

global HardSoftScoreHolder scoreHolder;

// 仅校验激活任务的时间冲突
rule "NoOverlappingActiveTasks"
when
    $task1: Task(active == true, $start1: startTime, $duration1: duration)
    $task2: Task(active == true, this != $task1, 
                 startTime < $start1.plus($duration1), 
                 startTime.plus(duration) > $start1)
then
    scoreHolder.addHardConstraintMatch(kcontext, -1);
end

额外注意事项

  • 可在任务实体的setActive方法中添加逻辑:当active设为false时,自动将startTime和duration置为null,确保实体状态一致。
  • 若使用OptaPlanner的注解式配置,确保@PlanningVariable的nullable属性设为true,允许变量为null。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 14:57:40