Skip to content
Snippets Groups Projects
Commit e80a84f3 authored by Jonas Blatt's avatar Jonas Blatt :ant:
Browse files

Add implementation for subsumption rules

parent 72723127
No related branches found
No related tags found
No related merge requests found
package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl; package de.unikoblenz.fgbks.core.dmn.verification.verifier.impl;
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.IS_EQUAL;
import static de.unikoblenz.fgbks.base.utils.boundary.checker.BoundaryCheckType.SUBSUMES;
import de.unikoblenz.fgbks.core.dmn.domain.ids.RuleId;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnDecision;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnDecisionTable;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputColumn;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnInputValue;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnRule;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.VDmnValue;
import de.unikoblenz.fgbks.core.dmn.domain.vdmn.utils.VDmnFunctions;
import de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntry.VerificationClassification;
import de.unikoblenz.fgbks.core.dmn.verification.result.VerificationResultEntryElement;
import de.unikoblenz.fgbks.core.dmn.verification.verifier.AbstractVerifier; import de.unikoblenz.fgbks.core.dmn.verification.verifier.AbstractVerifier;
import de.unikoblenz.fgbks.core.dmn.verification.verifier.DmnVerifier; import de.unikoblenz.fgbks.core.dmn.verification.verifier.DmnVerifier;
import de.unikoblenz.fgbks.core.dmn.verification.verifier.config.DefaultConfiguration; import de.unikoblenz.fgbks.core.dmn.verification.verifier.config.DefaultConfiguration;
import de.unikoblenz.fgbks.core.dmn.verification.verifier.types.SubsumptionVerification; import de.unikoblenz.fgbks.core.dmn.verification.verifier.types.SubsumptionVerification;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@DmnVerifier( @DmnVerifier(
verifierType = SubsumptionVerification.class, verifierType = SubsumptionVerification.class,
...@@ -11,5 +28,145 @@ import de.unikoblenz.fgbks.core.dmn.verification.verifier.types.SubsumptionVerif ...@@ -11,5 +28,145 @@ import de.unikoblenz.fgbks.core.dmn.verification.verifier.types.SubsumptionVerif
public class SubsumptionVerifier extends AbstractVerifier { public class SubsumptionVerifier extends AbstractVerifier {
@Override @Override
protected void doVerification() {} protected void doVerification() {
for (VDmnDecision decision : dmnObjectContainer.getVDmnDefinition().getDmnDecisions()) {
checkSubsumptions(decision.getDmnDecisionTable());
}
}
private void checkSubsumptions(VDmnDecisionTable dmnDecisionTable) {
checkSubsumptions(
new ArrayList<>(dmnDecisionTable.getInputColumns()),
0,
dmnDecisionTable.getRulesIds(),
false,
Collections.emptyList());
}
private void checkSubsumptions(List<VDmnInputColumn> inColumns,
int i,
List<RuleId> currentRuleIds,
boolean hasSubsumption,
List<VDmnRule> currentRootSubsumptionElements) {
if (i == inColumns.size()) {
if (hasSubsumption && currentRuleIds.size() > currentRootSubsumptionElements.size()) {
// add to rules to result
// TODO
currentRuleIds.forEach(
ruleId ->
vref.addElement(
VerificationResultEntryElement.create(inColumns.get(0).getDmnDecisionTable())
.withIdentifier(ruleId)));
vref.addToEntry(VerificationClassification.WARNING, "subsumption");
}
} else {
// get all input values from the current column, and filter with the prev. iteration
List<VDmnInputValue> selectedBounds =
VDmnFunctions.getColumnValuesInRules(inColumns.get(i), currentRuleIds);
List<List<VDmnInputValue>> clusters = new ArrayList<>(); // clusters of subsumptions
List<Boolean> subsumptions =
new ArrayList<>(); // is the value in selectedBounds a subsubmption?
List<List<VDmnInputValue>> subsumptionValue =
new ArrayList<>(); // save the subsumption value of the current cluster
// if previously a rule was found, which has a subsumption, than it must be also the element,
// which subsume the other elements.
// First, build clusters, which contain a subsumption set
if (!currentRootSubsumptionElements.isEmpty()) {
// get the value from the subsumption rule
for (VDmnRule sRule : currentRootSubsumptionElements) {
List<VDmnInputValue> subsumptionVals = new ArrayList<>();
VDmnInputValue nValue = sRule.getDmnInputValues().get(i);
List<VDmnInputValue> c1 = new ArrayList<>();
boolean foundSubsumption = false;
for (VDmnInputValue cb2 : selectedBounds) {
boolean fs = nValue.getBoundary().checkWith(SUBSUMES, cb2.getBoundary());
foundSubsumption |= fs;
if (fs) {
c1.add(cb2);
} else if (nValue.getBoundary().checkWith(IS_EQUAL, cb2.getBoundary())) {
c1.add(cb2);
if (currentRootSubsumptionElements.contains(cb2)) {
subsumptionVals.add(cb2);
}
}
}
if (c1.size() > 1) {
clusters.add(c1);
subsumptions.add(foundSubsumption);
subsumptionValue.add(subsumptionVals);
}
}
} else {
// no subsumption was found yet
// --> build all clusters, where one rule subsume other rules
for (VDmnInputValue cb1 : selectedBounds) {
List<VDmnInputValue> c1 = new ArrayList<>();
boolean foundSubsumption = false;
for (VDmnInputValue cb2 : selectedBounds) {
boolean fs = cb1.getBoundary().checkWith(SUBSUMES, cb2.getBoundary());
foundSubsumption |= fs;
if (fs) {
c1.add(cb2);
}
}
List<VDmnInputValue> subsumptionVals = new ArrayList<>();
for (VDmnInputValue cb2 : selectedBounds) {
if (cb1.getBoundary().checkWith(IS_EQUAL, cb2.getBoundary())) {
c1.add(cb2);
if (foundSubsumption) {
subsumptionVals.add(cb2);
}
}
}
if (c1.size() > 1) {
clusters.add(c1);
subsumptions.add(foundSubsumption);
if (foundSubsumption) {
subsumptionValue.add(subsumptionVals);
} else {
subsumptionValue.add(Collections.emptyList());
}
}
}
}
// check for subsets, that includes other subsets and remove them
a:
for (int x = 0; x < clusters.size(); x++) {
if (clusters.get(x) != null) {
List<VDmnInputValue> c1 = clusters.get(x);
for (int y = 0; y < clusters.size(); y++) {
if (clusters.get(y) != null) {
List<VDmnInputValue> c2 = clusters.get(y);
if (x != y
&& ((!subsumptionValue.get(x).isEmpty() && !subsumptionValue.get(y).isEmpty())
|| ((subsumptionValue.get(x).isEmpty() && subsumptionValue.get(y).isEmpty())
&& c1.containsAll(c2)
&& c2.containsAll(c1)))) {
if (c1.containsAll(c2)) {
clusters.set(y, null);
}
}
}
}
}
}
// recursively search next row for subsumption with all clusters
for (int x = 0; x < clusters.size(); x++) {
if (clusters.get(x) != null) {
List<VDmnInputValue> vals = clusters.get(x);
checkSubsumptions(
inColumns,
i + 1,
vals.stream().map(VDmnInputValue::getRuleId).collect(Collectors.toList()),
subsumptions.get(x) || hasSubsumption,
subsumptionValue.get(x)
.stream().map(VDmnValue::getDmnRule)
.collect(Collectors.toList()));
}
}
}
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment