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

OptaPlanner约束中数组元素级求和及阈值校验问题求助

核心问题:对象列表的整数序列元素级求和

要实现多个同长度整数序列的元素级求和,Java流可以通过reduce操作完成。注意:Java泛型不支持基本类型,原示例中的ArrayList<int>是非法写法,实际应使用ArrayList<Integer>或者int[]数组。

针对List<Integer>的实现

// 定义对象类
class MyObject {
    private List<Integer> arrayOfInts;

    public List<Integer> getArrayOfInts() {
        return arrayOfInts;
    }

    public void setArrayOfInts(List<Integer> arrayOfInts) {
        this.arrayOfInts = arrayOfInts;
    }
}

// 求和逻辑
List<MyObject> listOfObjects = Arrays.asList(
    new MyObject() {{ setArrayOfInts(Arrays.asList(1,1,1)); }},
    new MyObject() {{ setArrayOfInts(Arrays.asList(2,2,2)); }}
);

List<Integer> result = listOfObjects.stream()
    .map(MyObject::getArrayOfInts)
    .reduce((list1, list2) -> {
        // 实际场景建议添加长度一致性校验
        return IntStream.range(0, list1.size())
            .map(i -> list1.get(i) + list2.get(i))
            .boxed()
            .collect(Collectors.toList());
    })
    .orElse(Collections.emptyList()); // 空列表时返回空集合

// 输出结果:[3, 3, 3]
System.out.println(result);

针对int[]数组的实现(性能更优)

如果时间序列用int[]存储,效率会比List<Integer>更高:

// 定义对象类
class MyObject {
    private int[] arrayOfInts;

    public int[] getArrayOfInts() {
        return arrayOfInts;
    }

    public void setArrayOfInts(int[] arrayOfInts) {
        this.arrayOfInts = arrayOfInts;
    }
}

// 求和逻辑
List<MyObject> listOfObjects = Arrays.asList(
    new MyObject() {{ setArrayOfInts(new int[]{1,1,1}); }},
    new MyObject() {{ setArrayOfInts(new int[]{2,2,2}); }}
);

int[] result = listOfObjects.stream()
    .map(MyObject::getArrayOfInts)
    .reduce(new int[0], (arr1, arr2) -> {
        int[] sumArr = new int[arr1.length];
        for (int i = 0; i < arr1.length; i++) {
            sumArr[i] = arr1[i] + arr2[i];
        }
        return sumArr;
    });

// 输出结果:[3, 3, 3]
System.out.println(Arrays.toString(result));

OptaPlanner约束实现

回到你的OptaPlanner场景,要统计所有Operation的resourceUsage元素求和后超过阈值X的数量并惩罚,提供两种实现方案:

方案一:全数组汇总后校验

public Constraint resourceOveroccupation(ConstraintFactory constraintFactory) {
    int thresholdX = 5; // 替换为你的阈值

    return constraintFactory.forEach(Operation.class)
        .map(Operation::getResourceUsage) // 假设返回int[]类型
        .reduce((arr1, arr2) -> {
            int[] sumArr = new int[arr1.length];
            for (int i = 0; i < arr1.length; i++) {
                sumArr[i] = arr1[i] + arr2[i];
            }
            return sumArr;
        })
        .filter(sumArr -> IntStream.of(sumArr).anyMatch(val -> val > thresholdX))
        .penalize("Resource Overoccupation", 
            HardMediumSoftScore.ONE_MEDIUM,
            sumArr -> (int) IntStream.of(sumArr).filter(val -> val > thresholdX).count());
}

方案二:分时间点统计(推荐)

如果时间序列长度固定,按单个时间点单独统计更适合OptaPlanner的增量计算逻辑(当Operation变动时,仅需更新对应时间点的统计值):

public Constraint resourceOveroccupation(ConstraintFactory constraintFactory) {
    int thresholdX = 5;
    int timeSeriesLength = 3; // 替换为你的时间序列固定长度

    return constraintFactory.forEach(Operation.class)
        .flatMap(operation -> IntStream.range(0, timeSeriesLength)
            .mapToObj(timeIndex -> new AbstractMap.SimpleEntry<>(timeIndex, operation.getResourceUsage()[timeIndex])))
        .groupBy(Map.Entry::getKey, sum(Map.Entry::getValue))
        .filter((timeIndex, totalUsage) -> totalUsage > thresholdX)
        .penalize("Resource Overoccupation per Time Slot", 
            HardMediumSoftScore.ONE_MEDIUM,
            (timeIndex, totalUsage) -> 1); // 每个超阈值的时间点惩罚1次
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:22:53