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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
/*
* SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
*
* SPDX-License-Identifier: EPL-2.0
*/
package tools.refinery.store.statecoding.neighbourhood;
import org.eclipse.collections.api.factory.primitive.IntLongMaps;
import org.eclipse.collections.api.map.primitive.MutableIntLongMap;
import org.eclipse.collections.api.set.primitive.IntSet;
import tools.refinery.store.model.AnyInterpretation;
import tools.refinery.store.model.Interpretation;
import tools.refinery.store.model.Model;
import tools.refinery.store.statecoding.ObjectCode;
import tools.refinery.store.tuple.Tuple;
import tools.refinery.store.tuple.Tuple0;
import java.util.*;
public abstract class AbstractNeighbourhoodCalculator {
protected final Model model;
protected final List<AnyInterpretation> nullImpactValues;
protected final LinkedHashMap<AnyInterpretation, long[]> impactValues;
protected final MutableIntLongMap individualHashValues = IntLongMaps.mutable.empty();
protected static final long PRIME = 31;
protected AbstractNeighbourhoodCalculator(Model model, List<? extends AnyInterpretation> interpretations,
IntSet individuals) {
this.model = model;
this.nullImpactValues = new ArrayList<>();
this.impactValues = new LinkedHashMap<>();
// Random isn't used for cryptographical purposes but just to assign distinguishable identifiers to symbols.
@SuppressWarnings("squid:S2245")
Random random = new Random(1);
var individualsInOrder = individuals.toSortedList(Integer::compare);
for(int i = 0; i<individualsInOrder.size(); i++) {
individualHashValues.put(individualsInOrder.get(i), random.nextLong());
}
for (AnyInterpretation interpretation : interpretations) {
int arity = interpretation.getSymbol().arity();
if (arity == 0) {
nullImpactValues.add(interpretation);
} else {
long[] impact = new long[arity];
for (int i = 0; i < arity; i++) {
impact[i] = random.nextInt();
}
impactValues.put(interpretation, impact);
}
}
}
protected void initializeWithIndividuals(ObjectCodeImpl previous) {
for (var entry : individualHashValues.keyValuesView()) {
previous.set(entry.getOne(), entry.getTwo());
}
}
protected long getTupleHash1(Tuple tuple, Object value, ObjectCode objectCodeImpl) {
long result = Objects.hashCode(value);
result = result * PRIME + objectCodeImpl.get(tuple.get(0));
return result;
}
protected long getTupleHash2(Tuple tuple, Object value, ObjectCode objectCodeImpl) {
long result = Objects.hashCode(value);
result = result * PRIME + objectCodeImpl.get(tuple.get(0));
result = result * PRIME + objectCodeImpl.get(tuple.get(1));
if (tuple.get(0) == tuple.get(1)) {
result += PRIME;
result *= PRIME;
}
return result;
}
protected long getTupleHashN(Tuple tuple, Object value, ObjectCode objectCodeImpl) {
long result = Objects.hashCode(value);
for (int i = 0; i < tuple.getSize(); i++) {
result = result * PRIME + objectCodeImpl.get(tuple.get(i));
}
return result;
}
protected void addHash(ObjectCodeImpl objectCodeImpl, int o, long impact, long tupleHash) {
long x = tupleHash * impact;
objectCodeImpl.set(o, objectCodeImpl.get(o) + x);
}
protected long calculateModelCode(long lastSum) {
long result = 0;
for (var nullImpactValue : nullImpactValues) {
result = result * PRIME + Objects.hashCode(((Interpretation<?>) nullImpactValue).get(Tuple0.INSTANCE));
}
result += lastSum;
return result;
}
}
|