在 OptaPlanner 中生成基准报告期间出现 ArrayIndexOutOfBoundsException

ArrayIndexOutOfBoundsException during generating benchmarking report in OptaPlanner

所以我想运行 OptaPlanner 的基准测试,我已经能够针对各种问题(tsp、vrp)成功地实现它。

现在我正在 运行 将其用于更复杂的 vrp,但在生成基准报告期间我遇到了 ArrayIndexOutOfBoundsException

// start benchmark
PlannerBenchmarkFactory plannerBenchmarkFactory = PlannerBenchmarkFactory.createFromXmlFile(
    new File("src/main/resources/vehiclerouting/benchmark/vrpBenchmarkConfig.xml"));

PlannerBenchmark plannerBenchmark = plannerBenchmarkFactory.buildPlannerBenchmark();
plannerBenchmark.benchmark(); //exception is thrown here.

向下钻取我发现它发生在 writeBestScoreSummaryChart()BenchMarkReport

private void writeBestScoreSummaryChart() {
    // Each scoreLevel has it's own dataset and chartFile
    List<DefaultCategoryDataset> datasetList = new ArrayList<>(CHARTED_SCORE_LEVEL_SIZE);
    for (SolverBenchmarkResult solverBenchmarkResult : plannerBenchmarkResult.getSolverBenchmarkResultList()) {
        String solverLabel = solverBenchmarkResult.getNameWithFavoriteSuffix();
        for (SingleBenchmarkResult singleBenchmarkResult : solverBenchmarkResult.getSingleBenchmarkResultList()) {
            String planningProblemLabel = singleBenchmarkResult.getProblemBenchmarkResult().getName();
            if (singleBenchmarkResult.hasAllSuccess()) {
                double[] levelValues = ScoreUtils.extractLevelDoubles(singleBenchmarkResult.getAverageScore());
                for (int i = 0; i < levelValues.length && i < CHARTED_SCORE_LEVEL_SIZE; i++) {
                    if (i >= datasetList.size()) {
                        datasetList.add(new DefaultCategoryDataset());
                    }
                    datasetList.get(i).addValue(levelValues[i], solverLabel, planningProblemLabel);
                }
            }
        }
    }
    bestScoreSummaryChartFileList = new ArrayList<>(datasetList.size());
    int scoreLevelIndex = 0;
    for (DefaultCategoryDataset dataset : datasetList) {
        String scoreLevelLabel = plannerBenchmarkResult.findScoreLevelLabel(scoreLevelIndex);
        CategoryPlot plot = createBarChartPlot(dataset,
                "Best " + scoreLevelLabel, NumberFormat.getInstance(locale));
        JFreeChart chart = new JFreeChart("Best " + scoreLevelLabel + " summary (higher is better)",
                JFreeChart.DEFAULT_TITLE_FONT, plot, true);
        bestScoreSummaryChartFileList.add(writeChartToImageFile(chart, "bestScoreSummaryLevel" + scoreLevelIndex));
        scoreLevelIndex++;
    }
}

在上面的方法中 datasetList 达到了 7 的大小。(我们有 7 个分数级别 -> 6 个硬,1 个软)。

当在第二个循环中调用 plannerBenchmarkResult.findScoreLevelLabel(scoreLevelIndex);findScoreLevelLabel() 只有 returns 5 个分数级别。即:hard 0 scorehard 1 scorehard 2 scorehard 3 scoresoft 0 score

所以一旦 scoreLevelLabel 有一个值 >4 一个 ArrayIndexOutOfBoundsException 被抛出。关于为什么 Optaplanner 注册 5 个分数级别的任何想法/提示,而应该有 7 个。

编辑 堆栈跟踪:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at org.optaplanner.benchmark.impl.result.PlannerBenchmarkResult.findScoreLevelLabel(PlannerBenchmarkResult.java:242)
at org.optaplanner.benchmark.impl.report.BenchmarkReport.writeBestScoreSummaryChart(BenchmarkReport.java:365)
at org.optaplanner.benchmark.impl.report.BenchmarkReport.writeReport(BenchmarkReport.java:241)
at org.optaplanner.benchmark.impl.DefaultPlannerBenchmark.benchmarkingEnded(DefaultPlannerBenchmark.java:306)
at org.optaplanner.benchmark.impl.DefaultPlannerBenchmark.benchmark(DefaultPlannerBenchmark.java:104)
at benchmark.BenchMarker.main(BenchMarker.java:57)

我找到问题了。

@PlanningScore(bendableHardLevelsSize = 4, bendableSoftLevelsSize = 1)
public BendableLongScore getScore() {
    return score;
}

添加更多级别后,相应的分数级别未更新。 我不知道错误的声明如何影响 Optaplanner。这些级别是否用于(反)序列化以外的其他用途?