LimitViolationsResultEquivalence.java
/**
* Copyright (c) 2018, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.security.comparator;
import java.io.Writer;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import com.google.common.base.Equivalence;
import com.powsybl.security.LimitViolation;
import com.powsybl.security.LimitViolationsResult;
/**
*
* @author Massimo Ferraro {@literal <massimo.ferraro@techrain.eu>}
*/
public class LimitViolationsResultEquivalence extends Equivalence<LimitViolationsResult> {
private final double threshold;
private SecurityAnalysisResultComparisonWriter comparisonWriter;
public LimitViolationsResultEquivalence(double threshold, Writer writer) {
this(threshold, new SecurityAnalysisResultComparisonWriter(writer));
}
LimitViolationsResultEquivalence(double threshold, SecurityAnalysisResultComparisonWriter comparisonWriter) {
this.threshold = threshold;
this.comparisonWriter = comparisonWriter;
}
@Override
protected boolean doEquivalent(LimitViolationsResult result1, LimitViolationsResult result2) {
LimitViolationComparator violationComparator = new LimitViolationComparator();
LimitViolationEquivalence violationEquivalence = new LimitViolationEquivalence(threshold);
// compare computation
boolean equivalent = true;
// I still carry on the comparison even if equivalent is already false because I need to print the violations
// compare violations
List<LimitViolation> violations1 = result1.getLimitViolations();
List<LimitViolation> violations2 = result2.getLimitViolations();
Collections.sort(violations1, violationComparator);
Collections.sort(violations2, violationComparator);
int index1 = 0;
int index2 = 0;
while (index1 < violations1.size() && index2 < violations2.size()) {
LimitViolation violation1 = violations1.get(index1);
LimitViolation violation2 = violations2.get(index2);
int violationsComparison = violationComparator.compare(violation1, violation2);
if (violationsComparison == 0) { // same violations in both results
boolean violationsEquivalent = violationEquivalence.equivalent(violation1, violation2);
comparisonWriter.write(violation1, violation2, violationsEquivalent);
equivalent &= violationsEquivalent;
index1++;
index2++;
} else if (violationsComparison < 0) { // violation only on result1
equivalent &= isSmallViolation(violation1, false);
index1++;
} else { // violation only on result2
equivalent &= isSmallViolation(violation2, true);
index2++;
}
}
while (index1 < violations1.size()) { // possibly remaining result1 violations
LimitViolation violation1 = violations1.get(index1);
equivalent &= isSmallViolation(violation1, false);
index1++;
}
while (index2 < violations2.size()) { // possibly remaining result1 violations
LimitViolation violation2 = violations2.get(index1);
equivalent &= isSmallViolation(violation2, true);
index2++;
}
// compare actions
List<String> actions1 = result1.getActionsTaken();
List<String> actions2 = result2.getActionsTaken();
Collections.sort(actions1);
Collections.sort(actions2);
boolean actionsEquivalent = actions1.equals(actions2);
comparisonWriter.write(actions1, actions2, actionsEquivalent);
equivalent &= actionsEquivalent;
return equivalent;
}
private boolean isSmallViolation(LimitViolation violation, boolean missingResult1) {
boolean smallViolation = Math.abs(violation.getValue() - (violation.getLimit() * violation.getLimitReduction())) <= threshold;
comparisonWriter = missingResult1 ? comparisonWriter.write(null, violation, smallViolation) : comparisonWriter.write(violation, null, smallViolation);
return smallViolation;
}
@Override
protected int doHash(LimitViolationsResult result) {
return Objects.hashCode(result);
}
}