From 3ffb49bd423b28050fb9bea8769b42ef1ed17da1 Mon Sep 17 00:00:00 2001 From: Fred Date: Fri, 9 Aug 2024 15:21:11 -0300 Subject: [PATCH] fix: address scale equal to NaN --- .../api/solver/ProblemSizeStatistics.java | 4 ++++ .../descriptor/SolutionDescriptor.java | 6 +++++- .../api/solver/ProblemSizeStatisticsTest.java | 20 +++++++++++++++++++ .../descriptor/SolutionDescriptorTest.java | 17 ++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemSizeStatistics.java b/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemSizeStatistics.java index 2208248636..5794f8567f 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemSizeStatistics.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemSizeStatistics.java @@ -39,6 +39,10 @@ public String approximateProblemScaleAsFormattedString() { } String approximateProblemScaleAsFormattedString(Locale locale) { + if (Double.isNaN(approximateProblemSizeLog) || Double.isInfinite(approximateProblemSizeLog)) { + return "0"; + } + if (approximateProblemSizeLog < 10) { // log_10(10_000_000_000) = 10 return "%s".formatted(format(Math.pow(10d, approximateProblemSizeLog), BASIC_FORMATTER, locale)); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptor.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptor.java index 50f38afd6a..9cec59f48a 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptor.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptor.java @@ -1095,7 +1095,11 @@ public double getProblemScale(ScoreDirector scoreDirector, Solution_ result += MathUtils.getPossibleArrangementsScaledApproximateLog(MathUtils.LOG_PRECISION, logBase, totalListMovableValueCount, possibleTargetsForListValue); } - return (result / (double) MathUtils.LOG_PRECISION) / MathUtils.getLogInBase(logBase, 10d); + var scale = (result / (double) MathUtils.LOG_PRECISION) / MathUtils.getLogInBase(logBase, 10d); + if (Double.isNaN(scale) || Double.isInfinite(scale)) { + return 0; + } + return scale; } public ProblemSizeStatistics getProblemSizeStatistics(ScoreDirector scoreDirector, Solution_ solution) { diff --git a/core/src/test/java/ai/timefold/solver/core/api/solver/ProblemSizeStatisticsTest.java b/core/src/test/java/ai/timefold/solver/core/api/solver/ProblemSizeStatisticsTest.java index 0f4ecc463c..c79a710f9d 100644 --- a/core/src/test/java/ai/timefold/solver/core/api/solver/ProblemSizeStatisticsTest.java +++ b/core/src/test/java/ai/timefold/solver/core/api/solver/ProblemSizeStatisticsTest.java @@ -67,5 +67,25 @@ void formatApproximateProblemScale() { statistics = getProblemSizeStatistics(321_123_456_789L); assertThat(statistics.approximateProblemScaleAsFormattedString()) .isEqualTo("3.211235 × 10^11"); + + // scale = -infinity + statistics = new ProblemSizeStatistics(0L, 0L, 0L, Double.NEGATIVE_INFINITY); + assertThat(statistics.approximateProblemScaleAsFormattedString()) + .isEqualTo("0"); + + // scale = +infinity + statistics = new ProblemSizeStatistics(0L, 0L, 0L, Double.POSITIVE_INFINITY); + assertThat(statistics.approximateProblemScaleAsFormattedString()) + .isEqualTo("0"); + + // scale = NaN + statistics = new ProblemSizeStatistics(0L, 0L, 0L, Double.NaN); + assertThat(statistics.approximateProblemScaleAsFormattedString()) + .isEqualTo("0"); + + // scale = 0 + statistics = new ProblemSizeStatistics(0L, 0L, 0L, 0); + assertThat(statistics.approximateProblemScaleAsFormattedString()) + .isEqualTo("1"); } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptorTest.java b/core/src/test/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptorTest.java index a24863d865..15a90afa81 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptorTest.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptorTest.java @@ -409,6 +409,23 @@ void problemScaleBasic() { }); } + @Test + void emptyProblemScale() { + int valueCount = 27; + int entityCount = 27; + SolutionDescriptor solutionDescriptor = TestdataSolution.buildSolutionDescriptor(); + TestdataSolution solution = TestdataSolution.generateSolution(valueCount, entityCount); + solution.getValueList().clear(); + assertSoftly(softly -> { + softly.assertThat(solutionDescriptor.getGenuineEntityCount(solution)).isEqualTo(entityCount); + softly.assertThat(solutionDescriptor.getGenuineVariableCount(solution)).isEqualTo(entityCount); + softly.assertThat(solutionDescriptor.getMaximumValueRangeSize(solution)).isEqualTo(0); + softly.assertThat(solutionDescriptor.getApproximateValueCount(solution)).isEqualTo(0); + softly.assertThat(solutionDescriptor.getProblemScale(null, solution)) + .isEqualTo(0); + }); + } + @Test void problemScaleMultipleValueRanges() { var solutionDescriptor = TestdataValueRangeSolution.buildSolutionDescriptor();