Skip to content

Commit 608a239

Browse files
rounding + TU
Signed-off-by: Mathieu DEHARBE <[email protected]>
1 parent 80797df commit 608a239

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/SpecificationUtils.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ public static <X> Specification<X> notEqual(String field, Double value, Double t
5959
return (root, cq, cb) -> {
6060
Expression<Double> doubleExpression = getColumnPath(root, field).as(Double.class);
6161
/**
62-
* in order to be equal to doubleExpression, truncated value has to fit :
63-
* value <= doubleExpression < value + tolerance
62+
* in order to be equal to doubleExpression, value has to fit :
63+
* value - tolerance <= doubleExpression < value + tolerance
6464
* therefore in order to be different at least one of the opposite comparison needs to be true :
6565
*/
6666
return cb.or(
6767
cb.greaterThanOrEqualTo(doubleExpression, value + tolerance),
68-
cb.lessThan(doubleExpression, value)
68+
cb.lessThan(doubleExpression, value - tolerance)
6969
);
7070
};
7171
}
@@ -149,17 +149,18 @@ private static <X> Specification<X> appendNumberFilterToSpecification(Specificat
149149
return createNumberPredicate(specification, resourceFilter, value);
150150
}
151151

152-
private static <X> Specification<X> createNumberPredicate(Specification<X> specification, ResourceFilterDTO resourceFilter, String value) {
152+
private static <X> Specification<X> createNumberPredicate(Specification<X> specification, ResourceFilterDTO resourceFilter, String filterValue) {
153153
// the reference for the comparison is the number of digits after the decimal point in filterValue
154-
// filterValue is truncated, not rounded
155154
// extra digits are ignored, but the user may add '0's after the decimal point in order to get a better precision
156-
String[] splitValue = value.split("\\.");
155+
String[] splitValue = filterValue.split("\\.");
157156
int numberOfDecimalAfterDot = 0;
158157
if (splitValue.length > 1) {
159158
numberOfDecimalAfterDot = splitValue[1].length();
160159
}
161-
final double tolerance = Math.pow(10, -numberOfDecimalAfterDot); // tolerance for comparison
162-
Double valueDouble = Double.valueOf(value);
160+
// tolerance is multiplied by 5 to simulate the fact that the database value is rounded (in the front, from the user viewpoint)
161+
// more than 13 decimal after dot will likely cause rounding errors due to double precision
162+
final double tolerance = Math.pow(10, -numberOfDecimalAfterDot) * 0.5;
163+
Double valueDouble = Double.valueOf(filterValue);
163164
return switch (resourceFilter.type()) {
164165
case NOT_EQUAL -> specification.and(notEqual(resourceFilter.column(), valueDouble, tolerance));
165166
case LESS_THAN_OR_EQUAL ->

src/test/java/org/gridsuite/securityanalysis/server/FindPreContingencyLimitViolationTest.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ void findFilteredPrecontingencyLimitViolationResultsTest(List<ResourceFilterDTO>
7575
List<PreContingencyLimitViolationResultDTO> preContingencyLimitViolation = securityAnalysisResultService.findNResult(resultEntity.getId(), filters, sort);
7676

7777
// assert subject ids to check parent filters
78-
assertThat(preContingencyLimitViolation).extracting(SubjectLimitViolationEntity.Fields.subjectId).containsExactlyElementsOf(expectedResult.stream().map(PreContingencyLimitViolationResultDTO::getSubjectId).toList());
78+
assertThat(preContingencyLimitViolation).extracting(SubjectLimitViolationEntity.Fields.subjectId)
79+
.containsExactlyElementsOf(
80+
expectedResult.stream().map(PreContingencyLimitViolationResultDTO::getSubjectId).toList()
81+
);
7982
assertSelectCount(expectedSelectCount);
8083
}
8184

@@ -110,9 +113,11 @@ private static Stream<Arguments> provideChildFilter() {
110113

111114
private static Stream<Arguments> provideChildFilterWithTolerance() {
112115
return Stream.of(
113-
Arguments.of(List.of(new ResourceFilterDTO(ResourceFilterDTO.DataType.NUMBER, ResourceFilterDTO.Type.NOT_EQUAL, "11.02425", AbstractLimitViolationEntity.Fields.value),
116+
Arguments.of(List.of(
117+
new ResourceFilterDTO(ResourceFilterDTO.DataType.NUMBER, ResourceFilterDTO.Type.NOT_EQUAL, "11.02425", AbstractLimitViolationEntity.Fields.value),
114118
new ResourceFilterDTO(ResourceFilterDTO.DataType.NUMBER, ResourceFilterDTO.Type.LESS_THAN_OR_EQUAL, "10.51243", AbstractLimitViolationEntity.Fields.limit),
115-
new ResourceFilterDTO(ResourceFilterDTO.DataType.NUMBER, ResourceFilterDTO.Type.GREATER_THAN_OR_EQUAL, "1.00001", AbstractLimitViolationEntity.Fields.limitReduction)), Sort.by(Sort.Direction.ASC, "limit"),
119+
new ResourceFilterDTO(ResourceFilterDTO.DataType.NUMBER, ResourceFilterDTO.Type.GREATER_THAN_OR_EQUAL, "0.999999", AbstractLimitViolationEntity.Fields.limitReduction)
120+
), Sort.by(Sort.Direction.ASC, "limit"),
116121
getResultPreContingencyWithNestedFilter(p -> p.getLimitViolation().getLimit() <= 10.51243)
117122
.stream().sorted(Comparator.comparing(x -> x.getLimitViolation().getLimit())).toList(), 2)
118123
);

0 commit comments

Comments
 (0)