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

多规划变量场景下OptaPlanner SelectionFilter适配性及移动过滤方案咨询

多规划变量场景下OptaPlanner SelectionFilter适配性及移动过滤方案咨询

嗨,你的这个场景其实是OptaPlanner里非常典型的多规划变量依赖过滤问题,我来一步步给你拆解解答:

一、SelectionFilter能不能适配你的需求?

答案是肯定的,但需要灵活利用规划实体的上下文。虽然SelectionFilter的参数是Solution和候选的规划变量值,但你完全可以在Filter中获取当前的规划实体(B),进而拿到另一个变量的当前状态,以此做过滤:

  • 比如要过滤planningDate的候选值时,在Filter里先拿到当前实体的C字段值,再根据C的字段筛选允许的日期集合;
  • 同理,过滤C的候选值时,拿到当前实体的planningDate,再筛选符合该日期的C列表。

举个贴合你类结构的伪代码示例:

// 过滤planningDate的SelectionFilter实现
public class PlanningDateFilter implements SelectionFilter<A, LocalDate> {
    @Override
    public boolean accept(A solution, B entity, LocalDate candidateDate) {
        // 获取当前实体已赋值的C
        C currentC = entity.getC();
        if (currentC == null) {
            return true; // 未赋值C时允许所有日期候选
        }
        // 根据C的字段筛选合法日期
        return currentC.getAllowedFixedDates().contains(candidateDate);
    }
}

不过你担心的那个问题确实存在:如果C1和C2对应的日期集合完全无交集,仅用单变量的SelectionFilter会导致无法从C1切换到C2——因为切换C的单变量移动会要求当前的planningDate必须在C2的允许日期集里,而当前日期是C1的合法日期(不在C2的集合里),所以这个移动会被直接过滤掉。

二、更推荐的方案:Filtered Move Selection + 组合移动

针对这个痛点,Filtered Move Selection是更合适的选择,它比SelectionFilter更灵活,因为它是对整个移动操作(而非单个候选值)做合法性检查:

  1. 对于单变量移动:比如修改C时,检查移动后新的C对应的日期集是否包含当前的planningDate;如果不包含,就过滤掉这个单变量移动;
  2. 对于组合移动:允许同时修改C和planningDate的移动(比如ChangeMove同时改变两个变量),只要修改后的C和planningDate互相匹配,就允许这个移动——这样就能直接从「C1+合法日期D1」切换到「C2+合法日期D2」,完美解决无交集时无法切换的问题。

具体配置思路

在Solver配置中,你可以这么做:

  • 启用组合移动:配置同时修改C和planningDate的Composite Move,确保求解器能生成合法的跨变量组合操作;
  • 配置MoveFilter:编写一个过滤规则,检查移动后的实体状态是否满足「C和planningDate互相匹配」的要求,只要满足就允许该移动。

给你一个MoveFilter的伪代码参考:

public class ValidEntityMoveFilter implements MoveFilter<A> {
    @Override
    public boolean accept(A solution, Move move) {
        // 从移动操作中获取目标规划实体
        B targetEntity = (B) move.getPlanningEntities().get(0);
        // 模拟提取移动后的变量值(实际可通过Move的API获取修改后的状态)
        LocalDate newPlanningDate = extractNewPlanningDate(move);
        C newC = extractNewC(move);
        
        // 核心匹配检查:双向验证合法性
        if (newC != null && newPlanningDate != null) {
            return newC.getAllowedDates().contains(newPlanningDate) 
                    && newPlanningDate.getAllowedCList().contains(newC);
        }
        // 未完全赋值时的宽松规则(可根据业务需求调整)
        return true;
    }
    
    // 辅助方法:从移动中提取新的planningDate值
    private LocalDate extractNewPlanningDate(Move move) {
        // 实现根据Move类型提取新值的逻辑
        return ...;
    }
    
    private C extractNewC(Move move) {
        // 实现根据Move类型提取新C值的逻辑
        return ...;
    }
}

三、其他补充建议

  • 如果你希望更动态的候选值范围,也可以考虑动态ValueRangeProvider:比如在B类中,给planningDate的ValueRangeProvider加上对C的依赖,但要注意OptaPlanner的动态范围缓存机制,确保范围能随C的变化实时更新;
  • 避免过度过滤:不要把所有“过渡性”的移动都过滤掉,比如可以允许临时的不匹配但通过分数惩罚来约束,这样求解器能更灵活地探索解空间,避免陷入局部最优。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 11:33:01