aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Attila Ficsor <33845035+nagilooh@users.noreply.github.com>2023-08-25 17:59:07 +0200
committerLibravatar GitHub <noreply@github.com>2023-08-25 17:59:07 +0200
commiteeeb6fd53776e5c25745d02fd7166a3ad8fa9979 (patch)
tree904c7a674e4f0c9945ae68871ddad101f161efa1
parentMerge pull request #37 from nagilooh/design-space-exploration (diff)
parentSuppressWarnings for using pseudorandom number generator in non-security sens... (diff)
downloadrefinery-eeeb6fd53776e5c25745d02fd7166a3ad8fa9979.tar.gz
refinery-eeeb6fd53776e5c25745d02fd7166a3ad8fa9979.tar.zst
refinery-eeeb6fd53776e5c25745d02fd7166a3ad8fa9979.zip
Merge pull request #38 from nagilooh/design-space-exploration
Comparable transformation rule action
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java3
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java9
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java2
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/ActionVariable.java12
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/ActivationVariable.java54
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/AtomicAction.java18
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/DeleteAction.java40
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/InsertAction.java94
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/NewItemVariable.java45
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/TransformationAction.java129
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java1
-rw-r--r--subprojects/store-dse/src/test/java/tools/refinery/store/dse/ActionEqualsTest.java629
-rw-r--r--subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java1
13 files changed, 1037 insertions, 0 deletions
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java
index 5aed5298..ab87ddd5 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/DesignSpaceExplorationAdapter.java
@@ -6,6 +6,7 @@
6package tools.refinery.store.dse; 6package tools.refinery.store.dse;
7 7
8import tools.refinery.store.adapter.ModelAdapter; 8import tools.refinery.store.adapter.ModelAdapter;
9import tools.refinery.store.dse.internal.TransformationRule;
9import tools.refinery.store.map.Version; 10import tools.refinery.store.map.Version;
10import tools.refinery.store.dse.internal.Activation; 11import tools.refinery.store.dse.internal.Activation;
11import tools.refinery.store.dse.internal.DesignSpaceExplorationBuilderImpl; 12import tools.refinery.store.dse.internal.DesignSpaceExplorationBuilderImpl;
@@ -65,4 +66,6 @@ public interface DesignSpaceExplorationAdapter extends ModelAdapter {
65 public void setRandom(long seed); 66 public void setRandom(long seed);
66 67
67 public List<Version> getSolutions(); 68 public List<Version> getSolutions();
69
70 void addTransformationRule(TransformationRule transformationRule);
68} 71}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java
index 220f0b2d..1ae09916 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/DesignSpaceExplorationAdapterImpl.java
@@ -13,6 +13,7 @@ import tools.refinery.store.map.Version;
13import tools.refinery.store.model.Interpretation; 13import tools.refinery.store.model.Interpretation;
14import tools.refinery.store.model.Model; 14import tools.refinery.store.model.Model;
15import tools.refinery.store.query.ModelQueryAdapter; 15import tools.refinery.store.query.ModelQueryAdapter;
16import tools.refinery.store.query.dnf.Query;
16import tools.refinery.store.query.dnf.RelationalQuery; 17import tools.refinery.store.query.dnf.RelationalQuery;
17import tools.refinery.store.dse.DesignSpaceExplorationAdapter; 18import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
18import tools.refinery.store.dse.DesignSpaceExplorationStoreAdapter; 19import tools.refinery.store.dse.DesignSpaceExplorationStoreAdapter;
@@ -45,6 +46,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
45 private Map<Version, Version> parents = new HashMap<>(); 46 private Map<Version, Version> parents = new HashMap<>();
46 private final List<Version> solutions = new ArrayList<>(); 47 private final List<Version> solutions = new ArrayList<>();
47 private Map<Version, List<Activation>> statesAndTraversedActivations; 48 private Map<Version, List<Activation>> statesAndTraversedActivations;
49 @SuppressWarnings("squid:S2245")
48 private Random random = new Random(); 50 private Random random = new Random();
49 private boolean isNewState = false; 51 private boolean isNewState = false;
50 private final boolean isVisualizationEnabled; 52 private final boolean isVisualizationEnabled;
@@ -77,6 +79,12 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
77 79
78 } 80 }
79 81
82 @Override
83 public void addTransformationRule(TransformationRule rule) {
84 transformationRules.add(rule);
85 rule.prepare(model, queryEngine);
86 }
87
80 public List<Version> getTrajectory() { 88 public List<Version> getTrajectory() {
81 return new ArrayList<>(trajectory); 89 return new ArrayList<>(trajectory);
82 } 90 }
@@ -175,6 +183,7 @@ public class DesignSpaceExplorationAdapterImpl implements DesignSpaceExploration
175 } 183 }
176 184
177 @Override 185 @Override
186 @SuppressWarnings("squid:S2245")
178 public void setRandom(long seed) { 187 public void setRandom(long seed) {
179 this.random = new Random(seed); 188 this.random = new Random(seed);
180 } 189 }
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java
index 8123c0d6..37117164 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/TransformationRule.java
@@ -26,10 +26,12 @@ public class TransformationRule {
26 private Random random; 26 private Random random;
27 private ModelQueryAdapter queryEngine; 27 private ModelQueryAdapter queryEngine;
28 28
29 @SuppressWarnings("squid:S2245")
29 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory) { 30 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory) {
30 this(name, precondition, actionFactory, new Random()); 31 this(name, precondition, actionFactory, new Random());
31 } 32 }
32 33
34 @SuppressWarnings("squid:S2245")
33 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, long seed) { 35 public TransformationRule(String name, RelationalQuery precondition, ActionFactory actionFactory, long seed) {
34 this(name, precondition, actionFactory, new Random(seed)); 36 this(name, precondition, actionFactory, new Random(seed));
35 } 37 }
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/ActionVariable.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/ActionVariable.java
new file mode 100644
index 00000000..92de565d
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/ActionVariable.java
@@ -0,0 +1,12 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal.action;
7
8import tools.refinery.store.tuple.Tuple;
9
10public interface ActionVariable extends AtomicAction {
11 Tuple getValue();
12}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/ActivationVariable.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/ActivationVariable.java
new file mode 100644
index 00000000..6b4c6340
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/ActivationVariable.java
@@ -0,0 +1,54 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal.action;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.tuple.Tuple;
10
11public class ActivationVariable implements ActionVariable {
12
13 private final int index;
14 private Tuple value;
15
16 public ActivationVariable() {
17 this(0);
18 }
19
20 public ActivationVariable(int index) {
21 this.index = index;
22 }
23
24 @Override
25 public void fire(Tuple activation) {
26 value = Tuple.of(activation.get(index));
27 }
28
29 @Override
30 public ActivationVariable prepare(Model model) {
31 return this;
32 }
33
34 @Override
35 public Tuple getValue() {
36 return value;
37 }
38
39 @Override
40 public boolean equalsWithSubstitution(AtomicAction other) {
41 if (other == null || getClass() != other.getClass()) {
42 return false;
43 }
44 var otherAction = (ActivationVariable) other;
45
46 if (index != otherAction.index) {
47 return false;
48 }
49 if (value == null) {
50 return otherAction.value == null;
51 }
52 return value.equals(otherAction.value);
53 }
54}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/AtomicAction.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/AtomicAction.java
new file mode 100644
index 00000000..a8f10bca
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/AtomicAction.java
@@ -0,0 +1,18 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal.action;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.tuple.Tuple;
10
11public interface AtomicAction {
12
13 void fire(Tuple activation);
14
15 AtomicAction prepare(Model model);
16
17 boolean equalsWithSubstitution(AtomicAction other);
18}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/DeleteAction.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/DeleteAction.java
new file mode 100644
index 00000000..9900390f
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/DeleteAction.java
@@ -0,0 +1,40 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal.action;
7
8import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.tuple.Tuple;
11
12public class DeleteAction implements AtomicAction {
13
14 private final ActionVariable variable;
15 private DesignSpaceExplorationAdapter dseAdapter;
16
17 public DeleteAction(ActionVariable variable) {
18 this.variable = variable;
19 }
20
21 @Override
22 public void fire(Tuple activation) {
23 dseAdapter.deleteObject(variable.getValue());
24 }
25
26 @Override
27 public DeleteAction prepare(Model model) {
28 dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
29 return this;
30 }
31
32 @Override
33 public boolean equalsWithSubstitution(AtomicAction other) {
34 if (other == null || getClass() != other.getClass()) {
35 return false;
36 }
37 var otherAction = (DeleteAction) other;
38 return this.variable.getClass() == otherAction.variable.getClass();
39 }
40}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/InsertAction.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/InsertAction.java
new file mode 100644
index 00000000..90fcc5ac
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/InsertAction.java
@@ -0,0 +1,94 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal.action;
7
8import tools.refinery.store.model.Interpretation;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.tuple.Tuple;
11import tools.refinery.store.tuple.Tuple0;
12
13import java.util.Arrays;
14
15public class InsertAction<T> implements AtomicAction {
16
17 private final Interpretation<T> interpretation;
18 private final T value;
19 private final int arity;
20 private final ActionVariable[] variables;
21
22 public InsertAction(Interpretation<T> interpretation, T value, ActionVariable... variables) {
23 this.interpretation = interpretation;
24 this.value = value;
25 this.variables = variables;
26 this.arity = interpretation.getSymbol().arity();
27 if (variables.length != arity) {
28 throw new IllegalArgumentException("Expected " + arity + " variables, but got " + variables.length);
29 }
30 }
31
32 @Override
33 public void fire(Tuple activation) {
34 Tuple tuple;
35 if (arity == 0) {
36 tuple = Tuple0.INSTANCE;
37 }
38 else if (arity == 1) {
39 tuple = variables[0].getValue();
40 }
41 else if (arity == 2) {
42 tuple = Tuple.of(variables[0].getValue().get(0), variables[1].getValue().get(0));
43 }
44 else if (arity == 3) {
45 tuple = Tuple.of(variables[0].getValue().get(0), variables[1].getValue().get(0), variables[2].getValue().get(0));
46 }
47 else {
48 tuple = Tuple.of(Arrays.stream(variables).map(variable -> variable.getValue().get(0))
49 .mapToInt(Integer::intValue).toArray());
50 }
51 interpretation.put(tuple, value);
52 }
53
54 public void put(Tuple tuple) {
55 interpretation.put(tuple, value);
56 }
57
58 @Override
59 public InsertAction<T> prepare(Model model) {
60 return this;
61 }
62
63 public ActionVariable[] getVariables() {
64 return variables;
65 }
66
67 @Override
68 public boolean equalsWithSubstitution(AtomicAction other) {
69 if (other == null || getClass() != other.getClass()) {
70 return false;
71 }
72 var otherAction = (InsertAction<?>) other;
73 if (variables.length != otherAction.variables.length) {
74 return false;
75 }
76 if (!interpretation.equals(otherAction.interpretation)) {
77 return false;
78 }
79 if (value == null) {
80 if (otherAction.value != null) {
81 return false;
82 }
83 }
84 else if (!value.equals(otherAction.value)) {
85 return false;
86 }
87 for (var i = 0; i < variables.length; i++) {
88 if (!variables[i].equalsWithSubstitution(otherAction.variables[i])) {
89 return false;
90 }
91 }
92 return true;
93 }
94}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/NewItemVariable.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/NewItemVariable.java
new file mode 100644
index 00000000..cbb9697e
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/NewItemVariable.java
@@ -0,0 +1,45 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal.action;
7
8import tools.refinery.store.dse.DesignSpaceExplorationAdapter;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.tuple.Tuple;
11import tools.refinery.store.tuple.Tuple1;
12
13public class NewItemVariable implements ActionVariable {
14 private DesignSpaceExplorationAdapter dseAdapter;
15 private Tuple1 value;
16
17 @Override
18 public void fire(Tuple activation) {
19 value = dseAdapter.createObject();
20 }
21
22 @Override
23 public NewItemVariable prepare(Model model) {
24 dseAdapter = model.getAdapter(DesignSpaceExplorationAdapter.class);
25 return this;
26 }
27
28 @Override
29 public Tuple1 getValue() {
30 return value;
31 }
32
33 @Override
34 public boolean equalsWithSubstitution(AtomicAction other) {
35 if (other == null || getClass() != other.getClass()) {
36 return false;
37 }
38 var otherAction = (NewItemVariable) other;
39 if (value == null) {
40 return otherAction.value == null;
41 }
42 return value.equals(otherAction.value);
43
44 }
45}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/TransformationAction.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/TransformationAction.java
new file mode 100644
index 00000000..adc4df9e
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/internal/action/TransformationAction.java
@@ -0,0 +1,129 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.internal.action;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.tuple.Tuple;
10import tools.refinery.store.tuple.Tuple2;
11
12import java.util.*;
13
14public class TransformationAction {
15 private final List<ActionVariable> actionVariables = new ArrayList<>();
16 private final List<InsertAction<?>> insertActions = new ArrayList<>();
17 private final List<DeleteAction> deleteActions = new ArrayList<>();
18 private boolean configured = false;
19 private final Map<Integer, List<Tuple2>> actionVariableUsageMap = new LinkedHashMap<>();
20
21 public TransformationAction add(ActionVariable action) {
22 checkConfigured();
23 actionVariables.add(action);
24 return this;
25 }
26
27 public TransformationAction add(InsertAction<?> action) {
28 checkConfigured();
29 insertActions.add(action);
30 return this;
31 }
32
33 public TransformationAction add(DeleteAction action) {
34 checkConfigured();
35 deleteActions.add(action);
36 return this;
37 }
38
39 private void checkConfigured() {
40 if (configured) {
41 throw new IllegalStateException("Action already configured.");
42 }
43 }
44
45 public TransformationAction prepare(Model model) {
46 for (ActionVariable action : actionVariables) {
47 action.prepare(model);
48 }
49 for (InsertAction<?> action : insertActions) {
50 action.prepare(model);
51 }
52 for (DeleteAction action : deleteActions) {
53 action.prepare(model);
54 }
55
56 for (var insertAction : insertActions) {
57 var actionIndex = insertActions.indexOf(insertAction);
58 var variables = insertAction.getVariables();
59 for (var i = 0; i < variables.length; i++) {
60 var variablelGlobalIndex = actionVariables.indexOf(variables[i]);
61 actionVariableUsageMap.computeIfAbsent(variablelGlobalIndex, k -> new ArrayList<>());
62 actionVariableUsageMap.get(variablelGlobalIndex).add(Tuple.of(actionIndex, i));
63 }
64 }
65
66 configured = true;
67 return this;
68 }
69
70 public boolean fire(Tuple activation) {
71 for (ActionVariable action : actionVariables) {
72 action.fire(activation);
73 }
74 for (InsertAction<?> action : insertActions) {
75 action.fire(activation);
76 }
77 for (DeleteAction action : deleteActions) {
78 action.fire(activation);
79 }
80 return true;
81 }
82
83 // Returns true if ActionVariables and InsertActions are inserted in same order, ActionVariables are equal (they
84 // have the same index for getting the value from the activation Tuple) and InsertActions are equal (they have
85 // the same arity and value to be set).
86 public boolean equalsWithSubstitution(TransformationAction other) {
87 if (other == this) {
88 return true;
89 }
90
91 if (actionVariables.size() != other.actionVariables.size()) {
92 return false;
93 }
94
95 if (insertActions.size() != other.insertActions.size()) {
96 return false;
97 }
98
99 if (deleteActions.size() != other.deleteActions.size()) {
100 return false;
101 }
102
103 for (var i = 0; i < actionVariables.size(); i++) {
104 var variable = actionVariables.get(i);
105 var otherVariable = other.actionVariables.get(i);
106 if (!variable.equalsWithSubstitution(otherVariable)) {
107 return false;
108 }
109 }
110
111 for (var i = 0; i < insertActions.size(); i++) {
112 var insertAction = insertActions.get(i);
113 var otherInsertAction = other.insertActions.get(i);
114 if (!insertAction.equalsWithSubstitution(otherInsertAction)) {
115 return false;
116 }
117 }
118
119 for (var i = 0; i < deleteActions.size(); i++) {
120 var deleteAction = deleteActions.get(i);
121 var otherDeleteAction = other.deleteActions.get(i);
122 if (!deleteAction.equalsWithSubstitution(otherDeleteAction)) {
123 return false;
124 }
125 }
126 return this.actionVariableUsageMap.equals(other.actionVariableUsageMap);
127
128 }
129}
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java
index 327d5e2f..cdd1754f 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/objectives/AlwaysSatisfiedRandomHardObjective.java
@@ -22,6 +22,7 @@ import java.util.Random;
22public class AlwaysSatisfiedRandomHardObjective extends BaseObjective { 22public class AlwaysSatisfiedRandomHardObjective extends BaseObjective {
23 23
24 private static final String DEFAULT_NAME = "AlwaysSatisfiedDummyHardObjective"; 24 private static final String DEFAULT_NAME = "AlwaysSatisfiedDummyHardObjective";
25 @SuppressWarnings("squid:S2245")
25 private static final Random random = new Random(0); 26 private static final Random random = new Random(0);
26 27
27 public AlwaysSatisfiedRandomHardObjective() { 28 public AlwaysSatisfiedRandomHardObjective() {
diff --git a/subprojects/store-dse/src/test/java/tools/refinery/store/dse/ActionEqualsTest.java b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/ActionEqualsTest.java
new file mode 100644
index 00000000..d4a05d12
--- /dev/null
+++ b/subprojects/store-dse/src/test/java/tools/refinery/store/dse/ActionEqualsTest.java
@@ -0,0 +1,629 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse;
7
8import org.junit.jupiter.api.BeforeAll;
9import org.junit.jupiter.api.Test;
10import tools.refinery.store.dse.internal.action.*;
11import tools.refinery.store.dse.strategy.DepthFirstStrategy;
12import tools.refinery.store.model.Model;
13import tools.refinery.store.model.ModelStore;
14import tools.refinery.store.query.dnf.Query;
15import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
16import tools.refinery.store.query.view.KeyOnlyView;
17import tools.refinery.store.representation.Symbol;
18
19import static org.junit.jupiter.api.Assertions.assertFalse;
20import static org.junit.jupiter.api.Assertions.assertTrue;
21
22public class ActionEqualsTest {
23
24 private static Model model;
25 private static Symbol<Boolean> type1;
26 private static Symbol<Boolean> relation1;
27 private static Symbol<Boolean> relation2;
28
29 @BeforeAll
30 public static void init() {
31 type1 = Symbol.of("type1", 1);
32 relation1 = Symbol.of("relation1", 2);
33 relation2 = Symbol.of("relation2", 2);
34 var type1View = new KeyOnlyView<>(type1);
35 var precondition1 = Query.of("CreateClassPrecondition",
36 (builder, model) -> builder.clause(
37 type1View.call(model)
38 ));
39
40 var precondition2 = Query.of("CreateFeaturePrecondition",
41 (builder, model) -> builder.clause(
42 type1View.call(model)
43 ));
44 var store = ModelStore.builder()
45 .symbols(type1, relation2, relation1)
46 .with(ViatraModelQueryAdapter.builder()
47 .queries(precondition1, precondition2))
48 .with(DesignSpaceExplorationAdapter.builder()
49 .strategy(new DepthFirstStrategy()))
50 .build();
51
52
53 model = store.createEmptyModel();
54 }
55
56 @Test
57 void emptyActionEqualsTest() {
58 var action1 = new TransformationAction();
59 var action2 = new TransformationAction();
60
61 assertTrue(action1.equalsWithSubstitution(action1));
62 assertTrue(action2.equalsWithSubstitution(action2));
63 assertTrue(action1.equalsWithSubstitution(action2));
64 }
65
66 @Test
67 void actionTrivialTest() {
68 var newItemSymbol1 = new NewItemVariable();
69 var activationSymbol = new ActivationVariable();
70 var insertAction1 = new InsertAction<>(model.getInterpretation(type1), true, newItemSymbol1);
71 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
72 activationSymbol);
73 var insertAction3 = new InsertAction<>(model.getInterpretation(type1), true, newItemSymbol1);
74 var insertAction4 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
75 activationSymbol);
76
77 var action1 = new TransformationAction();
78 action1.add(newItemSymbol1);
79 action1.add(activationSymbol);
80 action1.add(insertAction1);
81 action1.add(insertAction2);
82 action1.prepare(model);
83
84 var action2 = new TransformationAction();
85 action2.add(newItemSymbol1);
86 action2.add(activationSymbol);
87 action2.add(insertAction3);
88 action2.add(insertAction4);
89 action2.prepare(model);
90
91 assertTrue(action1.equalsWithSubstitution(action2));
92 }
93
94 @Test
95 void actionIdenticalTest() {
96 var newItemSymbol1 = new NewItemVariable();
97 var activationSymbol1 = new ActivationVariable();
98 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
99 activationSymbol1);
100
101 var action1 = new TransformationAction();
102 action1.add(newItemSymbol1);
103 action1.add(activationSymbol1);
104 action1.add(insertAction1);
105 action1.prepare(model);
106
107 var newItemSymbol2 = new NewItemVariable();
108 var activationSymbol2 = new ActivationVariable();
109 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol2,
110 activationSymbol2);
111
112 var action2 = new TransformationAction();
113 action2.add(newItemSymbol2);
114 action2.add(activationSymbol2);
115 action2.add(insertAction2);
116 action2.prepare(model);
117
118 assertTrue(action1.equalsWithSubstitution(action2));
119 }
120
121 @Test
122 void actionSymbolGlobalOrderTest() {
123 var newItemSymbol1 = new NewItemVariable();
124 var activationSymbol1 = new ActivationVariable();
125 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
126 activationSymbol1);
127
128 var action1 = new TransformationAction();
129 action1.add(newItemSymbol1);
130 action1.add(activationSymbol1);
131 action1.add(insertAction1);
132 action1.prepare(model);
133
134 var newItemSymbol2 = new NewItemVariable();
135 var activationSymbol2 = new ActivationVariable();
136 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol2,
137 activationSymbol2);
138
139 var action2 = new TransformationAction();
140 action2.add(activationSymbol2);
141 action2.add(newItemSymbol2);
142 action2.add(insertAction2);
143 action2.prepare(model);
144
145 assertFalse(action1.equalsWithSubstitution(action2));
146 }
147
148 @Test
149 void actionSymbolRepeatedInInsertActionTest() {
150 var newItemSymbol1 = new NewItemVariable();
151 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
152 newItemSymbol1);
153
154 var action1 = new TransformationAction();
155 action1.add(newItemSymbol1);
156 action1.add(insertAction1);
157 action1.prepare(model);
158
159 var newItemSymbol2 = new NewItemVariable();
160 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol2,
161 newItemSymbol2);
162
163 var action2 = new TransformationAction();
164 action2.add(newItemSymbol2);
165 action2.add(insertAction2);
166 action2.prepare(model);
167
168 assertTrue(action1.equalsWithSubstitution(action2));
169 }
170
171 @Test
172 void identicalInsertActionInDifferentOrderTest() {
173 var newItemSymbol1 = new NewItemVariable();
174 var activationSymbol1 = new ActivationVariable();
175 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
176 activationSymbol1);
177 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
178 activationSymbol1);
179
180 var action1 = new TransformationAction();
181 action1.add(newItemSymbol1);
182 action1.add(activationSymbol1);
183 action1.add(insertAction1);
184 action1.add(insertAction2);
185 action1.prepare(model);
186
187 var action2 = new TransformationAction();
188 action2.add(newItemSymbol1);
189 action2.add(activationSymbol1);
190 action2.add(insertAction2);
191 action2.add(insertAction1);
192 action2.prepare(model);
193
194 assertTrue(action1.equalsWithSubstitution(action2));
195 }
196
197 @Test
198 void identicalActionAndSymbolDifferentOrderTest() {
199 var newItemSymbol1 = new NewItemVariable();
200 var newItemSymbol2 = new NewItemVariable();
201 var activationSymbol1 = new ActivationVariable();
202 var activationSymbol2 = new ActivationVariable();
203
204 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
205 activationSymbol1);
206
207 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol2,
208 activationSymbol2);
209
210 var action1 = new TransformationAction();
211 action1.add(newItemSymbol1);
212 action1.add(newItemSymbol2);
213 action1.add(activationSymbol1);
214 action1.add(activationSymbol2);
215 action1.add(insertAction1);
216 action1.add(insertAction2);
217 action1.prepare(model);
218
219 var action2 = new TransformationAction();
220 action2.add(newItemSymbol2);
221 action2.add(newItemSymbol1);
222 action2.add(activationSymbol2);
223 action2.add(activationSymbol1);
224 action2.add(insertAction2);
225 action2.add(insertAction1);
226 action2.prepare(model);
227
228 assertTrue(action1.equalsWithSubstitution(action2));
229 }
230
231 @Test
232 void identicalActionAndSymbolMixedOrderTest() {
233 var newItemSymbol1 = new NewItemVariable();
234 var activationSymbol1 = new ActivationVariable();
235 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
236 activationSymbol1);
237
238 var newItemSymbol2 = new NewItemVariable();
239 var activationSymbol2 = new ActivationVariable();
240 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol2,
241 activationSymbol2);
242
243 var action1 = new TransformationAction();
244 action1.add(newItemSymbol1);
245 action1.add(newItemSymbol2);
246 action1.add(activationSymbol1);
247 action1.add(activationSymbol2);
248 action1.add(insertAction1);
249 action1.add(insertAction2);
250 action1.prepare(model);
251
252 var action2 = new TransformationAction();
253 action2.add(insertAction1);
254 action2.add(newItemSymbol1);
255 action2.add(newItemSymbol2);
256 action2.add(activationSymbol1);
257 action2.add(insertAction2);
258 action2.add(activationSymbol2);
259 action2.prepare(model);
260
261 assertTrue(action1.equalsWithSubstitution(action2));
262 }
263
264 @Test
265 void insertActionInterpretationTest() {
266 var newItemSymbol1 = new NewItemVariable();
267 var activationSymbol1 = new ActivationVariable();
268 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
269 activationSymbol1);
270 var insertAction2 = new InsertAction<>(model.getInterpretation(relation2), true, newItemSymbol1,
271 activationSymbol1);
272
273 var action1 = new TransformationAction();
274 action1.add(newItemSymbol1);
275 action1.add(activationSymbol1);
276 action1.add(insertAction1);
277 action1.prepare(model);
278
279 var action2 = new TransformationAction();
280 action2.add(newItemSymbol1);
281 action2.add(activationSymbol1);
282 action2.add(insertAction2);
283 action2.prepare(model);
284
285 assertFalse(action1.equalsWithSubstitution(action2));
286 }
287
288 @Test
289 void insertActionValueTest() {
290 var newItemSymbol1 = new NewItemVariable();
291 var activationSymbol1 = new ActivationVariable();
292 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
293 activationSymbol1);
294 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), false, newItemSymbol1,
295 activationSymbol1);
296
297 var action1 = new TransformationAction();
298 action1.add(newItemSymbol1);
299 action1.add(activationSymbol1);
300 action1.add(insertAction1);
301 action1.prepare(model);
302
303 var action2 = new TransformationAction();
304 action2.add(newItemSymbol1);
305 action2.add(activationSymbol1);
306 action2.add(insertAction2);
307 action2.prepare(model);
308
309 assertFalse(action1.equalsWithSubstitution(action2));
310 }
311
312 @Test
313 void newItemSymbolDuplicateTest() {
314 var newItemSymbol1 = new NewItemVariable();
315 var newItemSymbol2 = new NewItemVariable();
316 var activationSymbol1 = new ActivationVariable();
317 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
318 activationSymbol1);
319 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol2,
320 activationSymbol1);
321
322 var action1 = new TransformationAction();
323 action1.add(newItemSymbol1);
324 action1.add(activationSymbol1);
325 action1.add(insertAction1);
326 action1.prepare(model);
327
328 var action2 = new TransformationAction();
329 action2.add(newItemSymbol2);
330 action2.add(activationSymbol1);
331 action2.add(insertAction2);
332 action2.prepare(model);
333
334 assertTrue(action1.equalsWithSubstitution(action2));
335 }
336
337 @Test
338 void activationSymbolDuplicateTest() {
339 var newItemSymbol1 = new NewItemVariable();
340 var activationSymbol1 = new ActivationVariable();
341 var activationSymbol2 = new ActivationVariable();
342 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
343 activationSymbol1);
344 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
345 activationSymbol2);
346
347 var action1 = new TransformationAction();
348 action1.add(newItemSymbol1);
349 action1.add(activationSymbol1);
350 action1.add(insertAction1);
351 action1.prepare(model);
352
353 var action2 = new TransformationAction();
354 action2.add(newItemSymbol1);
355 action2.add(activationSymbol2);
356 action2.add(insertAction2);
357 action2.prepare(model);
358
359 assertTrue(action1.equalsWithSubstitution(action2));
360 }
361
362 @Test
363 void activationSymbolIndexTest() {
364 var newItemSymbol1 = new NewItemVariable();
365 var activationSymbol1 = new ActivationVariable(0);
366 var activationSymbol2 = new ActivationVariable(1);
367 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
368 activationSymbol1);
369 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
370 activationSymbol2);
371
372 var action1 = new TransformationAction();
373 action1.add(newItemSymbol1);
374 action1.add(activationSymbol1);
375 action1.add(insertAction1);
376 action1.prepare(model);
377
378 var action2 = new TransformationAction();
379 action2.add(newItemSymbol1);
380 action2.add(activationSymbol2);
381 action2.add(insertAction2);
382 action2.prepare(model);
383
384 assertFalse(action1.equalsWithSubstitution(action2));
385 }
386
387 @Test
388 void deleteActionTest() {
389 var newItemSymbol = new NewItemVariable();
390 var activationSymbol = new ActivationVariable(0);
391 var insertAction = new InsertAction<>(model.getInterpretation(relation1), false, newItemSymbol,
392 activationSymbol);
393 var deleteAction = new DeleteAction(activationSymbol);
394
395 var action1 = new TransformationAction();
396 action1.add(newItemSymbol);
397 action1.add(activationSymbol);
398 action1.add(insertAction);
399 action1.add(deleteAction);
400 action1.prepare(model);
401
402 var action2 = new TransformationAction();
403 action2.add(newItemSymbol);
404 action2.add(activationSymbol);
405 action2.add(insertAction);
406 action2.add(deleteAction);
407 action2.prepare(model);
408
409 assertTrue(action1.equalsWithSubstitution(action2));
410 }
411
412 @Test
413 void deleteActionMissingTest() {
414 var newItemSymbol = new NewItemVariable();
415 var activationSymbol = new ActivationVariable(0);
416 var insertAction = new InsertAction<>(model.getInterpretation(relation1), false, newItemSymbol,
417 activationSymbol);
418 var deleteAction = new DeleteAction(activationSymbol);
419
420 var action1 = new TransformationAction();
421 action1.add(newItemSymbol);
422 action1.add(activationSymbol);
423 action1.add(insertAction);
424 action1.add(deleteAction);
425 action1.prepare(model);
426
427 var action2 = new TransformationAction();
428 action2.add(newItemSymbol);
429 action2.add(activationSymbol);
430 action2.add(insertAction);
431 action2.prepare(model);
432
433 assertFalse(action1.equalsWithSubstitution(action2));
434 }
435
436 @Test
437 void deleteActionIdenticalTest() {
438 var newItemSymbol = new NewItemVariable();
439 var activationSymbol = new ActivationVariable(0);
440 var insertAction = new InsertAction<>(model.getInterpretation(relation1), false, newItemSymbol,
441 activationSymbol);
442 var deleteAction1 = new DeleteAction(activationSymbol);
443 var deleteAction2 = new DeleteAction(activationSymbol);
444
445 var action1 = new TransformationAction();
446 action1.add(newItemSymbol);
447 action1.add(activationSymbol);
448 action1.add(insertAction);
449 action1.add(deleteAction1);
450 action1.prepare(model);
451
452 var action2 = new TransformationAction();
453 action2.add(newItemSymbol);
454 action2.add(activationSymbol);
455 action2.add(insertAction);
456 action2.add(deleteAction2);
457 action2.prepare(model);
458
459 assertTrue(action1.equalsWithSubstitution(action2));
460 }
461
462 @Test
463 void deleteActionSymbolTypeTest() {
464 var newItemSymbol = new NewItemVariable();
465 var activationSymbol = new ActivationVariable(0);
466 var insertAction = new InsertAction<>(model.getInterpretation(relation1), false, newItemSymbol,
467 activationSymbol);
468 var deleteAction1 = new DeleteAction(activationSymbol);
469 var deleteAction2 = new DeleteAction(newItemSymbol);
470
471 var action1 = new TransformationAction();
472 action1.add(newItemSymbol);
473 action1.add(activationSymbol);
474 action1.add(insertAction);
475 action1.add(deleteAction1);
476 action1.prepare(model);
477
478 var action2 = new TransformationAction();
479 action2.add(newItemSymbol);
480 action2.add(activationSymbol);
481 action2.add(insertAction);
482 action2.add(deleteAction2);
483 action2.prepare(model);
484
485 assertFalse(action1.equalsWithSubstitution(action2));
486 }
487
488 @Test
489 void deleteActionOrderTest() {
490 var newItemSymbol = new NewItemVariable();
491 var activationSymbol = new ActivationVariable(0);
492 var insertAction = new InsertAction<>(model.getInterpretation(relation1), false, newItemSymbol,
493 activationSymbol);
494 var deleteAction1 = new DeleteAction(activationSymbol);
495 var deleteAction2 = new DeleteAction(newItemSymbol);
496
497 var action1 = new TransformationAction();
498 action1.add(newItemSymbol);
499 action1.add(activationSymbol);
500 action1.add(insertAction);
501 action1.add(deleteAction1);
502 action1.add(deleteAction2);
503 action1.prepare(model);
504
505 var action2 = new TransformationAction();
506 action2.add(newItemSymbol);
507 action2.add(activationSymbol);
508 action2.add(insertAction);
509 action2.add(deleteAction2);
510 action2.add(deleteAction1);
511 action2.prepare(model);
512
513 assertFalse(action1.equalsWithSubstitution(action2));
514 }
515
516 @Test
517 void actionsMixedOrderTest() {
518 var newItemSymbol1 = new NewItemVariable();
519 var activationSymbol1 = new ActivationVariable();
520 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
521 activationSymbol1);
522 var deleteAction1 = new DeleteAction(newItemSymbol1);
523
524 var newItemSymbol2 = new NewItemVariable();
525 var activationSymbol2 = new ActivationVariable();
526 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol2,
527 activationSymbol2);
528 var deleteAction2 = new DeleteAction(activationSymbol2);
529
530 var action1 = new TransformationAction();
531 action1.add(newItemSymbol1);
532 action1.add(newItemSymbol2);
533 action1.add(activationSymbol1);
534 action1.add(activationSymbol2);
535 action1.add(insertAction1);
536 action1.add(insertAction2);
537 action1.add(deleteAction1);
538 action1.add(deleteAction2);
539 action1.prepare(model);
540
541 var action2 = new TransformationAction();
542 action2.add(deleteAction1);
543 action2.add(newItemSymbol1);
544 action2.add(insertAction1);
545 action2.add(newItemSymbol2);
546 action2.add(deleteAction2);
547 action2.add(activationSymbol1);
548 action2.add(insertAction2);
549 action2.add(activationSymbol2);
550 action2.prepare(model);
551
552 assertTrue(action1.equalsWithSubstitution(action2));
553 }
554
555 @Test
556 void twoUnpreparedActionsTest() {
557 var newItemSymbol1 = new NewItemVariable();
558 var activationSymbol1 = new ActivationVariable();
559 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
560 activationSymbol1);
561 var deleteAction1 = new DeleteAction(newItemSymbol1);
562
563 var newItemSymbol2 = new NewItemVariable();
564 var activationSymbol2 = new ActivationVariable();
565 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol2,
566 activationSymbol2);
567 var deleteAction2 = new DeleteAction(activationSymbol2);
568
569 var action1 = new TransformationAction();
570 action1.add(newItemSymbol1);
571 action1.add(newItemSymbol2);
572 action1.add(activationSymbol1);
573 action1.add(activationSymbol2);
574 action1.add(insertAction1);
575 action1.add(insertAction2);
576 action1.add(deleteAction1);
577 action1.add(deleteAction2);
578
579 var action2 = new TransformationAction();
580 action2.add(deleteAction1);
581 action2.add(newItemSymbol1);
582 action2.add(insertAction1);
583 action2.add(newItemSymbol2);
584 action2.add(deleteAction2);
585 action2.add(activationSymbol1);
586 action2.add(insertAction2);
587 action2.add(activationSymbol2);
588
589 assertTrue(action1.equalsWithSubstitution(action2));
590 }
591
592 @Test
593 void oneUnpreparedActionTest() {
594 var newItemSymbol1 = new NewItemVariable();
595 var activationSymbol1 = new ActivationVariable();
596 var insertAction1 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol1,
597 activationSymbol1);
598 var deleteAction1 = new DeleteAction(newItemSymbol1);
599
600 var newItemSymbol2 = new NewItemVariable();
601 var activationSymbol2 = new ActivationVariable();
602 var insertAction2 = new InsertAction<>(model.getInterpretation(relation1), true, newItemSymbol2,
603 activationSymbol2);
604 var deleteAction2 = new DeleteAction(activationSymbol2);
605
606 var action1 = new TransformationAction();
607 action1.add(newItemSymbol1);
608 action1.add(newItemSymbol2);
609 action1.add(activationSymbol1);
610 action1.add(activationSymbol2);
611 action1.add(insertAction1);
612 action1.add(insertAction2);
613 action1.add(deleteAction1);
614 action1.add(deleteAction2);
615 action1.prepare(model);
616
617 var action2 = new TransformationAction();
618 action2.add(deleteAction1);
619 action2.add(newItemSymbol1);
620 action2.add(insertAction1);
621 action2.add(newItemSymbol2);
622 action2.add(deleteAction2);
623 action2.add(activationSymbol1);
624 action2.add(insertAction2);
625 action2.add(activationSymbol2);
626
627 assertFalse(action1.equalsWithSubstitution(action2));
628 }
629}
diff --git a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java
index 531969b4..e60ae4b7 100644
--- a/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java
+++ b/subprojects/visualization/src/main/java/tools/refinery/visualization/internal/ModelVisualizerAdapterImpl.java
@@ -220,6 +220,7 @@ public class ModelVisualizerAdapterImpl implements ModelVisualizerAdapter {
220 } 220 }
221 221
222 private Integer[] typeColor(String name) { 222 private Integer[] typeColor(String name) {
223 @SuppressWarnings("squid:S2245")
223 var random = new Random(name.hashCode()); 224 var random = new Random(name.hashCode());
224 return new Integer[] { random.nextInt(128) + 128, random.nextInt(128) + 128, random.nextInt(128) + 128 }; 225 return new Integer[] { random.nextInt(128) + 128, random.nextInt(128) + 128, random.nextInt(128) + 128 };
225 } 226 }