Optaplanner:如何让求解器优先最小化Medium分数再处理Soft分数?
解决OptaPlanner中Medium约束优先于Soft约束的配置问题
嘿,这个问题我之前做OptaPlanner POC的时候也踩过坑!核心原因是你需要明确告诉求解器约束层级的优先级顺序,让它先优先优化Medium分数,再处理Soft分数。下面给你一步步拆解解决方案:
1. 确认Score类型是否正确
首先要确保你用的是支持三层优先级的HardMediumSoftScore,而不是只有两层的HardSoftScore。因为你的场景需要区分Hard→Medium→Soft的优先级,这个类型是基础。
在你的规划解决方案类里,要明确指定Score类型:
@PlanningScore private HardMediumSoftScore score;
2. 约束定义时绑定正确的层级权重
不管你用的是Constraint Streams(推荐方式)还是Drools规则,都要把Medium约束和Soft约束分别绑定到对应的层级:
如果你用Constraint Streams:
Medium约束要使用ofMedium()来设置权重,Soft约束用ofSoft():
// Medium约束:违反一次扣1分Medium分数 constraintFactory.from(YourPlanningEntity.class) .filter(entity -> /* 你的约束条件 */) .penalize("Medium可空实体约束", HardMediumSoftScore.ofMedium(1)) .asConstraint(); // Soft约束:违反一次扣1分Soft分数 constraintFactory.from(YourPlanningEntity.class) .filter(entity -> /* 你的约束条件 */) .penalize("Soft优化约束", HardMediumSoftScore.ofSoft(1)) .asConstraint();
如果你用Drools规则:
要确保使用HardMediumSoftScoreHolder,并分别调用addMediumConstraintMatch和addSoftConstraintMatch:
global HardMediumSoftScoreHolder scoreHolder; rule "Medium可空实体约束" when // 你的约束条件 then scoreHolder.addMediumConstraintMatch(kcontext, -1); end rule "Soft优化约束" when // 你的约束条件 then scoreHolder.addSoftConstraintMatch(kcontext, -1); end
3. 配置求解器的Score定义类型
在求解器配置中,明确指定Score类型为HARD_MEDIUM_SOFT,确保求解器识别层级优先级:
XML配置方式:
<solver> <scoreDirectorFactory> <scoreDefinitionType>HARD_MEDIUM_SOFT</scoreDefinitionType> <!-- 其他配置(如约束提供者/规则文件) --> </scoreDirectorFactory> <!-- 其他求解器配置 --> </solver>
Java代码配置方式:
SolverConfig solverConfig = new SolverConfig(); solverConfig.getScoreDirectorFactoryConfig() .setScoreDefinitionType(ScoreDefinitionType.HARD_MEDIUM_SOFT); // 其他求解器配置
为什么之前的配置会出问题?
你提到添加Soft约束后,Medium分数从-2变差到-8,大概率是这两个原因:
- 误用了
HardSoftScore类型,导致Medium和Soft约束被放在同一层级处理,求解器会同时优化两者,自然会牺牲Medium来换取Soft分数 - 约束定义时层级绑定错误,比如把Medium约束写成了Soft层级,或者反过来
OptaPlanner的HardMediumSoftScore本身就是层级优先的:先保证Hard约束不被违反(你的场景Hard分数是0,没问题),然后尽可能优化Medium分数,最后才会考虑Soft分数。只要配置正确,求解器就会自动遵循这个优先级逻辑。
内容的提问来源于stack exchange,提问作者Sébastien Heilig
相关产品推荐
相关产品推荐

