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

如何在OptaPlanner约束中获取@PlanningEntity/@PlanningVariable完整列表

解决OptaPlanner航空座位分配中获取全部Passenger实例的约束逻辑实现

在航空座位分配场景里,要基于乘客出价(Bid)奖励最高出价的已分配乘客,核心是在约束逻辑中获取所有已分配的Passenger实例来做全局判断。你之前用groupBy只拿到单个实例,是因为没做全局分组——默认的分组会按实例属性拆分,要获取完整列表,需要把所有目标实例归到同一个全局组里。

具体实现方式(Constraint Streams API)

用OptaPlanner的Constraint Streams API,通过全局分组收集所有已分配乘客,再筛选出最高出价者给予奖励:

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.stream.Collectors;

public class SeatAssignmentConstraintProvider implements ConstraintProvider {

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

    private Constraint rewardTopBidAssignedPassenger(ConstraintFactory constraintFactory) {
        // 1. 筛选所有已分配座位的乘客,全局分组收集为列表
        return constraintFactory.forEach(Passenger.class)
                .filter(passenger -> passenger.getAssignedSeat() != null)
                // 用固定常量作为分组键,将所有已分配乘客归入同一组
                .groupBy(() -> "allAssignedPassengers", Collectors.toList())
                // 2. 从全局列表中找出最高出价,筛选出对应乘客
                .flatMap((groupKey, assignedPassengers) -> {
                    int maxBid = assignedPassengers.stream()
                            .mapToInt(Passenger::getBid)
                            .max()
                            .orElse(0);
                    return assignedPassengers.stream()
                            .filter(p -> p.getBid() == maxBid);
                })
                // 3. 对最高出价乘客给予奖励分数(这里用Soft分,可根据需求调整分值)
                .reward("Reward highest bid assigned passenger", HardSoftScore.ofSoft(150));
    }
}

关键说明

  • 全局分组:groupBy(() -> "allAssignedPassengers", Collectors.toList()) 是核心——用固定字符串作为分组键,强制所有已分配乘客进入同一个组,这样就能拿到完整的实例列表。
  • 筛选逻辑:通过flatMap从全局列表中提取最高出价的乘客,避免重复判断。
  • 分数调整:HardSoftScore.ofSoft(150) 可根据业务需求修改分值,或换成其他分数类型(如SimpleScore)。

另一种简化实现(直接判断单个乘客是否为全局最高)

如果不需要对所有最高出价乘客批量处理,也可以在遍历单个乘客时,通过关联判断确认是否为全局最高出价者:

private Constraint rewardTopBidPassengerSimplified(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(Passenger.class)
            .filter(p -> p.getAssignedSeat() != null)
            // 关联所有已分配乘客,判断当前乘客的Bid是否是全局最大
            .join(Passenger.class, 
                    Joiners.equal(p -> true, other -> true), // 全局关联
                    Joiners.filtering((p, other) -> other.getAssignedSeat() != null),
                    Joiners.filtering((p, other) -> p.getBid() >= other.getBid()))
            // 确保当前乘客的Bid大于等于所有其他已分配乘客的Bid
            .groupBy((p, other) -> p, Collectors.counting())
            .filter((p, count) -> count == constraintFactory.from(Passenger.class)
                    .filter(other -> other.getAssignedSeat() != null)
                    .count())
            .reward("Reward top bid passenger", HardSoftScore.ofSoft(150));
}

这种方式不需要显式收集列表,但逻辑稍复杂,适合场景简单的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 09:55:31