aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/generator
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-11-03 19:12:08 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-11-03 19:12:19 +0100
commit32d469d0284d1ab1540423e705a5d3c8e7d99705 (patch)
treedcff140c1af411612c2ca61a34471134d762843a /subprojects/generator
parentrefactor(langauge-web): use generator facades (diff)
downloadrefinery-32d469d0284d1ab1540423e705a5d3c8e7d99705.tar.gz
refinery-32d469d0284d1ab1540423e705a5d3c8e7d99705.tar.zst
refinery-32d469d0284d1ab1540423e705a5d3c8e7d99705.zip
refactor: smenatics and facades
Also moves model metadata into language-web, since we only use it on the frontent.
Diffstat (limited to 'subprojects/generator')
-rw-r--r--subprojects/generator/build.gradle.kts2
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/AbstractRefinery.java54
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/AbstractRefineryBuilder.java159
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java58
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java78
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorBuilder.java41
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java63
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java36
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsBuilder.java37
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java45
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java90
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ProblemTrace.java35
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/StandaloneInjectorHolder.java27
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/impl/ProblemTraceImpl.java127
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java46
15 files changed, 333 insertions, 565 deletions
diff --git a/subprojects/generator/build.gradle.kts b/subprojects/generator/build.gradle.kts
index f1a4ed54..d87ce6de 100644
--- a/subprojects/generator/build.gradle.kts
+++ b/subprojects/generator/build.gradle.kts
@@ -10,6 +10,6 @@ plugins {
10 10
11dependencies { 11dependencies {
12 api(project(":refinery-language-semantics")) 12 api(project(":refinery-language-semantics"))
13 api(libs.eclipseCollections.api)
13 implementation(project(":refinery-store-query-interpreter")) 14 implementation(project(":refinery-store-query-interpreter"))
14 implementation(project(":refinery-store-reasoning-scope"))
15} 15}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/AbstractRefinery.java b/subprojects/generator/src/main/java/tools/refinery/generator/AbstractRefinery.java
deleted file mode 100644
index 56c7a23b..00000000
--- a/subprojects/generator/src/main/java/tools/refinery/generator/AbstractRefinery.java
+++ /dev/null
@@ -1,54 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import tools.refinery.generator.impl.ProblemTraceImpl;
9import tools.refinery.language.semantics.metadata.NodeMetadata;
10import tools.refinery.store.model.Model;
11import tools.refinery.store.model.ModelStore;
12import tools.refinery.store.reasoning.ReasoningAdapter;
13import tools.refinery.store.reasoning.ReasoningStoreAdapter;
14import tools.refinery.store.reasoning.seed.ModelSeed;
15import tools.refinery.store.reasoning.translator.TranslationException;
16
17import java.util.List;
18
19public abstract class AbstractRefinery {
20 protected final ProblemTrace problemTrace;
21 protected final ModelStore store;
22 protected final Model model;
23 protected final ReasoningAdapter reasoningAdapter;
24
25 protected AbstractRefinery(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) {
26 this.problemTrace = problemTrace;
27 this.store = store;
28 try {
29 model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed);
30 } catch (TranslationException e) {
31 throw ProblemTraceImpl.wrapException(problemTrace, e);
32 }
33 reasoningAdapter = model.getAdapter(ReasoningAdapter.class);
34 }
35
36 public ProblemTrace getProblemTrace() {
37 return problemTrace;
38 }
39
40 public ModelStore getModelStore() {
41 return store;
42 }
43
44 public Model getModel() {
45 return model;
46 }
47
48 public List<NodeMetadata> getNodesMetadata() {
49 int nodeCount = reasoningAdapter.getNodeCount();
50 return problemTrace.getNodesMetadata(nodeCount, isPreserveNewNodes());
51 }
52
53 protected abstract boolean isPreserveNewNodes();
54}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/AbstractRefineryBuilder.java b/subprojects/generator/src/main/java/tools/refinery/generator/AbstractRefineryBuilder.java
deleted file mode 100644
index d4649051..00000000
--- a/subprojects/generator/src/main/java/tools/refinery/generator/AbstractRefineryBuilder.java
+++ /dev/null
@@ -1,159 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import org.eclipse.emf.common.util.URI;
11import org.eclipse.emf.ecore.resource.Resource;
12import org.eclipse.xtext.diagnostics.Severity;
13import org.eclipse.xtext.resource.IResourceFactory;
14import org.eclipse.xtext.resource.XtextResourceSet;
15import org.eclipse.xtext.util.LazyStringInputStream;
16import org.eclipse.xtext.validation.CheckMode;
17import org.eclipse.xtext.validation.IResourceValidator;
18import tools.refinery.generator.impl.ProblemTraceImpl;
19import tools.refinery.language.model.problem.Problem;
20import tools.refinery.language.semantics.model.ModelInitializer;
21import tools.refinery.store.query.ModelQueryBuilder;
22import tools.refinery.store.query.interpreter.QueryInterpreterAdapter;
23import tools.refinery.store.reasoning.literal.Concreteness;
24import tools.refinery.store.reasoning.translator.TranslationException;
25import tools.refinery.store.util.CancellationToken;
26
27import java.io.File;
28import java.io.IOException;
29import java.io.InputStream;
30import java.util.Collection;
31import java.util.Map;
32
33// This class is used as a fluent builder.
34@SuppressWarnings("UnusedReturnValue")
35public abstract class AbstractRefineryBuilder<T> {
36 @Inject
37 private Provider<XtextResourceSet> resourceSetProvider;
38
39 @Inject
40 private IResourceFactory resourceFactory;
41
42 @Inject
43 private IResourceValidator resourceValidator;
44
45 @Inject
46 protected ModelInitializer initializer;
47
48 @Inject
49 private ProblemTraceImpl problemTrace;
50
51 protected CancellationToken cancellationToken = CancellationToken.NONE;
52 private boolean problemLoaded;
53 private ModelQueryBuilder queryEngineBuilder;
54 protected Collection<Concreteness> requiredInterpretations;
55
56 protected AbstractRefineryBuilder(Collection<Concreteness> defaultRequiredInterpretations) {
57 requiredInterpretations = defaultRequiredInterpretations;
58 }
59
60 protected abstract T self();
61
62 public T cancellationToken(CancellationToken cancellationToken) {
63 this.cancellationToken = cancellationToken;
64 return self();
65 }
66
67 public T fromString(String problemString) throws IOException {
68 try (var stream = new LazyStringInputStream(problemString)) {
69 return fromStream(stream);
70 }
71 }
72
73 public T fromStream(InputStream inputStream) throws IOException {
74 var resourceSet = resourceSetProvider.get();
75 var resource = resourceFactory.createResource(URI.createFileURI("__synthetic.problem"));
76 resourceSet.getResources().add(resource);
77 resource.load(inputStream, Map.of());
78 return fromResource(resource);
79 }
80
81 public T fromFile(File file) throws IOException {
82 return fromFile(file.getAbsolutePath());
83 }
84
85 public T fromFile(String filePath) throws IOException {
86 return fromUri(URI.createFileURI(filePath));
87 }
88
89 public T fromUri(URI uri) throws IOException {
90 var resourceSet = resourceSetProvider.get();
91 var resource = resourceFactory.createResource(uri);
92 resourceSet.getResources().add(resource);
93 resource.load(Map.of());
94 return fromResource(resource);
95 }
96
97 public T fromResource(Resource resource) {
98 var issues = resourceValidator.validate(resource, CheckMode.ALL, () -> {
99 cancellationToken.checkCancelled();
100 return Thread.interrupted();
101 });
102 cancellationToken.checkCancelled();
103 var errors = issues.stream()
104 .filter(issue -> issue.getSeverity() == Severity.ERROR)
105 .toList();
106 if (!errors.isEmpty()) {
107 throw new ValidationErrorsException(resource.getURI(), errors);
108 }
109 if (resource.getContents().isEmpty() || !(resource.getContents().get(0) instanceof Problem problem)) {
110 throw new IllegalArgumentException("Model generation problem not found in resource " + resource.getURI());
111 }
112 return problem(problem);
113 }
114
115 public T problem(Problem problem) {
116 if (problemLoaded) {
117 throw new IllegalStateException("Problem was already set");
118 }
119 problemTrace.setInitializer(initializer);
120 try {
121 initializer.readProblem(problem);
122 } catch (TranslationException e) {
123 throw ProblemTraceImpl.wrapException(problemTrace, e);
124 }
125 problemLoaded = true;
126 return self();
127 }
128
129 public ProblemTrace getProblemTrace() {
130 checkProblem();
131 return problemTrace;
132 }
133
134 public T queryEngine(ModelQueryBuilder queryEngineBuilder) {
135 if (this.queryEngineBuilder != null) {
136 throw new IllegalStateException("Query engine was already set");
137 }
138 this.queryEngineBuilder = queryEngineBuilder;
139 return self();
140 }
141
142 public T requiredInterpretations(Collection<Concreteness> requiredInterpretations) {
143 this.requiredInterpretations = requiredInterpretations;
144 return self();
145 }
146
147 protected void checkProblem() {
148 if (!problemLoaded) {
149 throw new IllegalStateException("Problem was not loaded");
150 }
151 }
152
153 protected ModelQueryBuilder getQueryEngineBuilder() {
154 if (queryEngineBuilder == null) {
155 return QueryInterpreterAdapter.builder();
156 }
157 return queryEngineBuilder;
158 }
159}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java
new file mode 100644
index 00000000..a00ddc46
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java
@@ -0,0 +1,58 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import tools.refinery.language.semantics.ProblemTrace;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.reasoning.ReasoningAdapter;
12import tools.refinery.store.reasoning.ReasoningStoreAdapter;
13import tools.refinery.store.reasoning.interpretation.PartialInterpretation;
14import tools.refinery.store.reasoning.literal.Concreteness;
15import tools.refinery.store.reasoning.representation.PartialSymbol;
16import tools.refinery.store.reasoning.seed.ModelSeed;
17import tools.refinery.store.reasoning.translator.TranslationException;
18
19public abstract class ModelFacade {
20 private final ProblemTrace problemTrace;
21 private final ModelStore store;
22 private final Model model;
23 private final ReasoningAdapter reasoningAdapter;
24 private final Concreteness concreteness;
25
26 protected ModelFacade(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed,
27 Concreteness concreteness) {
28 this.problemTrace = problemTrace;
29 this.store = store;
30 try {
31 model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed);
32 } catch (TranslationException e) {
33 throw problemTrace.wrapException(e);
34 }
35 reasoningAdapter = model.getAdapter(ReasoningAdapter.class);
36 this.concreteness = concreteness;
37 }
38
39 public ProblemTrace getProblemTrace() {
40 return problemTrace;
41 }
42
43 public ModelStore getModelStore() {
44 return store;
45 }
46
47 public Model getModel() {
48 return model;
49 }
50
51 public Concreteness getConcreteness() {
52 return concreteness;
53 }
54
55 public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) {
56 return reasoningAdapter.getPartialInterpretation(concreteness, partialSymbol);
57 }
58}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java
index 78c807d1..5b44c10a 100644
--- a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java
@@ -5,33 +5,25 @@
5 */ 5 */
6package tools.refinery.generator; 6package tools.refinery.generator;
7 7
8import org.eclipse.xtext.naming.QualifiedName; 8import tools.refinery.language.semantics.ProblemTrace;
9import tools.refinery.language.model.problem.Relation;
10import tools.refinery.store.dse.strategy.BestFirstStoreManager; 9import tools.refinery.store.dse.strategy.BestFirstStoreManager;
11import tools.refinery.store.dse.transition.VersionWithObjectiveValue;
12import tools.refinery.store.map.Version; 10import tools.refinery.store.map.Version;
13import tools.refinery.store.model.ModelStore; 11import tools.refinery.store.model.ModelStore;
14import tools.refinery.store.reasoning.interpretation.PartialInterpretation; 12import tools.refinery.store.reasoning.interpretation.PartialInterpretation;
15import tools.refinery.store.reasoning.literal.Concreteness; 13import tools.refinery.store.reasoning.literal.Concreteness;
16import tools.refinery.store.reasoning.representation.PartialSymbol; 14import tools.refinery.store.reasoning.representation.PartialSymbol;
17import tools.refinery.store.reasoning.seed.ModelSeed; 15import tools.refinery.store.reasoning.seed.ModelSeed;
18import tools.refinery.store.representation.TruthValue;
19 16
20import java.util.Collection; 17public class ModelGenerator extends ModelFacade {
21
22public class ModelGenerator extends AbstractRefinery {
23 private final Version initialVersion; 18 private final Version initialVersion;
24 19
25 private int randomSeed = 1; 20 private int randomSeed = 0;
26 21
27 public ModelGenerator(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) { 22 private boolean lastGenerationSuccessful;
28 super(problemTrace, store, modelSeed);
29 initialVersion = model.commit();
30 }
31 23
32 @Override 24 public ModelGenerator(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) {
33 protected boolean isPreserveNewNodes() { 25 super(problemTrace, store, modelSeed, Concreteness.CANDIDATE);
34 return false; 26 initialVersion = getModel().commit();
35 } 27 }
36 28
37 public int getRandomSeed() { 29 public int getRandomSeed() {
@@ -40,56 +32,40 @@ public class ModelGenerator extends AbstractRefinery {
40 32
41 public void setRandomSeed(int randomSeed) { 33 public void setRandomSeed(int randomSeed) {
42 this.randomSeed = randomSeed; 34 this.randomSeed = randomSeed;
35 this.lastGenerationSuccessful = false;
43 } 36 }
44 37
45 public Collection<Version> run(int maxNumberOfSolutions) { 38 public boolean isLastGenerationSuccessful() {
46 var bestFirst = new BestFirstStoreManager(store, maxNumberOfSolutions); 39 return lastGenerationSuccessful;
47 int currentRandomSeed = randomSeed;
48 // Increment random seed even if generation is unsuccessful.
49 randomSeed++;
50 bestFirst.startExploration(initialVersion, currentRandomSeed);
51 return bestFirst.getSolutionStore()
52 .getSolutions()
53 .stream()
54 .map(VersionWithObjectiveValue::version)
55 .toList();
56 } 40 }
57 41
58 // This method only makes sense if it returns {@code true} on success. 42 // This method only makes sense if it returns {@code true} on success.
59 @SuppressWarnings("BooleanMethodIsAlwaysInverted") 43 @SuppressWarnings("BooleanMethodIsAlwaysInverted")
60 public boolean tryRun() { 44 public boolean tryGenerate() {
61 var iterator = run(1).iterator(); 45 lastGenerationSuccessful = false;
62 if (!iterator.hasNext()) { 46 randomSeed++;
47 var bestFirst = new BestFirstStoreManager(getModelStore(), 1);
48 bestFirst.startExploration(initialVersion, randomSeed);
49 var solutions = bestFirst.getSolutionStore().getSolutions();
50 if (solutions.isEmpty()) {
63 return false; 51 return false;
64 } 52 }
65 model.restore(iterator.next()); 53 getModel().restore(solutions.get(0).version());
54 lastGenerationSuccessful = true;
66 return true; 55 return true;
67 } 56 }
68 57
69 public void run() { 58 public void generate() {
70 if (!tryRun()) { 59 if (!tryGenerate()) {
71 throw new UnsatisfiableProblemException(); 60 throw new UnsatisfiableProblemException();
72 } 61 }
73 } 62 }
74 63
75 public <A, C> PartialInterpretation<A, C> getCandidateInterpretation(PartialSymbol<A, C> partialSymbol) { 64 @Override
76 return reasoningAdapter.getPartialInterpretation(Concreteness.CANDIDATE, partialSymbol); 65 public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) {
77 } 66 if (!lastGenerationSuccessful) {
78 67 throw new IllegalStateException("No generated model is available");
79 public PartialInterpretation<TruthValue, Boolean> getCandidateInterpretation(Relation relation) { 68 }
80 return getCandidateInterpretation(problemTrace.getPartialRelation(relation)); 69 return super.getPartialInterpretation(partialSymbol);
81 }
82
83 public PartialInterpretation<TruthValue, Boolean> getCandidateInterpretation(QualifiedName qualifiedName) {
84 return getCandidateInterpretation(problemTrace.getPartialRelation(qualifiedName));
85 }
86
87 public PartialInterpretation<TruthValue, Boolean> getCandidateInterpretation(String qualifiedName) {
88 return getCandidateInterpretation(problemTrace.getPartialRelation(qualifiedName));
89 }
90
91 public static ModelGeneratorBuilder standaloneBuilder() {
92 var injector = StandaloneInjectorHolder.getInjector();
93 return injector.getInstance(ModelGeneratorBuilder.class);
94 } 70 }
95} 71}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorBuilder.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorBuilder.java
deleted file mode 100644
index d14cbe3a..00000000
--- a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorBuilder.java
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import tools.refinery.store.dse.propagation.PropagationAdapter;
9import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
10import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.reasoning.ReasoningAdapter;
12import tools.refinery.store.reasoning.literal.Concreteness;
13import tools.refinery.store.statecoding.StateCoderAdapter;
14
15import java.util.Set;
16
17public final class ModelGeneratorBuilder extends AbstractRefineryBuilder<ModelGeneratorBuilder> {
18 public ModelGeneratorBuilder() {
19 super(Set.of(Concreteness.CANDIDATE));
20 }
21
22 @Override
23 protected ModelGeneratorBuilder self() {
24 return this;
25 }
26
27 public ModelGenerator build() {
28 checkProblem();
29 var storeBuilder = ModelStore.builder()
30 .cancellationToken(cancellationToken)
31 .with(getQueryEngineBuilder())
32 .with(PropagationAdapter.builder())
33 .with(StateCoderAdapter.builder())
34 .with(DesignSpaceExplorationAdapter.builder())
35 .with(ReasoningAdapter.builder()
36 .requiredInterpretations(requiredInterpretations));
37 initializer.configureStoreBuilder(storeBuilder);
38 var store = storeBuilder.build();
39 return new ModelGenerator(getProblemTrace(), store, initializer.getModelSeed());
40 }
41}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java
new file mode 100644
index 00000000..6642d591
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java
@@ -0,0 +1,63 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import tools.refinery.language.model.problem.Problem;
11import tools.refinery.language.semantics.ModelInitializer;
12import tools.refinery.store.dse.propagation.PropagationAdapter;
13import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
14import tools.refinery.store.model.ModelStore;
15import tools.refinery.store.query.interpreter.QueryInterpreterAdapter;
16import tools.refinery.store.reasoning.ReasoningAdapter;
17import tools.refinery.store.reasoning.literal.Concreteness;
18import tools.refinery.store.statecoding.StateCoderAdapter;
19import tools.refinery.store.util.CancellationToken;
20
21import java.util.Collection;
22import java.util.Set;
23
24public final class ModelGeneratorFactory {
25 @Inject
26 private Provider<ModelInitializer> initializerProvider;
27
28 private CancellationToken cancellationToken = CancellationToken.NONE;
29
30 private boolean debugPartialInterpretations;
31
32 public ModelGeneratorFactory cancellationToken(CancellationToken cancellationToken) {
33 this.cancellationToken = cancellationToken;
34 return this;
35 }
36
37 public ModelGeneratorFactory debugPartialInterpretations(boolean debugPartialInterpretations) {
38 this.debugPartialInterpretations = debugPartialInterpretations;
39 return this;
40 }
41
42 public ModelGenerator createGenerator(Problem problem) {
43 var initializer = initializerProvider.get();
44 initializer.readProblem(problem);
45 cancellationToken.checkCancelled();
46 var storeBuilder = ModelStore.builder()
47 .cancellationToken(cancellationToken)
48 .with(QueryInterpreterAdapter.builder())
49 .with(PropagationAdapter.builder())
50 .with(StateCoderAdapter.builder())
51 .with(DesignSpaceExplorationAdapter.builder())
52 .with(ReasoningAdapter.builder()
53 .requiredInterpretations(getRequiredInterpretations()));
54 initializer.configureStoreBuilder(storeBuilder);
55 var store = storeBuilder.build();
56 return new ModelGenerator(initializer.getProblemTrace(), store, initializer.getModelSeed());
57 }
58
59 private Collection<Concreteness> getRequiredInterpretations() {
60 return debugPartialInterpretations ? Set.of(Concreteness.PARTIAL, Concreteness.CANDIDATE) :
61 Set.of(Concreteness.CANDIDATE);
62 }
63}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java
index 661bc97c..bc02c887 100644
--- a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java
@@ -5,43 +5,13 @@
5 */ 5 */
6package tools.refinery.generator; 6package tools.refinery.generator;
7 7
8import org.eclipse.xtext.naming.QualifiedName; 8import tools.refinery.language.semantics.ProblemTrace;
9import tools.refinery.language.model.problem.Relation;
10import tools.refinery.store.model.ModelStore; 9import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.reasoning.interpretation.PartialInterpretation;
12import tools.refinery.store.reasoning.literal.Concreteness; 10import tools.refinery.store.reasoning.literal.Concreteness;
13import tools.refinery.store.reasoning.representation.PartialSymbol;
14import tools.refinery.store.reasoning.seed.ModelSeed; 11import tools.refinery.store.reasoning.seed.ModelSeed;
15import tools.refinery.store.representation.TruthValue;
16 12
17public class ModelSemantics extends AbstractRefinery { 13public class ModelSemantics extends ModelFacade {
18 public ModelSemantics(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) { 14 public ModelSemantics(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) {
19 super(problemTrace, store, modelSeed); 15 super(problemTrace, store, modelSeed, Concreteness.PARTIAL);
20 }
21
22 @Override
23 protected boolean isPreserveNewNodes() {
24 return true;
25 }
26
27 public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) {
28 return reasoningAdapter.getPartialInterpretation(Concreteness.PARTIAL, partialSymbol);
29 }
30
31 public PartialInterpretation<TruthValue, Boolean> getPartialInterpretation(Relation relation) {
32 return getPartialInterpretation(problemTrace.getPartialRelation(relation));
33 }
34
35 public PartialInterpretation<TruthValue, Boolean> getPartialInterpretation(QualifiedName qualifiedName) {
36 return getPartialInterpretation(problemTrace.getPartialRelation(qualifiedName));
37 }
38
39 public PartialInterpretation<TruthValue, Boolean> getPartialInterpretation(String qualifiedName) {
40 return getPartialInterpretation(problemTrace.getPartialRelation(qualifiedName));
41 }
42
43 public static ModelSemanticsBuilder standaloneBuilder() {
44 var injector = StandaloneInjectorHolder.getInjector();
45 return injector.getInstance(ModelSemanticsBuilder.class);
46 } 16 }
47} 17}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsBuilder.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsBuilder.java
deleted file mode 100644
index a560ebe4..00000000
--- a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsBuilder.java
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import tools.refinery.store.dse.propagation.PropagationAdapter;
9import tools.refinery.store.model.ModelStore;
10import tools.refinery.store.reasoning.ReasoningAdapter;
11import tools.refinery.store.reasoning.literal.Concreteness;
12
13import java.util.Set;
14
15public final class ModelSemanticsBuilder extends AbstractRefineryBuilder<ModelSemanticsBuilder> {
16 public ModelSemanticsBuilder() {
17 super(Set.of(Concreteness.PARTIAL));
18 }
19
20 @Override
21 protected ModelSemanticsBuilder self() {
22 return this;
23 }
24
25 public ModelSemantics build() {
26 checkProblem();
27 var storeBuilder = ModelStore.builder()
28 .cancellationToken(cancellationToken)
29 .with(getQueryEngineBuilder())
30 .with(PropagationAdapter.builder())
31 .with(ReasoningAdapter.builder()
32 .requiredInterpretations(requiredInterpretations));
33 initializer.configureStoreBuilder(storeBuilder);
34 var store = storeBuilder.build();
35 return new ModelSemantics(getProblemTrace(), store, initializer.getModelSeed());
36 }
37}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java
new file mode 100644
index 00000000..b6263b37
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java
@@ -0,0 +1,45 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import tools.refinery.language.model.problem.Problem;
11import tools.refinery.language.semantics.ModelInitializer;
12import tools.refinery.store.dse.propagation.PropagationAdapter;
13import tools.refinery.store.model.ModelStore;
14import tools.refinery.store.query.interpreter.QueryInterpreterAdapter;
15import tools.refinery.store.reasoning.ReasoningAdapter;
16import tools.refinery.store.reasoning.literal.Concreteness;
17import tools.refinery.store.util.CancellationToken;
18
19import java.util.Set;
20
21public final class ModelSemanticsFactory {
22 @Inject
23 private Provider<ModelInitializer> initializerProvider;
24
25 private CancellationToken cancellationToken = CancellationToken.NONE;
26
27 public ModelSemanticsFactory cancellationToken(CancellationToken cancellationToken) {
28 this.cancellationToken = cancellationToken;
29 return this;
30 }
31
32 public ModelSemantics createSemantics(Problem problem) {
33 var initializer = initializerProvider.get();
34 initializer.readProblem(problem);
35 var storeBuilder = ModelStore.builder()
36 .cancellationToken(cancellationToken)
37 .with(QueryInterpreterAdapter.builder())
38 .with(PropagationAdapter.builder())
39 .with(ReasoningAdapter.builder()
40 .requiredInterpretations(Set.of(Concreteness.PARTIAL)));
41 initializer.configureStoreBuilder(storeBuilder);
42 var store = storeBuilder.build();
43 return new ModelSemantics(initializer.getProblemTrace(), store, initializer.getModelSeed());
44 }
45}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java b/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java
new file mode 100644
index 00000000..29f80714
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java
@@ -0,0 +1,90 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import org.eclipse.emf.common.util.URI;
11import org.eclipse.emf.ecore.resource.Resource;
12import org.eclipse.xtext.diagnostics.Severity;
13import org.eclipse.xtext.resource.IResourceFactory;
14import org.eclipse.xtext.resource.XtextResourceSet;
15import org.eclipse.xtext.util.LazyStringInputStream;
16import org.eclipse.xtext.validation.CheckMode;
17import org.eclipse.xtext.validation.IResourceValidator;
18import tools.refinery.language.model.problem.Problem;
19import tools.refinery.store.util.CancellationToken;
20
21import java.io.File;
22import java.io.IOException;
23import java.io.InputStream;
24import java.util.Map;
25
26public class ProblemLoader {
27 @Inject
28 private Provider<XtextResourceSet> resourceSetProvider;
29
30 @Inject
31 private IResourceFactory resourceFactory;
32
33 @Inject
34 private IResourceValidator resourceValidator;
35
36 private CancellationToken cancellationToken = CancellationToken.NONE;
37
38 public ProblemLoader cancellationToken(CancellationToken cancellationToken) {
39 this.cancellationToken = cancellationToken;
40 return this;
41 }
42
43 public Problem loadString(String problemString) throws IOException {
44 try (var stream = new LazyStringInputStream(problemString)) {
45 return loadStream(stream);
46 }
47 }
48
49 public Problem loadStream(InputStream inputStream) throws IOException {
50 var resourceSet = resourceSetProvider.get();
51 var resource = resourceFactory.createResource(URI.createFileURI("__synthetic.problem"));
52 resourceSet.getResources().add(resource);
53 resource.load(inputStream, Map.of());
54 return loadResource(resource);
55 }
56
57 public Problem loadFile(File file) throws IOException {
58 return loadFile(file.getAbsolutePath());
59 }
60
61 public Problem loadFile(String filePath) throws IOException {
62 return loadUri(URI.createFileURI(filePath));
63 }
64
65 public Problem loadUri(URI uri) throws IOException {
66 var resourceSet = resourceSetProvider.get();
67 var resource = resourceFactory.createResource(uri);
68 resourceSet.getResources().add(resource);
69 resource.load(Map.of());
70 return loadResource(resource);
71 }
72
73 public Problem loadResource(Resource resource) {
74 var issues = resourceValidator.validate(resource, CheckMode.ALL, () -> {
75 cancellationToken.checkCancelled();
76 return Thread.interrupted();
77 });
78 cancellationToken.checkCancelled();
79 var errors = issues.stream()
80 .filter(issue -> issue.getSeverity() == Severity.ERROR)
81 .toList();
82 if (!errors.isEmpty()) {
83 throw new ValidationErrorsException(resource.getURI(), errors);
84 }
85 if (resource.getContents().isEmpty() || !(resource.getContents().get(0) instanceof Problem problem)) {
86 throw new IllegalArgumentException("Model generation problem not found in resource " + resource.getURI());
87 }
88 return problem;
89 }
90}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ProblemTrace.java b/subprojects/generator/src/main/java/tools/refinery/generator/ProblemTrace.java
deleted file mode 100644
index f7963c58..00000000
--- a/subprojects/generator/src/main/java/tools/refinery/generator/ProblemTrace.java
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import org.eclipse.xtext.naming.QualifiedName;
9import tools.refinery.language.model.problem.Problem;
10import tools.refinery.language.model.problem.Relation;
11import tools.refinery.language.semantics.metadata.NodeMetadata;
12import tools.refinery.language.semantics.metadata.RelationMetadata;
13import tools.refinery.store.reasoning.representation.AnyPartialSymbol;
14import tools.refinery.store.reasoning.representation.PartialRelation;
15
16import java.util.List;
17import java.util.Map;
18
19public interface ProblemTrace {
20 Problem getProblem();
21
22 Map<Relation, PartialRelation> getRelationTrace();
23
24 Relation getInverseTrace(AnyPartialSymbol partialSymbol);
25
26 PartialRelation getPartialRelation(Relation relation);
27
28 PartialRelation getPartialRelation(QualifiedName qualifiedName);
29
30 PartialRelation getPartialRelation(String qualifiedName);
31
32 List<RelationMetadata> getRelationsMetadata();
33
34 List<NodeMetadata> getNodesMetadata(int nodeCount, boolean preserveNewNodes);
35}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/StandaloneInjectorHolder.java b/subprojects/generator/src/main/java/tools/refinery/generator/StandaloneInjectorHolder.java
deleted file mode 100644
index 7db96163..00000000
--- a/subprojects/generator/src/main/java/tools/refinery/generator/StandaloneInjectorHolder.java
+++ /dev/null
@@ -1,27 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8import com.google.inject.Injector;
9import tools.refinery.language.ProblemStandaloneSetup;
10
11public final class StandaloneInjectorHolder {
12 private StandaloneInjectorHolder() {
13 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly");
14 }
15
16 public static Injector getInjector() {
17 return LazyHolder.INJECTOR;
18 }
19
20 private static final class LazyHolder {
21 private static final Injector INJECTOR = createInjector();
22
23 private static Injector createInjector() {
24 return new ProblemStandaloneSetup().createInjectorAndDoEMFRegistration();
25 }
26 }
27}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/impl/ProblemTraceImpl.java b/subprojects/generator/src/main/java/tools/refinery/generator/impl/ProblemTraceImpl.java
deleted file mode 100644
index 5671d3f8..00000000
--- a/subprojects/generator/src/main/java/tools/refinery/generator/impl/ProblemTraceImpl.java
+++ /dev/null
@@ -1,127 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator.impl;
7
8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import org.eclipse.emf.ecore.util.EcoreUtil;
11import org.eclipse.xtext.naming.IQualifiedNameConverter;
12import org.eclipse.xtext.naming.IQualifiedNameProvider;
13import org.eclipse.xtext.naming.QualifiedName;
14import org.eclipse.xtext.scoping.IScopeProvider;
15import tools.refinery.generator.ProblemTrace;
16import tools.refinery.language.model.problem.Problem;
17import tools.refinery.language.model.problem.ProblemPackage;
18import tools.refinery.language.model.problem.Relation;
19import tools.refinery.language.semantics.metadata.MetadataCreator;
20import tools.refinery.language.semantics.metadata.NodeMetadata;
21import tools.refinery.language.semantics.metadata.RelationMetadata;
22import tools.refinery.language.semantics.model.ModelInitializer;
23import tools.refinery.language.semantics.model.TracedException;
24import tools.refinery.store.reasoning.representation.AnyPartialSymbol;
25import tools.refinery.store.reasoning.representation.PartialRelation;
26import tools.refinery.store.reasoning.translator.TranslationException;
27
28import java.util.Collections;
29import java.util.List;
30import java.util.Map;
31
32public final class ProblemTraceImpl implements ProblemTrace {
33 @Inject
34 private IQualifiedNameConverter qualifiedNameConverter;
35
36 @Inject
37 private IQualifiedNameProvider qualifiedNameProvider;
38
39 @Inject
40 private IScopeProvider scopeProvider;
41
42 @Inject
43 private Provider<MetadataCreator> metadataCreatorProvider;
44
45 private ModelInitializer initializer;
46 private Map<Relation, PartialRelation> relationTrace;
47 private MetadataCreator metadataCreator;
48
49 public void setInitializer(ModelInitializer initializer) {
50 this.initializer = initializer;
51 relationTrace = Collections.unmodifiableMap(initializer.getRelationTrace());
52 }
53
54 public Problem getProblem() {
55 return initializer.getProblem();
56 }
57
58 public Map<Relation, PartialRelation> getRelationTrace() {
59 return relationTrace;
60 }
61
62 @Override
63 public Relation getInverseTrace(AnyPartialSymbol partialSymbol) {
64 return initializer.getInverseTrace(partialSymbol);
65 }
66
67 public PartialRelation getPartialRelation(Relation relation) {
68 var partialRelation = relationTrace.get(relation);
69 if (partialRelation == null) {
70 var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(relation);
71 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
72 throw new IllegalArgumentException("No partial relation for relation " + qualifiedNameString);
73 }
74 return partialRelation;
75 }
76
77 public PartialRelation getPartialRelation(QualifiedName qualifiedName) {
78 var scope = scopeProvider.getScope(getProblem(), ProblemPackage.Literals.ASSERTION__RELATION);
79 var iterator = scope.getElements(qualifiedName).iterator();
80 if (!iterator.hasNext()) {
81 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
82 throw new IllegalArgumentException("No such relation: " + qualifiedNameString);
83 }
84 var eObjectDescription = iterator.next();
85 if (iterator.hasNext()) {
86 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
87 throw new IllegalArgumentException("Ambiguous relation: " + qualifiedNameString);
88 }
89 var eObject = EcoreUtil.resolve(eObjectDescription.getEObjectOrProxy(), getProblem());
90 if (!(eObject instanceof Relation relation)) {
91 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
92 throw new IllegalArgumentException("Not a relation: " + qualifiedNameString);
93 }
94 return getPartialRelation(relation);
95 }
96
97 public PartialRelation getPartialRelation(String qualifiedName) {
98 var convertedName = qualifiedNameConverter.toQualifiedName(qualifiedName);
99 return getPartialRelation(convertedName);
100 }
101
102 @Override
103 public List<RelationMetadata> getRelationsMetadata() {
104 return getMetadataCreator().getRelationsMetadata();
105 }
106
107 @Override
108 public List<NodeMetadata> getNodesMetadata(int nodeCount, boolean preserveNewNodes) {
109 return getMetadataCreator().getNodesMetadata(nodeCount, preserveNewNodes);
110 }
111
112 private MetadataCreator getMetadataCreator() {
113 if (metadataCreator == null) {
114 metadataCreator = metadataCreatorProvider.get();
115 metadataCreator.setInitializer(initializer);
116 }
117 return metadataCreator;
118 }
119
120 public static RuntimeException wrapException(ProblemTrace trace, TranslationException translationException) {
121 var source = trace.getInverseTrace(translationException.getPartialSymbol());
122 if (source == null) {
123 return translationException;
124 }
125 return new TracedException(source, translationException);
126 }
127}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java b/subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java
new file mode 100644
index 00000000..b444491b
--- /dev/null
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java
@@ -0,0 +1,46 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator.standalone;
7
8import com.google.inject.Injector;
9import tools.refinery.generator.ModelGeneratorFactory;
10import tools.refinery.generator.ModelSemanticsFactory;
11import tools.refinery.language.ProblemStandaloneSetup;
12import tools.refinery.generator.ProblemLoader;
13
14public final class StandaloneRefinery {
15 private StandaloneRefinery() {
16 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly");
17 }
18
19 public static Injector getInjector() {
20 return LazyHolder.INJECTOR;
21 }
22
23 public static <T> T getInstance(Class<T> type) {
24 return getInjector().getInstance(type);
25 }
26
27 public static ProblemLoader getProblemLoader() {
28 return getInstance(ProblemLoader.class);
29 }
30
31 public static ModelGeneratorFactory getGeneratorFactory() {
32 return getInstance(ModelGeneratorFactory.class);
33 }
34
35 public static ModelSemanticsFactory getSemanticsFactory() {
36 return getInstance(ModelSemanticsFactory.class);
37 }
38
39 private static final class LazyHolder {
40 private static final Injector INJECTOR = createInjector();
41
42 private static Injector createInjector() {
43 return new ProblemStandaloneSetup().createInjectorAndDoEMFRegistration();
44 }
45 }
46}