diff options
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.java | 195 |
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 @@ | |||
1 | package org.eclipse.viatra.solver.language.resource; | ||
2 | |||
3 | import java.util.HashSet; | ||
4 | import java.util.List; | ||
5 | import java.util.Set; | ||
6 | |||
7 | import org.eclipse.viatra.solver.language.model.problem.Argument; | ||
8 | import org.eclipse.viatra.solver.language.model.problem.Atom; | ||
9 | import org.eclipse.viatra.solver.language.model.problem.Conjunction; | ||
10 | import org.eclipse.viatra.solver.language.model.problem.ExistentialQuantifier; | ||
11 | import org.eclipse.viatra.solver.language.model.problem.ImplicitVariable; | ||
12 | import org.eclipse.viatra.solver.language.model.problem.Literal; | ||
13 | import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral; | ||
14 | import org.eclipse.viatra.solver.language.model.problem.Parameter; | ||
15 | import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; | ||
16 | import org.eclipse.viatra.solver.language.model.problem.Problem; | ||
17 | import org.eclipse.viatra.solver.language.model.problem.ProblemFactory; | ||
18 | import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; | ||
19 | import org.eclipse.viatra.solver.language.model.problem.Statement; | ||
20 | import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument; | ||
21 | import org.eclipse.viatra.solver.language.naming.NamingUtil; | ||
22 | import org.eclipse.xtext.linking.impl.LinkingHelper; | ||
23 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | ||
24 | import org.eclipse.xtext.nodemodel.INode; | ||
25 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; | ||
26 | import org.eclipse.xtext.scoping.IScope; | ||
27 | import org.eclipse.xtext.scoping.IScopeProvider; | ||
28 | import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; | ||
29 | |||
30 | import com.google.inject.Inject; | ||
31 | import com.google.inject.Singleton; | ||
32 | import com.google.inject.name.Named; | ||
33 | |||
34 | @Singleton | ||
35 | public 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 | } | ||