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

如何在OptaPlanner中排除特定匹配?约束流实现示例

用Constraint Streams实现Profile匹配的分配约束示例

核心需求

确保仅当ProjectMember与StockMember的profile属性完全匹配时,才能进行分配;不匹配的分配属于违反硬约束,必须被OptaPlanner禁止。


基础实体结构(基于需求假设)

假设你的规划实体、问题事实类结构如下(如果实际代码有差异,对应调整约束逻辑即可):

Planning Entity(分配实体)

@PlanningEntity
public class Allocation {
    @PlanningId
    private Long id;

    // 需求方:ProjectMember(问题事实)
    private ProjectMember projectMember;

    // 待分配的库存:StockMember(规划变量)
    @PlanningVariable(valueRangeProviderRefs = "stockMemberRange")
    private StockMember stockMember;

    // 省略getter、setter
}

问题事实类

// 需求对象
public class ProjectMember {
    private String profile; // 所需型材规格
    // 省略其他属性、getter、setter
}

// 库存对象
public class StockMember {
    private String profile; // 库存型材规格
    // 省略其他属性、getter、setter
}

Planning Solution

@PlanningSolution
public class AllocationSolution {
    @PlanningScore
    private HardSoftScore score;

    @ProblemFactCollectionProperty
    private List<ProjectMember> projectMemberList;

    @ProblemFactCollectionProperty
    private List<StockMember> stockMemberList;

    @PlanningEntityCollectionProperty
    private List<Allocation> allocationList;

    // 省略getter、setter
}

修正后的Constraint Provider代码

通过Constraint Streams实现硬约束,强制profile匹配:

import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintFactory;
import org.optaplanner.core.api.score.stream.ConstraintProvider;
import java.util.Objects;

public class AllocationConstraintProvider implements ConstraintProvider {

    @Override
    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
        return new Constraint[] {
            profileMatchHardConstraint(constraintFactory)
        };
    }

    private Constraint profileMatchHardConstraint(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Allocation.class)
                // 过滤已分配库存的Allocation实例(未分配的无需检查)
                .filter(allocation -> allocation.getStockMember() != null)
                // 筛选出profile不匹配的无效分配
                .filter(allocation -> !Objects.equals(
                        allocation.getProjectMember().getProfile(),
                        allocation.getStockMember().getProfile()))
                // 对每个无效分配施加硬惩罚(OptaPlanner会优先避免硬约束被违反)
                .penalize("Profile不匹配的无效分配", HardSoftScore.ONE_HARD);
    }
}

代码逻辑说明

  1. 流起点:从Allocation实体流开始,遍历所有分配实例
  2. 过滤未分配情况:排除还没分配StockMember的实例,避免无意义检查
  3. 匹配检查:对比ProjectMember和StockMember的profile,筛选出不匹配的分配
  4. 硬惩罚:对每个无效分配添加硬惩罚分数,OptaPlanner在求解时会优先保证硬约束不被违反,最终只会保留profile匹配的分配结果

适配不同实体结构的调整

如果你的Planning Entity直接是ProjectMember(规划变量为StockMember),只需修改约束逻辑的遍历对象:

private Constraint profileMatchHardConstraint(ConstraintFactory constraintFactory) {
    return constraintFactory.from(ProjectMember.class)
            .filter(projectMember -> projectMember.getAssignedStockMember() != null)
            .filter(projectMember -> !Objects.equals(
                    projectMember.getProfile(),
                    projectMember.getAssignedStockMember().getProfile()))
            .penalize("Profile不匹配的无效分配", HardSoftScore.ONE_HARD);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:31:00