aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/containment/ContainsRefiner.java
blob: 00820040671b6eb0b6958e4ed952f762940db36f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
 * SPDX-FileCopyrightText: 2023-2024 The Refinery Authors <https://refinery.tools/>
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package tools.refinery.store.reasoning.translator.containment;

import tools.refinery.store.model.Interpretation;
import tools.refinery.store.reasoning.ReasoningAdapter;
import tools.refinery.store.reasoning.refinement.AbstractPartialInterpretationRefiner;
import tools.refinery.store.reasoning.refinement.PartialInterpretationRefiner;
import tools.refinery.store.reasoning.representation.PartialSymbol;
import tools.refinery.store.representation.Symbol;
import tools.refinery.logic.term.truthvalue.TruthValue;
import tools.refinery.store.tuple.Tuple;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

class ContainsRefiner extends AbstractPartialInterpretationRefiner<TruthValue, Boolean> {
	private static final Map<TruthValue, InferredContainment> EMPTY_VALUES;

	static {
		var values = TruthValue.values();
		EMPTY_VALUES = LinkedHashMap.newLinkedHashMap(values.length);
		for (var value : values) {
			EMPTY_VALUES.put(value, new InferredContainment(value, Set.of(), Set.of()));
		}
	}

	private final Interpretation<InferredContainment> interpretation;
	private final PartialInterpretationRefiner<TruthValue, Boolean> containedRefiner;

	private ContainsRefiner(ReasoningAdapter adapter, PartialSymbol<TruthValue, Boolean> partialSymbol,
							Symbol<InferredContainment> containsStorage) {
		super(adapter, partialSymbol);
		interpretation = adapter.getModel().getInterpretation(containsStorage);
		containedRefiner = adapter.getRefiner(ContainmentHierarchyTranslator.CONTAINED_SYMBOL);
	}

	@Override
	public boolean merge(Tuple key, TruthValue value) {
		var oldValue = interpretation.get(key);
		var newValue = mergeLink(oldValue, value);
		if (oldValue != newValue) {
			interpretation.put(key, newValue);
		}
		if (value.must()) {
			return containedRefiner.merge(Tuple.of(key.get(1)), TruthValue.TRUE);
		}
		return true;
	}

	public InferredContainment mergeLink(InferredContainment oldValue, TruthValue toMerge) {
		var newContains = oldValue.contains().meet(toMerge);
		if (newContains.equals(oldValue.contains())) {
			return oldValue;
		}
		var mustLinks = oldValue.mustLinks();
		var forbiddenLinks = oldValue.forbiddenLinks();
		if (mustLinks.isEmpty() && forbiddenLinks.isEmpty()) {
			return EMPTY_VALUES.get(newContains);
		}
		return new InferredContainment(newContains, mustLinks, forbiddenLinks);
	}

	public static PartialInterpretationRefiner.Factory<TruthValue, Boolean> of(Symbol<InferredContainment> symbol) {
		return (adapter, partialSymbol) -> new ContainsRefiner(adapter, partialSymbol, symbol);
	}
}