作业组分配约束问题:资源不足时如何使组内作业全未分配?
作业组分配一致性约束问题
我正在为作业组构建作业分配模型,场景里每个组包含多个作业,每个作业需要不同的资源技能来执行。核心需求是同一组内的所有作业必须保持相同的分配状态——要么全部分配,要么全部未分配。
我尝试用以下代码给分配状态不一致的组设置HARD惩罚约束,但求解器输出的结果硬分数为1,达不到预期效果。现在想解决的是:当组内作业没有足够资源执行时,如何确保组内所有作业都处于未分配状态?
我的约束代码:
constraintFactory.forEachIncludingNullVars(Allocation.class) .groupBy( a -> a.getTask() .getProject() .getId(), ConstraintCollectors.sum(b -> b.isAssigned() ? 1 : 0), ConstraintCollectors.count() ) .filter((project, assigned, size) -> { return assigned != size && assigned > 0; }) .penalize( HardMediumSoftScore.ONE_HARD, (project, assigned, act) -> 1 ) .asConstraint("projectTasksConsistent");
现有两个作业组:[0,1,2,3,4]、[5,6,7,8,9],当前分配结果如下:
Task: 0 => 5 Task: 1 => 6 Task: 2 => 7 Task: 3 => 8 Task: 4 => 9 Task: 5 => 0 Task: 6 => 1 Task: 7 => 2 Task: 8 => 3 Task: 9 => null
问题分析与解决办法
你的约束逻辑存在两个关键问题:
- 惩罚力度不足:当前只要组内状态不一致,仅惩罚1个HARD分数,求解器可能会为了满足资源分配的部分收益,选择接受这种轻微的硬约束违反。
- 约束的强制力不够:现有逻辑是事后惩罚而非事前强制,导致求解器有钻空子的空间。
方案1:提升惩罚权重,强化硬约束
把惩罚值改成组内作业的数量,让违反一致性的代价远高于部分分配的收益,迫使求解器必须选择全分配或全未分配:
constraintFactory.forEachIncludingNullVars(Allocation.class) .groupBy( a -> a.getTask().getProject().getId(), ConstraintCollectors.sum(b -> b.isAssigned() ? 1 : 0), ConstraintCollectors.count() ) .filter((project, assigned, size) -> assigned != size && assigned > 0) .penalize( HardMediumSoftScore.ONE_HARD, (project, assigned, size) -> size // 用组规模作为惩罚值,放大违反成本 ) .asConstraint("projectTasksConsistent");
方案2:直接强制二选一(更严谨)
创建硬约束直接限制组内状态只能是全分配或全未分配,从逻辑上杜绝不一致的可能:
// 约束:若组内有作业已分配,则所有作业必须分配 constraintFactory.forEach(Allocation.class) .filter(Allocation::isAssigned) .join(Allocation.class, Joiners.equal(a -> a.getTask().getProject().getId()), Joiners.filtering((a1, a2) -> !a2.isAssigned())) .penalize(HardMediumSoftScore.ONE_HARD) .asConstraint("ifAnyAssignedAllMustBeAssigned"); // 约束:若组内有作业未分配,则所有作业必须未分配(与上一条互补,强化逻辑) constraintFactory.forEach(Allocation.class) .filter(a -> !a.isAssigned()) .join(Allocation.class, Joiners.equal(a -> a.getTask().getProject().getId()), Joiners.filtering((a1, a2) -> a2.isAssigned())) .penalize(HardMediumSoftScore.ONE_HARD) .asConstraint("ifAnyUnassignedAllMustBeUnassigned");
额外注意事项
确保资源技能匹配的约束也是HARD级别,这样当组内存在无法匹配资源的作业时,求解器会优先选择整个组不分配,而不是违反一致性约束。
内容的提问来源于stack exchange,提问作者KevinW
相关产品推荐
相关产品推荐

