diff options
Diffstat (limited to 'subprojects/logic/src/main/java/tools/refinery/logic/dnf/DnfPostProcessor.java')
-rw-r--r-- | subprojects/logic/src/main/java/tools/refinery/logic/dnf/DnfPostProcessor.java | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/subprojects/logic/src/main/java/tools/refinery/logic/dnf/DnfPostProcessor.java b/subprojects/logic/src/main/java/tools/refinery/logic/dnf/DnfPostProcessor.java new file mode 100644 index 00000000..87d07187 --- /dev/null +++ b/subprojects/logic/src/main/java/tools/refinery/logic/dnf/DnfPostProcessor.java | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023-2024 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.logic.dnf; | ||
7 | |||
8 | import tools.refinery.logic.InvalidQueryException; | ||
9 | import tools.refinery.logic.equality.DnfEqualityChecker; | ||
10 | import tools.refinery.logic.equality.SubstitutingLiteralEqualityHelper; | ||
11 | import tools.refinery.logic.equality.SubstitutingLiteralHashCodeHelper; | ||
12 | import tools.refinery.logic.literal.Literal; | ||
13 | import tools.refinery.logic.term.ParameterDirection; | ||
14 | import tools.refinery.logic.term.Variable; | ||
15 | |||
16 | import java.util.*; | ||
17 | |||
18 | class DnfPostProcessor { | ||
19 | private final List<SymbolicParameter> parameters; | ||
20 | private final List<List<Literal>> clauses; | ||
21 | |||
22 | public DnfPostProcessor(List<SymbolicParameter> parameters, List<List<Literal>> clauses) { | ||
23 | this.parameters = parameters; | ||
24 | this.clauses = clauses; | ||
25 | } | ||
26 | |||
27 | public List<DnfClause> postProcessClauses() { | ||
28 | var parameterInfoMap = getParameterInfoMap(); | ||
29 | var postProcessedClauses = LinkedHashSet.<CanonicalClause>newLinkedHashSet(clauses.size()); | ||
30 | int index = 0; | ||
31 | for (var literals : clauses) { | ||
32 | var postProcessor = new ClausePostProcessor(parameterInfoMap, literals); | ||
33 | ClausePostProcessor.Result result; | ||
34 | try { | ||
35 | result = postProcessor.postProcessClause(); | ||
36 | } catch (InvalidQueryException e) { | ||
37 | throw new InvalidClauseException(index, e); | ||
38 | } | ||
39 | if (result instanceof ClausePostProcessor.ClauseResult clauseResult) { | ||
40 | postProcessedClauses.add(new CanonicalClause(clauseResult.clause())); | ||
41 | } else if (result instanceof ClausePostProcessor.ConstantResult constantResult) { | ||
42 | switch (constantResult) { | ||
43 | case ALWAYS_TRUE -> { | ||
44 | var inputVariables = getInputVariables(); | ||
45 | return List.of(new DnfClause(inputVariables, List.of())); | ||
46 | } | ||
47 | case ALWAYS_FALSE -> { | ||
48 | // Skip this clause because it can never match. | ||
49 | } | ||
50 | default -> throw new IllegalStateException("Unexpected ClausePostProcessor.ConstantResult: " + | ||
51 | constantResult); | ||
52 | } | ||
53 | } else { | ||
54 | throw new IllegalStateException("Unexpected ClausePostProcessor.Result: " + result); | ||
55 | } | ||
56 | index++; | ||
57 | } | ||
58 | return postProcessedClauses.stream().map(CanonicalClause::getDnfClause).toList(); | ||
59 | } | ||
60 | |||
61 | private Map<Variable, ClausePostProcessor.ParameterInfo> getParameterInfoMap() { | ||
62 | var mutableParameterInfoMap = new LinkedHashMap<Variable, ClausePostProcessor.ParameterInfo>(); | ||
63 | int arity = parameters.size(); | ||
64 | for (int i = 0; i < arity; i++) { | ||
65 | var parameter = parameters.get(i); | ||
66 | mutableParameterInfoMap.put(parameter.getVariable(), | ||
67 | new ClausePostProcessor.ParameterInfo(parameter.getDirection(), i)); | ||
68 | } | ||
69 | return Collections.unmodifiableMap(mutableParameterInfoMap); | ||
70 | } | ||
71 | |||
72 | private Set<Variable> getInputVariables() { | ||
73 | var inputParameters = new LinkedHashSet<Variable>(); | ||
74 | for (var parameter : parameters) { | ||
75 | if (parameter.getDirection() == ParameterDirection.IN) { | ||
76 | inputParameters.add(parameter.getVariable()); | ||
77 | } | ||
78 | } | ||
79 | return Collections.unmodifiableSet(inputParameters); | ||
80 | } | ||
81 | |||
82 | private class CanonicalClause { | ||
83 | private final DnfClause dnfClause; | ||
84 | |||
85 | public CanonicalClause(DnfClause dnfClause) { | ||
86 | this.dnfClause = dnfClause; | ||
87 | } | ||
88 | |||
89 | public DnfClause getDnfClause() { | ||
90 | return dnfClause; | ||
91 | } | ||
92 | |||
93 | @Override | ||
94 | public boolean equals(Object obj) { | ||
95 | if (this == obj) { | ||
96 | return true; | ||
97 | } | ||
98 | if (obj == null || getClass() != obj.getClass()) { | ||
99 | return false; | ||
100 | } | ||
101 | var otherCanonicalClause = (CanonicalClause) obj; | ||
102 | var helper = new SubstitutingLiteralEqualityHelper(DnfEqualityChecker.DEFAULT, parameters, parameters); | ||
103 | return dnfClause.equalsWithSubstitution(helper, otherCanonicalClause.dnfClause); | ||
104 | } | ||
105 | |||
106 | @Override | ||
107 | public int hashCode() { | ||
108 | var helper = new SubstitutingLiteralHashCodeHelper(parameters); | ||
109 | return dnfClause.hashCodeWithSubstitution(helper); | ||
110 | } | ||
111 | } | ||
112 | } | ||