aboutsummaryrefslogtreecommitdiffstats
path: root/language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java
diff options
context:
space:
mode:
Diffstat (limited to 'language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java')
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java195
1 files changed, 195 insertions, 0 deletions
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java b/language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java
new file mode 100644
index 00000000..1b0146b6
--- /dev/null
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java
@@ -0,0 +1,195 @@
1package org.eclipse.viatra.solver.language.resource;
2
3import java.util.HashSet;
4import java.util.List;
5import java.util.Set;
6
7import org.eclipse.viatra.solver.language.model.problem.Argument;
8import org.eclipse.viatra.solver.language.model.problem.Atom;
9import org.eclipse.viatra.solver.language.model.problem.Conjunction;
10import org.eclipse.viatra.solver.language.model.problem.ExistentialQuantifier;
11import org.eclipse.viatra.solver.language.model.problem.ImplicitVariable;
12import org.eclipse.viatra.solver.language.model.problem.Literal;
13import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral;
14import org.eclipse.viatra.solver.language.model.problem.Parameter;
15import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition;
16import org.eclipse.viatra.solver.language.model.problem.Problem;
17import org.eclipse.viatra.solver.language.model.problem.ProblemFactory;
18import org.eclipse.viatra.solver.language.model.problem.ProblemPackage;
19import org.eclipse.viatra.solver.language.model.problem.Statement;
20import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument;
21import org.eclipse.viatra.solver.language.naming.NamingUtil;
22import org.eclipse.xtext.linking.impl.LinkingHelper;
23import org.eclipse.xtext.naming.IQualifiedNameConverter;
24import org.eclipse.xtext.nodemodel.INode;
25import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
26import org.eclipse.xtext.scoping.IScope;
27import org.eclipse.xtext.scoping.IScopeProvider;
28import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
29
30import com.google.inject.Inject;
31import com.google.inject.Singleton;
32import com.google.inject.name.Named;
33
34@Singleton
35public class DerivedVariableComputer {
36 @Inject
37 private LinkingHelper linkingHelper;
38
39 @Inject
40 private IQualifiedNameConverter qualifiedNameConverter;
41
42 @Inject
43 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)
44 private IScopeProvider scopeProvider;
45
46 public void installDerivedVariables(Problem problem, Set<String> nodeNames) {
47 for (Statement statement : problem.getStatements()) {
48 if (statement instanceof PredicateDefinition) {
49 PredicateDefinition definition = (PredicateDefinition) statement;
50 installDerivedPredicateDefinitionState(definition, nodeNames);
51 }
52 }
53 }
54
55 protected void installDerivedPredicateDefinitionState(PredicateDefinition definition, Set<String> nodeNames) {
56 Set<String> knownVariables = new HashSet<>();
57 knownVariables.addAll(nodeNames);
58 for (Parameter parameter : definition.getParameters()) {
59 String name = parameter.getName();
60 if (name != null) {
61 knownVariables.add(name);
62 }
63 }
64 for (Conjunction body : definition.getBodies()) {
65 installDeriveConjunctionState(body, knownVariables);
66 }
67 }
68
69 protected void installDeriveConjunctionState(Conjunction conjunction, Set<String> knownVariables) {
70 Set<String> newVariables = new HashSet<>();
71 for (Literal literal : conjunction.getLiterals()) {
72 if (literal instanceof Atom) {
73 var atom = (Atom) literal;
74 createSigletonVariablesAndCollectVariables(atom, knownVariables, newVariables);
75 }
76 }
77 createVariables(conjunction, newVariables);
78 newVariables.addAll(knownVariables);
79 for (Literal literal : conjunction.getLiterals()) {
80 if (literal instanceof NegativeLiteral) {
81 var negativeLiteral = (NegativeLiteral) literal;
82 installDeriveNegativeLiteralState(negativeLiteral, newVariables);
83 }
84 }
85 }
86
87 protected void installDeriveNegativeLiteralState(NegativeLiteral negativeLiteral, Set<String> knownVariables) {
88 Set<String> newVariables = new HashSet<>();
89 createSigletonVariablesAndCollectVariables(negativeLiteral.getAtom(), knownVariables, newVariables);
90 createVariables(negativeLiteral, newVariables);
91 }
92
93 protected void createSigletonVariablesAndCollectVariables(Atom atom, Set<String> knownVariables,
94 Set<String> newVariables) {
95 for (Argument argument : atom.getArguments()) {
96 if (argument instanceof VariableOrNodeArgument) {
97 var variableOrNodeArgument = (VariableOrNodeArgument) argument;
98 IScope scope = scopeProvider.getScope(variableOrNodeArgument,
99 ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE);
100 List<INode> nodes = NodeModelUtils.findNodesForFeature(variableOrNodeArgument,
101 ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE);
102 for (INode node : nodes) {
103 var variableName = linkingHelper.getCrossRefNodeAsString(node, true);
104 var created = tryCreateVariableForArgument(variableOrNodeArgument, variableName, scope,
105 knownVariables, newVariables);
106 if (created) {
107 break;
108 }
109 }
110 }
111 }
112 }
113
114 protected boolean tryCreateVariableForArgument(VariableOrNodeArgument variableOrNodeArgument, String variableName,
115 IScope scope, Set<String> knownVariables, Set<String> newVariables) {
116 if (!NamingUtil.isValidId(variableName)) {
117 return false;
118 }
119 var qualifiedName = qualifiedNameConverter.toQualifiedName(variableName);
120 if (scope.getSingleElement(qualifiedName) != null) {
121 return false;
122 }
123 if (NamingUtil.isSingletonVariableName(variableName)) {
124 createSingletonVariable(variableOrNodeArgument, variableName);
125 return true;
126 }
127 if (!knownVariables.contains(variableName)) {
128 newVariables.add(variableName);
129 return true;
130 }
131 return false;
132 }
133
134 protected void createVariables(ExistentialQuantifier quantifier, Set<String> newVariables) {
135 for (String variableName : newVariables) {
136 createVariable(quantifier, variableName);
137 }
138 }
139
140 protected void createVariable(ExistentialQuantifier quantifier, String variableName) {
141 if (NamingUtil.isValidId(variableName)) {
142 ImplicitVariable variable = createNamedVariable(variableName);
143 quantifier.getImplicitVariables().add(variable);
144 }
145 }
146
147 protected void createSingletonVariable(VariableOrNodeArgument argument, String variableName) {
148 if (NamingUtil.isValidId(variableName)) {
149 ImplicitVariable variable = createNamedVariable(variableName);
150 argument.setSingletonVariable(variable);
151 }
152 }
153
154 protected ImplicitVariable createNamedVariable(String variableName) {
155 var variable = ProblemFactory.eINSTANCE.createImplicitVariable();
156 variable.setName(variableName);
157 return variable;
158 }
159
160 public void discardDerivedVariables(Problem problem) {
161 for (Statement statement : problem.getStatements()) {
162 if (statement instanceof PredicateDefinition) {
163 discardPredicateDefinitionState((PredicateDefinition) statement);
164 }
165 }
166 }
167
168 protected void discardPredicateDefinitionState(PredicateDefinition definition) {
169 for (Conjunction body : definition.getBodies()) {
170 body.getImplicitVariables().clear();
171 for (Literal literal : body.getLiterals()) {
172 if (literal instanceof Atom) {
173 discardDerivedAtomState((Atom) literal);
174 }
175 if (literal instanceof NegativeLiteral) {
176 var negativeLiteral = (NegativeLiteral) literal;
177 negativeLiteral.getImplicitVariables().clear();
178 discardDerivedAtomState(negativeLiteral.getAtom());
179 }
180 }
181 }
182 }
183
184 protected void discardDerivedAtomState(Atom atom) {
185 if (atom == null) {
186 return;
187 }
188 for (Argument argument : atom.getArguments()) {
189 if (argument instanceof VariableOrNodeArgument) {
190 var variableOrNodeArgument = (VariableOrNodeArgument) argument;
191 variableOrNodeArgument.setSingletonVariable(null);
192 }
193 }
194 }
195}