diff options
Diffstat (limited to 'Solvers/VIATRA-Solver')
217 files changed, 21862 insertions, 2854 deletions
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF index 23e3ad13..ec1557e8 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF | |||
@@ -4,8 +4,12 @@ Bundle-Name: Logic2viatra | |||
4 | Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery;singleton:=true | 4 | Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery;singleton:=true |
5 | Bundle-Version: 1.0.0.qualifier | 5 | Bundle-Version: 1.0.0.qualifier |
6 | Export-Package: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra, | 6 | Export-Package: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra, |
7 | hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality, | ||
8 | hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval, | ||
9 | hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.aggregators, | ||
7 | hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns, | 10 | hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns, |
8 | hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries | 11 | hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries, |
12 | hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules | ||
9 | Require-Bundle: hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0", | 13 | Require-Bundle: hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0", |
10 | hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage;bundle-version="1.0.0", | 14 | hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage;bundle-version="1.0.0", |
11 | hu.bme.mit.inf.dslreasoner.ecore2logic;bundle-version="1.0.0", | 15 | hu.bme.mit.inf.dslreasoner.ecore2logic;bundle-version="1.0.0", |
@@ -14,13 +18,16 @@ Require-Bundle: hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0", | |||
14 | org.eclipse.xtext.xbase.lib, | 18 | org.eclipse.xtext.xbase.lib, |
15 | org.eclipse.xtend.lib, | 19 | org.eclipse.xtend.lib, |
16 | org.eclipse.xtend.lib.macro, | 20 | org.eclipse.xtend.lib.macro, |
17 | org.eclipse.viatra.query.runtime;bundle-version="1.5.0", | 21 | org.eclipse.viatra.query.runtime;bundle-version="2.0.0", |
18 | org.eclipse.viatra.query.runtime.base.itc;bundle-version="1.5.0", | 22 | org.eclipse.viatra.query.runtime.base.itc;bundle-version="2.0.0", |
19 | org.eclipse.viatra.query.patternlanguage.emf;bundle-version="1.5.0", | 23 | org.eclipse.viatra.query.patternlanguage.emf;bundle-version="2.0.0", |
20 | com.google.inject;bundle-version="3.0.0", | 24 | com.google.inject;bundle-version="3.0.0", |
21 | org.eclipse.xtext;bundle-version="2.10.0", | 25 | org.eclipse.xtext;bundle-version="2.10.0", |
22 | org.eclipse.viatra.transformation.runtime.emf;bundle-version="1.5.0", | 26 | org.eclipse.viatra.transformation.runtime.emf;bundle-version="2.0.0", |
23 | org.eclipse.xtext.xbase;bundle-version="2.10.0" | 27 | org.eclipse.xtext.xbase;bundle-version="2.10.0", |
28 | com.microsoft.z3;bundle-version="4.8.5", | ||
29 | hu.bme.mit.inf.dslreasoner.ilp.cbc;bundle-version="1.0.0", | ||
30 | org.eclipse.viatra.query.runtime.rete;bundle-version="2.0.0" | ||
24 | Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | 31 | Bundle-RequiredExecutionEnvironment: JavaSE-1.8 |
25 | Import-Package: org.apache.log4j | 32 | Import-Package: org.apache.log4j |
26 | Automatic-Module-Name: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery | 33 | Automatic-Module-Name: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/build.properties b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/build.properties index 585df5ce..9ffc994a 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/build.properties +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/build.properties | |||
@@ -4,6 +4,5 @@ bin.includes = META-INF/,\ | |||
4 | source.. = src/,\ | 4 | source.. = src/,\ |
5 | patterns/,\ | 5 | patterns/,\ |
6 | vql-gen/,\ | 6 | vql-gen/,\ |
7 | xtend-gen/,\ | 7 | xtend-gen/ |
8 | src-gen/ | ||
9 | output.. = bin/ | 8 | output.. = bin/ |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/plugin.xml b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/plugin.xml index 05e00983..6e4d96ca 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/plugin.xml +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/plugin.xml | |||
@@ -1,14 +1,14 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?><plugin> | 1 | <?xml version="1.0" encoding="UTF-8"?><plugin> |
2 | <extension id="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis" point="org.eclipse.viatra.query.runtime.queryspecification"> | 2 | <extension id="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis" point="org.eclipse.viatra.query.runtime.queryspecification"> |
3 | <group group="org.eclipse.viatra.query.runtime.extensibility.SingletonExtensionFactory:hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis" id="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis"> | 3 | <group group="org.eclipse.viatra.query.runtime.extensibility.SingletonExtensionFactory:hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis" id="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis"> |
4 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.hasDefinedSupertype"/> | 4 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.hasDefinedSupertype"/> |
5 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.dontHaveDefinedSupertype"/> | 5 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.dontHaveDefinedSupertype"/> |
6 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeConstructor"/> | 6 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeConstructor"/> |
7 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeRefinementTarget"/> | 7 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeRefinementTarget"/> |
8 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.incompatibleSuperType"/> | 8 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.incompatibleSuperType"/> |
9 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.incompatibleTopType"/> | 9 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.incompatibleTopType"/> |
10 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeRefinementNegativeConstraint"/> | 10 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeRefinementNegativeConstraint"/> |
11 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementMayTypeNegativeConstraint"/> | 11 | <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementMayTypeNegativeConstraint"/> |
12 | </group> | 12 | </group> |
13 | </extension> | 13 | </extension> |
14 | </plugin> | 14 | </plugin> |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/Modality.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/Modality.java index d2132cea..f3a6ec32 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/Modality.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/Modality.java | |||
@@ -2,21 +2,46 @@ package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra; | |||
2 | 2 | ||
3 | public enum Modality { | 3 | public enum Modality { |
4 | MUST, MAY, CURRENT; | 4 | MUST, MAY, CURRENT; |
5 | |||
5 | public boolean isMust() { | 6 | public boolean isMust() { |
6 | return this == MUST; | 7 | return this == MUST; |
7 | } | 8 | } |
9 | |||
8 | public boolean isMay() { | 10 | public boolean isMay() { |
9 | return this == MAY; | 11 | return this == MAY; |
10 | } | 12 | } |
13 | |||
11 | public boolean isCurrent() { | 14 | public boolean isCurrent() { |
12 | return this == CURRENT; | 15 | return this == CURRENT; |
13 | } | 16 | } |
17 | |||
14 | public boolean isMustOrCurrent() { | 18 | public boolean isMustOrCurrent() { |
15 | return isMust() || isCurrent(); | 19 | return isMust() || isCurrent(); |
16 | } | 20 | } |
21 | |||
17 | public Modality getDual() { | 22 | public Modality getDual() { |
18 | if(this.isCurrent()) return CURRENT; | 23 | switch (this) { |
19 | else if(this.isMust())return MAY; | 24 | case CURRENT: |
20 | else return MUST; | 25 | return CURRENT; |
26 | case MUST: | ||
27 | return MAY; | ||
28 | case MAY: | ||
29 | return MUST; | ||
30 | default: | ||
31 | throw new UnsupportedOperationException("Unknown Modality: " + this); | ||
32 | } | ||
33 | } | ||
34 | |||
35 | public Modality toBase() { | ||
36 | if (this.isCurrent()) { | ||
37 | return MUST; | ||
38 | } else { | ||
39 | return this; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public String toString() { | ||
45 | return super.toString().toLowerCase(); | ||
21 | } | 46 | } |
22 | } | 47 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ModelGenerationMethodProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ModelGenerationMethodProvider.xtend deleted file mode 100644 index 8a26470a..00000000 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ModelGenerationMethodProvider.xtend +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
5 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.RefinementRuleProvider | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
10 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace | ||
11 | import java.util.Collection | ||
12 | import java.util.List | ||
13 | import java.util.Set | ||
14 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
15 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
16 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
17 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | ||
18 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule | ||
19 | import org.eclipse.xtend.lib.annotations.Data | ||
20 | |||
21 | class ModelGenerationStatistics { | ||
22 | public var long transformationExecutionTime = 0 | ||
23 | public var long metricCalculationTime = 0 | ||
24 | |||
25 | synchronized def addExecutionTime(long amount) { | ||
26 | transformationExecutionTime+=amount | ||
27 | } | ||
28 | |||
29 | synchronized def addMetricCalculationTime(long amount) { | ||
30 | metricCalculationTime+=amount | ||
31 | } | ||
32 | |||
33 | public var long PreliminaryTypeAnalisisTime = 0 | ||
34 | } | ||
35 | @Data class ModelGenerationMethod { | ||
36 | ModelGenerationStatistics statistics | ||
37 | |||
38 | Collection<? extends BatchTransformationRule<?,?>> objectRefinementRules | ||
39 | Collection<? extends BatchTransformationRule<?,?>> relationRefinementRules | ||
40 | |||
41 | List<MultiplicityGoalConstraintCalculator> unfinishedMultiplicities | ||
42 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF | ||
43 | |||
44 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWF | ||
45 | |||
46 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allPatterns | ||
47 | } | ||
48 | enum TypeInferenceMethod { | ||
49 | Generic, PreliminaryAnalysis | ||
50 | } | ||
51 | |||
52 | class ModelGenerationMethodProvider { | ||
53 | private val PatternProvider patternProvider = new PatternProvider | ||
54 | private val RefinementRuleProvider refinementRuleProvider = new RefinementRuleProvider | ||
55 | private val GoalConstraintProvider goalConstraintProvider = new GoalConstraintProvider | ||
56 | |||
57 | public def ModelGenerationMethod createModelGenerationMethod( | ||
58 | LogicProblem logicProblem, | ||
59 | PartialInterpretation emptySolution, | ||
60 | ReasonerWorkspace workspace, | ||
61 | boolean nameNewElements, | ||
62 | TypeInferenceMethod typeInferenceMethod, | ||
63 | ScopePropagator scopePropagator, | ||
64 | DocumentationLevel debugLevel | ||
65 | ) { | ||
66 | val statistics = new ModelGenerationStatistics | ||
67 | val writeFiles = (debugLevel === DocumentationLevel.NORMAL || debugLevel === DocumentationLevel.FULL) | ||
68 | |||
69 | val Set<PQuery> existingQueries = logicProblem | ||
70 | .relations | ||
71 | .map[annotations] | ||
72 | .flatten | ||
73 | .filter(TransfomedViatraQuery) | ||
74 | .map[it.patternPQuery as PQuery] | ||
75 | .toSet | ||
76 | |||
77 | val queries = patternProvider.generateQueries(logicProblem,emptySolution,statistics,existingQueries,workspace,typeInferenceMethod,writeFiles) | ||
78 | val //LinkedHashMap<Pair<Relation, ? extends Type>, BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>>> | ||
79 | objectRefinementRules = refinementRuleProvider.createObjectRefinementRules(queries,scopePropagator,nameNewElements,statistics) | ||
80 | val relationRefinementRules = refinementRuleProvider.createRelationRefinementRules(queries,statistics) | ||
81 | |||
82 | val unfinishedMultiplicities = goalConstraintProvider.getUnfinishedMultiplicityQueries(queries) | ||
83 | val unfinishedWF = queries.getUnfinishedWFQueries.values | ||
84 | |||
85 | val invalidWF = queries.getInvalidWFQueries.values | ||
86 | |||
87 | return new ModelGenerationMethod( | ||
88 | statistics, | ||
89 | objectRefinementRules.values, | ||
90 | relationRefinementRules.values, | ||
91 | unfinishedMultiplicities, | ||
92 | unfinishedWF, | ||
93 | invalidWF, | ||
94 | queries.allQueries | ||
95 | ) | ||
96 | } | ||
97 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ModelGenerationStatistics.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ModelGenerationStatistics.xtend new file mode 100644 index 00000000..ab4fa039 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ModelGenerationStatistics.xtend | |||
@@ -0,0 +1,52 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra | ||
2 | |||
3 | class ModelGenerationStatistics { | ||
4 | public var long transformationExecutionTime = 0 | ||
5 | public var long metricCalculationTime = 0 | ||
6 | |||
7 | |||
8 | synchronized def addMetricCalculationTime(long amount) { | ||
9 | metricCalculationTime+=amount | ||
10 | } | ||
11 | synchronized def addExecutionTime(long amount) { | ||
12 | transformationExecutionTime += amount | ||
13 | } | ||
14 | |||
15 | public var long scopePropagationTime = 0 | ||
16 | |||
17 | synchronized def addScopePropagationTime(long amount) { | ||
18 | scopePropagationTime += amount | ||
19 | } | ||
20 | |||
21 | public var long mustRelationPropagationTime = 0 | ||
22 | |||
23 | synchronized def addMustRelationPropagationTime(long amount) { | ||
24 | mustRelationPropagationTime += amount | ||
25 | } | ||
26 | |||
27 | public var long preliminaryTypeAnalisisTime = 0 | ||
28 | |||
29 | public var int decisionsTried = 0 | ||
30 | |||
31 | synchronized def incrementDecisionCount() { | ||
32 | decisionsTried++ | ||
33 | } | ||
34 | |||
35 | public var int transformationInvocations | ||
36 | |||
37 | synchronized def incrementTransformationCount() { | ||
38 | transformationInvocations++ | ||
39 | } | ||
40 | |||
41 | public var int scopePropagatorInvocations | ||
42 | |||
43 | synchronized def incrementScopePropagationCount() { | ||
44 | scopePropagatorInvocations++ | ||
45 | } | ||
46 | |||
47 | public var int scopePropagatorSolverInvocations | ||
48 | |||
49 | synchronized def incrementScopePropagationSolverCount() { | ||
50 | scopePropagatorSolverInvocations++ | ||
51 | } | ||
52 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/MultiplicityGoalConstraintCalculator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/MultiplicityGoalConstraintCalculator.xtend deleted file mode 100644 index e05160d0..00000000 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/MultiplicityGoalConstraintCalculator.xtend +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra | ||
2 | |||
3 | import org.eclipse.emf.common.notify.Notifier | ||
4 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
5 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
6 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
7 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
8 | |||
9 | class MultiplicityGoalConstraintCalculator { | ||
10 | val String targetRelationName; | ||
11 | val IQuerySpecification<?> querySpecification; | ||
12 | var ViatraQueryMatcher<?> matcher; | ||
13 | |||
14 | public new(String targetRelationName, IQuerySpecification<?> querySpecification) { | ||
15 | this.targetRelationName = targetRelationName | ||
16 | this.querySpecification = querySpecification | ||
17 | this.matcher = null | ||
18 | } | ||
19 | |||
20 | public new(MultiplicityGoalConstraintCalculator other) { | ||
21 | this.targetRelationName = other.targetRelationName | ||
22 | this.querySpecification = other.querySpecification | ||
23 | this.matcher = null | ||
24 | } | ||
25 | |||
26 | def public getName() { | ||
27 | targetRelationName | ||
28 | } | ||
29 | |||
30 | def public init(Notifier notifier) { | ||
31 | val engine = ViatraQueryEngine.on(new EMFScope(notifier)) | ||
32 | matcher = querySpecification.getMatcher(engine) | ||
33 | } | ||
34 | |||
35 | def public calculateValue() { | ||
36 | var res = 0 | ||
37 | val allMatches = this.matcher.allMatches | ||
38 | for(match : allMatches) { | ||
39 | //println(targetRelationName+ " missing multiplicity: "+match.get(3)) | ||
40 | val missingMultiplicity = match.get(4) as Integer | ||
41 | res += missingMultiplicity | ||
42 | } | ||
43 | //println(targetRelationName+ " all missing multiplicities: "+res) | ||
44 | return res | ||
45 | } | ||
46 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/PropagationModality.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/PropagationModality.java new file mode 100644 index 00000000..2288ad7e --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/PropagationModality.java | |||
@@ -0,0 +1,8 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra; | ||
2 | |||
3 | public enum PropagationModality { | ||
4 | /**The value was originally ? and set to 1 */ | ||
5 | UP, | ||
6 | /**The value was originally ? and set to 0 */ | ||
7 | DOWN | ||
8 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/TypeInferenceMethod.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/TypeInferenceMethod.xtend new file mode 100644 index 00000000..9296a0be --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/TypeInferenceMethod.xtend | |||
@@ -0,0 +1,44 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra | ||
2 | |||
3 | import com.google.common.collect.ImmutableMap | ||
4 | import com.google.common.collect.ImmutableSet | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
7 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.CachingSimplePolyhedronScopePropagatorStrategy | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.CbcPolyhedronSolver | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint | ||
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronScopePropagator | ||
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraintCalculator | ||
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.TypeHierarchyScopePropagator | ||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Z3PolyhedronSolver | ||
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns | ||
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider | ||
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.UnitPropagationPatternGenerator | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider | ||
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.RefinementRuleProvider | ||
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
25 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace | ||
26 | import java.util.Collection | ||
27 | import java.util.List | ||
28 | import java.util.Map | ||
29 | import java.util.Set | ||
30 | import org.eclipse.viatra.query.runtime.api.GenericQueryGroup | ||
31 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
32 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
33 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
34 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
35 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
36 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
37 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | ||
38 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule | ||
39 | import org.eclipse.xtend.lib.annotations.Data | ||
40 | |||
41 | enum TypeInferenceMethod { | ||
42 | Generic, | ||
43 | PreliminaryAnalysis | ||
44 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/AbstractPolyhedronSaturationOperator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/AbstractPolyhedronSaturationOperator.xtend new file mode 100644 index 00000000..94f97e94 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/AbstractPolyhedronSaturationOperator.xtend | |||
@@ -0,0 +1,53 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import org.eclipse.xtend.lib.annotations.Accessors | ||
5 | |||
6 | abstract class AbstractPolyhedronSaturationOperator implements PolyhedronSaturationOperator { | ||
7 | @Accessors val Polyhedron polyhedron | ||
8 | |||
9 | new(Polyhedron polyhedron) { | ||
10 | if (polyhedron.dimensions.empty) { | ||
11 | throw new IllegalArgumentException("Polyhedron must have at least one dimension.") | ||
12 | } | ||
13 | this.polyhedron = polyhedron | ||
14 | } | ||
15 | |||
16 | override saturate() { | ||
17 | if (polyhedron.expressionsToSaturate.empty) { | ||
18 | return PolyhedronSaturationResult.SATURATED | ||
19 | } | ||
20 | for (constraint : polyhedron.constraints) { | ||
21 | if (constraint.zero) { | ||
22 | if (constraint.lowerBound !== null && constraint.lowerBound > 0) { | ||
23 | return PolyhedronSaturationResult.EMPTY | ||
24 | } | ||
25 | if (constraint.upperBound !== null && constraint.upperBound < 0) { | ||
26 | return PolyhedronSaturationResult.EMPTY | ||
27 | } | ||
28 | } else { | ||
29 | if (constraint.lowerBound !== null && constraint.upperBound !== null && | ||
30 | constraint.upperBound < constraint.lowerBound) { | ||
31 | return PolyhedronSaturationResult.EMPTY | ||
32 | } | ||
33 | } | ||
34 | } | ||
35 | doSaturate() | ||
36 | } | ||
37 | |||
38 | protected def PolyhedronSaturationResult doSaturate() | ||
39 | |||
40 | protected def getNonTrivialConstraints() { | ||
41 | ImmutableList.copyOf(polyhedron.constraints.filter [ constraint | | ||
42 | (constraint.lowerBound !== null || constraint.upperBound !== null) && !constraint.zero | ||
43 | ]) | ||
44 | } | ||
45 | |||
46 | private static def isZero(LinearConstraint constraint) { | ||
47 | constraint.coefficients.values.forall[it == 0] | ||
48 | } | ||
49 | |||
50 | override close() throws Exception { | ||
51 | // Nothing to close by default. | ||
52 | } | ||
53 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/CbcPolyhedronSolver.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/CbcPolyhedronSolver.xtend new file mode 100644 index 00000000..708f93dc --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/CbcPolyhedronSolver.xtend | |||
@@ -0,0 +1,241 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import com.google.common.collect.ImmutableMap | ||
5 | import hu.bme.mit.inf.dslreasoner.ilp.cbc.CbcResult | ||
6 | import hu.bme.mit.inf.dslreasoner.ilp.cbc.CbcSolver | ||
7 | import java.util.HashSet | ||
8 | import java.util.List | ||
9 | import java.util.Map | ||
10 | import java.util.Set | ||
11 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
12 | |||
13 | @FinalFieldsConstructor | ||
14 | class CbcPolyhedronSolver implements PolyhedronSolver { | ||
15 | val boolean lpRelaxation | ||
16 | val double timeoutSeconds | ||
17 | val boolean silent | ||
18 | |||
19 | new() { | ||
20 | this(false, -1, true) | ||
21 | } | ||
22 | |||
23 | override createSaturationOperator(Polyhedron polyhedron) { | ||
24 | new CbcSaturationOperator(polyhedron, lpRelaxation, timeoutSeconds, silent) | ||
25 | } | ||
26 | } | ||
27 | |||
28 | class CbcSaturationOperator extends AbstractPolyhedronSaturationOperator { | ||
29 | static val EPSILON = 1e-6 | ||
30 | |||
31 | val boolean lpRelaxation | ||
32 | val double timeoutSeconds | ||
33 | val boolean silent | ||
34 | val double[] columnLowerBounds | ||
35 | val double[] columnUpperBounds | ||
36 | val double[] objective | ||
37 | val Map<Dimension, Integer> dimensionsToIndicesMap | ||
38 | |||
39 | new(Polyhedron polyhedron, boolean lpRelaxation, double timeoutSeconds, boolean silent) { | ||
40 | super(polyhedron) | ||
41 | this.lpRelaxation = lpRelaxation | ||
42 | this.timeoutSeconds = timeoutSeconds | ||
43 | this.silent = silent | ||
44 | val numDimensions = polyhedron.dimensions.size | ||
45 | columnLowerBounds = newDoubleArrayOfSize(numDimensions) | ||
46 | columnUpperBounds = newDoubleArrayOfSize(numDimensions) | ||
47 | objective = newDoubleArrayOfSize(numDimensions) | ||
48 | dimensionsToIndicesMap = ImmutableMap.copyOf(polyhedron.dimensions.indexed.toMap([value], [key])) | ||
49 | } | ||
50 | |||
51 | override doSaturate() { | ||
52 | val numDimensions = polyhedron.dimensions.size | ||
53 | for (var int j = 0; j < numDimensions; j++) { | ||
54 | val dimension = polyhedron.dimensions.get(j) | ||
55 | columnLowerBounds.set(j, dimension.lowerBound.toDouble(Double.NEGATIVE_INFINITY)) | ||
56 | columnUpperBounds.set(j, dimension.upperBound.toDouble(Double.POSITIVE_INFINITY)) | ||
57 | } | ||
58 | val constraints = nonTrivialConstraints | ||
59 | val numConstraints = constraints.size | ||
60 | val rowStarts = newIntArrayOfSize(numConstraints + 1) | ||
61 | val rowLowerBounds = newDoubleArrayOfSize(numConstraints) | ||
62 | val rowUpperBounds = newDoubleArrayOfSize(numConstraints) | ||
63 | val numEntries = constraints.map[coefficients.size].reduce[a, b|a + b] ?: 0 | ||
64 | rowStarts.set(numConstraints, numEntries) | ||
65 | val columnIndices = newIntArrayOfSize(numEntries) | ||
66 | val entries = newDoubleArrayOfSize(numEntries) | ||
67 | val unconstrainedDimensions = new HashSet | ||
68 | for (dimension : polyhedron.dimensions) { | ||
69 | if (dimension.lowerBound === null && dimension.upperBound === null) { | ||
70 | unconstrainedDimensions += dimension | ||
71 | } | ||
72 | } | ||
73 | var int index = 0 | ||
74 | for (var int i = 0; i < numConstraints; i++) { | ||
75 | rowStarts.set(i, index) | ||
76 | val constraint = constraints.get(i) | ||
77 | rowLowerBounds.set(i, constraint.lowerBound.toDouble(Double.NEGATIVE_INFINITY)) | ||
78 | rowUpperBounds.set(i, constraint.upperBound.toDouble(Double.POSITIVE_INFINITY)) | ||
79 | if (!dimensionsToIndicesMap.keySet.containsAll(constraint.coefficients.keySet)) { | ||
80 | throw new IllegalArgumentException("Constrains has unknown dimensions") | ||
81 | } | ||
82 | for (var int j = 0; j < numDimensions; j++) { | ||
83 | val dimension = polyhedron.dimensions.get(j) | ||
84 | val coefficient = constraint.coefficients.get(dimension) | ||
85 | if (coefficient !== null && coefficient != 0) { | ||
86 | unconstrainedDimensions -= dimension | ||
87 | columnIndices.set(index, j) | ||
88 | entries.set(index, coefficient) | ||
89 | index++ | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | if (index != numEntries) { | ||
94 | throw new AssertionError("Last entry does not equal the number of entries in the constraint matrix") | ||
95 | } | ||
96 | for (expressionToSaturate : polyhedron.expressionsToSaturate) { | ||
97 | val result = saturate(expressionToSaturate, rowStarts, columnIndices, entries, rowLowerBounds, | ||
98 | rowUpperBounds, unconstrainedDimensions, constraints) | ||
99 | if (result != PolyhedronSaturationResult.SATURATED) { | ||
100 | return result | ||
101 | } | ||
102 | } | ||
103 | PolyhedronSaturationResult.SATURATED | ||
104 | } | ||
105 | |||
106 | protected def saturate(LinearBoundedExpression expressionToSaturate, int[] rowStarts, int[] columnIndices, | ||
107 | double[] entries, double[] rowLowerBounds, double[] rowUpperBounds, Set<Dimension> unconstrainedDimensions, | ||
108 | ImmutableList<LinearConstraint> constraints) { | ||
109 | val numDimensions = objective.size | ||
110 | for (var int j = 0; j < numDimensions; j++) { | ||
111 | objective.set(j, 0) | ||
112 | } | ||
113 | switch (expressionToSaturate) { | ||
114 | Dimension: { | ||
115 | // CBC will return nonsensical results or call free() with invalid arguments if | ||
116 | // it is passed a fully unconstrained (-Inf lower and +Int upper bound, no inequalities) variable | ||
117 | // in the objective function. | ||
118 | if (unconstrainedDimensions.contains(expressionToSaturate)) { | ||
119 | return PolyhedronSaturationResult.SATURATED | ||
120 | } | ||
121 | val j = getIndex(expressionToSaturate) | ||
122 | objective.set(j, 1) | ||
123 | } | ||
124 | LinearConstraint: { | ||
125 | for (pair : expressionToSaturate.coefficients.entrySet) { | ||
126 | val dimension = pair.key | ||
127 | // We also have to check for unconstrained dimensions here to avoid crashing. | ||
128 | if (unconstrainedDimensions.contains(dimension)) { | ||
129 | expressionToSaturate.lowerBound = null | ||
130 | expressionToSaturate.upperBound = null | ||
131 | return PolyhedronSaturationResult.SATURATED | ||
132 | } | ||
133 | val j = getIndex(dimension) | ||
134 | objective.set(j, pair.value) | ||
135 | } | ||
136 | } | ||
137 | default: | ||
138 | throw new IllegalArgumentException("Unknown expression: " + expressionToSaturate) | ||
139 | } | ||
140 | val minimizationResult = CbcSolver.solve(columnLowerBounds, columnUpperBounds, rowStarts, columnIndices, | ||
141 | entries, rowLowerBounds, rowUpperBounds, objective, lpRelaxation, timeoutSeconds, silent) | ||
142 | switch (minimizationResult) { | ||
143 | CbcResult.SolutionBounded: { | ||
144 | val doubleValue = minimizationResult.value | ||
145 | val roundedValue = Math.ceil(doubleValue - EPSILON) | ||
146 | val intValue = roundedValue as int | ||
147 | val oldBound = expressionToSaturate.lowerBound | ||
148 | if (oldBound === null || intValue >= oldBound) { | ||
149 | expressionToSaturate.lowerBound = intValue | ||
150 | setBound(expressionToSaturate, constraints, roundedValue, columnLowerBounds, rowLowerBounds) | ||
151 | } else { | ||
152 | throw new IllegalStateException("Unexpected decrease of lower bound by " + (oldBound - doubleValue)) | ||
153 | } | ||
154 | } | ||
155 | case CbcResult.SOLUTION_UNBOUNDED: { | ||
156 | if (expressionToSaturate.lowerBound !== null) { | ||
157 | throw new IllegalStateException("Finite lower bound became infinite") | ||
158 | } | ||
159 | setBound(expressionToSaturate, constraints, Double.NEGATIVE_INFINITY, columnLowerBounds, rowLowerBounds) | ||
160 | } | ||
161 | case CbcResult.UNSAT: | ||
162 | return PolyhedronSaturationResult.EMPTY | ||
163 | case CbcResult.ABANDONED, | ||
164 | case CbcResult.TIMEOUT: | ||
165 | return PolyhedronSaturationResult.UNKNOWN | ||
166 | default: | ||
167 | throw new RuntimeException("Unknown CbcResult: " + minimizationResult) | ||
168 | } | ||
169 | for (var int j = 0; j < numDimensions; j++) { | ||
170 | val objectiveCoefficient = objective.get(j) | ||
171 | objective.set(j, -objectiveCoefficient) | ||
172 | } | ||
173 | val maximizationResult = CbcSolver.solve(columnLowerBounds, columnUpperBounds, rowStarts, columnIndices, | ||
174 | entries, rowLowerBounds, rowUpperBounds, objective, lpRelaxation, timeoutSeconds, silent) | ||
175 | switch (maximizationResult) { | ||
176 | CbcResult.SolutionBounded: { | ||
177 | val doubleValue = -maximizationResult.value | ||
178 | val roundedValue = Math.floor(doubleValue + EPSILON) | ||
179 | val intValue = roundedValue as int | ||
180 | val oldBound = expressionToSaturate.upperBound | ||
181 | if (oldBound === null || intValue <= oldBound) { | ||
182 | expressionToSaturate.upperBound = intValue | ||
183 | setBound(expressionToSaturate, constraints, roundedValue, columnUpperBounds, rowUpperBounds) | ||
184 | } else { | ||
185 | throw new IllegalStateException("Unexpected increase of upper bound by " + (doubleValue - oldBound)) | ||
186 | } | ||
187 | } | ||
188 | case CbcResult.SOLUTION_UNBOUNDED: { | ||
189 | if (expressionToSaturate.lowerBound !== null) { | ||
190 | throw new IllegalStateException("Finite upper bound became infinite") | ||
191 | } | ||
192 | expressionToSaturate.upperBound = null | ||
193 | setBound(expressionToSaturate, constraints, Double.POSITIVE_INFINITY, columnUpperBounds, rowUpperBounds) | ||
194 | } | ||
195 | case CbcResult.UNSAT: | ||
196 | if (lpRelaxation) { | ||
197 | return PolyhedronSaturationResult.EMPTY | ||
198 | } else { | ||
199 | throw new RuntimeException("Minimization was SAT, but maximization is UNSAT") | ||
200 | } | ||
201 | case CbcResult.ABANDONED, | ||
202 | case CbcResult.TIMEOUT: | ||
203 | return PolyhedronSaturationResult.UNKNOWN | ||
204 | default: | ||
205 | throw new RuntimeException("Unknown CbcResult: " + maximizationResult) | ||
206 | } | ||
207 | return PolyhedronSaturationResult.SATURATED | ||
208 | } | ||
209 | |||
210 | private def toDouble(Integer nullableInt, double defaultValue) { | ||
211 | if (nullableInt === null) { | ||
212 | defaultValue | ||
213 | } else { | ||
214 | nullableInt.doubleValue | ||
215 | } | ||
216 | } | ||
217 | |||
218 | private def int getIndex(Dimension dimension) { | ||
219 | val index = dimensionsToIndicesMap.get(dimension) | ||
220 | if (index === null) { | ||
221 | throw new IllegalArgumentException("Unknown dimension: " + dimension) | ||
222 | } | ||
223 | index | ||
224 | } | ||
225 | |||
226 | private def void setBound(LinearBoundedExpression expression, List<LinearConstraint> constraints, double bound, | ||
227 | double[] columnBounds, double[] rowBounds) { | ||
228 | switch (expression) { | ||
229 | Dimension: { | ||
230 | val j = getIndex(expression) | ||
231 | columnBounds.set(j, bound) | ||
232 | } | ||
233 | LinearConstraint: { | ||
234 | val i = constraints.indexOf(expression) | ||
235 | if (i >= 0) { | ||
236 | rowBounds.set(i, bound) | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ExtendedLinearExpressionBuilderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ExtendedLinearExpressionBuilderFactory.xtend new file mode 100644 index 00000000..e97fa5d7 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ExtendedLinearExpressionBuilderFactory.xtend | |||
@@ -0,0 +1,140 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import com.google.common.collect.ImmutableMap | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
6 | import java.util.ArrayList | ||
7 | import java.util.HashMap | ||
8 | import java.util.HashSet | ||
9 | import java.util.List | ||
10 | import java.util.Map | ||
11 | import java.util.Set | ||
12 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
13 | import org.eclipse.xtend.lib.annotations.Accessors | ||
14 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
15 | |||
16 | interface BoundSaturationListener { | ||
17 | def void boundsSaturated(Integer lower, Integer upper) | ||
18 | } | ||
19 | |||
20 | interface ExtendedLinearExpressionBuilderFactory { | ||
21 | def ExtendedLinearExpressionBuilder createBuilder() | ||
22 | |||
23 | def Dimension getDimension(IPatternMatch patternMatch) | ||
24 | } | ||
25 | |||
26 | interface ExtendedLinearExpressionBuilder extends LinearTypeExpressionBuilder { | ||
27 | override ExtendedLinearExpressionBuilder add(int scale, Type type) | ||
28 | |||
29 | def ExtendedLinearExpressionBuilder add(int scale, IPatternMatch patternMatch) | ||
30 | |||
31 | def ExtendedLinearExpressionBuilder add(int scale, Dimension dimension) | ||
32 | |||
33 | def LinearBoundedExpression build(BoundSaturationListener listener) | ||
34 | } | ||
35 | |||
36 | class ExtendedPolyhedronBuilder implements ExtendedLinearExpressionBuilderFactory { | ||
37 | val Map<Type, LinearBoundedExpression> typeBounds | ||
38 | val Map<Map<Dimension, Integer>, LinearBoundedExpression> expressionsCache | ||
39 | |||
40 | val ImmutableList.Builder<Dimension> dimensions = ImmutableList.builder | ||
41 | val Set<LinearConstraint> constraints = new HashSet | ||
42 | val Set<LinearBoundedExpression> expressionsToSaturate = new HashSet | ||
43 | val Map<IPatternMatch, Dimension> patternMatchCounts = new HashMap | ||
44 | @Accessors(PUBLIC_GETTER) val List<Pair<LinearBoundedExpression, BoundSaturationListener>> saturationListeners = new ArrayList | ||
45 | |||
46 | new(Polyhedron polyhedron, Map<Type, LinearBoundedExpression> typeBounds, | ||
47 | Map<Map<Dimension, Integer>, LinearBoundedExpression> initialExpressionsCache) { | ||
48 | this.typeBounds = typeBounds | ||
49 | this.expressionsCache = new HashMap(initialExpressionsCache) | ||
50 | dimensions.addAll(polyhedron.dimensions) | ||
51 | constraints.addAll(polyhedron.constraints) | ||
52 | expressionsToSaturate.addAll(polyhedron.expressionsToSaturate) | ||
53 | } | ||
54 | |||
55 | override createBuilder() { | ||
56 | new ExtendedLinearExpressionBuilderImpl(this) | ||
57 | } | ||
58 | |||
59 | override getDimension(IPatternMatch patternMatch) { | ||
60 | patternMatchCounts.computeIfAbsent(patternMatch) [ key | | ||
61 | val dimension = new Dimension(key.toString, 0, null) | ||
62 | dimensions.add(dimension) | ||
63 | dimension | ||
64 | ] | ||
65 | } | ||
66 | |||
67 | def buildPolyhedron() { | ||
68 | new Polyhedron( | ||
69 | dimensions.build, | ||
70 | ImmutableList.copyOf(constraints), | ||
71 | ImmutableList.copyOf(expressionsToSaturate) | ||
72 | ) | ||
73 | } | ||
74 | |||
75 | @FinalFieldsConstructor | ||
76 | private static class ExtendedLinearExpressionBuilderImpl implements ExtendedLinearExpressionBuilder { | ||
77 | val ExtendedPolyhedronBuilder polyhedronBuilder | ||
78 | |||
79 | val Map<Dimension, Integer> coefficients = new HashMap | ||
80 | |||
81 | override add(int scale, Type type) { | ||
82 | val expression = polyhedronBuilder.typeBounds.get(type) | ||
83 | if (expression === null) { | ||
84 | throw new IllegalArgumentException("Unknown Type: " + type) | ||
85 | } | ||
86 | add(scale, expression) | ||
87 | } | ||
88 | |||
89 | override add(int scale, IPatternMatch patternMatch) { | ||
90 | val dimension = polyhedronBuilder.getDimension(patternMatch) | ||
91 | add(scale, dimension) | ||
92 | } | ||
93 | |||
94 | private def add(int scale, LinearBoundedExpression expression) { | ||
95 | switch (expression) { | ||
96 | Dimension: add(scale, expression) | ||
97 | LinearConstraint: add(scale, expression.coefficients) | ||
98 | default: throw new IllegalArgumentException("Unknown LinearBoundedExpression: " + expression) | ||
99 | } | ||
100 | } | ||
101 | |||
102 | private def add(int scale, Map<Dimension, Integer> coefficients) { | ||
103 | for (pair : coefficients.entrySet) { | ||
104 | add(scale * pair.value, pair.key) | ||
105 | } | ||
106 | this | ||
107 | } | ||
108 | |||
109 | override add(int scale, Dimension dimension) { | ||
110 | coefficients.merge(dimension, scale)[a, b|a + b] | ||
111 | this | ||
112 | } | ||
113 | |||
114 | override build() { | ||
115 | val filteredCoefficients = ImmutableMap.copyOf(coefficients.filter [ x, coefficient | | ||
116 | coefficient != 0 | ||
117 | ]) | ||
118 | polyhedronBuilder.expressionsCache.computeIfAbsent(filteredCoefficients) [ map | | ||
119 | if (map.size == 1) { | ||
120 | val pair = map.entrySet.head | ||
121 | if (pair.value == 1) { | ||
122 | return pair.key | ||
123 | } | ||
124 | } | ||
125 | val constraint = new LinearConstraint(map) | ||
126 | polyhedronBuilder.constraints.add(constraint) | ||
127 | constraint | ||
128 | ] | ||
129 | } | ||
130 | |||
131 | override build(BoundSaturationListener listener) { | ||
132 | val expression = build() | ||
133 | if (listener !== null) { | ||
134 | polyhedronBuilder.expressionsToSaturate.add(expression) | ||
135 | polyhedronBuilder.saturationListeners.add(expression -> listener) | ||
136 | } | ||
137 | expression | ||
138 | } | ||
139 | } | ||
140 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ExtendedPolyhedronScopePropagatorStrategy.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ExtendedPolyhedronScopePropagatorStrategy.xtend new file mode 100644 index 00000000..32923396 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ExtendedPolyhedronScopePropagatorStrategy.xtend | |||
@@ -0,0 +1,63 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics | ||
5 | import java.util.Collection | ||
6 | import java.util.Map | ||
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
8 | |||
9 | interface PolyhedronExtensionOperator { | ||
10 | def void extendPolyhedron(ExtendedLinearExpressionBuilderFactory factory) | ||
11 | } | ||
12 | |||
13 | class ExtendedPolyhedronScopePropagatorStrategy extends PolyhedronScopePropagatorStrategy { | ||
14 | val PolyhedronSolver solver | ||
15 | val Collection<PolyhedronExtensionOperator> extensionOperators | ||
16 | |||
17 | var Map<Type, LinearBoundedExpression> typeBounds | ||
18 | var Map<Map<Dimension, Integer>, LinearBoundedExpression> initialExpressionsCache | ||
19 | |||
20 | new(PolyhedronSolver solver, Collection<PolyhedronExtensionOperator> extensionOperators, | ||
21 | ModelGenerationStatistics statistics) { | ||
22 | super(statistics) | ||
23 | this.solver = solver | ||
24 | this.extensionOperators = extensionOperators | ||
25 | } | ||
26 | |||
27 | override setPolyhedron(Polyhedron polyhedron, Map<Type, LinearBoundedExpression> typeBounds, | ||
28 | Map<Map<Dimension, Integer>, LinearBoundedExpression> initialExpressionsCache) { | ||
29 | super.setPolyhedron(polyhedron, typeBounds, initialExpressionsCache) | ||
30 | this.typeBounds = typeBounds | ||
31 | this.initialExpressionsCache = initialExpressionsCache | ||
32 | } | ||
33 | |||
34 | override isRelevantRelation(Relation relation) { | ||
35 | true | ||
36 | } | ||
37 | |||
38 | override protected doSaturate() { | ||
39 | val builder = new ExtendedPolyhedronBuilder(polyhedron, typeBounds, initialExpressionsCache) | ||
40 | for (extensionOperator : extensionOperators) { | ||
41 | extensionOperator.extendPolyhedron(builder) | ||
42 | } | ||
43 | val extendedPolyhedron = builder.buildPolyhedron() | ||
44 | val saturationOperator = solver.createSaturationOperator(extendedPolyhedron) | ||
45 | val result = try { | ||
46 | saturationOperator.saturate() | ||
47 | } finally { | ||
48 | saturationOperator.close() | ||
49 | } | ||
50 | if (result == PolyhedronSaturationResult.EMPTY) { | ||
51 | // The partial model cannot be refined any more, we can't provide objective bounds. | ||
52 | for (pair : builder.saturationListeners) { | ||
53 | pair.value.boundsSaturated(null, null) | ||
54 | } | ||
55 | return false | ||
56 | } | ||
57 | for (pair : builder.saturationListeners) { | ||
58 | val expression = pair.key | ||
59 | pair.value.boundsSaturated(expression.lowerBound, expression.upperBound) | ||
60 | } | ||
61 | true | ||
62 | } | ||
63 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/LinearTypeConstraintHint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/LinearTypeConstraintHint.xtend new file mode 100644 index 00000000..31f98e36 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/LinearTypeConstraintHint.xtend | |||
@@ -0,0 +1,32 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternGenerator | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
6 | import java.util.Map | ||
7 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
8 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
9 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | ||
10 | |||
11 | interface LinearTypeExpressionBuilderFactory { | ||
12 | def ViatraQueryMatcher<? extends IPatternMatch> createMatcher(String queryName) | ||
13 | |||
14 | def LinearTypeExpressionBuilder createBuilder() | ||
15 | } | ||
16 | |||
17 | interface LinearTypeExpressionBuilder { | ||
18 | def LinearTypeExpressionBuilder add(int scale, Type type) | ||
19 | |||
20 | def LinearBoundedExpression build() | ||
21 | } | ||
22 | |||
23 | @FunctionalInterface | ||
24 | interface RelationConstraintUpdater { | ||
25 | def void update(PartialInterpretation p) | ||
26 | } | ||
27 | |||
28 | interface LinearTypeConstraintHint { | ||
29 | def CharSequence getAdditionalPatterns(PatternGenerator patternGenerator, Map<String, PQuery> fqnToPQuery) | ||
30 | |||
31 | def RelationConstraintUpdater createConstraintUpdater(LinearTypeExpressionBuilderFactory builderFactory) | ||
32 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/MultiplicityGoalConstraintCalculator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/MultiplicityGoalConstraintCalculator.xtend new file mode 100644 index 00000000..273e0ac3 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/MultiplicityGoalConstraintCalculator.xtend | |||
@@ -0,0 +1,57 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import org.eclipse.emf.common.notify.Notifier | ||
4 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
5 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
6 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
7 | |||
8 | class MultiplicityGoalConstraintCalculator { | ||
9 | val String targetRelationName | ||
10 | val IQuerySpecification<?> querySpecification | ||
11 | var MultiplicityCalculator<?> calculator | ||
12 | val boolean containment | ||
13 | val int lowerBound | ||
14 | val int cost | ||
15 | |||
16 | new(String targetRelationName, IQuerySpecification<?> querySpecification, boolean containment, int lowerBound, int cost) { | ||
17 | if (lowerBound <= 0) { | ||
18 | throw new IllegalArgumentException("Invalid lower bound: " + lowerBound) | ||
19 | } | ||
20 | this.targetRelationName = targetRelationName | ||
21 | this.querySpecification = querySpecification | ||
22 | this.calculator = null | ||
23 | this.containment = containment | ||
24 | this.lowerBound = lowerBound | ||
25 | this.cost = cost | ||
26 | } | ||
27 | |||
28 | new(MultiplicityGoalConstraintCalculator other) { | ||
29 | this.targetRelationName = other.targetRelationName | ||
30 | this.querySpecification = other.querySpecification | ||
31 | this.calculator = null | ||
32 | this.containment = other.containment | ||
33 | this.lowerBound = other.lowerBound | ||
34 | this.cost = other.cost | ||
35 | } | ||
36 | |||
37 | def getName() { | ||
38 | targetRelationName | ||
39 | } | ||
40 | |||
41 | def isContainment() { | ||
42 | return containment | ||
43 | } | ||
44 | |||
45 | def init(Notifier notifier) { | ||
46 | val engine = ViatraQueryEngine.on(new EMFScope(notifier)) | ||
47 | val matcher = querySpecification.getMatcher(engine) | ||
48 | calculator = RemainingMultiplicityCalculator.of(matcher, lowerBound) | ||
49 | } | ||
50 | |||
51 | def calculateValue() { | ||
52 | val res = calculator.multiplicity | ||
53 | // if(res>0) | ||
54 | // println(targetRelationName+ " all missing multiplicities: "+res + "*"+cost+"="+res*cost) | ||
55 | return res*cost | ||
56 | } | ||
57 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagator.xtend new file mode 100644 index 00000000..ad8f94ab --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagator.xtend | |||
@@ -0,0 +1,522 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import com.google.common.collect.ImmutableMap | ||
5 | import com.google.common.collect.ImmutableSet | ||
6 | import com.google.common.collect.Maps | ||
7 | import com.google.common.collect.Sets | ||
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics | ||
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.UnifinishedMultiplicityQueries | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope | ||
16 | import java.util.ArrayDeque | ||
17 | import java.util.ArrayList | ||
18 | import java.util.Collection | ||
19 | import java.util.HashMap | ||
20 | import java.util.HashSet | ||
21 | import java.util.List | ||
22 | import java.util.Map | ||
23 | import java.util.Set | ||
24 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
25 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
26 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
27 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
28 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
29 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
30 | |||
31 | class PolyhedronScopePropagator extends TypeHierarchyScopePropagator { | ||
32 | val boolean updateHeuristic | ||
33 | val Map<Scope, LinearBoundedExpression> scopeBounds | ||
34 | val LinearBoundedExpression topLevelBounds | ||
35 | val Polyhedron polyhedron | ||
36 | val PolyhedronScopePropagatorStrategy strategy | ||
37 | val Set<Relation> relevantRelations | ||
38 | List<RelationConstraintUpdater> updaters = emptyList | ||
39 | |||
40 | new(PartialInterpretation p, ModelGenerationStatistics statistics, Set<? extends Type> possibleNewDynamicTypes, | ||
41 | Map<RelationMultiplicityConstraint, UnifinishedMultiplicityQueries> unfinishedMultiplicityQueries, | ||
42 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hasElementInContainmentQuery, | ||
43 | Map<String, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allPatternsByName, | ||
44 | Collection<LinearTypeConstraintHint> hints, PolyhedronScopePropagatorStrategy strategy, | ||
45 | boolean propagateRelations, boolean updateHeuristic) { | ||
46 | super(p, statistics) | ||
47 | this.updateHeuristic = updateHeuristic | ||
48 | this.strategy = strategy | ||
49 | val builder = new PolyhedronBuilder(p) | ||
50 | builder.buildPolyhedron(possibleNewDynamicTypes) | ||
51 | scopeBounds = builder.scopeBounds | ||
52 | topLevelBounds = builder.topLevelBounds | ||
53 | polyhedron = builder.polyhedron | ||
54 | strategy.setPolyhedron(polyhedron, builder.typeBounds, builder.expressionsCache) | ||
55 | propagateAllScopeConstraints() | ||
56 | if (propagateRelations) { | ||
57 | val maximumNumberOfNewNodes = topLevelBounds.upperBound | ||
58 | if (maximumNumberOfNewNodes === null) { | ||
59 | throw new IllegalStateException("Could not determine maximum number of new nodes, it may be unbounded") | ||
60 | } | ||
61 | if (maximumNumberOfNewNodes <= 0) { | ||
62 | throw new IllegalStateException("Maximum number of new nodes is not positive") | ||
63 | } | ||
64 | builder.buildMultiplicityConstraints(unfinishedMultiplicityQueries, hasElementInContainmentQuery, | ||
65 | allPatternsByName, hints, maximumNumberOfNewNodes) | ||
66 | relevantRelations = builder.relevantRelations | ||
67 | updaters = builder.updaters | ||
68 | } else { | ||
69 | relevantRelations = emptySet | ||
70 | } | ||
71 | } | ||
72 | |||
73 | override void doPropagateAllScopeConstraints() { | ||
74 | super.doPropagateAllScopeConstraints() | ||
75 | resetBounds() | ||
76 | populatePolyhedronFromScope() | ||
77 | // println(polyhedron) | ||
78 | if (strategy.saturate) { | ||
79 | populateScopesFromPolyhedron() | ||
80 | } else { | ||
81 | setScopesInvalid() | ||
82 | } | ||
83 | // println(polyhedron) | ||
84 | if (updateHeuristic) { | ||
85 | copyScopeBoundsToHeuristic() | ||
86 | } | ||
87 | } | ||
88 | |||
89 | override isPropagationNeededAfterAdditionToRelation(Relation r) { | ||
90 | relevantRelations.contains(r) || strategy.isRelevantRelation(r) || super.isPropagationNeededAfterAdditionToRelation(r) | ||
91 | } | ||
92 | |||
93 | override isQueryEngineFlushRequiredBeforePropagation() { | ||
94 | true | ||
95 | } | ||
96 | |||
97 | def resetBounds() { | ||
98 | for (dimension : polyhedron.dimensions) { | ||
99 | dimension.lowerBound = 0 | ||
100 | dimension.upperBound = null | ||
101 | } | ||
102 | for (constraint : polyhedron.constraints) { | ||
103 | constraint.lowerBound = null | ||
104 | constraint.upperBound = null | ||
105 | } | ||
106 | } | ||
107 | |||
108 | private def populatePolyhedronFromScope() { | ||
109 | topLevelBounds.tightenLowerBound(partialInterpretation.minNewElements) | ||
110 | if (partialInterpretation.maxNewElements >= 0) { | ||
111 | topLevelBounds.tightenUpperBound(partialInterpretation.maxNewElements) | ||
112 | } | ||
113 | for (pair : scopeBounds.entrySet) { | ||
114 | val scope = pair.key | ||
115 | val bounds = pair.value | ||
116 | bounds.tightenLowerBound(scope.minNewElements) | ||
117 | if (scope.maxNewElements >= 0) { | ||
118 | bounds.tightenUpperBound(scope.maxNewElements) | ||
119 | } | ||
120 | } | ||
121 | for (updater : updaters) { | ||
122 | updater.update(partialInterpretation) | ||
123 | } | ||
124 | } | ||
125 | |||
126 | private def populateScopesFromPolyhedron() { | ||
127 | checkBounds(topLevelBounds) | ||
128 | if (partialInterpretation.minNewElements > topLevelBounds.lowerBound) { | ||
129 | throw new IllegalArgumentException('''Lower bound of «topLevelBounds» smaller than top-level scope: «partialInterpretation.minNewElements»''') | ||
130 | } else if (partialInterpretation.minNewElements != topLevelBounds.lowerBound) { | ||
131 | partialInterpretation.minNewElements = topLevelBounds.lowerBound | ||
132 | } | ||
133 | val topLevelUpperBound = topLevelBounds.upperBound ?: -1 | ||
134 | if (partialInterpretation.maxNewElements >= 0 && topLevelUpperBound >= 0 && | ||
135 | partialInterpretation.maxNewElements < topLevelUpperBound) { | ||
136 | throw new IllegalArgumentException('''Upper bound of «topLevelBounds» larger than top-level scope: «partialInterpretation.maxNewElements»''') | ||
137 | } else if (partialInterpretation.maxNewElements != topLevelUpperBound) { | ||
138 | partialInterpretation.maxNewElements = topLevelUpperBound | ||
139 | } | ||
140 | for (pair : scopeBounds.entrySet) { | ||
141 | val scope = pair.key | ||
142 | val bounds = pair.value | ||
143 | checkBounds(bounds) | ||
144 | if (scope.minNewElements > bounds.lowerBound) { | ||
145 | throw new IllegalArgumentException('''Lower bound of «bounds» smaller than «scope.targetTypeInterpretation» scope: «scope.minNewElements»''') | ||
146 | } else if (scope.minNewElements != bounds.lowerBound) { | ||
147 | scope.minNewElements = bounds.lowerBound | ||
148 | } | ||
149 | val upperBound = bounds.upperBound ?: -1 | ||
150 | if (scope.maxNewElements >= 0 && upperBound >= 0 && scope.maxNewElements < upperBound) { | ||
151 | throw new IllegalArgumentException('''Upper bound of «bounds» larger than «scope.targetTypeInterpretation» scope: «scope.maxNewElements»''') | ||
152 | } else if (scope.maxNewElements != upperBound) { | ||
153 | scope.maxNewElements = upperBound | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | private def checkBounds(LinearBoundedExpression bounds) { | ||
159 | if (bounds.lowerBound === null) { | ||
160 | throw new IllegalArgumentException("Infinite lower bound: " + bounds) | ||
161 | } else if (bounds.lowerBound < 0) { | ||
162 | throw new IllegalArgumentException("Negative lower bound: " + bounds) | ||
163 | } | ||
164 | if (bounds.upperBound !== null && bounds.upperBound < 0) { | ||
165 | throw new IllegalArgumentException("Negative upper bound: " + bounds) | ||
166 | } | ||
167 | } | ||
168 | |||
169 | @FinalFieldsConstructor | ||
170 | private static class PolyhedronBuilder implements LinearTypeExpressionBuilderFactory { | ||
171 | static val INFINITY_SCALE = 10 | ||
172 | |||
173 | val PartialInterpretation p | ||
174 | |||
175 | Map<Type, Dimension> instanceCounts | ||
176 | Map<Type, Map<Dimension, Integer>> subtypeDimensions | ||
177 | Map<Map<Dimension, Integer>, LinearBoundedExpression> expressionsCache | ||
178 | Map<Type, LinearBoundedExpression> typeBounds | ||
179 | int infinity | ||
180 | ViatraQueryEngine queryEngine | ||
181 | Map<String, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allPatternsByName | ||
182 | ImmutableList.Builder<RelationConstraintUpdater> updatersBuilder | ||
183 | |||
184 | Map<Scope, LinearBoundedExpression> scopeBounds | ||
185 | LinearBoundedExpression topLevelBounds | ||
186 | Polyhedron polyhedron | ||
187 | Set<Relation> relevantRelations | ||
188 | List<RelationConstraintUpdater> updaters | ||
189 | |||
190 | def buildPolyhedron(Set<? extends Type> possibleNewDynamicTypes) { | ||
191 | instanceCounts = possibleNewDynamicTypes.toInvertedMap[new Dimension(name, 0, null)] | ||
192 | val types = p.problem.types | ||
193 | expressionsCache = Maps.newHashMapWithExpectedSize(types.size) | ||
194 | subtypeDimensions = types.toInvertedMap[findSubtypeDimensions.toInvertedMap[1]] | ||
195 | typeBounds = ImmutableMap.copyOf(subtypeDimensions.mapValues[toExpression]) | ||
196 | scopeBounds = buildScopeBounds | ||
197 | topLevelBounds = instanceCounts.values.toInvertedMap[1].toExpression | ||
198 | val dimensions = ImmutableList.copyOf(instanceCounts.values) | ||
199 | val expressionsToSaturate = ImmutableList.copyOf(scopeBounds.values) | ||
200 | polyhedron = new Polyhedron(dimensions, new ArrayList, expressionsToSaturate) | ||
201 | addCachedConstraintsToPolyhedron() | ||
202 | } | ||
203 | |||
204 | def buildMultiplicityConstraints( | ||
205 | Map<RelationMultiplicityConstraint, UnifinishedMultiplicityQueries> constraints, | ||
206 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hasElementInContainmentQuery, | ||
207 | Map<String, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allPatternsByName, | ||
208 | Collection<LinearTypeConstraintHint> hints, int maximumNuberOfNewNodes) { | ||
209 | infinity = if (maximumNuberOfNewNodes <= Integer.MAX_VALUE / INFINITY_SCALE) { | ||
210 | maximumNuberOfNewNodes * INFINITY_SCALE | ||
211 | } else { | ||
212 | Integer.MAX_VALUE | ||
213 | } | ||
214 | |||
215 | queryEngine = ViatraQueryEngine.on(new EMFScope(p)) | ||
216 | this.allPatternsByName = allPatternsByName | ||
217 | updatersBuilder = ImmutableList.builder | ||
218 | val containmentConstraints = constraints.entrySet.filter[key.containment].groupBy[key.targetType] | ||
219 | for (pair : containmentConstraints.entrySet) { | ||
220 | buildContainmentConstraints(pair.key, pair.value) | ||
221 | } | ||
222 | buildConstainmentRootConstraints(containmentConstraints.keySet, hasElementInContainmentQuery) | ||
223 | for (pair : constraints.entrySet) { | ||
224 | val constraint = pair.key | ||
225 | if (!constraint.containment && !constraint.container) { | ||
226 | buildNonContainmentConstraints(constraint, pair.value) | ||
227 | } | ||
228 | } | ||
229 | buildRelevantRelations(constraints.keySet) | ||
230 | for (hint : hints) { | ||
231 | val updater = hint.createConstraintUpdater(this) | ||
232 | if (updater !== null) { | ||
233 | updatersBuilder.add(updater) | ||
234 | } | ||
235 | } | ||
236 | updaters = updatersBuilder.build | ||
237 | addCachedConstraintsToPolyhedron() | ||
238 | } | ||
239 | |||
240 | private def buildRelevantRelations(Set<RelationMultiplicityConstraint> constraints) { | ||
241 | val builder = ImmutableSet.builder | ||
242 | for (constraint : constraints) { | ||
243 | builder.add(constraint.relation) | ||
244 | if (constraint.inverseRelation !== null) { | ||
245 | builder.add(constraint.inverseRelation) | ||
246 | } | ||
247 | } | ||
248 | relevantRelations = builder.build | ||
249 | } | ||
250 | |||
251 | private def addCachedConstraintsToPolyhedron() { | ||
252 | val constraints = new HashSet | ||
253 | constraints.addAll(expressionsCache.values.filter(LinearConstraint)) | ||
254 | constraints.removeAll(polyhedron.constraints) | ||
255 | polyhedron.constraints.addAll(constraints) | ||
256 | } | ||
257 | |||
258 | private def buildContainmentConstraints(Type containedType, | ||
259 | List<Map.Entry<RelationMultiplicityConstraint, UnifinishedMultiplicityQueries>> constraints) { | ||
260 | val typeCoefficients = subtypeDimensions.get(containedType) | ||
261 | val orphansLowerBoundCoefficients = new HashMap(typeCoefficients) | ||
262 | val orphansUpperBoundCoefficients = new HashMap(typeCoefficients) | ||
263 | val unfinishedMultiplicitiesBuilder = ImmutableList.builder | ||
264 | val remainingContentsBuilder = ImmutableList.builder | ||
265 | for (pair : constraints) { | ||
266 | val constraint = pair.key | ||
267 | val containerCoefficients = subtypeDimensions.get(constraint.sourceType) | ||
268 | if (constraint.isUpperBoundFinite) { | ||
269 | orphansLowerBoundCoefficients.addCoefficients(-constraint.upperBound, containerCoefficients) | ||
270 | } else { | ||
271 | orphansLowerBoundCoefficients.addCoefficients(-infinity, containerCoefficients) | ||
272 | } | ||
273 | orphansUpperBoundCoefficients.addCoefficients(-constraint.lowerBound, containerCoefficients) | ||
274 | val queries = pair.value | ||
275 | if (queries.existingMultiplicityQuery !== null) { | ||
276 | val matcher = queries.existingMultiplicityQuery.getMatcher(queryEngine) | ||
277 | if (constraint.constrainsUnfinished) { | ||
278 | unfinishedMultiplicitiesBuilder.add( | ||
279 | RemainingMultiplicityCalculator.of(matcher, constraint.lowerBound)) | ||
280 | } | ||
281 | remainingContentsBuilder.add(RemainingMultiplicityCalculator.of(matcher, constraint.upperBound)) | ||
282 | } else if (constraint.constrainsUnfinished) { | ||
283 | throw new IllegalArgumentException("Containment constraints need multiplicity queries") | ||
284 | } | ||
285 | } | ||
286 | val orphanLowerBound = orphansLowerBoundCoefficients.toExpression | ||
287 | val orphanUpperBound = orphansUpperBoundCoefficients.toExpression | ||
288 | val updater = new ContainmentConstraintUpdater(orphanLowerBound, orphanUpperBound, | ||
289 | unfinishedMultiplicitiesBuilder.build, remainingContentsBuilder.build) | ||
290 | updatersBuilder.add(updater) | ||
291 | } | ||
292 | |||
293 | private def buildConstainmentRootConstraints(Set<Type> containedTypes, | ||
294 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hasElementInContainmentQuery) { | ||
295 | val matcher = hasElementInContainmentQuery.getMatcher(queryEngine) | ||
296 | val rootDimensions = Sets.newHashSet(instanceCounts.values) | ||
297 | for (type : containedTypes) { | ||
298 | val containedDimensions = subtypeDimensions.get(type).keySet | ||
299 | rootDimensions.removeAll(containedDimensions) | ||
300 | } | ||
301 | for (dimension : rootDimensions) { | ||
302 | updatersBuilder.add(new ContainmentRootConstraintUpdater(dimension, matcher)) | ||
303 | } | ||
304 | } | ||
305 | |||
306 | private def buildNonContainmentConstraints(RelationMultiplicityConstraint constraint, | ||
307 | UnifinishedMultiplicityQueries queries) { | ||
308 | if (!constraint.reference) { | ||
309 | return | ||
310 | } | ||
311 | if (constraint.constrainsRemainingInverse) { | ||
312 | if (queries.getExistingMultiplicityQuery === null) { | ||
313 | throw new IllegalArgumentException("Reference constraints need unfinished multiplicity queries: " + | ||
314 | constraint.relation) | ||
315 | } | ||
316 | val existingMultiplicityMatcher = queries.getExistingMultiplicityQuery.getMatcher(queryEngine) | ||
317 | val unfinishedMultiplicityCalculator = RemainingMultiplicityCalculator.of(existingMultiplicityMatcher, | ||
318 | constraint.lowerBound) | ||
319 | val existingInverseMultiplicityMatcher = queries.existingInverseMultiplicityQuery.getMatcher( | ||
320 | queryEngine) | ||
321 | val remainingInverseMultiplicityCalculator = new RemainingInverseMultiplicityCalculator( | ||
322 | existingInverseMultiplicityMatcher, constraint.upperBound) | ||
323 | val availableMultiplicityCoefficients = new HashMap | ||
324 | availableMultiplicityCoefficients.addCoefficients(constraint.inverseUpperBound, | ||
325 | subtypeDimensions.get(constraint.targetType)) | ||
326 | availableMultiplicityCoefficients.addCoefficients(-constraint.lowerBound, | ||
327 | subtypeDimensions.get(constraint.targetType)) | ||
328 | val availableMultiplicity = availableMultiplicityCoefficients.toExpression | ||
329 | updatersBuilder.add( | ||
330 | new UnfinishedMultiplicityConstraintUpdater(availableMultiplicity, unfinishedMultiplicityCalculator, | ||
331 | remainingInverseMultiplicityCalculator)) | ||
332 | } | ||
333 | if (constraint.constrainsUnrepairable) { | ||
334 | if (queries.existingMultiplicityQuery.parameters.size < 5) { | ||
335 | throw new IllegalArgumentException("Reference constraints need repairable multiplicity queries: " + | ||
336 | constraint.relation) | ||
337 | } | ||
338 | val matcher = queries.existingMultiplicityQuery.getMatcher(queryEngine) | ||
339 | val calculator = new UnrepairableMultiplicityCalculator(matcher, constraint.lowerBound) | ||
340 | val targetTypeCardinality = typeBounds.get(constraint.targetType) | ||
341 | updatersBuilder.add(new UnrepairableMultiplicityConstraintUpdater(targetTypeCardinality, calculator)) | ||
342 | } | ||
343 | } | ||
344 | |||
345 | private static def addCoefficients(Map<Dimension, Integer> accumulator, int scale, Map<Dimension, Integer> a) { | ||
346 | for (pair : a.entrySet) { | ||
347 | val dimension = pair.key | ||
348 | val currentValue = accumulator.get(pair.key) ?: 0 | ||
349 | val newValue = currentValue + scale * pair.value | ||
350 | if (newValue == 0) { | ||
351 | accumulator.remove(dimension) | ||
352 | } else { | ||
353 | accumulator.put(dimension, newValue) | ||
354 | } | ||
355 | } | ||
356 | } | ||
357 | |||
358 | private def findSubtypeDimensions(Type type) { | ||
359 | val subtypes = new HashSet | ||
360 | val dimensions = new HashSet | ||
361 | val stack = new ArrayDeque | ||
362 | stack.addLast(type) | ||
363 | while (!stack.empty) { | ||
364 | val subtype = stack.removeLast | ||
365 | if (subtypes.add(subtype)) { | ||
366 | val dimension = instanceCounts.get(subtype) | ||
367 | if (dimension !== null) { | ||
368 | dimensions.add(dimension) | ||
369 | } | ||
370 | stack.addAll(subtype.subtypes) | ||
371 | } | ||
372 | } | ||
373 | dimensions | ||
374 | } | ||
375 | |||
376 | private def toExpression(Map<Dimension, Integer> coefficients) { | ||
377 | expressionsCache.computeIfAbsent(coefficients) [ c | | ||
378 | if (c.size == 1 && c.entrySet.head.value == 1) { | ||
379 | c.entrySet.head.key | ||
380 | } else { | ||
381 | new LinearConstraint(c, null, null) | ||
382 | } | ||
383 | ] | ||
384 | } | ||
385 | |||
386 | private def buildScopeBounds() { | ||
387 | val scopeBoundsBuilder = ImmutableMap.builder | ||
388 | for (scope : p.scopes) { | ||
389 | switch (targetTypeInterpretation : scope.targetTypeInterpretation) { | ||
390 | PartialPrimitiveInterpretation: | ||
391 | throw new IllegalStateException("Primitive type scopes are not yet implemented") | ||
392 | PartialComplexTypeInterpretation: { | ||
393 | val complexType = targetTypeInterpretation.interpretationOf | ||
394 | val typeBound = typeBounds.get(complexType) | ||
395 | if (typeBound === null) { | ||
396 | if (scope.minNewElements > 0) { | ||
397 | throw new IllegalArgumentException("Found scope for " + complexType.name + | ||
398 | ", but the type cannot be instantiated") | ||
399 | } | ||
400 | } else { | ||
401 | scopeBoundsBuilder.put(scope, typeBound) | ||
402 | } | ||
403 | } | ||
404 | default: | ||
405 | throw new IllegalArgumentException("Unknown PartialTypeInterpretation: " + | ||
406 | targetTypeInterpretation) | ||
407 | } | ||
408 | } | ||
409 | scopeBoundsBuilder.build | ||
410 | } | ||
411 | |||
412 | override createMatcher(String queryName) { | ||
413 | val querySpecification = allPatternsByName.get(queryName) | ||
414 | if (querySpecification === null) { | ||
415 | throw new IllegalArgumentException("Unknown pattern: " + queryName) | ||
416 | } | ||
417 | querySpecification.getMatcher(queryEngine) | ||
418 | } | ||
419 | |||
420 | override createBuilder() { | ||
421 | new PolyhedronBuilderLinearTypeExpressionBuilder(this) | ||
422 | } | ||
423 | } | ||
424 | |||
425 | @FinalFieldsConstructor | ||
426 | private static class PolyhedronBuilderLinearTypeExpressionBuilder implements LinearTypeExpressionBuilder { | ||
427 | val PolyhedronBuilder polyhedronBuilder | ||
428 | val Map<Dimension, Integer> coefficients = new HashMap | ||
429 | |||
430 | override add(int scale, Type type) { | ||
431 | val typeCoefficients = polyhedronBuilder.subtypeDimensions.get(type) | ||
432 | if (typeCoefficients === null) { | ||
433 | throw new IllegalArgumentException("Unknown type: " + type) | ||
434 | } | ||
435 | PolyhedronBuilder.addCoefficients(coefficients, scale, typeCoefficients) | ||
436 | this | ||
437 | } | ||
438 | |||
439 | override build() { | ||
440 | polyhedronBuilder.toExpression(coefficients) | ||
441 | } | ||
442 | } | ||
443 | |||
444 | @FinalFieldsConstructor | ||
445 | private static class ContainmentConstraintUpdater implements RelationConstraintUpdater { | ||
446 | val LinearBoundedExpression orphansLowerBound | ||
447 | val LinearBoundedExpression orphansUpperBound | ||
448 | val List<MultiplicityCalculator<? extends IPatternMatch>> unfinishedMultiplicities | ||
449 | val List<MultiplicityCalculator<? extends IPatternMatch>> remainingContents | ||
450 | |||
451 | override update(PartialInterpretation p) { | ||
452 | tightenLowerBound(p) | ||
453 | tightenUpperBound(p) | ||
454 | } | ||
455 | |||
456 | private def tightenLowerBound(PartialInterpretation p) { | ||
457 | var int sum = 0 | ||
458 | for (calculator : remainingContents) { | ||
459 | val value = calculator.getMultiplicity(p) | ||
460 | if (value < 0) { | ||
461 | // Infinite upper bound, no need to tighten. | ||
462 | return | ||
463 | } | ||
464 | sum += value | ||
465 | } | ||
466 | orphansLowerBound.tightenUpperBound(sum) | ||
467 | } | ||
468 | |||
469 | private def tightenUpperBound(PartialInterpretation p) { | ||
470 | var int sum = 0 | ||
471 | for (calculator : unfinishedMultiplicities) { | ||
472 | val value = calculator.getMultiplicity(p) | ||
473 | sum += value | ||
474 | } | ||
475 | orphansUpperBound.tightenLowerBound(sum) | ||
476 | } | ||
477 | } | ||
478 | |||
479 | @FinalFieldsConstructor | ||
480 | private static class ContainmentRootConstraintUpdater implements RelationConstraintUpdater { | ||
481 | val LinearBoundedExpression typeCardinality | ||
482 | val ViatraQueryMatcher<? extends IPatternMatch> hasElementInContainmentMatcher | ||
483 | |||
484 | override update(PartialInterpretation p) { | ||
485 | if (hasElementInContainmentMatcher.hasMatch(p)) { | ||
486 | typeCardinality.tightenUpperBound(0) | ||
487 | } else { | ||
488 | typeCardinality.tightenUpperBound(1) | ||
489 | } | ||
490 | } | ||
491 | |||
492 | private static def <T extends IPatternMatch> hasMatch(ViatraQueryMatcher<T> matcher, PartialInterpretation p) { | ||
493 | val match = matcher.newMatch(p.problem, p) | ||
494 | matcher.countMatches(match) != 0 | ||
495 | } | ||
496 | } | ||
497 | |||
498 | @FinalFieldsConstructor | ||
499 | private static class UnfinishedMultiplicityConstraintUpdater implements RelationConstraintUpdater { | ||
500 | val LinearBoundedExpression availableMultiplicityExpression | ||
501 | val MultiplicityCalculator<? extends IPatternMatch> unfinishedMultiplicityCalculator | ||
502 | val MultiplicityCalculator<? extends IPatternMatch> remainingInverseMultiplcityCalculator | ||
503 | |||
504 | override update(PartialInterpretation p) { | ||
505 | val unfinishedMultiplicity = unfinishedMultiplicityCalculator.getMultiplicity(p) | ||
506 | val remainingInverseMultiplicity = remainingInverseMultiplcityCalculator.getMultiplicity(p) | ||
507 | val int requiredMultiplicity = unfinishedMultiplicity - remainingInverseMultiplicity | ||
508 | availableMultiplicityExpression.tightenLowerBound(requiredMultiplicity) | ||
509 | } | ||
510 | } | ||
511 | |||
512 | @FinalFieldsConstructor | ||
513 | private static class UnrepairableMultiplicityConstraintUpdater implements RelationConstraintUpdater { | ||
514 | val LinearBoundedExpression targetCardinalityExpression | ||
515 | val MultiplicityCalculator<? extends IPatternMatch> calculator | ||
516 | |||
517 | override update(PartialInterpretation p) { | ||
518 | val value = calculator.getMultiplicity(p) | ||
519 | targetCardinalityExpression.tightenLowerBound(value) | ||
520 | } | ||
521 | } | ||
522 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagatorStrategy.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagatorStrategy.xtend new file mode 100644 index 00000000..f93dcd18 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagatorStrategy.xtend | |||
@@ -0,0 +1,92 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import com.google.common.cache.Cache | ||
4 | import com.google.common.cache.CacheBuilder | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics | ||
8 | import java.util.Map | ||
9 | import org.eclipse.xtend.lib.annotations.Accessors | ||
10 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
11 | |||
12 | @FinalFieldsConstructor | ||
13 | abstract class PolyhedronScopePropagatorStrategy { | ||
14 | val ModelGenerationStatistics statistics | ||
15 | |||
16 | @Accessors(PUBLIC_GETTER) var Polyhedron polyhedron | ||
17 | |||
18 | def void setPolyhedron(Polyhedron polyhedron, Map<Type, LinearBoundedExpression> typeBounds, | ||
19 | Map<Map<Dimension, Integer>, LinearBoundedExpression> initialExpressionsCache) { | ||
20 | if (this.polyhedron !== null) { | ||
21 | throw new IllegalStateException("polyhedron was already set") | ||
22 | } | ||
23 | this.polyhedron = polyhedron | ||
24 | initialize() | ||
25 | } | ||
26 | |||
27 | def boolean saturate() { | ||
28 | if (polyhedron === null) { | ||
29 | throw new IllegalStateException("polyhedron was not set") | ||
30 | } | ||
31 | doSaturate() | ||
32 | } | ||
33 | |||
34 | def boolean isRelevantRelation(Relation relation) { | ||
35 | false | ||
36 | } | ||
37 | |||
38 | protected def incrementScopePropagationSolverCount() { | ||
39 | statistics.incrementScopePropagationSolverCount() | ||
40 | } | ||
41 | |||
42 | protected def void initialize() { | ||
43 | } | ||
44 | |||
45 | protected def boolean doSaturate() | ||
46 | } | ||
47 | |||
48 | @FinalFieldsConstructor | ||
49 | class CachingSimplePolyhedronScopePropagatorStrategy extends PolyhedronScopePropagatorStrategy { | ||
50 | static val CACHE_SIZE = 10000 | ||
51 | |||
52 | val PolyhedronSolver solver | ||
53 | |||
54 | val Cache<PolyhedronSignature, PolyhedronSignature> cache = CacheBuilder.newBuilder.maximumSize(CACHE_SIZE).build | ||
55 | var PolyhedronSaturationOperator operator | ||
56 | |||
57 | new(PolyhedronSolver solver, ModelGenerationStatistics statistics) { | ||
58 | super(statistics) | ||
59 | this.solver = solver | ||
60 | } | ||
61 | |||
62 | override protected initialize() { | ||
63 | operator = solver.createSaturationOperator(polyhedron) | ||
64 | } | ||
65 | |||
66 | override protected doSaturate() { | ||
67 | val signature = polyhedron.createSignature | ||
68 | val cachedSignature = cache.getIfPresent(signature) | ||
69 | switch (cachedSignature) { | ||
70 | case null: { | ||
71 | incrementScopePropagationSolverCount() | ||
72 | val result = operator.saturate() | ||
73 | if (result == PolyhedronSaturationResult.EMPTY) { | ||
74 | cache.put(signature, PolyhedronSignature.EMPTY) | ||
75 | false | ||
76 | } else { | ||
77 | val resultSignature = polyhedron.createSignature | ||
78 | cache.put(signature, resultSignature) | ||
79 | true | ||
80 | } | ||
81 | } | ||
82 | case PolyhedronSignature.EMPTY: | ||
83 | false | ||
84 | PolyhedronSignature.Bounds: { | ||
85 | polyhedron.applySignature(signature) | ||
86 | true | ||
87 | } | ||
88 | default: | ||
89 | throw new IllegalStateException("Unknown polyhedron signature: " + signature) | ||
90 | } | ||
91 | } | ||
92 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronSolver.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronSolver.xtend new file mode 100644 index 00000000..21bd2d9e --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronSolver.xtend | |||
@@ -0,0 +1,186 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import java.util.List | ||
4 | import java.util.Map | ||
5 | import org.eclipse.xtend.lib.annotations.Accessors | ||
6 | import org.eclipse.xtend.lib.annotations.Data | ||
7 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
8 | |||
9 | interface PolyhedronSolver { | ||
10 | def PolyhedronSaturationOperator createSaturationOperator(Polyhedron polyhedron) | ||
11 | } | ||
12 | |||
13 | enum PolyhedronSaturationResult { | ||
14 | SATURATED, | ||
15 | EMPTY, | ||
16 | UNKNOWN | ||
17 | } | ||
18 | |||
19 | interface PolyhedronSaturationOperator extends AutoCloseable { | ||
20 | def Polyhedron getPolyhedron() | ||
21 | |||
22 | def PolyhedronSaturationResult saturate() | ||
23 | } | ||
24 | |||
25 | @FinalFieldsConstructor | ||
26 | @Accessors | ||
27 | class Polyhedron { | ||
28 | /** | ||
29 | * The list of dimensions (variables) for this polyhedron. | ||
30 | * | ||
31 | * This list must not be modified after the polyhedron was created. | ||
32 | * However, lower and upper bounds of the dimensions may be changed. | ||
33 | * | ||
34 | * Names of dimensions in this list are assumed to be unique. | ||
35 | */ | ||
36 | val List<Dimension> dimensions | ||
37 | |||
38 | /** | ||
39 | * The list of constraints defining this polyhedron. | ||
40 | * | ||
41 | * The list and its elements may be freely modified. | ||
42 | */ | ||
43 | val List<LinearConstraint> constraints | ||
44 | |||
45 | /** | ||
46 | * The list of constraints that should be saturated (tightened) | ||
47 | * when a {@link PolyhedronSaturationOperator} is invoked. | ||
48 | * | ||
49 | * This list may be freely modified. | ||
50 | * | ||
51 | * Place all dimensions and constraints here to saturate all the bounds. | ||
52 | */ | ||
53 | val List<LinearBoundedExpression> expressionsToSaturate | ||
54 | |||
55 | override toString() ''' | ||
56 | Dimensions: | ||
57 | «FOR dimension : dimensions» | ||
58 | «dimension» | ||
59 | «ENDFOR» | ||
60 | Constraints: | ||
61 | «FOR constraint : constraints» | ||
62 | «constraint» | ||
63 | «ENDFOR» | ||
64 | ''' | ||
65 | |||
66 | def createSignature() { | ||
67 | val size = dimensions.size + constraints.size | ||
68 | val lowerBounds = newArrayOfSize(size) | ||
69 | val upperBounds = newArrayOfSize(size) | ||
70 | var int i = 0 | ||
71 | for (dimension : dimensions) { | ||
72 | lowerBounds.set(i, dimension.lowerBound) | ||
73 | upperBounds.set(i, dimension.upperBound) | ||
74 | i++ | ||
75 | } | ||
76 | for (constraint : constraints) { | ||
77 | lowerBounds.set(i, constraint.lowerBound) | ||
78 | upperBounds.set(i, constraint.upperBound) | ||
79 | i++ | ||
80 | } | ||
81 | new PolyhedronSignature.Bounds(lowerBounds, upperBounds) | ||
82 | } | ||
83 | |||
84 | def applySignature(PolyhedronSignature.Bounds signature) { | ||
85 | val lowerBounds = signature.lowerBounds | ||
86 | val upperBounds = signature.upperBounds | ||
87 | var int i = 0 | ||
88 | for (dimension : dimensions) { | ||
89 | dimension.lowerBound = lowerBounds.get(i) | ||
90 | dimension.upperBound = upperBounds.get(i) | ||
91 | i++ | ||
92 | } | ||
93 | for (constraint : constraints) { | ||
94 | constraint.lowerBound = lowerBounds.get(i) | ||
95 | constraint.upperBound = upperBounds.get(i) | ||
96 | i++ | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | abstract class PolyhedronSignature { | ||
102 | public static val EMPTY = new PolyhedronSignature { | ||
103 | override toString() { | ||
104 | "PolyhedronSignature.EMPTY" | ||
105 | } | ||
106 | } | ||
107 | |||
108 | private new() { | ||
109 | } | ||
110 | |||
111 | @Data | ||
112 | static class Bounds extends PolyhedronSignature { | ||
113 | val Integer[] lowerBounds | ||
114 | val Integer[] upperBounds | ||
115 | } | ||
116 | } | ||
117 | |||
118 | @Accessors | ||
119 | class Bounds { | ||
120 | var Integer lowerBound | ||
121 | var Integer upperBound | ||
122 | |||
123 | def void tightenLowerBound(Integer tighterBound) { | ||
124 | if (lowerBound === null || (tighterBound !== null && lowerBound < tighterBound)) { | ||
125 | lowerBound = tighterBound | ||
126 | } | ||
127 | } | ||
128 | |||
129 | def void tightenUpperBound(Integer tighterBound) { | ||
130 | if (upperBound === null || (tighterBound !== null && upperBound > tighterBound)) { | ||
131 | upperBound = tighterBound | ||
132 | } | ||
133 | } | ||
134 | |||
135 | def void assertBetween(Integer tighterLowerBound, Integer tighterUpperBound) { | ||
136 | tightenLowerBound(tighterLowerBound) | ||
137 | tightenUpperBound(tighterUpperBound) | ||
138 | } | ||
139 | |||
140 | def void assertEqualsTo(int bound) { | ||
141 | assertBetween(bound, bound) | ||
142 | } | ||
143 | } | ||
144 | |||
145 | abstract class LinearBoundedExpression extends Bounds { | ||
146 | } | ||
147 | |||
148 | @Accessors | ||
149 | class Dimension extends LinearBoundedExpression { | ||
150 | val String name | ||
151 | |||
152 | @FinalFieldsConstructor | ||
153 | new() { | ||
154 | } | ||
155 | |||
156 | new(String name, Integer lowerBound, Integer upperBound) { | ||
157 | this(name) | ||
158 | this.lowerBound = lowerBound | ||
159 | this.upperBound = upperBound | ||
160 | } | ||
161 | |||
162 | override toString() { | ||
163 | '''«IF lowerBound !== null»«lowerBound» <= «ENDIF»«name»«IF upperBound !== null» <= «upperBound»«ENDIF»''' | ||
164 | } | ||
165 | |||
166 | } | ||
167 | |||
168 | @Accessors | ||
169 | class LinearConstraint extends LinearBoundedExpression { | ||
170 | val Map<Dimension, Integer> coefficients | ||
171 | |||
172 | @FinalFieldsConstructor | ||
173 | new() { | ||
174 | } | ||
175 | |||
176 | new(Map<Dimension, Integer> coefficients, Integer lowerBound, Integer upperBound) { | ||
177 | this(coefficients) | ||
178 | this.lowerBound = lowerBound | ||
179 | this.upperBound = upperBound | ||
180 | } | ||
181 | |||
182 | override toString() { | ||
183 | '''«IF lowerBound !== null»«lowerBound» <= «ENDIF»«FOR pair : coefficients.entrySet SEPARATOR " + "»«IF pair.value != 1»«pair.value» * «ENDIF»«pair.key.name»«ENDFOR»«IF upperBound !== null» <= «upperBound»«ENDIF»''' | ||
184 | } | ||
185 | |||
186 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend new file mode 100644 index 00000000..abf65be3 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend | |||
@@ -0,0 +1,156 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import com.google.common.collect.ImmutableSet | ||
5 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion | ||
6 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion | ||
7 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.UpperMultiplicityAssertion | ||
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | ||
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
11 | import java.util.HashMap | ||
12 | import java.util.List | ||
13 | import org.eclipse.xtend.lib.annotations.Data | ||
14 | |||
15 | @Data | ||
16 | class RelationConstraints { | ||
17 | val List<RelationMultiplicityConstraint> multiplicityConstraints | ||
18 | } | ||
19 | |||
20 | @Data | ||
21 | class RelationMultiplicityConstraint { | ||
22 | Relation relation | ||
23 | Relation inverseRelation | ||
24 | boolean containment | ||
25 | boolean container | ||
26 | int lowerBound | ||
27 | int upperBound | ||
28 | int inverseUpperBound | ||
29 | |||
30 | def isUpperBoundFinite() { | ||
31 | upperBound >= 0 | ||
32 | } | ||
33 | |||
34 | private def isInverseUpperBoundFinite() { | ||
35 | inverseUpperBound >= 0 | ||
36 | } | ||
37 | |||
38 | private def canHaveMultipleSourcesPerTarget() { | ||
39 | inverseUpperBound != 1 | ||
40 | } | ||
41 | |||
42 | def constrainsUnfinished() { | ||
43 | lowerBound >= 1 && (!container || lowerBound >= 2) | ||
44 | } | ||
45 | |||
46 | def constrainsUnrepairable() { | ||
47 | // TODO Optimize the unrepairable matches computation, | ||
48 | // or come up with a heuristic when does computing unrepairables worth the overhead. | ||
49 | false && constrainsUnfinished && canHaveMultipleSourcesPerTarget && reference | ||
50 | } | ||
51 | |||
52 | def constrainsRemainingInverse() { | ||
53 | lowerBound >= 1 && !containment && !container && inverseUpperBoundFinite && reference | ||
54 | } | ||
55 | |||
56 | def constrainsRemainingContents() { | ||
57 | containment | ||
58 | } | ||
59 | |||
60 | def isActive() { | ||
61 | constrainsUnfinished || constrainsUnrepairable || constrainsRemainingInverse || constrainsRemainingContents | ||
62 | } | ||
63 | |||
64 | def isSourceTypeComplex() { | ||
65 | getParamTypeReference(0) instanceof ComplexTypeReference | ||
66 | } | ||
67 | |||
68 | def isTargetTypeComplex() { | ||
69 | getParamTypeReference(1) instanceof ComplexTypeReference | ||
70 | } | ||
71 | |||
72 | def isReference() { | ||
73 | sourceTypeComplex && targetTypeComplex | ||
74 | } | ||
75 | |||
76 | def getSourceType() { | ||
77 | getParamType(0) | ||
78 | } | ||
79 | |||
80 | def getTargetType() { | ||
81 | getParamType(1) | ||
82 | } | ||
83 | |||
84 | private def getParamTypeReference(int i) { | ||
85 | val parameters = relation.parameters | ||
86 | if (i < parameters.size) { | ||
87 | return parameters.get(i) | ||
88 | } | ||
89 | throw new IllegalArgumentException("Argument index out of range") | ||
90 | } | ||
91 | |||
92 | private def getParamType(int i) { | ||
93 | val reference = getParamTypeReference(i) | ||
94 | if (reference instanceof ComplexTypeReference) { | ||
95 | return reference.referred | ||
96 | } | ||
97 | throw new IllegalArgumentException("Constraint with primitive type") | ||
98 | } | ||
99 | } | ||
100 | |||
101 | class RelationConstraintCalculator { | ||
102 | def calculateRelationConstraints(LogicProblem problem) { | ||
103 | val containmentRelations = switch (problem.containmentHierarchies.size) { | ||
104 | case 0: | ||
105 | <Relation>emptySet | ||
106 | case 1: | ||
107 | ImmutableSet.copyOf(problem.containmentHierarchies.head.containmentRelations) | ||
108 | default: | ||
109 | throw new IllegalArgumentException("Only a single containment hierarchy is supported") | ||
110 | } | ||
111 | val inverseRelations = new HashMap<Relation, Relation> | ||
112 | val lowerMultiplicities = new HashMap<Relation, Integer> | ||
113 | val upperMultiplicities = new HashMap<Relation, Integer> | ||
114 | for (relation : problem.relations) { | ||
115 | lowerMultiplicities.put(relation, 0) | ||
116 | upperMultiplicities.put(relation, -1) | ||
117 | } | ||
118 | for (annotation : problem.annotations) { | ||
119 | switch (annotation) { | ||
120 | InverseRelationAssertion: { | ||
121 | inverseRelations.put(annotation.inverseA, annotation.inverseB) | ||
122 | inverseRelations.put(annotation.inverseB, annotation.inverseA) | ||
123 | } | ||
124 | LowerMultiplicityAssertion: | ||
125 | lowerMultiplicities.put(annotation.relation, annotation.lower) | ||
126 | UpperMultiplicityAssertion: | ||
127 | upperMultiplicities.put(annotation.relation, annotation.upper) | ||
128 | } | ||
129 | } | ||
130 | val multiplicityConstraintsBuilder = ImmutableList.builder() | ||
131 | for (relation : problem.relations) { | ||
132 | val containment = containmentRelations.contains(relation) | ||
133 | val lowerMultiplicity = lowerMultiplicities.get(relation) | ||
134 | val upperMultiplicity = upperMultiplicities.get(relation) | ||
135 | var container = false | ||
136 | var inverseUpperMultiplicity = -1 | ||
137 | val inverseRelation = inverseRelations.get(relation) | ||
138 | if (inverseRelation !== null) { | ||
139 | inverseUpperMultiplicity = upperMultiplicities.get(inverseRelation) | ||
140 | container = containmentRelations.contains(inverseRelation) | ||
141 | } | ||
142 | if (containment) { | ||
143 | inverseUpperMultiplicity = 1 | ||
144 | } | ||
145 | val constraint = new RelationMultiplicityConstraint(relation, inverseRelation, containment, container, | ||
146 | lowerMultiplicity, upperMultiplicity, inverseUpperMultiplicity) | ||
147 | if (constraint.isActive) { | ||
148 | if (relation.parameters.size != 2) { | ||
149 | throw new IllegalArgumentException('''Relation «relation.name» has multiplicity or containment constraints, but it is not binary''') | ||
150 | } | ||
151 | multiplicityConstraintsBuilder.add(constraint) | ||
152 | } | ||
153 | } | ||
154 | new RelationConstraints(multiplicityConstraintsBuilder.build) | ||
155 | } | ||
156 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RemainingMultiplicityCalculator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RemainingMultiplicityCalculator.xtend new file mode 100644 index 00000000..48b52d28 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RemainingMultiplicityCalculator.xtend | |||
@@ -0,0 +1,111 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
4 | import java.util.Iterator | ||
5 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
6 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
7 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
8 | |||
9 | @FinalFieldsConstructor | ||
10 | abstract class MultiplicityCalculator<Match extends IPatternMatch> { | ||
11 | val ViatraQueryMatcher<Match> matcher | ||
12 | |||
13 | def getMultiplicity() { | ||
14 | val iterator = matcher.streamAllMatches.iterator | ||
15 | getMultiplicity(iterator) | ||
16 | } | ||
17 | |||
18 | def getMultiplicity(PartialInterpretation interpretation) { | ||
19 | val partialMatch = matcher.newEmptyMatch | ||
20 | partialMatch.set(0, interpretation.problem) | ||
21 | partialMatch.set(1, interpretation) | ||
22 | val iterator = matcher.streamAllMatches(partialMatch).iterator | ||
23 | getMultiplicity(iterator) | ||
24 | } | ||
25 | |||
26 | protected def int getMultiplicity(Iterator<? extends Match> iterator) | ||
27 | } | ||
28 | |||
29 | class RemainingMultiplicityCalculator<Match extends IPatternMatch> extends MultiplicityCalculator<Match> { | ||
30 | val int bound | ||
31 | |||
32 | @FinalFieldsConstructor | ||
33 | private new() { | ||
34 | } | ||
35 | |||
36 | protected override getMultiplicity(Iterator<? extends Match> iterator) { | ||
37 | var res = 0 | ||
38 | while (iterator.hasNext) { | ||
39 | val match = iterator.next | ||
40 | val existingMultiplicity = match.get(3) as Integer | ||
41 | if (existingMultiplicity < bound) { | ||
42 | res += bound - existingMultiplicity | ||
43 | } | ||
44 | } | ||
45 | res | ||
46 | } | ||
47 | |||
48 | static def <Match extends IPatternMatch> of(ViatraQueryMatcher<Match> matcher, int bound) { | ||
49 | if (bound < 0) { | ||
50 | new RemainingInfiniteMultiplicityCalculator(matcher) | ||
51 | } else { | ||
52 | new RemainingMultiplicityCalculator(matcher, bound) | ||
53 | } | ||
54 | } | ||
55 | } | ||
56 | |||
57 | package class RemainingInfiniteMultiplicityCalculator<Match extends IPatternMatch> extends MultiplicityCalculator<Match> { | ||
58 | |||
59 | @FinalFieldsConstructor | ||
60 | package new() { | ||
61 | } | ||
62 | |||
63 | protected override getMultiplicity(Iterator<? extends Match> iterator) { | ||
64 | if (iterator.hasNext) { | ||
65 | -1 | ||
66 | } else { | ||
67 | 0 | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
72 | @FinalFieldsConstructor | ||
73 | class UnrepairableMultiplicityCalculator<Match extends IPatternMatch> extends MultiplicityCalculator<Match> { | ||
74 | val int lowerBound | ||
75 | |||
76 | override protected getMultiplicity(Iterator<? extends Match> iterator) { | ||
77 | var res = 0 | ||
78 | while (iterator.hasNext) { | ||
79 | val match = iterator.next | ||
80 | val existingMultiplicity = match.get(3) as Integer | ||
81 | if (existingMultiplicity < lowerBound) { | ||
82 | val missingMultiplcity = lowerBound - existingMultiplicity | ||
83 | val numerOfRepairMatches = match.get(4) as Integer | ||
84 | val unrepairableMultiplicty = missingMultiplcity - numerOfRepairMatches | ||
85 | if (unrepairableMultiplicty > res) { | ||
86 | res = unrepairableMultiplicty | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | res | ||
91 | } | ||
92 | } | ||
93 | |||
94 | @FinalFieldsConstructor | ||
95 | class RemainingInverseMultiplicityCalculator<Match extends IPatternMatch> extends MultiplicityCalculator<Match> { | ||
96 | val int upperBound | ||
97 | |||
98 | override protected getMultiplicity(Iterator<? extends Match> iterator) { | ||
99 | var res = 0 | ||
100 | while (iterator.hasNext) { | ||
101 | val match = iterator.next | ||
102 | val existingMultiplicity = match.get(3) as Integer | ||
103 | if (existingMultiplicity < upperBound) { | ||
104 | val availableMultiplicity = upperBound - existingMultiplicity | ||
105 | val numberOfRepairMatches = match.get(4) as Integer | ||
106 | res += Math.min(availableMultiplicity, numberOfRepairMatches) | ||
107 | } | ||
108 | } | ||
109 | res | ||
110 | } | ||
111 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagator.xtend new file mode 100644 index 00000000..cacba3c6 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagator.xtend | |||
@@ -0,0 +1,161 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope | ||
10 | import java.util.HashMap | ||
11 | import java.util.HashSet | ||
12 | import java.util.Map | ||
13 | import java.util.Set | ||
14 | import org.eclipse.xtend.lib.annotations.Accessors | ||
15 | |||
16 | class ScopePropagator { | ||
17 | @Accessors(PROTECTED_GETTER) val PartialInterpretation partialInterpretation | ||
18 | @Accessors(PROTECTED_GETTER) val ModelGenerationStatistics statistics | ||
19 | val Map<PartialTypeInterpratation, Scope> type2Scope | ||
20 | @Accessors(PROTECTED_GETTER) val Map<Scope, Set<Scope>> superScopes | ||
21 | @Accessors(PROTECTED_GETTER) val Map<Scope, Set<Scope>> subScopes | ||
22 | |||
23 | @Accessors(PUBLIC_GETTER) var scopePropagationNeeded = false | ||
24 | |||
25 | new(PartialInterpretation p, ModelGenerationStatistics statistics) { | ||
26 | partialInterpretation = p | ||
27 | this.statistics = statistics | ||
28 | type2Scope = new HashMap | ||
29 | for (scope : p.scopes) { | ||
30 | type2Scope.put(scope.targetTypeInterpretation, scope) | ||
31 | } | ||
32 | |||
33 | superScopes = new HashMap | ||
34 | subScopes = new HashMap | ||
35 | for (scope : p.scopes) { | ||
36 | superScopes.put(scope, new HashSet) | ||
37 | subScopes.put(scope, new HashSet) | ||
38 | } | ||
39 | |||
40 | for (scope : p.scopes) { | ||
41 | val target = scope.targetTypeInterpretation | ||
42 | if (target instanceof PartialComplexTypeInterpretation) { | ||
43 | val supertypeInterpretations = target.supertypeInterpretation | ||
44 | for (supertypeInterpretation : supertypeInterpretations) { | ||
45 | val supertypeScope = type2Scope.get(supertypeInterpretation) | ||
46 | superScopes.get(scope).add(supertypeScope) | ||
47 | subScopes.get(supertypeScope).add(scope) | ||
48 | } | ||
49 | } | ||
50 | } | ||
51 | var boolean changed | ||
52 | do { | ||
53 | changed = false | ||
54 | for (scope : p.scopes) { | ||
55 | val subScopeSet = subScopes.get(scope) | ||
56 | val superScopeSet = superScopes.get(scope) | ||
57 | for (subScope : subScopeSet) { | ||
58 | changed = changed || superScopes.get(subScope).addAll(superScopeSet) | ||
59 | } | ||
60 | for (superScope : superScopeSet) { | ||
61 | changed = changed || subScopes.get(superScope).addAll(subScopeSet) | ||
62 | } | ||
63 | } | ||
64 | } while (changed) | ||
65 | |||
66 | copyScopeBoundsToHeuristic() | ||
67 | } | ||
68 | |||
69 | def void propagateAllScopeConstraints() { | ||
70 | scopePropagationNeeded = false | ||
71 | if (!valid) { | ||
72 | return | ||
73 | } | ||
74 | statistics.incrementScopePropagationCount() | ||
75 | doPropagateAllScopeConstraints() | ||
76 | } | ||
77 | |||
78 | def isValid() { | ||
79 | partialInterpretation.maxNewElements == -1 || | ||
80 | partialInterpretation.minNewElements <= partialInterpretation.maxNewElements | ||
81 | } | ||
82 | |||
83 | protected def copyScopeBoundsToHeuristic() { | ||
84 | partialInterpretation.minNewElementsHeuristic = partialInterpretation.minNewElements | ||
85 | for (scope : partialInterpretation.scopes) { | ||
86 | scope.minNewElementsHeuristic = scope.minNewElements | ||
87 | } | ||
88 | } | ||
89 | |||
90 | protected def void doPropagateAllScopeConstraints() { | ||
91 | // Nothing to propagate. | ||
92 | } | ||
93 | |||
94 | def decrementTypeScope(PartialTypeInterpratation t) { | ||
95 | val isPrimitive = t instanceof PartialPrimitiveInterpretation || t === null | ||
96 | if (isPrimitive) { | ||
97 | return | ||
98 | } | ||
99 | scopePropagationNeeded = true | ||
100 | // println('''Adding to «(t as PartialComplexTypeInterpretation).interpretationOf.name»''') | ||
101 | val targetScope = type2Scope.get(t) | ||
102 | if (targetScope !== null) { | ||
103 | targetScope.removeOne | ||
104 | val sups = superScopes.get(targetScope) | ||
105 | sups.forEach[removeOne] | ||
106 | } | ||
107 | if (this.partialInterpretation.minNewElements > 0) { | ||
108 | this.partialInterpretation.minNewElements = this.partialInterpretation.minNewElements - 1 | ||
109 | } | ||
110 | if (this.partialInterpretation.minNewElementsHeuristic > 0) { | ||
111 | this.partialInterpretation.minNewElementsHeuristic = this.partialInterpretation.minNewElementsHeuristic - 1 | ||
112 | } | ||
113 | if (this.partialInterpretation.maxNewElements > 0) { | ||
114 | this.partialInterpretation.maxNewElements = this.partialInterpretation.maxNewElements - 1 | ||
115 | } else if (this.partialInterpretation.maxNewElements === 0) { | ||
116 | setScopesInvalid() | ||
117 | } | ||
118 | |||
119 | // println('''Target Scope: «targetScope.minNewElements» - «targetScope.maxNewElements»''') | ||
120 | // println(''' «this.partialInterpretation.minNewElements» - «this.partialInterpretation.maxNewElements»''') | ||
121 | // this.partialInterpretation.scopes.forEach[println(''' «(it.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name»: «it.minNewElements»-«it.maxNewElements»''')] | ||
122 | // println('''All constraints are propagated upon increasing «(t as PartialComplexTypeInterpretation).interpretationOf.name»''') | ||
123 | } | ||
124 | |||
125 | def addedToRelation(Relation r) { | ||
126 | if (isPropagationNeededAfterAdditionToRelation(r)) { | ||
127 | scopePropagationNeeded = true | ||
128 | } | ||
129 | } | ||
130 | |||
131 | protected def setScopesInvalid() { | ||
132 | partialInterpretation.minNewElements = Integer.MAX_VALUE | ||
133 | partialInterpretation.maxNewElements = 0 | ||
134 | for (scope : partialInterpretation.scopes) { | ||
135 | scope.minNewElements = Integer.MAX_VALUE | ||
136 | scope.maxNewElements = 0 | ||
137 | } | ||
138 | } | ||
139 | |||
140 | protected def isPropagationNeededAfterAdditionToRelation(Relation r) { | ||
141 | false | ||
142 | } | ||
143 | |||
144 | def isQueryEngineFlushRequiredBeforePropagation() { | ||
145 | false | ||
146 | } | ||
147 | |||
148 | private def removeOne(Scope scope) { | ||
149 | if (scope.minNewElements > 0) { | ||
150 | scope.minNewElements = scope.minNewElements - 1 | ||
151 | } | ||
152 | if (scope.minNewElementsHeuristic > 0) { | ||
153 | scope.minNewElementsHeuristic = scope.minNewElementsHeuristic - 1 | ||
154 | } | ||
155 | if (scope.maxNewElements > 0) { | ||
156 | scope.maxNewElements = scope.maxNewElements - 1 | ||
157 | } else if (scope.maxNewElements === 0) { | ||
158 | setScopesInvalid() | ||
159 | } | ||
160 | } | ||
161 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagatorStrategy.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagatorStrategy.xtend new file mode 100644 index 00000000..3165917a --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagatorStrategy.xtend | |||
@@ -0,0 +1,71 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import org.eclipse.xtend.lib.annotations.Data | ||
4 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
5 | |||
6 | enum PolyhedralScopePropagatorConstraints { | ||
7 | TypeHierarchy, | ||
8 | Relational | ||
9 | } | ||
10 | |||
11 | enum PolyhedralScopePropagatorSolver { | ||
12 | Z3Real, | ||
13 | Z3Integer, | ||
14 | Cbc, | ||
15 | Clp | ||
16 | } | ||
17 | |||
18 | abstract class ScopePropagatorStrategy { | ||
19 | public static val None = new Simple("None") | ||
20 | |||
21 | public static val Basic = new Simple("Basic") | ||
22 | |||
23 | public static val BasicTypeHierarchy = new Simple("BasicTypeHierarchy") | ||
24 | |||
25 | private new() { | ||
26 | } | ||
27 | |||
28 | def boolean requiresUpperBoundIndexing() | ||
29 | |||
30 | static class Simple extends ScopePropagatorStrategy { | ||
31 | val String name | ||
32 | |||
33 | @FinalFieldsConstructor | ||
34 | private new() { | ||
35 | } | ||
36 | |||
37 | override requiresUpperBoundIndexing() { | ||
38 | false | ||
39 | } | ||
40 | |||
41 | override toString() { | ||
42 | name | ||
43 | } | ||
44 | } | ||
45 | |||
46 | @Data | ||
47 | static class Polyhedral extends ScopePropagatorStrategy { | ||
48 | public static val UNLIMITED_TIME = -1 | ||
49 | |||
50 | val PolyhedralScopePropagatorConstraints constraints | ||
51 | val PolyhedralScopePropagatorSolver solver | ||
52 | val boolean updateHeuristic | ||
53 | val double timeoutSeconds | ||
54 | |||
55 | @FinalFieldsConstructor | ||
56 | new() { | ||
57 | } | ||
58 | |||
59 | new(PolyhedralScopePropagatorConstraints constraints, PolyhedralScopePropagatorSolver solver, boolean updateHeuristic) { | ||
60 | this(constraints, solver, updateHeuristic, UNLIMITED_TIME) | ||
61 | } | ||
62 | |||
63 | new(PolyhedralScopePropagatorConstraints constraints, PolyhedralScopePropagatorSolver solver) { | ||
64 | this(constraints, solver, true) | ||
65 | } | ||
66 | |||
67 | override requiresUpperBoundIndexing() { | ||
68 | constraints == PolyhedralScopePropagatorConstraints.Relational | ||
69 | } | ||
70 | } | ||
71 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/TypeHierarchyScopePropagator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/TypeHierarchyScopePropagator.xtend new file mode 100644 index 00000000..d1704b39 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/TypeHierarchyScopePropagator.xtend | |||
@@ -0,0 +1,85 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope | ||
6 | |||
7 | class TypeHierarchyScopePropagator extends ScopePropagator { | ||
8 | |||
9 | new(PartialInterpretation p, ModelGenerationStatistics statistics) { | ||
10 | super(p, statistics) | ||
11 | } | ||
12 | |||
13 | protected override doPropagateAllScopeConstraints() { | ||
14 | var boolean hadChanged | ||
15 | do { | ||
16 | hadChanged = false | ||
17 | for (superScopeEntry : superScopes.entrySet) { | ||
18 | val sub = superScopeEntry.key | ||
19 | hadChanged = propagateLowerLimitUp(sub, partialInterpretation) || hadChanged | ||
20 | hadChanged = propagateUpperLimitDown(sub, partialInterpretation) || hadChanged | ||
21 | for (sup : superScopeEntry.value) { | ||
22 | hadChanged = propagateLowerLimitUp(sub, sup) || hadChanged | ||
23 | hadChanged = propagateUpperLimitDown(sub, sup) || hadChanged | ||
24 | } | ||
25 | } | ||
26 | } while (hadChanged) | ||
27 | } | ||
28 | |||
29 | private def propagateLowerLimitUp(Scope subScope, Scope superScope) { | ||
30 | var changed = false | ||
31 | if (subScope.minNewElements > superScope.minNewElements) { | ||
32 | superScope.minNewElements = subScope.minNewElements | ||
33 | changed = true | ||
34 | } | ||
35 | if (subScope.minNewElementsHeuristic > superScope.minNewElementsHeuristic) { | ||
36 | superScope.minNewElementsHeuristic = subScope.minNewElementsHeuristic | ||
37 | changed = true | ||
38 | } | ||
39 | changed | ||
40 | } | ||
41 | |||
42 | private def propagateUpperLimitDown(Scope subScope, Scope superScope) { | ||
43 | if (superScope.maxNewElements >= 0 && | ||
44 | (superScope.maxNewElements < subScope.maxNewElements || subScope.maxNewElements < 0)) { | ||
45 | // println(''' | ||
46 | // «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> «(superScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» | ||
47 | // subScope.maxNewElements «subScope.maxNewElements» = superScope.maxNewElements «superScope.maxNewElements» | ||
48 | // ''') | ||
49 | subScope.maxNewElements = superScope.maxNewElements | ||
50 | return true | ||
51 | } else { | ||
52 | return false | ||
53 | } | ||
54 | } | ||
55 | |||
56 | private def propagateLowerLimitUp(Scope subScope, PartialInterpretation p) { | ||
57 | var changed = false | ||
58 | if (subScope.minNewElements > p.minNewElements) { | ||
59 | // println(''' | ||
60 | // «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes | ||
61 | // p.minNewElements «p.minNewElements» = subScope.minNewElements «subScope.minNewElements» | ||
62 | // ''') | ||
63 | p.minNewElements = subScope.minNewElements | ||
64 | changed = true | ||
65 | } | ||
66 | if (subScope.minNewElementsHeuristic > p.minNewElementsHeuristic) { | ||
67 | p.minNewElementsHeuristic = subScope.minNewElementsHeuristic | ||
68 | changed = true | ||
69 | } | ||
70 | changed | ||
71 | } | ||
72 | |||
73 | private def propagateUpperLimitDown(Scope subScope, PartialInterpretation p) { | ||
74 | if (p.maxNewElements >= 0 && (p.maxNewElements < subScope.maxNewElements || subScope.maxNewElements < 0)) { | ||
75 | // println(''' | ||
76 | // «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes | ||
77 | // subScope.maxNewElements «subScope.maxNewElements» = p.maxNewElements «p.maxNewElements» | ||
78 | // ''') | ||
79 | subScope.maxNewElements = p.maxNewElements | ||
80 | return true | ||
81 | } else { | ||
82 | return false | ||
83 | } | ||
84 | } | ||
85 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/Z3PolyhedronSolver.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/Z3PolyhedronSolver.xtend new file mode 100644 index 00000000..3b831433 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/Z3PolyhedronSolver.xtend | |||
@@ -0,0 +1,272 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality | ||
2 | |||
3 | import com.microsoft.z3.AlgebraicNum | ||
4 | import com.microsoft.z3.ArithExpr | ||
5 | import com.microsoft.z3.Context | ||
6 | import com.microsoft.z3.Expr | ||
7 | import com.microsoft.z3.IntNum | ||
8 | import com.microsoft.z3.Optimize | ||
9 | import com.microsoft.z3.RatNum | ||
10 | import com.microsoft.z3.Status | ||
11 | import com.microsoft.z3.Symbol | ||
12 | import java.math.BigDecimal | ||
13 | import java.math.MathContext | ||
14 | import java.math.RoundingMode | ||
15 | import java.util.Map | ||
16 | import org.eclipse.xtend.lib.annotations.Accessors | ||
17 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
18 | |||
19 | class Z3PolyhedronSolver implements PolyhedronSolver { | ||
20 | val boolean lpRelaxation | ||
21 | val double timeoutSeconds | ||
22 | |||
23 | @FinalFieldsConstructor | ||
24 | new() { | ||
25 | } | ||
26 | |||
27 | new() { | ||
28 | this(false, -1) | ||
29 | } | ||
30 | |||
31 | override createSaturationOperator(Polyhedron polyhedron) { | ||
32 | new DisposingZ3SaturationOperator(this, polyhedron) | ||
33 | } | ||
34 | |||
35 | def createPersistentSaturationOperator(Polyhedron polyhedron) { | ||
36 | new Z3SaturationOperator(polyhedron, lpRelaxation, timeoutSeconds) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | @FinalFieldsConstructor | ||
41 | class DisposingZ3SaturationOperator implements PolyhedronSaturationOperator { | ||
42 | val Z3PolyhedronSolver solver | ||
43 | @Accessors val Polyhedron polyhedron | ||
44 | |||
45 | override saturate() { | ||
46 | val persistentOperator = solver.createPersistentSaturationOperator(polyhedron) | ||
47 | try { | ||
48 | persistentOperator.saturate | ||
49 | } finally { | ||
50 | persistentOperator.close | ||
51 | } | ||
52 | } | ||
53 | |||
54 | override close() throws Exception { | ||
55 | // Nothing to close. | ||
56 | } | ||
57 | } | ||
58 | |||
59 | class Z3SaturationOperator extends AbstractPolyhedronSaturationOperator { | ||
60 | static val INFINITY_SYMBOL_NAME = "oo" | ||
61 | static val MULT_SYMBOL_NAME = "*" | ||
62 | static val TIMEOUT_SYMBOL_NAME = "timeout" | ||
63 | static val INTEGER_PRECISION = new BigDecimal(Integer.MAX_VALUE).precision | ||
64 | static val ROUND_DOWN = new MathContext(INTEGER_PRECISION, RoundingMode.FLOOR) | ||
65 | static val ROUND_UP = new MathContext(INTEGER_PRECISION, RoundingMode.CEILING) | ||
66 | // The interval isolating the number is smaller than 1/10^precision. | ||
67 | static val ALGEBRAIC_NUMBER_ROUNDING = 0 | ||
68 | |||
69 | extension val Context context | ||
70 | val Symbol infinitySymbol | ||
71 | val Symbol multSymbol | ||
72 | val Map<Dimension, ArithExpr> variables | ||
73 | val int timeoutMilliseconds | ||
74 | |||
75 | new(Polyhedron polyhedron, boolean lpRelaxation, double timeoutSeconds) { | ||
76 | super(polyhedron) | ||
77 | context = new Context | ||
78 | infinitySymbol = context.mkSymbol(INFINITY_SYMBOL_NAME) | ||
79 | multSymbol = context.mkSymbol(MULT_SYMBOL_NAME) | ||
80 | variables = polyhedron.dimensions.toInvertedMap [ dimension | | ||
81 | val name = dimension.name | ||
82 | if (lpRelaxation) { | ||
83 | mkRealConst(name) | ||
84 | } else { | ||
85 | mkIntConst(name) | ||
86 | } | ||
87 | ] | ||
88 | timeoutMilliseconds = Math.ceil(timeoutSeconds * 1000) as int | ||
89 | } | ||
90 | |||
91 | override doSaturate() { | ||
92 | val status = executeSolver() | ||
93 | convertStatusToSaturationResult(status) | ||
94 | } | ||
95 | |||
96 | private def convertStatusToSaturationResult(Status status) { | ||
97 | switch (status) { | ||
98 | case SATISFIABLE: | ||
99 | PolyhedronSaturationResult.SATURATED | ||
100 | case UNSATISFIABLE: | ||
101 | PolyhedronSaturationResult.EMPTY | ||
102 | case UNKNOWN: | ||
103 | PolyhedronSaturationResult.UNKNOWN | ||
104 | default: | ||
105 | throw new IllegalArgumentException("Unknown Status: " + status) | ||
106 | } | ||
107 | } | ||
108 | |||
109 | private def executeSolver() { | ||
110 | for (expressionToSaturate : polyhedron.expressionsToSaturate) { | ||
111 | val expr = expressionToSaturate.toExpr | ||
112 | val lowerResult = saturateLowerBound(expr, expressionToSaturate) | ||
113 | if (lowerResult != Status.SATISFIABLE) { | ||
114 | return lowerResult | ||
115 | } | ||
116 | val upperResult = saturateUpperBound(expr, expressionToSaturate) | ||
117 | if (upperResult != Status.SATISFIABLE) { | ||
118 | return upperResult | ||
119 | } | ||
120 | } | ||
121 | Status.SATISFIABLE | ||
122 | } | ||
123 | |||
124 | private def saturateLowerBound(ArithExpr expr, LinearBoundedExpression expressionToSaturate) { | ||
125 | val optimize = prepareOptimize | ||
126 | val handle = optimize.MkMinimize(expr) | ||
127 | val status = optimize.Check() | ||
128 | if (status == Status.SATISFIABLE) { | ||
129 | val value = switch (resultExpr : handle.lower) { | ||
130 | IntNum: | ||
131 | resultExpr.getInt() | ||
132 | RatNum: | ||
133 | ceil(resultExpr) | ||
134 | AlgebraicNum: | ||
135 | ceil(resultExpr.toUpper(ALGEBRAIC_NUMBER_ROUNDING)) | ||
136 | default: | ||
137 | if (isNegativeInfinity(resultExpr)) { | ||
138 | null | ||
139 | } else { | ||
140 | throw new IllegalArgumentException("Integer result expected, got: " + resultExpr) | ||
141 | } | ||
142 | } | ||
143 | expressionToSaturate.lowerBound = value | ||
144 | } | ||
145 | status | ||
146 | } | ||
147 | |||
148 | private def floor(RatNum ratNum) { | ||
149 | val numerator = new BigDecimal(ratNum.numerator.bigInteger) | ||
150 | val denominator = new BigDecimal(ratNum.denominator.bigInteger) | ||
151 | numerator.divide(denominator, ROUND_DOWN).setScale(0, RoundingMode.FLOOR).intValue | ||
152 | } | ||
153 | |||
154 | private def saturateUpperBound(ArithExpr expr, LinearBoundedExpression expressionToSaturate) { | ||
155 | val optimize = prepareOptimize | ||
156 | val handle = optimize.MkMaximize(expr) | ||
157 | val status = optimize.Check() | ||
158 | if (status == Status.SATISFIABLE) { | ||
159 | val value = switch (resultExpr : handle.upper) { | ||
160 | IntNum: | ||
161 | resultExpr.getInt() | ||
162 | RatNum: | ||
163 | floor(resultExpr) | ||
164 | AlgebraicNum: | ||
165 | floor(resultExpr.toLower(ALGEBRAIC_NUMBER_ROUNDING)) | ||
166 | default: | ||
167 | if (isPositiveInfinity(resultExpr)) { | ||
168 | null | ||
169 | } else { | ||
170 | throw new IllegalArgumentException("Integer result expected, got: " + resultExpr) | ||
171 | } | ||
172 | } | ||
173 | expressionToSaturate.upperBound = value | ||
174 | } | ||
175 | status | ||
176 | } | ||
177 | |||
178 | private def ceil(RatNum ratNum) { | ||
179 | val numerator = new BigDecimal(ratNum.numerator.bigInteger) | ||
180 | val denominator = new BigDecimal(ratNum.denominator.bigInteger) | ||
181 | numerator.divide(denominator, ROUND_UP).setScale(0, RoundingMode.CEILING).intValue | ||
182 | } | ||
183 | |||
184 | private def isPositiveInfinity(Expr expr) { | ||
185 | expr.app && expr.getFuncDecl.name == infinitySymbol | ||
186 | } | ||
187 | |||
188 | private def isNegativeInfinity(Expr expr) { | ||
189 | // Negative infinity is represented as (* (- 1) oo) | ||
190 | if (!expr.app || expr.getFuncDecl.name != multSymbol || expr.numArgs != 2) { | ||
191 | return false | ||
192 | } | ||
193 | isPositiveInfinity(expr.args.get(1)) | ||
194 | } | ||
195 | |||
196 | private def prepareOptimize() { | ||
197 | val optimize = mkOptimize() | ||
198 | if (timeoutMilliseconds >= 0) { | ||
199 | val params = mkParams() | ||
200 | // We cannot turn TIMEOUT_SYMBOL_NAME into a Symbol in the constructor, | ||
201 | // because there is no add(Symbol, int) overload. | ||
202 | params.add(TIMEOUT_SYMBOL_NAME, timeoutMilliseconds) | ||
203 | optimize.parameters = params | ||
204 | } | ||
205 | assertConstraints(optimize) | ||
206 | optimize | ||
207 | } | ||
208 | |||
209 | private def assertConstraints(Optimize it) { | ||
210 | for (pair : variables.entrySet) { | ||
211 | assertBounds(pair.value, pair.key) | ||
212 | } | ||
213 | for (constraint : nonTrivialConstraints) { | ||
214 | val expr = createLinearCombination(constraint.coefficients) | ||
215 | assertBounds(expr, constraint) | ||
216 | } | ||
217 | } | ||
218 | |||
219 | private def assertBounds(Optimize it, ArithExpr expression, LinearBoundedExpression bounds) { | ||
220 | val lowerBound = bounds.lowerBound | ||
221 | val upperBound = bounds.upperBound | ||
222 | if (lowerBound == upperBound) { | ||
223 | if (lowerBound === null) { | ||
224 | return | ||
225 | } | ||
226 | Assert(mkEq(expression, mkInt(lowerBound))) | ||
227 | } else { | ||
228 | if (lowerBound !== null) { | ||
229 | Assert(mkGe(expression, mkInt(lowerBound))) | ||
230 | } | ||
231 | if (upperBound !== null) { | ||
232 | Assert(mkLe(expression, mkInt(upperBound))) | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
237 | private def toExpr(LinearBoundedExpression linearBoundedExpression) { | ||
238 | switch (linearBoundedExpression) { | ||
239 | Dimension: variables.get(linearBoundedExpression) | ||
240 | LinearConstraint: createLinearCombination(linearBoundedExpression.coefficients) | ||
241 | default: throw new IllegalArgumentException("Unknown linear bounded expression:" + linearBoundedExpression) | ||
242 | } | ||
243 | } | ||
244 | |||
245 | private def createLinearCombination(Map<Dimension, Integer> coefficients) { | ||
246 | val size = coefficients.size | ||
247 | if (size == 0) { | ||
248 | return mkInt(0) | ||
249 | } | ||
250 | val array = newArrayOfSize(size) | ||
251 | var int i = 0 | ||
252 | for (pair : coefficients.entrySet) { | ||
253 | val variable = variables.get(pair.key) | ||
254 | if (variable === null) { | ||
255 | throw new IllegalArgumentException("Unknown dimension: " + pair.key.name) | ||
256 | } | ||
257 | val coefficient = pair.value | ||
258 | val term = if (coefficient == 1) { | ||
259 | variable | ||
260 | } else { | ||
261 | mkMul(mkInt(coefficient), variable) | ||
262 | } | ||
263 | array.set(i, term) | ||
264 | i++ | ||
265 | } | ||
266 | mkAdd(array) | ||
267 | } | ||
268 | |||
269 | override close() throws Exception { | ||
270 | context.close() | ||
271 | } | ||
272 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/CanonisedFormulae.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/CanonisedFormulae.xtend index e511a961..fd4374f5 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/CanonisedFormulae.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/CanonisedFormulae.xtend | |||
@@ -11,7 +11,5 @@ import org.eclipse.xtend.lib.annotations.Data | |||
11 | class CanonisedFormulae { | 11 | class CanonisedFormulae { |
12 | CharSequence viatraCode | 12 | CharSequence viatraCode |
13 | Map<Assertion,String> assertion2ConstraintPattern | 13 | Map<Assertion,String> assertion2ConstraintPattern |
14 | Map<ConstantDefinition,String> constant2ValuePattern | ||
15 | Map<RelationDefinition,String> relation2ValuePattern | 14 | Map<RelationDefinition,String> relation2ValuePattern |
16 | Map<FunctionDefinition,String> function2ValuePattern | ||
17 | } \ No newline at end of file | 15 | } \ No newline at end of file |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/FormulaCanoniser.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/FormulaCanoniser.xtend index 0af0b36a..182f3a3a 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/FormulaCanoniser.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/FormulaCanoniser.xtend | |||
@@ -5,17 +5,35 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ConstantDefinition | |||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.FunctionDefinition | 5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.FunctionDefinition |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition |
7 | import java.util.List | 7 | import java.util.List |
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Term | ||
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.SymbolicValue | ||
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Variable | ||
8 | 11 | ||
9 | /** | 12 | /** |
10 | * Translates a set of assertions and definitions to viatra patterns. | 13 | * Translates a Terms into format |
14 | * <P(x1,...,xn)> := Bodies(x1,...,xn) | ||
15 | * <Bodies(x1,...,xn)> := <Body(x1,...,xn)> | <Body(x1,...,xn)> or <Bodies(x1,...,xn)> | ||
16 | * <Body(x1,...,xn)> := Exists y1,...,ym : <Constraints(x1,...,xn,y1,....,ym)> | ||
17 | * <Constraints(x1,...,xn)> := Constraint(x1,...xn) | Constraint(x1,...,xn) and <Constraints(x1,...,xn)> | ||
11 | */ | 18 | */ |
12 | class FormulaCanoniser { | 19 | class FormulaCanoniser { |
13 | def canonise( | 20 | // def canonise( |
14 | List<Assertion> assertions, | 21 | // List<Assertion> assertions, |
15 | List<RelationDefinition> relations, | 22 | // List<RelationDefinition> relations) |
16 | List<ConstantDefinition> constants, | 23 | // { |
17 | List<FunctionDefinition> functions) | 24 | // |
18 | { | 25 | // } |
19 | 26 | // | |
20 | } | 27 | // |
28 | // def canoniseToConstraintBlock(Term predicate, List<Variable> variables) { | ||
29 | // val | ||
30 | // } | ||
31 | // | ||
32 | // def freeVariables(Term t) { | ||
33 | // val subterms = #[t]+t.eAllContents.toList | ||
34 | // val variables = subterms.filter(Variable).toSet | ||
35 | // val variableReferences = subterms.filter(SymbolicValue).filter[it.symbolicReference instanceof Variable] | ||
36 | // val freeVariables = variableReferences.filter[!variables.contains(it.symbolicReference)] | ||
37 | // return freeVariables.map | ||
38 | // } | ||
21 | } \ No newline at end of file | 39 | } \ No newline at end of file |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/Interval.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/Interval.xtend new file mode 100644 index 00000000..691c8783 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/Interval.xtend | |||
@@ -0,0 +1,584 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval | ||
2 | |||
3 | import java.math.BigDecimal | ||
4 | import java.math.MathContext | ||
5 | import java.math.RoundingMode | ||
6 | import org.eclipse.xtend.lib.annotations.Data | ||
7 | |||
8 | abstract class Interval implements Comparable<Interval> { | ||
9 | static val PRECISION = 32 | ||
10 | package static val ROUND_DOWN = new MathContext(PRECISION, RoundingMode.FLOOR) | ||
11 | package static val ROUND_UP = new MathContext(PRECISION, RoundingMode.CEILING) | ||
12 | |||
13 | private new() { | ||
14 | } | ||
15 | |||
16 | abstract def boolean mustEqual(Interval other) | ||
17 | |||
18 | abstract def boolean mayEqual(Interval other) | ||
19 | |||
20 | def mustNotEqual(Interval other) { | ||
21 | !mayEqual(other) | ||
22 | } | ||
23 | |||
24 | def mayNotEqual(Interval other) { | ||
25 | !mustEqual(other) | ||
26 | } | ||
27 | |||
28 | abstract def boolean mustBeLessThan(Interval other) | ||
29 | |||
30 | abstract def boolean mayBeLessThan(Interval other) | ||
31 | |||
32 | def mustBeLessThanOrEqual(Interval other) { | ||
33 | !mayBeGreaterThan(other) | ||
34 | } | ||
35 | |||
36 | def mayBeLessThanOrEqual(Interval other) { | ||
37 | !mustBeGreaterThan(other) | ||
38 | } | ||
39 | |||
40 | def mustBeGreaterThan(Interval other) { | ||
41 | other.mustBeLessThan(this) | ||
42 | } | ||
43 | |||
44 | def mayBeGreaterThan(Interval other) { | ||
45 | other.mayBeLessThan(this) | ||
46 | } | ||
47 | |||
48 | def mustBeGreaterThanOrEqual(Interval other) { | ||
49 | other.mustBeLessThanOrEqual(this) | ||
50 | } | ||
51 | |||
52 | def mayBeGreaterThanOrEqual(Interval other) { | ||
53 | other.mayBeLessThanOrEqual(this) | ||
54 | } | ||
55 | |||
56 | abstract def Interval min(Interval other) | ||
57 | |||
58 | abstract def Interval max(Interval other) | ||
59 | |||
60 | abstract def Interval join(Interval other) | ||
61 | |||
62 | def +() { | ||
63 | this | ||
64 | } | ||
65 | |||
66 | abstract def Interval -() | ||
67 | |||
68 | abstract def Interval +(Interval other) | ||
69 | |||
70 | abstract def Interval -(Interval other) | ||
71 | |||
72 | abstract def Interval *(int count) | ||
73 | |||
74 | abstract def Interval *(Interval other) | ||
75 | |||
76 | abstract def Interval /(Interval other) | ||
77 | |||
78 | abstract def Interval **(Interval other) | ||
79 | |||
80 | public static val EMPTY = new Interval { | ||
81 | override mustEqual(Interval other) { | ||
82 | true | ||
83 | } | ||
84 | |||
85 | override mayEqual(Interval other) { | ||
86 | false | ||
87 | } | ||
88 | |||
89 | override mustBeLessThan(Interval other) { | ||
90 | true | ||
91 | } | ||
92 | |||
93 | override mayBeLessThan(Interval other) { | ||
94 | false | ||
95 | } | ||
96 | |||
97 | override min(Interval other) { | ||
98 | EMPTY | ||
99 | } | ||
100 | |||
101 | override max(Interval other) { | ||
102 | EMPTY | ||
103 | } | ||
104 | |||
105 | override join(Interval other) { | ||
106 | other | ||
107 | } | ||
108 | |||
109 | override -() { | ||
110 | EMPTY | ||
111 | } | ||
112 | |||
113 | override +(Interval other) { | ||
114 | EMPTY | ||
115 | } | ||
116 | |||
117 | override -(Interval other) { | ||
118 | EMPTY | ||
119 | } | ||
120 | |||
121 | override *(int count) { | ||
122 | EMPTY | ||
123 | } | ||
124 | |||
125 | override *(Interval other) { | ||
126 | EMPTY | ||
127 | } | ||
128 | |||
129 | override /(Interval other) { | ||
130 | EMPTY | ||
131 | } | ||
132 | |||
133 | override **(Interval other) { | ||
134 | EMPTY | ||
135 | } | ||
136 | |||
137 | override toString() { | ||
138 | "∅" | ||
139 | } | ||
140 | |||
141 | override compareTo(Interval o) { | ||
142 | if (o == EMPTY) { | ||
143 | 0 | ||
144 | } else { | ||
145 | -1 | ||
146 | } | ||
147 | } | ||
148 | |||
149 | } | ||
150 | |||
151 | public static val Interval ZERO = new NonEmpty(BigDecimal.ZERO, BigDecimal.ZERO) | ||
152 | |||
153 | public static val Interval UNBOUNDED = new NonEmpty(null, null) | ||
154 | |||
155 | static def Interval of(BigDecimal lower, BigDecimal upper) { | ||
156 | new NonEmpty(lower, upper) | ||
157 | } | ||
158 | |||
159 | static def between(double lower, double upper) { | ||
160 | of(new BigDecimal(lower, ROUND_DOWN), new BigDecimal(upper, ROUND_UP)) | ||
161 | } | ||
162 | |||
163 | static def upTo(double upper) { | ||
164 | of(null, new BigDecimal(upper, ROUND_UP)) | ||
165 | } | ||
166 | |||
167 | static def above(double lower) { | ||
168 | of(new BigDecimal(lower, ROUND_DOWN), null) | ||
169 | } | ||
170 | |||
171 | @Data | ||
172 | private static class NonEmpty extends Interval { | ||
173 | val BigDecimal lower | ||
174 | val BigDecimal upper | ||
175 | |||
176 | /** | ||
177 | * Construct a new non-empty interval. | ||
178 | * | ||
179 | * @param lower The lower bound of the interval. Use <code>null</code> for negative infinity. | ||
180 | * @param upper The upper bound of the interval. Use <code>null</code> for positive infinity. | ||
181 | */ | ||
182 | new(BigDecimal lower, BigDecimal upper) { | ||
183 | if (lower !== null && upper !== null && lower > upper) { | ||
184 | throw new IllegalArgumentException("Lower bound of interval must not be larger than upper bound") | ||
185 | } | ||
186 | this.lower = lower | ||
187 | this.upper = upper | ||
188 | } | ||
189 | |||
190 | override mustEqual(Interval other) { | ||
191 | switch (other) { | ||
192 | case EMPTY: true | ||
193 | NonEmpty: lower == upper && lower == other.lower && lower == other.upper | ||
194 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
195 | } | ||
196 | } | ||
197 | |||
198 | override mayEqual(Interval other) { | ||
199 | if (other instanceof NonEmpty) { | ||
200 | (lower === null || other.upper === null || lower <= other.upper) && | ||
201 | (other.lower === null || upper === null || other.lower <= upper) | ||
202 | } else { | ||
203 | false | ||
204 | } | ||
205 | } | ||
206 | |||
207 | override mustBeLessThan(Interval other) { | ||
208 | switch (other) { | ||
209 | case EMPTY: true | ||
210 | NonEmpty: upper !== null && other.lower !== null && upper < other.lower | ||
211 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
212 | } | ||
213 | } | ||
214 | |||
215 | override mayBeLessThan(Interval other) { | ||
216 | if (other instanceof NonEmpty) { | ||
217 | lower === null || other.upper === null || lower < other.upper | ||
218 | } else { | ||
219 | false | ||
220 | } | ||
221 | } | ||
222 | |||
223 | override min(Interval other) { | ||
224 | switch (other) { | ||
225 | case EMPTY: this | ||
226 | NonEmpty: min(other) | ||
227 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
228 | } | ||
229 | } | ||
230 | |||
231 | def min(NonEmpty other) { | ||
232 | new NonEmpty( | ||
233 | lower.tryMin(other.lower), | ||
234 | if(other.upper === null) upper else if(upper === null) other.upper else upper.min(other.upper) | ||
235 | ) | ||
236 | } | ||
237 | |||
238 | override max(Interval other) { | ||
239 | switch (other) { | ||
240 | case EMPTY: this | ||
241 | NonEmpty: max(other) | ||
242 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
243 | } | ||
244 | } | ||
245 | |||
246 | def max(NonEmpty other) { | ||
247 | new NonEmpty( | ||
248 | if(other.lower === null) lower else if(lower === null) other.lower else lower.max(other.lower), | ||
249 | upper.tryMax(other.upper) | ||
250 | ) | ||
251 | } | ||
252 | |||
253 | override join(Interval other) { | ||
254 | switch (other) { | ||
255 | case EMPTY: this | ||
256 | NonEmpty: new NonEmpty(lower.tryMin(other.lower), upper.tryMax(other.upper)) | ||
257 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
258 | } | ||
259 | } | ||
260 | |||
261 | override -() { | ||
262 | new NonEmpty(upper?.negate(ROUND_DOWN), lower?.negate(ROUND_UP)) | ||
263 | } | ||
264 | |||
265 | override +(Interval other) { | ||
266 | switch (other) { | ||
267 | case EMPTY: EMPTY | ||
268 | NonEmpty: this + other | ||
269 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
270 | } | ||
271 | } | ||
272 | |||
273 | def +(NonEmpty other) { | ||
274 | new NonEmpty( | ||
275 | lower.tryAdd(other.lower, ROUND_DOWN), | ||
276 | upper.tryAdd(other.upper, ROUND_UP) | ||
277 | ) | ||
278 | } | ||
279 | |||
280 | private static def tryAdd(BigDecimal a, BigDecimal b, MathContext mc) { | ||
281 | if (b === null) { | ||
282 | null | ||
283 | } else { | ||
284 | a?.add(b, mc) | ||
285 | } | ||
286 | } | ||
287 | |||
288 | override -(Interval other) { | ||
289 | switch (other) { | ||
290 | case EMPTY: EMPTY | ||
291 | NonEmpty: this - other | ||
292 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
293 | } | ||
294 | } | ||
295 | |||
296 | def -(NonEmpty other) { | ||
297 | new NonEmpty( | ||
298 | lower.trySubtract(other.upper, ROUND_DOWN), | ||
299 | upper.trySubtract(other.lower, ROUND_UP) | ||
300 | ) | ||
301 | } | ||
302 | |||
303 | private static def trySubtract(BigDecimal a, BigDecimal b, MathContext mc) { | ||
304 | if (b === null) { | ||
305 | null | ||
306 | } else { | ||
307 | a?.subtract(b, mc) | ||
308 | } | ||
309 | } | ||
310 | |||
311 | override *(int count) { | ||
312 | val bigCount = new BigDecimal(count) | ||
313 | new NonEmpty( | ||
314 | lower.tryMultiply(bigCount, ROUND_DOWN), | ||
315 | upper.tryMultiply(bigCount, ROUND_UP) | ||
316 | ) | ||
317 | } | ||
318 | |||
319 | override *(Interval other) { | ||
320 | switch (other) { | ||
321 | case EMPTY: EMPTY | ||
322 | NonEmpty: this * other | ||
323 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
324 | } | ||
325 | } | ||
326 | |||
327 | def *(NonEmpty other) { | ||
328 | if (this == ZERO || other == ZERO) { | ||
329 | ZERO | ||
330 | } else if (nonpositive) { | ||
331 | if (other.nonpositive) { | ||
332 | new NonEmpty( | ||
333 | upper.multiply(other.upper, ROUND_DOWN), | ||
334 | lower.tryMultiply(other.lower, ROUND_UP) | ||
335 | ) | ||
336 | } else if (other.nonnegative) { | ||
337 | new NonEmpty( | ||
338 | lower.tryMultiply(other.upper, ROUND_DOWN), | ||
339 | upper.multiply(other.lower, ROUND_UP) | ||
340 | ) | ||
341 | } else { | ||
342 | new NonEmpty( | ||
343 | lower.tryMultiply(other.upper, ROUND_DOWN), | ||
344 | lower.tryMultiply(other.lower, ROUND_UP) | ||
345 | ) | ||
346 | } | ||
347 | } else if (nonnegative) { | ||
348 | if (other.nonpositive) { | ||
349 | new NonEmpty( | ||
350 | upper.tryMultiply(other.lower, ROUND_DOWN), | ||
351 | lower.multiply(other.upper, ROUND_UP) | ||
352 | ) | ||
353 | } else if (other.nonnegative) { | ||
354 | new NonEmpty( | ||
355 | lower.multiply(other.lower, ROUND_DOWN), | ||
356 | upper.tryMultiply(other.upper, ROUND_UP) | ||
357 | ) | ||
358 | } else { | ||
359 | new NonEmpty( | ||
360 | upper.tryMultiply(other.lower, ROUND_DOWN), | ||
361 | upper.tryMultiply(other.upper, ROUND_UP) | ||
362 | ) | ||
363 | } | ||
364 | } else { | ||
365 | if (other.nonpositive) { | ||
366 | new NonEmpty( | ||
367 | upper.tryMultiply(other.lower, ROUND_DOWN), | ||
368 | lower.tryMultiply(other.lower, ROUND_UP) | ||
369 | ) | ||
370 | } else if (other.nonnegative) { | ||
371 | new NonEmpty( | ||
372 | lower.tryMultiply(other.upper, ROUND_DOWN), | ||
373 | upper.tryMultiply(other.upper, ROUND_UP) | ||
374 | ) | ||
375 | } else { | ||
376 | new NonEmpty( | ||
377 | lower.tryMultiply(other.upper, ROUND_DOWN).tryMin(upper.tryMultiply(other.lower, ROUND_DOWN)), | ||
378 | lower.tryMultiply(other.lower, ROUND_UP).tryMax(upper.tryMultiply(other.upper, ROUND_UP)) | ||
379 | ) | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | |||
384 | private def isNonpositive() { | ||
385 | upper !== null && upper <= BigDecimal.ZERO | ||
386 | } | ||
387 | |||
388 | private def isNonnegative() { | ||
389 | lower !== null && lower >= BigDecimal.ZERO | ||
390 | } | ||
391 | |||
392 | private static def tryMultiply(BigDecimal a, BigDecimal b, MathContext mc) { | ||
393 | if (b === null) { | ||
394 | null | ||
395 | } else { | ||
396 | a?.multiply(b, mc) | ||
397 | } | ||
398 | } | ||
399 | |||
400 | private static def tryMin(BigDecimal a, BigDecimal b) { | ||
401 | if (b === null) { | ||
402 | null | ||
403 | } else { | ||
404 | a?.min(b) | ||
405 | } | ||
406 | } | ||
407 | |||
408 | private static def tryMax(BigDecimal a, BigDecimal b) { | ||
409 | if (b === null) { | ||
410 | null | ||
411 | } else { | ||
412 | a?.max(b) | ||
413 | } | ||
414 | } | ||
415 | |||
416 | override /(Interval other) { | ||
417 | switch (other) { | ||
418 | case EMPTY: EMPTY | ||
419 | NonEmpty: this / other | ||
420 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
421 | } | ||
422 | } | ||
423 | |||
424 | def /(NonEmpty other) { | ||
425 | if (other == ZERO) { | ||
426 | EMPTY | ||
427 | } else if (this == ZERO) { | ||
428 | ZERO | ||
429 | } else if (other.strictlyNegative) { | ||
430 | if (nonpositive) { | ||
431 | new NonEmpty( | ||
432 | upper.tryDivide(other.lower, ROUND_DOWN), | ||
433 | lower.tryDivide(other.upper, ROUND_UP) | ||
434 | ) | ||
435 | } else if (nonnegative) { | ||
436 | new NonEmpty( | ||
437 | upper.tryDivide(other.upper, ROUND_DOWN), | ||
438 | lower.tryDivide(other.lower, ROUND_UP) | ||
439 | ) | ||
440 | } else { // lower < 0 < upper | ||
441 | new NonEmpty( | ||
442 | upper.tryDivide(other.upper, ROUND_DOWN), | ||
443 | lower.tryDivide(other.upper, ROUND_UP) | ||
444 | ) | ||
445 | } | ||
446 | } else if (other.strictlyPositive) { | ||
447 | if (nonpositive) { | ||
448 | new NonEmpty( | ||
449 | lower.tryDivide(other.lower, ROUND_DOWN), | ||
450 | upper.tryDivide(other.upper, ROUND_UP) | ||
451 | ) | ||
452 | } else if (nonnegative) { | ||
453 | new NonEmpty( | ||
454 | lower.tryDivide(other.upper, ROUND_DOWN), | ||
455 | upper.tryDivide(other.lower, ROUND_UP) | ||
456 | ) | ||
457 | } else { // lower < 0 < upper | ||
458 | new NonEmpty( | ||
459 | lower.tryDivide(other.lower, ROUND_DOWN), | ||
460 | upper.tryDivide(other.lower, ROUND_UP) | ||
461 | ) | ||
462 | } | ||
463 | } else { // other contains 0 | ||
464 | if (other.lower == BigDecimal.ZERO) { // 0 == other.lower < other.upper, because [0, 0] was exluded earlier | ||
465 | if (nonpositive) { | ||
466 | new NonEmpty(null, upper.tryDivide(other.upper, ROUND_UP)) | ||
467 | } else if (nonnegative) { | ||
468 | new NonEmpty(lower.tryDivide(other.upper, ROUND_DOWN), null) | ||
469 | } else { // lower < 0 < upper | ||
470 | UNBOUNDED | ||
471 | } | ||
472 | } else if (other.upper == BigDecimal.ZERO) { // other.lower < other.upper == 0 | ||
473 | if (nonpositive) { | ||
474 | new NonEmpty(upper.tryDivide(other.lower, ROUND_DOWN), null) | ||
475 | } else if (nonnegative) { | ||
476 | new NonEmpty(null, lower.tryDivide(other.lower, ROUND_UP)) | ||
477 | } else { // lower < 0 < upper | ||
478 | UNBOUNDED | ||
479 | } | ||
480 | } else { // other.lower < 0 < other.upper | ||
481 | UNBOUNDED | ||
482 | } | ||
483 | } | ||
484 | } | ||
485 | |||
486 | private def isStrictlyNegative() { | ||
487 | upper !== null && upper < BigDecimal.ZERO | ||
488 | } | ||
489 | |||
490 | private def isStrictlyPositive() { | ||
491 | lower !== null && lower > BigDecimal.ZERO | ||
492 | } | ||
493 | |||
494 | private static def tryDivide(BigDecimal a, BigDecimal b, MathContext mc) { | ||
495 | if (b === null) { | ||
496 | BigDecimal.ZERO | ||
497 | } else { | ||
498 | a?.divide(b, mc) | ||
499 | } | ||
500 | } | ||
501 | |||
502 | override **(Interval other) { | ||
503 | switch (other) { | ||
504 | case EMPTY: EMPTY | ||
505 | NonEmpty: this ** other | ||
506 | default: throw new IllegalArgumentException("Unknown interval: " + other) | ||
507 | } | ||
508 | } | ||
509 | |||
510 | def **(NonEmpty other) { | ||
511 | // XXX This should use proper rounding for log and exp instead of | ||
512 | // converting to double. | ||
513 | // XXX We should not ignore (integer) powers of negative numbers. | ||
514 | val lowerLog = if (lower === null || lower <= BigDecimal.ZERO) { | ||
515 | null | ||
516 | } else { | ||
517 | new BigDecimal(Math.log(lower.doubleValue), ROUND_DOWN) | ||
518 | } | ||
519 | val upperLog = if (upper === null) { | ||
520 | null | ||
521 | } else if (upper == BigDecimal.ZERO) { | ||
522 | return ZERO | ||
523 | } else if (upper < BigDecimal.ZERO) { | ||
524 | return EMPTY | ||
525 | } else { | ||
526 | new BigDecimal(Math.log(upper.doubleValue), ROUND_UP) | ||
527 | } | ||
528 | val log = new NonEmpty(lowerLog, upperLog) | ||
529 | val product = log * other | ||
530 | if (product instanceof NonEmpty) { | ||
531 | val lowerResult = if (product.lower === null) { | ||
532 | BigDecimal.ZERO | ||
533 | } else { | ||
534 | new BigDecimal(Math.exp(product.lower.doubleValue), ROUND_DOWN) | ||
535 | } | ||
536 | val upperResult = if (product.upper === null) { | ||
537 | null | ||
538 | } else { | ||
539 | new BigDecimal(Math.exp(product.upper.doubleValue), ROUND_UP) | ||
540 | } | ||
541 | new NonEmpty(lowerResult, upperResult) | ||
542 | } else { | ||
543 | throw new IllegalArgumentException("Unknown interval: " + product) | ||
544 | } | ||
545 | } | ||
546 | |||
547 | override toString() { | ||
548 | '''«IF lower === null»(-∞«ELSE»[«lower»«ENDIF», «IF upper === null»∞)«ELSE»«upper»]«ENDIF»''' | ||
549 | } | ||
550 | |||
551 | override compareTo(Interval o) { | ||
552 | switch (o) { | ||
553 | case EMPTY: 1 | ||
554 | NonEmpty: compareTo(o) | ||
555 | default: throw new IllegalArgumentException("Unknown interval: " + o) | ||
556 | } | ||
557 | } | ||
558 | |||
559 | def compareTo(NonEmpty o) { | ||
560 | if (lower === null) { | ||
561 | if (o.lower !== null) { | ||
562 | return -1 | ||
563 | } | ||
564 | } else if (o.lower === null) { // lower !== null | ||
565 | return 1 | ||
566 | } else { // both lower and o.lower are finite | ||
567 | val lowerDifference = lower.compareTo(o.lower) | ||
568 | if (lowerDifference != 0) { | ||
569 | return lowerDifference | ||
570 | } | ||
571 | } | ||
572 | if (upper === null) { | ||
573 | if (o.upper === null) { | ||
574 | return 0 | ||
575 | } else { | ||
576 | return 1 | ||
577 | } | ||
578 | } else if (o.upper === null) { // upper !== null | ||
579 | return -1 | ||
580 | } | ||
581 | upper.compareTo(o.upper) | ||
582 | } | ||
583 | } | ||
584 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalAggregationMode.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalAggregationMode.java new file mode 100644 index 00000000..f106e305 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalAggregationMode.java | |||
@@ -0,0 +1,99 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval; | ||
2 | |||
3 | import java.util.function.BinaryOperator; | ||
4 | |||
5 | public enum IntervalAggregationMode implements BinaryOperator<Interval> { | ||
6 | SUM("intervalSum", "Sum a set of intervals") { | ||
7 | @Override | ||
8 | public IntervalRedBlackNode createNode(Interval interval) { | ||
9 | return new IntervalRedBlackNode(interval) { | ||
10 | public boolean isMultiplicitySensitive() { | ||
11 | return true; | ||
12 | } | ||
13 | |||
14 | public Interval multiply(Interval interval, int count) { | ||
15 | return interval.operator_multiply(count); | ||
16 | }; | ||
17 | |||
18 | @Override | ||
19 | public Interval op(Interval left, Interval right) { | ||
20 | return left.operator_plus(right); | ||
21 | } | ||
22 | }; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public Interval getNeutral() { | ||
27 | return Interval.ZERO; | ||
28 | } | ||
29 | }, | ||
30 | |||
31 | MIN("intervalMin", "Find the minimum a set of intervals") { | ||
32 | @Override | ||
33 | public IntervalRedBlackNode createNode(Interval interval) { | ||
34 | return new IntervalRedBlackNode(interval) { | ||
35 | @Override | ||
36 | public Interval op(Interval left, Interval right) { | ||
37 | return left.min(right); | ||
38 | } | ||
39 | }; | ||
40 | } | ||
41 | }, | ||
42 | |||
43 | MAX("intervalMax", "Find the maximum a set of intervals") { | ||
44 | @Override | ||
45 | public IntervalRedBlackNode createNode(Interval interval) { | ||
46 | return new IntervalRedBlackNode(interval) { | ||
47 | @Override | ||
48 | public Interval op(Interval left, Interval right) { | ||
49 | return left.max(right); | ||
50 | } | ||
51 | }; | ||
52 | } | ||
53 | }, | ||
54 | |||
55 | JOIN("intervalJoin", "Calculate the smallest interval containing all the intervals in a set") { | ||
56 | @Override | ||
57 | public IntervalRedBlackNode createNode(Interval interval) { | ||
58 | return new IntervalRedBlackNode(interval) { | ||
59 | @Override | ||
60 | public Interval op(Interval left, Interval right) { | ||
61 | return left.join(right); | ||
62 | } | ||
63 | }; | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | private final String modeName; | ||
68 | private final String description; | ||
69 | private final IntervalRedBlackNode empty; | ||
70 | |||
71 | IntervalAggregationMode(String modeName, String description) { | ||
72 | this.modeName = modeName; | ||
73 | this.description = description; | ||
74 | empty = createNode(null); | ||
75 | } | ||
76 | |||
77 | public String getModeName() { | ||
78 | return modeName; | ||
79 | } | ||
80 | |||
81 | public String getDescription() { | ||
82 | return description; | ||
83 | } | ||
84 | |||
85 | public IntervalRedBlackNode getEmpty() { | ||
86 | return empty; | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public Interval apply(Interval left, Interval right) { | ||
91 | return empty.op(left, right); | ||
92 | } | ||
93 | |||
94 | public abstract IntervalRedBlackNode createNode(Interval interval); | ||
95 | |||
96 | public Interval getNeutral() { | ||
97 | return Interval.EMPTY; | ||
98 | } | ||
99 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalAggregationOperator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalAggregationOperator.xtend new file mode 100644 index 00000000..21d3d73b --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalAggregationOperator.xtend | |||
@@ -0,0 +1,48 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval | ||
2 | |||
3 | import java.util.stream.Stream | ||
4 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator | ||
5 | import org.eclipse.xtend.lib.annotations.Accessors | ||
6 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
7 | |||
8 | @FinalFieldsConstructor | ||
9 | class IntervalAggregationOperator implements IMultisetAggregationOperator<Interval, IntervalRedBlackNode, Interval> { | ||
10 | @Accessors val IntervalAggregationMode mode | ||
11 | |||
12 | override getName() { | ||
13 | mode.modeName | ||
14 | } | ||
15 | |||
16 | override getShortDescription() { | ||
17 | mode.description | ||
18 | } | ||
19 | |||
20 | override createNeutral() { | ||
21 | mode.empty | ||
22 | } | ||
23 | |||
24 | override isNeutral(IntervalRedBlackNode result) { | ||
25 | result.leaf | ||
26 | } | ||
27 | |||
28 | override update(IntervalRedBlackNode oldResult, Interval updateValue, boolean isInsertion) { | ||
29 | if (isInsertion) { | ||
30 | val newNode = mode.createNode(updateValue) | ||
31 | oldResult.add(newNode) | ||
32 | } else { | ||
33 | oldResult.remove(updateValue) | ||
34 | } | ||
35 | } | ||
36 | |||
37 | override getAggregate(IntervalRedBlackNode result) { | ||
38 | if (result.leaf) { | ||
39 | mode.neutral | ||
40 | } else { | ||
41 | result.result | ||
42 | } | ||
43 | } | ||
44 | |||
45 | override aggregateStream(Stream<Interval> stream) { | ||
46 | stream.reduce(mode).orElse(mode.neutral) | ||
47 | } | ||
48 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalHullAggregatorOperator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalHullAggregatorOperator.xtend new file mode 100644 index 00000000..ce48eca1 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalHullAggregatorOperator.xtend | |||
@@ -0,0 +1,87 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval | ||
2 | |||
3 | import java.math.BigDecimal | ||
4 | import java.math.MathContext | ||
5 | import java.util.SortedMap | ||
6 | import java.util.TreeMap | ||
7 | import java.util.stream.Stream | ||
8 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator | ||
9 | |||
10 | abstract class IntervalHullAggregatorOperator<T extends Comparable<T>> implements IMultisetAggregationOperator<T, SortedMap<T, Integer>, Interval> { | ||
11 | protected new() { | ||
12 | } | ||
13 | |||
14 | override getName() { | ||
15 | "intervalHull" | ||
16 | } | ||
17 | |||
18 | override getShortDescription() { | ||
19 | "Calculates the interval hull of a set of numbers" | ||
20 | } | ||
21 | |||
22 | override createNeutral() { | ||
23 | new TreeMap | ||
24 | } | ||
25 | |||
26 | override getAggregate(SortedMap<T, Integer> result) { | ||
27 | if (result.neutral) { | ||
28 | Interval.EMPTY | ||
29 | } else { | ||
30 | toInterval(result.firstKey, result.lastKey) | ||
31 | } | ||
32 | } | ||
33 | |||
34 | protected abstract def BigDecimal toBigDecimal(T value, MathContext mc) | ||
35 | |||
36 | private def toInterval(T min, T max) { | ||
37 | Interval.of(min.toBigDecimal(Interval.ROUND_DOWN), max.toBigDecimal(Interval.ROUND_UP)) | ||
38 | } | ||
39 | |||
40 | override isNeutral(SortedMap<T, Integer> result) { | ||
41 | result.empty | ||
42 | } | ||
43 | |||
44 | override update(SortedMap<T, Integer> oldResult, T updateValue, boolean isInsertion) { | ||
45 | if (isInsertion) { | ||
46 | oldResult.compute(updateValue) [ key, value | | ||
47 | if (value === null) { | ||
48 | 1 | ||
49 | } else if (value > 0) { | ||
50 | value + 1 | ||
51 | } else { | ||
52 | throw new IllegalStateException("Invalid count: " + value) | ||
53 | } | ||
54 | ] | ||
55 | } else { | ||
56 | oldResult.compute(updateValue) [ key, value | | ||
57 | if (value === 1) { | ||
58 | null | ||
59 | } else if (value > 1) { | ||
60 | value - 1 | ||
61 | } else { | ||
62 | throw new IllegalStateException("Invalid count: " + value) | ||
63 | } | ||
64 | ] | ||
65 | } | ||
66 | oldResult | ||
67 | } | ||
68 | |||
69 | override aggregateStream(Stream<T> stream) { | ||
70 | val iterator = stream.iterator | ||
71 | if (!iterator.hasNext) { | ||
72 | return Interval.EMPTY | ||
73 | } | ||
74 | var min = iterator.next | ||
75 | var max = min | ||
76 | while (iterator.hasNext) { | ||
77 | val element = iterator.next | ||
78 | if (element.compareTo(min) < 0) { | ||
79 | min = element | ||
80 | } | ||
81 | if (element.compareTo(max) > 0) { | ||
82 | max = element | ||
83 | } | ||
84 | } | ||
85 | toInterval(min, max) | ||
86 | } | ||
87 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalRedBlackNode.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalRedBlackNode.xtend new file mode 100644 index 00000000..3aa575bc --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalRedBlackNode.xtend | |||
@@ -0,0 +1,177 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval | ||
2 | |||
3 | abstract class IntervalRedBlackNode extends RedBlackNode<IntervalRedBlackNode> { | ||
4 | public val Interval interval | ||
5 | public var int count = 1 | ||
6 | public var Interval result | ||
7 | |||
8 | new(Interval interval) { | ||
9 | this.interval = interval | ||
10 | } | ||
11 | |||
12 | def boolean isMultiplicitySensitive() { | ||
13 | false | ||
14 | } | ||
15 | |||
16 | def Interval multiply(Interval interval, int count) { | ||
17 | interval | ||
18 | } | ||
19 | |||
20 | abstract def Interval op(Interval left, Interval right) | ||
21 | |||
22 | override augment() { | ||
23 | val value = calcualteAugmentation() | ||
24 | if (result == value) { | ||
25 | false | ||
26 | } else { | ||
27 | result = value | ||
28 | true | ||
29 | } | ||
30 | } | ||
31 | |||
32 | private def calcualteAugmentation() { | ||
33 | var value = multiply(interval, count) | ||
34 | if (!left.leaf) { | ||
35 | value = op(value, left.result) | ||
36 | } | ||
37 | if (!right.leaf) { | ||
38 | value = op(value, right.result) | ||
39 | } | ||
40 | value | ||
41 | } | ||
42 | |||
43 | override assertNodeIsValid() { | ||
44 | super.assertNodeIsValid() | ||
45 | if (leaf) { | ||
46 | return | ||
47 | } | ||
48 | if (count <= 0) { | ||
49 | throw new IllegalStateException("Node with nonpositive count") | ||
50 | } | ||
51 | val value = calcualteAugmentation() | ||
52 | if (result != value) { | ||
53 | throw new IllegalStateException("Node with invalid augmentation: " + result + " != " + value) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | override assertSubtreeIsValid() { | ||
58 | super.assertSubtreeIsValid() | ||
59 | assertNodeIsValid() | ||
60 | } | ||
61 | |||
62 | override compareTo(IntervalRedBlackNode other) { | ||
63 | if (leaf || other.leaf) { | ||
64 | throw new IllegalArgumentException("One of the nodes is a leaf node") | ||
65 | } | ||
66 | interval.compareTo(other.interval) | ||
67 | } | ||
68 | |||
69 | def add(IntervalRedBlackNode newNode) { | ||
70 | if (parent !== null) { | ||
71 | throw new IllegalArgumentException("This is not the root of a tree") | ||
72 | } | ||
73 | if (leaf) { | ||
74 | newNode.isRed = false | ||
75 | newNode.left = this | ||
76 | newNode.right = this | ||
77 | newNode.parent = null | ||
78 | newNode.augment | ||
79 | return newNode | ||
80 | } | ||
81 | val modifiedNode = addWithoutFixup(newNode) | ||
82 | if (modifiedNode === newNode) { | ||
83 | // Must augment here, because fixInsertion() might call augment() | ||
84 | // on a node repeatedly, which might lose the change notification the | ||
85 | // second time it is called, and the augmentation will fail to | ||
86 | // reach the root. | ||
87 | modifiedNode.augmentRecursively | ||
88 | modifiedNode.isRed = true | ||
89 | return modifiedNode.fixInsertion | ||
90 | } | ||
91 | if (multiplicitySensitive) { | ||
92 | modifiedNode.augmentRecursively | ||
93 | } | ||
94 | this | ||
95 | } | ||
96 | |||
97 | private def addWithoutFixup(IntervalRedBlackNode newNode) { | ||
98 | var node = this | ||
99 | while (!node.leaf) { | ||
100 | val comparison = node.interval.compareTo(newNode.interval) | ||
101 | if (comparison < 0) { | ||
102 | if (node.left.leaf) { | ||
103 | newNode.left = node.left | ||
104 | newNode.right = node.left | ||
105 | node.left = newNode | ||
106 | newNode.parent = node | ||
107 | return newNode | ||
108 | } else { | ||
109 | node = node.left | ||
110 | } | ||
111 | } else if (comparison > 0) { | ||
112 | if (node.right.leaf) { | ||
113 | newNode.left = node.right | ||
114 | newNode.right = node.right | ||
115 | node.right = newNode | ||
116 | newNode.parent = node | ||
117 | return newNode | ||
118 | } else { | ||
119 | node = node.right | ||
120 | } | ||
121 | } else { // comparison == 0 | ||
122 | newNode.parent = null | ||
123 | node.count++ | ||
124 | return node | ||
125 | } | ||
126 | } | ||
127 | throw new IllegalStateException("Reached leaf node while searching for insertion point") | ||
128 | } | ||
129 | |||
130 | private def augmentRecursively() { | ||
131 | for (var node = this; node !== null; node = node.parent) { | ||
132 | if (!node.augment) { | ||
133 | return | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | def remove(Interval interval) { | ||
139 | val node = find(interval) | ||
140 | node.count-- | ||
141 | if (node.count == 0) { | ||
142 | return node.remove | ||
143 | } | ||
144 | if (multiplicitySensitive) { | ||
145 | node.augmentRecursively | ||
146 | } | ||
147 | this | ||
148 | } | ||
149 | |||
150 | private def find(Interval interval) { | ||
151 | var node = this | ||
152 | while (!node.leaf) { | ||
153 | val comparison = node.interval.compareTo(interval) | ||
154 | if (comparison < 0) { | ||
155 | node = node.left | ||
156 | } else if (comparison > 0) { | ||
157 | node = node.right | ||
158 | } else { // comparison == 0 | ||
159 | return node | ||
160 | } | ||
161 | } | ||
162 | throw new IllegalStateException("Reached leaf node while searching for interval to remove") | ||
163 | } | ||
164 | |||
165 | override toString() { | ||
166 | if (leaf) { | ||
167 | "L" | ||
168 | } else { | ||
169 | ''' | ||
170 | «IF isRed»R«ELSE»B«ENDIF» «count»«interval» : «result» | ||
171 | «left» | ||
172 | «right» | ||
173 | ''' | ||
174 | } | ||
175 | } | ||
176 | |||
177 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/RedBlackNode.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/RedBlackNode.java new file mode 100644 index 00000000..8c40816b --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/RedBlackNode.java | |||
@@ -0,0 +1,1392 @@ | |||
1 | /* | ||
2 | * The MIT License (MIT) | ||
3 | * | ||
4 | * Copyright (c) 2016 btrekkie | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | * of this software and associated documentation files (the "Software"), to deal | ||
8 | * in the Software without restriction, including without limitation the rights | ||
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | * copies of the Software, and to permit persons to whom the Software is | ||
11 | * furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be included in all | ||
14 | * copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | * SOFTWARE. | ||
23 | */ | ||
24 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval; | ||
25 | |||
26 | import java.lang.reflect.Array; | ||
27 | import java.util.Collection; | ||
28 | import java.util.Comparator; | ||
29 | import java.util.HashSet; | ||
30 | import java.util.Iterator; | ||
31 | import java.util.Set; | ||
32 | |||
33 | /** | ||
34 | * A node in a red-black tree ( https://en.wikipedia.org/wiki/Red%E2%80%93black_tree ). Compared to a class like Java's | ||
35 | * TreeMap, RedBlackNode is a low-level data structure. The internals of a node are exposed as public fields, allowing | ||
36 | * clients to directly observe and manipulate the structure of the tree. This gives clients flexibility, although it | ||
37 | * also enables them to violate the red-black or BST properties. The RedBlackNode class provides methods for performing | ||
38 | * various standard operations, such as insertion and removal. | ||
39 | * | ||
40 | * Unlike most implementations of binary search trees, RedBlackNode supports arbitrary augmentation. By subclassing | ||
41 | * RedBlackNode, clients can add arbitrary data and augmentation information to each node. For example, if we were to | ||
42 | * use a RedBlackNode subclass to implement a sorted set, the subclass would have a field storing an element in the set. | ||
43 | * If we wanted to keep track of the number of non-leaf nodes in each subtree, we would store this as a "size" field and | ||
44 | * override augment() to update this field. All RedBlackNode methods (such as "insert" and remove()) call augment() as | ||
45 | * necessary to correctly maintain the augmentation information, unless otherwise indicated. | ||
46 | * | ||
47 | * The values of the tree are stored in the non-leaf nodes. RedBlackNode does not support use cases where values must be | ||
48 | * stored in the leaf nodes. It is recommended that all of the leaf nodes in a given tree be the same (black) | ||
49 | * RedBlackNode instance, to save space. The root of an empty tree is a leaf node, as opposed to null. | ||
50 | * | ||
51 | * For reference, a red-black tree is a binary search tree satisfying the following properties: | ||
52 | * | ||
53 | * - Every node is colored red or black. | ||
54 | * - The leaf nodes, which are dummy nodes that do not store any values, are colored black. | ||
55 | * - The root is black. | ||
56 | * - Both children of each red node are black. | ||
57 | * - Every path from the root to a leaf contains the same number of black nodes. | ||
58 | * | ||
59 | * @param <N> The type of node in the tree. For example, we might have | ||
60 | * "class FooNode<T> extends RedBlackNode<FooNode<T>>". | ||
61 | * @author Bill Jacobs | ||
62 | */ | ||
63 | public abstract class RedBlackNode<N extends RedBlackNode<N>> implements Comparable<N> { | ||
64 | /** A Comparator that compares Comparable elements using their natural order. */ | ||
65 | private static final Comparator<Comparable<Object>> NATURAL_ORDER = new Comparator<Comparable<Object>>() { | ||
66 | @Override | ||
67 | public int compare(Comparable<Object> value1, Comparable<Object> value2) { | ||
68 | return value1.compareTo(value2); | ||
69 | } | ||
70 | }; | ||
71 | |||
72 | /** The parent of this node, if any. "parent" is null if this is a leaf node. */ | ||
73 | public N parent; | ||
74 | |||
75 | /** The left child of this node. "left" is null if this is a leaf node. */ | ||
76 | public N left; | ||
77 | |||
78 | /** The right child of this node. "right" is null if this is a leaf node. */ | ||
79 | public N right; | ||
80 | |||
81 | /** Whether the node is colored red, as opposed to black. */ | ||
82 | public boolean isRed; | ||
83 | |||
84 | /** | ||
85 | * Sets any augmentation information about the subtree rooted at this node that is stored in this node. For | ||
86 | * example, if we augment each node by subtree size (the number of non-leaf nodes in the subtree), this method would | ||
87 | * set the size field of this node to be equal to the size field of the left child plus the size field of the right | ||
88 | * child plus one. | ||
89 | * | ||
90 | * "Augmentation information" is information that we can compute about a subtree rooted at some node, preferably | ||
91 | * based only on the augmentation information in the node's two children and the information in the node. Examples | ||
92 | * of augmentation information are the sum of the values in a subtree and the number of non-leaf nodes in a subtree. | ||
93 | * Augmentation information may not depend on the colors of the nodes. | ||
94 | * | ||
95 | * This method returns whether the augmentation information in any of the ancestors of this node might have been | ||
96 | * affected by changes in this subtree since the last call to augment(). In the usual case, where the augmentation | ||
97 | * information depends only on the information in this node and the augmentation information in its immediate | ||
98 | * children, this is equivalent to whether the augmentation information changed as a result of this call to | ||
99 | * augment(). For example, in the case of subtree size, this returns whether the value of the size field prior to | ||
100 | * calling augment() differed from the size field of the left child plus the size field of the right child plus one. | ||
101 | * False positives are permitted. The return value is unspecified if we have not called augment() on this node | ||
102 | * before. | ||
103 | * | ||
104 | * This method may assume that this is not a leaf node. It may not assume that the augmentation information stored | ||
105 | * in any of the tree's nodes is correct. However, if the augmentation information stored in all of the node's | ||
106 | * descendants is correct, then the augmentation information stored in this node must be correct after calling | ||
107 | * augment(). | ||
108 | */ | ||
109 | public boolean augment() { | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Throws a RuntimeException if we detect that this node locally violates any invariants specific to this subclass | ||
115 | * of RedBlackNode. For example, if this stores the size of the subtree rooted at this node, this should throw a | ||
116 | * RuntimeException if the size field of this is not equal to the size field of the left child plus the size field | ||
117 | * of the right child plus one. Note that we may call this on a leaf node. | ||
118 | * | ||
119 | * assertSubtreeIsValid() calls assertNodeIsValid() on each node, or at least starts to do so until it detects a | ||
120 | * problem. assertNodeIsValid() should assume the node is in a tree that satisfies all properties common to all | ||
121 | * red-black trees, as assertSubtreeIsValid() is responsible for such checks. assertNodeIsValid() should be | ||
122 | * "downward-looking", i.e. it should ignore any information in "parent", and it should be "local", i.e. it should | ||
123 | * only check a constant number of descendants. To include "global" checks, such as verifying the BST property | ||
124 | * concerning ordering, override assertSubtreeIsValid(). assertOrderIsValid is useful for checking the BST | ||
125 | * property. | ||
126 | */ | ||
127 | public void assertNodeIsValid() { | ||
128 | |||
129 | } | ||
130 | |||
131 | /** Returns whether this is a leaf node. */ | ||
132 | public boolean isLeaf() { | ||
133 | return left == null; | ||
134 | } | ||
135 | |||
136 | /** Returns the root of the tree that contains this node. */ | ||
137 | public N root() { | ||
138 | @SuppressWarnings("unchecked") | ||
139 | N node = (N)this; | ||
140 | while (node.parent != null) { | ||
141 | node = node.parent; | ||
142 | } | ||
143 | return node; | ||
144 | } | ||
145 | |||
146 | /** Returns the first node in the subtree rooted at this node, if any. */ | ||
147 | public N min() { | ||
148 | if (isLeaf()) { | ||
149 | return null; | ||
150 | } | ||
151 | @SuppressWarnings("unchecked") | ||
152 | N node = (N)this; | ||
153 | while (!node.left.isLeaf()) { | ||
154 | node = node.left; | ||
155 | } | ||
156 | return node; | ||
157 | } | ||
158 | |||
159 | /** Returns the last node in the subtree rooted at this node, if any. */ | ||
160 | public N max() { | ||
161 | if (isLeaf()) { | ||
162 | return null; | ||
163 | } | ||
164 | @SuppressWarnings("unchecked") | ||
165 | N node = (N)this; | ||
166 | while (!node.right.isLeaf()) { | ||
167 | node = node.right; | ||
168 | } | ||
169 | return node; | ||
170 | } | ||
171 | |||
172 | /** Returns the node immediately before this in the tree that contains this node, if any. */ | ||
173 | public N predecessor() { | ||
174 | if (!left.isLeaf()) { | ||
175 | N node; | ||
176 | for (node = left; !node.right.isLeaf(); node = node.right); | ||
177 | return node; | ||
178 | } else if (parent == null) { | ||
179 | return null; | ||
180 | } else { | ||
181 | @SuppressWarnings("unchecked") | ||
182 | N node = (N)this; | ||
183 | while (node.parent != null && node.parent.left == node) { | ||
184 | node = node.parent; | ||
185 | } | ||
186 | return node.parent; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | /** Returns the node immediately after this in the tree that contains this node, if any. */ | ||
191 | public N successor() { | ||
192 | if (!right.isLeaf()) { | ||
193 | N node; | ||
194 | for (node = right; !node.left.isLeaf(); node = node.left); | ||
195 | return node; | ||
196 | } else if (parent == null) { | ||
197 | return null; | ||
198 | } else { | ||
199 | @SuppressWarnings("unchecked") | ||
200 | N node = (N)this; | ||
201 | while (node.parent != null && node.parent.right == node) { | ||
202 | node = node.parent; | ||
203 | } | ||
204 | return node.parent; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * Performs a left rotation about this node. This method assumes that !isLeaf() && !right.isLeaf(). It calls | ||
210 | * augment() on this node and on its resulting parent. However, it does not call augment() on any of the resulting | ||
211 | * parent's ancestors, because that is normally the responsibility of the caller. | ||
212 | * @return The return value from calling augment() on the resulting parent. | ||
213 | */ | ||
214 | public boolean rotateLeft() { | ||
215 | if (isLeaf() || right.isLeaf()) { | ||
216 | throw new IllegalArgumentException("The node or its right child is a leaf"); | ||
217 | } | ||
218 | N newParent = right; | ||
219 | right = newParent.left; | ||
220 | @SuppressWarnings("unchecked") | ||
221 | N nThis = (N)this; | ||
222 | if (!right.isLeaf()) { | ||
223 | right.parent = nThis; | ||
224 | } | ||
225 | newParent.parent = parent; | ||
226 | parent = newParent; | ||
227 | newParent.left = nThis; | ||
228 | if (newParent.parent != null) { | ||
229 | if (newParent.parent.left == this) { | ||
230 | newParent.parent.left = newParent; | ||
231 | } else { | ||
232 | newParent.parent.right = newParent; | ||
233 | } | ||
234 | } | ||
235 | augment(); | ||
236 | return newParent.augment(); | ||
237 | } | ||
238 | |||
239 | /** | ||
240 | * Performs a right rotation about this node. This method assumes that !isLeaf() && !left.isLeaf(). It calls | ||
241 | * augment() on this node and on its resulting parent. However, it does not call augment() on any of the resulting | ||
242 | * parent's ancestors, because that is normally the responsibility of the caller. | ||
243 | * @return The return value from calling augment() on the resulting parent. | ||
244 | */ | ||
245 | public boolean rotateRight() { | ||
246 | if (isLeaf() || left.isLeaf()) { | ||
247 | throw new IllegalArgumentException("The node or its left child is a leaf"); | ||
248 | } | ||
249 | N newParent = left; | ||
250 | left = newParent.right; | ||
251 | @SuppressWarnings("unchecked") | ||
252 | N nThis = (N)this; | ||
253 | if (!left.isLeaf()) { | ||
254 | left.parent = nThis; | ||
255 | } | ||
256 | newParent.parent = parent; | ||
257 | parent = newParent; | ||
258 | newParent.right = nThis; | ||
259 | if (newParent.parent != null) { | ||
260 | if (newParent.parent.left == this) { | ||
261 | newParent.parent.left = newParent; | ||
262 | } else { | ||
263 | newParent.parent.right = newParent; | ||
264 | } | ||
265 | } | ||
266 | augment(); | ||
267 | return newParent.augment(); | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * Performs red-black insertion fixup. To be more precise, this fixes a tree that satisfies all of the requirements | ||
272 | * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be | ||
273 | * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs | ||
274 | * any rotations by calling rotateLeft() and rotateRight(). This method is more efficient than fixInsertion if | ||
275 | * "augment" is false or augment() might return false. | ||
276 | * @param augment Whether to set the augmentation information for "node" and its ancestors, by calling augment(). | ||
277 | */ | ||
278 | public void fixInsertionWithoutGettingRoot(boolean augment) { | ||
279 | if (!isRed) { | ||
280 | throw new IllegalArgumentException("The node must be red"); | ||
281 | } | ||
282 | boolean changed = augment; | ||
283 | if (augment) { | ||
284 | augment(); | ||
285 | } | ||
286 | |||
287 | RedBlackNode<N> node = this; | ||
288 | while (node.parent != null && node.parent.isRed) { | ||
289 | N parent = node.parent; | ||
290 | N grandparent = parent.parent; | ||
291 | if (grandparent.left.isRed && grandparent.right.isRed) { | ||
292 | grandparent.left.isRed = false; | ||
293 | grandparent.right.isRed = false; | ||
294 | grandparent.isRed = true; | ||
295 | |||
296 | if (changed) { | ||
297 | changed = parent.augment(); | ||
298 | if (changed) { | ||
299 | changed = grandparent.augment(); | ||
300 | } | ||
301 | } | ||
302 | node = grandparent; | ||
303 | } else { | ||
304 | if (parent.left == node) { | ||
305 | if (grandparent.right == parent) { | ||
306 | parent.rotateRight(); | ||
307 | node = parent; | ||
308 | parent = node.parent; | ||
309 | } | ||
310 | } else if (grandparent.left == parent) { | ||
311 | parent.rotateLeft(); | ||
312 | node = parent; | ||
313 | parent = node.parent; | ||
314 | } | ||
315 | |||
316 | if (parent.left == node) { | ||
317 | boolean grandparentChanged = grandparent.rotateRight(); | ||
318 | if (augment) { | ||
319 | changed = grandparentChanged; | ||
320 | } | ||
321 | } else { | ||
322 | boolean grandparentChanged = grandparent.rotateLeft(); | ||
323 | if (augment) { | ||
324 | changed = grandparentChanged; | ||
325 | } | ||
326 | } | ||
327 | |||
328 | parent.isRed = false; | ||
329 | grandparent.isRed = true; | ||
330 | node = parent; | ||
331 | break; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | if (node.parent == null) { | ||
336 | node.isRed = false; | ||
337 | } | ||
338 | if (changed) { | ||
339 | for (node = node.parent; node != null; node = node.parent) { | ||
340 | if (!node.augment()) { | ||
341 | break; | ||
342 | } | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | |||
347 | /** | ||
348 | * Performs red-black insertion fixup. To be more precise, this fixes a tree that satisfies all of the requirements | ||
349 | * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be | ||
350 | * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs | ||
351 | * any rotations by calling rotateLeft() and rotateRight(). This method is more efficient than fixInsertion() if | ||
352 | * augment() might return false. | ||
353 | */ | ||
354 | public void fixInsertionWithoutGettingRoot() { | ||
355 | fixInsertionWithoutGettingRoot(true); | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * Performs red-black insertion fixup. To be more precise, this fixes a tree that satisfies all of the requirements | ||
360 | * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be | ||
361 | * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs | ||
362 | * any rotations by calling rotateLeft() and rotateRight(). | ||
363 | * @param augment Whether to set the augmentation information for "node" and its ancestors, by calling augment(). | ||
364 | * @return The root of the resulting tree. | ||
365 | */ | ||
366 | public N fixInsertion(boolean augment) { | ||
367 | fixInsertionWithoutGettingRoot(augment); | ||
368 | return root(); | ||
369 | } | ||
370 | |||
371 | /** | ||
372 | * Performs red-black insertion fixup. To be more precise, this fixes a tree that satisfies all of the requirements | ||
373 | * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be | ||
374 | * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs | ||
375 | * any rotations by calling rotateLeft() and rotateRight(). | ||
376 | * @return The root of the resulting tree. | ||
377 | */ | ||
378 | public N fixInsertion() { | ||
379 | fixInsertionWithoutGettingRoot(true); | ||
380 | return root(); | ||
381 | } | ||
382 | |||
383 | /** Returns a Comparator that compares instances of N using their natural order, as in N.compareTo. */ | ||
384 | @SuppressWarnings({"rawtypes", "unchecked"}) | ||
385 | private Comparator<N> naturalOrder() { | ||
386 | Comparator comparator = (Comparator)NATURAL_ORDER; | ||
387 | return (Comparator<N>)comparator; | ||
388 | } | ||
389 | |||
390 | /** | ||
391 | * Inserts the specified node into the tree rooted at this node. Assumes this is the root. We treat newNode as a | ||
392 | * solitary node that does not belong to any tree, and we ignore its initial "parent", "left", "right", and isRed | ||
393 | * fields. | ||
394 | * | ||
395 | * If it is not efficient or convenient to find the location for a node using a Comparator, then you should manually | ||
396 | * add the node to the appropriate location, color it red, and call fixInsertion(). | ||
397 | * | ||
398 | * @param newNode The node to insert. | ||
399 | * @param allowDuplicates Whether to insert newNode if there is an equal node in the tree. To check whether we | ||
400 | * inserted newNode, check whether newNode.parent is null and the return value differs from newNode. | ||
401 | * @param comparator A comparator indicating where to put the node. If this is null, we use the nodes' natural | ||
402 | * order, as in N.compareTo. If you are passing null, then you must override the compareTo method, because the | ||
403 | * default implementation requires the nodes to already be in the same tree. | ||
404 | * @return The root of the resulting tree. | ||
405 | */ | ||
406 | public N insert(N newNode, boolean allowDuplicates, Comparator<? super N> comparator) { | ||
407 | if (parent != null) { | ||
408 | throw new IllegalArgumentException("This is not the root of a tree"); | ||
409 | } | ||
410 | @SuppressWarnings("unchecked") | ||
411 | N nThis = (N)this; | ||
412 | if (isLeaf()) { | ||
413 | newNode.isRed = false; | ||
414 | newNode.left = nThis; | ||
415 | newNode.right = nThis; | ||
416 | newNode.parent = null; | ||
417 | newNode.augment(); | ||
418 | return newNode; | ||
419 | } | ||
420 | if (comparator == null) { | ||
421 | comparator = naturalOrder(); | ||
422 | } | ||
423 | |||
424 | N node = nThis; | ||
425 | int comparison; | ||
426 | while (true) { | ||
427 | comparison = comparator.compare(newNode, node); | ||
428 | if (comparison < 0) { | ||
429 | if (!node.left.isLeaf()) { | ||
430 | node = node.left; | ||
431 | } else { | ||
432 | newNode.left = node.left; | ||
433 | newNode.right = node.left; | ||
434 | node.left = newNode; | ||
435 | newNode.parent = node; | ||
436 | break; | ||
437 | } | ||
438 | } else if (comparison > 0 || allowDuplicates) { | ||
439 | if (!node.right.isLeaf()) { | ||
440 | node = node.right; | ||
441 | } else { | ||
442 | newNode.left = node.right; | ||
443 | newNode.right = node.right; | ||
444 | node.right = newNode; | ||
445 | newNode.parent = node; | ||
446 | break; | ||
447 | } | ||
448 | } else { | ||
449 | newNode.parent = null; | ||
450 | return nThis; | ||
451 | } | ||
452 | } | ||
453 | newNode.isRed = true; | ||
454 | return newNode.fixInsertion(); | ||
455 | } | ||
456 | |||
457 | /** | ||
458 | * Moves this node to its successor's former position in the tree and vice versa, i.e. sets the "left", "right", | ||
459 | * "parent", and isRed fields of each. This method assumes that this is not a leaf node. | ||
460 | * @return The node with which we swapped. | ||
461 | */ | ||
462 | private N swapWithSuccessor() { | ||
463 | N replacement = successor(); | ||
464 | boolean oldReplacementIsRed = replacement.isRed; | ||
465 | N oldReplacementLeft = replacement.left; | ||
466 | N oldReplacementRight = replacement.right; | ||
467 | N oldReplacementParent = replacement.parent; | ||
468 | |||
469 | replacement.isRed = isRed; | ||
470 | replacement.left = left; | ||
471 | replacement.right = right; | ||
472 | replacement.parent = parent; | ||
473 | if (parent != null) { | ||
474 | if (parent.left == this) { | ||
475 | parent.left = replacement; | ||
476 | } else { | ||
477 | parent.right = replacement; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | @SuppressWarnings("unchecked") | ||
482 | N nThis = (N)this; | ||
483 | isRed = oldReplacementIsRed; | ||
484 | left = oldReplacementLeft; | ||
485 | right = oldReplacementRight; | ||
486 | if (oldReplacementParent == this) { | ||
487 | parent = replacement; | ||
488 | parent.right = nThis; | ||
489 | } else { | ||
490 | parent = oldReplacementParent; | ||
491 | parent.left = nThis; | ||
492 | } | ||
493 | |||
494 | replacement.right.parent = replacement; | ||
495 | if (!replacement.left.isLeaf()) { | ||
496 | replacement.left.parent = replacement; | ||
497 | } | ||
498 | if (!right.isLeaf()) { | ||
499 | right.parent = nThis; | ||
500 | } | ||
501 | return replacement; | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * Performs red-black deletion fixup. To be more precise, this fixes a tree that satisfies all of the requirements | ||
506 | * of red-black trees, except that all paths from the root to a leaf that pass through the sibling of this node have | ||
507 | * one fewer black node than all other root-to-leaf paths. This method assumes that this is not a leaf node. | ||
508 | */ | ||
509 | private void fixSiblingDeletion() { | ||
510 | RedBlackNode<N> sibling = this; | ||
511 | boolean changed = true; | ||
512 | boolean haveAugmentedParent = false; | ||
513 | boolean haveAugmentedGrandparent = false; | ||
514 | while (true) { | ||
515 | N parent = sibling.parent; | ||
516 | if (sibling.isRed) { | ||
517 | parent.isRed = true; | ||
518 | sibling.isRed = false; | ||
519 | if (parent.left == sibling) { | ||
520 | changed = parent.rotateRight(); | ||
521 | sibling = parent.left; | ||
522 | } else { | ||
523 | changed = parent.rotateLeft(); | ||
524 | sibling = parent.right; | ||
525 | } | ||
526 | haveAugmentedParent = true; | ||
527 | haveAugmentedGrandparent = true; | ||
528 | } else if (!sibling.left.isRed && !sibling.right.isRed) { | ||
529 | sibling.isRed = true; | ||
530 | if (parent.isRed) { | ||
531 | parent.isRed = false; | ||
532 | break; | ||
533 | } else { | ||
534 | if (changed && !haveAugmentedParent) { | ||
535 | changed = parent.augment(); | ||
536 | } | ||
537 | N grandparent = parent.parent; | ||
538 | if (grandparent == null) { | ||
539 | break; | ||
540 | } else if (grandparent.left == parent) { | ||
541 | sibling = grandparent.right; | ||
542 | } else { | ||
543 | sibling = grandparent.left; | ||
544 | } | ||
545 | haveAugmentedParent = haveAugmentedGrandparent; | ||
546 | haveAugmentedGrandparent = false; | ||
547 | } | ||
548 | } else { | ||
549 | if (sibling == parent.left) { | ||
550 | if (!sibling.left.isRed) { | ||
551 | sibling.rotateLeft(); | ||
552 | sibling = sibling.parent; | ||
553 | } | ||
554 | } else if (!sibling.right.isRed) { | ||
555 | sibling.rotateRight(); | ||
556 | sibling = sibling.parent; | ||
557 | } | ||
558 | sibling.isRed = parent.isRed; | ||
559 | parent.isRed = false; | ||
560 | if (sibling == parent.left) { | ||
561 | sibling.left.isRed = false; | ||
562 | changed = parent.rotateRight(); | ||
563 | } else { | ||
564 | sibling.right.isRed = false; | ||
565 | changed = parent.rotateLeft(); | ||
566 | } | ||
567 | haveAugmentedParent = haveAugmentedGrandparent; | ||
568 | haveAugmentedGrandparent = false; | ||
569 | break; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | // Update augmentation info | ||
574 | N parent = sibling.parent; | ||
575 | if (changed && parent != null) { | ||
576 | if (!haveAugmentedParent) { | ||
577 | changed = parent.augment(); | ||
578 | } | ||
579 | if (changed && parent.parent != null) { | ||
580 | parent = parent.parent; | ||
581 | if (!haveAugmentedGrandparent) { | ||
582 | changed = parent.augment(); | ||
583 | } | ||
584 | if (changed) { | ||
585 | for (parent = parent.parent; parent != null; parent = parent.parent) { | ||
586 | if (!parent.augment()) { | ||
587 | break; | ||
588 | } | ||
589 | } | ||
590 | } | ||
591 | } | ||
592 | } | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * Removes this node from the tree that contains it. The effect of this method on the fields of this node is | ||
597 | * unspecified. This method assumes that this is not a leaf node. This method is more efficient than remove() if | ||
598 | * augment() might return false. | ||
599 | * | ||
600 | * If the node has two children, we begin by moving the node's successor to its former position, by changing the | ||
601 | * successor's "left", "right", "parent", and isRed fields. | ||
602 | */ | ||
603 | public void removeWithoutGettingRoot() { | ||
604 | if (isLeaf()) { | ||
605 | throw new IllegalArgumentException("Attempted to remove a leaf node"); | ||
606 | } | ||
607 | N replacement; | ||
608 | if (left.isLeaf() || right.isLeaf()) { | ||
609 | replacement = null; | ||
610 | } else { | ||
611 | replacement = swapWithSuccessor(); | ||
612 | } | ||
613 | |||
614 | N child; | ||
615 | if (!left.isLeaf()) { | ||
616 | child = left; | ||
617 | } else if (!right.isLeaf()) { | ||
618 | child = right; | ||
619 | } else { | ||
620 | child = null; | ||
621 | } | ||
622 | |||
623 | if (child != null) { | ||
624 | // Replace this node with its child | ||
625 | child.parent = parent; | ||
626 | if (parent != null) { | ||
627 | if (parent.left == this) { | ||
628 | parent.left = child; | ||
629 | } else { | ||
630 | parent.right = child; | ||
631 | } | ||
632 | } | ||
633 | child.isRed = false; | ||
634 | |||
635 | if (child.parent != null) { | ||
636 | N parent; | ||
637 | for (parent = child.parent; parent != null; parent = parent.parent) { | ||
638 | if (!parent.augment()) { | ||
639 | break; | ||
640 | } | ||
641 | } | ||
642 | } | ||
643 | } else if (parent != null) { | ||
644 | // Replace this node with a leaf node | ||
645 | N leaf = left; | ||
646 | N parent = this.parent; | ||
647 | N sibling; | ||
648 | if (parent.left == this) { | ||
649 | parent.left = leaf; | ||
650 | sibling = parent.right; | ||
651 | } else { | ||
652 | parent.right = leaf; | ||
653 | sibling = parent.left; | ||
654 | } | ||
655 | |||
656 | if (!isRed) { | ||
657 | RedBlackNode<N> siblingNode = sibling; | ||
658 | siblingNode.fixSiblingDeletion(); | ||
659 | } else { | ||
660 | while (parent != null) { | ||
661 | if (!parent.augment()) { | ||
662 | break; | ||
663 | } | ||
664 | parent = parent.parent; | ||
665 | } | ||
666 | } | ||
667 | } | ||
668 | |||
669 | if (replacement != null) { | ||
670 | replacement.augment(); | ||
671 | for (N parent = replacement.parent; parent != null; parent = parent.parent) { | ||
672 | if (!parent.augment()) { | ||
673 | break; | ||
674 | } | ||
675 | } | ||
676 | } | ||
677 | |||
678 | // Clear any previously existing links, so that we're more likely to encounter an exception if we attempt to | ||
679 | // access the removed node | ||
680 | parent = null; | ||
681 | left = null; | ||
682 | right = null; | ||
683 | isRed = true; | ||
684 | } | ||
685 | |||
686 | /** | ||
687 | * Removes this node from the tree that contains it. The effect of this method on the fields of this node is | ||
688 | * unspecified. This method assumes that this is not a leaf node. | ||
689 | * | ||
690 | * If the node has two children, we begin by moving the node's successor to its former position, by changing the | ||
691 | * successor's "left", "right", "parent", and isRed fields. | ||
692 | * | ||
693 | * @return The root of the resulting tree. | ||
694 | */ | ||
695 | public N remove() { | ||
696 | if (isLeaf()) { | ||
697 | throw new IllegalArgumentException("Attempted to remove a leaf node"); | ||
698 | } | ||
699 | |||
700 | // Find an arbitrary non-leaf node in the tree other than this node | ||
701 | N node; | ||
702 | if (parent != null) { | ||
703 | node = parent; | ||
704 | } else if (!left.isLeaf()) { | ||
705 | node = left; | ||
706 | } else if (!right.isLeaf()) { | ||
707 | node = right; | ||
708 | } else { | ||
709 | return left; | ||
710 | } | ||
711 | |||
712 | removeWithoutGettingRoot(); | ||
713 | return node.root(); | ||
714 | } | ||
715 | |||
716 | /** | ||
717 | * Returns the root of a perfectly height-balanced subtree containing the next "size" (non-leaf) nodes from | ||
718 | * "iterator", in iteration order. This method is responsible for setting the "left", "right", "parent", and isRed | ||
719 | * fields of the nodes, and calling augment() as appropriate. It ignores the initial values of the "left", "right", | ||
720 | * "parent", and isRed fields. | ||
721 | * @param iterator The nodes. | ||
722 | * @param size The number of nodes. | ||
723 | * @param height The "height" of the subtree's root node above the deepest leaf in the tree that contains it. Since | ||
724 | * insertion fixup is slow if there are too many red nodes and deleteion fixup is slow if there are too few red | ||
725 | * nodes, we compromise and have red nodes at every fourth level. We color a node red iff its "height" is equal | ||
726 | * to 1 mod 4. | ||
727 | * @param leaf The leaf node. | ||
728 | * @return The root of the subtree. | ||
729 | */ | ||
730 | private static <N extends RedBlackNode<N>> N createTree( | ||
731 | Iterator<? extends N> iterator, int size, int height, N leaf) { | ||
732 | if (size == 0) { | ||
733 | return leaf; | ||
734 | } else { | ||
735 | N left = createTree(iterator, (size - 1) / 2, height - 1, leaf); | ||
736 | N node = iterator.next(); | ||
737 | N right = createTree(iterator, size / 2, height - 1, leaf); | ||
738 | |||
739 | node.isRed = height % 4 == 1; | ||
740 | node.left = left; | ||
741 | node.right = right; | ||
742 | if (!left.isLeaf()) { | ||
743 | left.parent = node; | ||
744 | } | ||
745 | if (!right.isLeaf()) { | ||
746 | right.parent = node; | ||
747 | } | ||
748 | |||
749 | node.augment(); | ||
750 | return node; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | /** | ||
755 | * Returns the root of a perfectly height-balanced tree containing the specified nodes, in iteration order. This | ||
756 | * method is responsible for setting the "left", "right", "parent", and isRed fields of the nodes (excluding | ||
757 | * "leaf"), and calling augment() as appropriate. It ignores the initial values of the "left", "right", "parent", | ||
758 | * and isRed fields. | ||
759 | * @param nodes The nodes. | ||
760 | * @param leaf The leaf node. | ||
761 | * @return The root of the tree. | ||
762 | */ | ||
763 | public static <N extends RedBlackNode<N>> N createTree(Collection<? extends N> nodes, N leaf) { | ||
764 | int size = nodes.size(); | ||
765 | if (size == 0) { | ||
766 | return leaf; | ||
767 | } | ||
768 | |||
769 | int height = 0; | ||
770 | for (int subtreeSize = size; subtreeSize > 0; subtreeSize /= 2) { | ||
771 | height++; | ||
772 | } | ||
773 | |||
774 | N node = createTree(nodes.iterator(), size, height, leaf); | ||
775 | node.parent = null; | ||
776 | node.isRed = false; | ||
777 | return node; | ||
778 | } | ||
779 | |||
780 | /** | ||
781 | * Concatenates to the end of the tree rooted at this node. To be precise, given that all of the nodes in this | ||
782 | * precede the node "pivot", which precedes all of the nodes in "last", this returns the root of a tree containing | ||
783 | * all of these nodes. This method destroys the trees rooted at "this" and "last". We treat "pivot" as a solitary | ||
784 | * node that does not belong to any tree, and we ignore its initial "parent", "left", "right", and isRed fields. | ||
785 | * This method assumes that this node and "last" are the roots of their respective trees. | ||
786 | * | ||
787 | * This method takes O(log N) time. It is more efficient than inserting "pivot" and then calling concatenate(last). | ||
788 | * It is considerably more efficient than inserting "pivot" and all of the nodes in "last". | ||
789 | */ | ||
790 | public N concatenate(N last, N pivot) { | ||
791 | // If the black height of "first", where first = this, is less than or equal to that of "last", starting at the | ||
792 | // root of "last", we keep going left until we reach a black node whose black height is equal to that of | ||
793 | // "first". Then, we make "pivot" the parent of that node and of "first", coloring it red, and perform | ||
794 | // insertion fixup on the pivot. If the black height of "first" is greater than that of "last", we do the | ||
795 | // mirror image of the above. | ||
796 | |||
797 | if (parent != null) { | ||
798 | throw new IllegalArgumentException("This is not the root of a tree"); | ||
799 | } | ||
800 | if (last.parent != null) { | ||
801 | throw new IllegalArgumentException("\"last\" is not the root of a tree"); | ||
802 | } | ||
803 | |||
804 | // Compute the black height of the trees | ||
805 | int firstBlackHeight = 0; | ||
806 | @SuppressWarnings("unchecked") | ||
807 | N first = (N)this; | ||
808 | for (N node = first; node != null; node = node.right) { | ||
809 | if (!node.isRed) { | ||
810 | firstBlackHeight++; | ||
811 | } | ||
812 | } | ||
813 | int lastBlackHeight = 0; | ||
814 | for (N node = last; node != null; node = node.right) { | ||
815 | if (!node.isRed) { | ||
816 | lastBlackHeight++; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | // Identify the children and parent of pivot | ||
821 | N firstChild = first; | ||
822 | N lastChild = last; | ||
823 | N parent; | ||
824 | if (firstBlackHeight <= lastBlackHeight) { | ||
825 | parent = null; | ||
826 | int blackHeight = lastBlackHeight; | ||
827 | while (blackHeight > firstBlackHeight) { | ||
828 | if (!lastChild.isRed) { | ||
829 | blackHeight--; | ||
830 | } | ||
831 | parent = lastChild; | ||
832 | lastChild = lastChild.left; | ||
833 | } | ||
834 | if (lastChild.isRed) { | ||
835 | parent = lastChild; | ||
836 | lastChild = lastChild.left; | ||
837 | } | ||
838 | } else { | ||
839 | parent = null; | ||
840 | int blackHeight = firstBlackHeight; | ||
841 | while (blackHeight > lastBlackHeight) { | ||
842 | if (!firstChild.isRed) { | ||
843 | blackHeight--; | ||
844 | } | ||
845 | parent = firstChild; | ||
846 | firstChild = firstChild.right; | ||
847 | } | ||
848 | if (firstChild.isRed) { | ||
849 | parent = firstChild; | ||
850 | firstChild = firstChild.right; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | // Add "pivot" to the tree | ||
855 | pivot.isRed = true; | ||
856 | pivot.parent = parent; | ||
857 | if (parent != null) { | ||
858 | if (firstBlackHeight < lastBlackHeight) { | ||
859 | parent.left = pivot; | ||
860 | } else { | ||
861 | parent.right = pivot; | ||
862 | } | ||
863 | } | ||
864 | pivot.left = firstChild; | ||
865 | if (!firstChild.isLeaf()) { | ||
866 | firstChild.parent = pivot; | ||
867 | } | ||
868 | pivot.right = lastChild; | ||
869 | if (!lastChild.isLeaf()) { | ||
870 | lastChild.parent = pivot; | ||
871 | } | ||
872 | |||
873 | // Perform insertion fixup | ||
874 | return pivot.fixInsertion(); | ||
875 | } | ||
876 | |||
877 | /** | ||
878 | * Concatenates the tree rooted at "last" to the end of the tree rooted at this node. To be precise, given that all | ||
879 | * of the nodes in this precede all of the nodes in "last", this returns the root of a tree containing all of these | ||
880 | * nodes. This method destroys the trees rooted at "this" and "last". It assumes that this node and "last" are the | ||
881 | * roots of their respective trees. This method takes O(log N) time. It is considerably more efficient than | ||
882 | * inserting all of the nodes in "last". | ||
883 | */ | ||
884 | public N concatenate(N last) { | ||
885 | if (parent != null || last.parent != null) { | ||
886 | throw new IllegalArgumentException("The node is not the root of a tree"); | ||
887 | } | ||
888 | if (isLeaf()) { | ||
889 | return last; | ||
890 | } else if (last.isLeaf()) { | ||
891 | @SuppressWarnings("unchecked") | ||
892 | N nThis = (N)this; | ||
893 | return nThis; | ||
894 | } else { | ||
895 | N node = last.min(); | ||
896 | last = node.remove(); | ||
897 | return concatenate(last, node); | ||
898 | } | ||
899 | } | ||
900 | |||
901 | /** | ||
902 | * Splits the tree rooted at this node into two trees, so that the first element of the return value is the root of | ||
903 | * a tree consisting of the nodes that were before the specified node, and the second element of the return value is | ||
904 | * the root of a tree consisting of the nodes that were equal to or after the specified node. This method is | ||
905 | * destructive, meaning it does not preserve the original tree. It assumes that this node is the root and is in the | ||
906 | * same tree as splitNode. It takes O(log N) time. It is considerably more efficient than removing all of the | ||
907 | * nodes at or after splitNode and then creating a new tree from those nodes. | ||
908 | * @param The node at which to split the tree. | ||
909 | * @return An array consisting of the resulting trees. | ||
910 | */ | ||
911 | public N[] split(N splitNode) { | ||
912 | // To split the tree, we accumulate a pre-split tree and a post-split tree. We walk down the tree toward the | ||
913 | // position where we are splitting. Whenever we go left, we concatenate the right subtree with the post-split | ||
914 | // tree, and whenever we go right, we concatenate the pre-split tree with the left subtree. We use the | ||
915 | // concatenation algorithm described in concatenate(Object, Object). For the pivot, we use the last node where | ||
916 | // we went left in the case of a left move, and the last node where we went right in the case of a right move. | ||
917 | // | ||
918 | // The method uses the following variables: | ||
919 | // | ||
920 | // node: The current node in our walk down the tree. | ||
921 | // first: A node on the right spine of the pre-split tree. At the beginning of each iteration, it is the black | ||
922 | // node with the same black height as "node". If the pre-split tree is empty, this is null instead. | ||
923 | // firstParent: The parent of "first". If the pre-split tree is empty, this is null. Otherwise, this is the | ||
924 | // same as first.parent, unless first.isLeaf(). | ||
925 | // firstPivot: The node where we last went right, i.e. the next node to use as a pivot when concatenating with | ||
926 | // the pre-split tree. | ||
927 | // advanceFirst: Whether to set "first" to be its next black descendant at the end of the loop. | ||
928 | // last, lastParent, lastPivot, advanceLast: Analogous to "first", firstParent, firstPivot, and advanceFirst, | ||
929 | // but for the post-split tree. | ||
930 | if (parent != null) { | ||
931 | throw new IllegalArgumentException("This is not the root of a tree"); | ||
932 | } | ||
933 | if (isLeaf() || splitNode.isLeaf()) { | ||
934 | throw new IllegalArgumentException("The root or the split node is a leaf"); | ||
935 | } | ||
936 | |||
937 | // Create an array containing the path from the root to splitNode | ||
938 | int depth = 1; | ||
939 | N parent; | ||
940 | for (parent = splitNode; parent.parent != null; parent = parent.parent) { | ||
941 | depth++; | ||
942 | } | ||
943 | if (parent != this) { | ||
944 | throw new IllegalArgumentException("The split node does not belong to this tree"); | ||
945 | } | ||
946 | RedBlackNode<?>[] path = new RedBlackNode<?>[depth]; | ||
947 | for (parent = splitNode; parent != null; parent = parent.parent) { | ||
948 | depth--; | ||
949 | path[depth] = parent; | ||
950 | } | ||
951 | |||
952 | @SuppressWarnings("unchecked") | ||
953 | N node = (N)this; | ||
954 | N first = null; | ||
955 | N firstParent = null; | ||
956 | N last = null; | ||
957 | N lastParent = null; | ||
958 | N firstPivot = null; | ||
959 | N lastPivot = null; | ||
960 | while (!node.isLeaf()) { | ||
961 | boolean advanceFirst = !node.isRed && firstPivot != null; | ||
962 | boolean advanceLast = !node.isRed && lastPivot != null; | ||
963 | if ((depth + 1 < path.length && path[depth + 1] == node.left) || depth + 1 == path.length) { | ||
964 | // Left move | ||
965 | if (lastPivot == null) { | ||
966 | // The post-split tree is empty | ||
967 | last = node.right; | ||
968 | last.parent = null; | ||
969 | if (last.isRed) { | ||
970 | last.isRed = false; | ||
971 | lastParent = last; | ||
972 | last = last.left; | ||
973 | } | ||
974 | } else { | ||
975 | // Concatenate node.right and the post-split tree | ||
976 | if (node.right.isRed) { | ||
977 | node.right.isRed = false; | ||
978 | } else if (!node.isRed) { | ||
979 | lastParent = last; | ||
980 | last = last.left; | ||
981 | if (last.isRed) { | ||
982 | lastParent = last; | ||
983 | last = last.left; | ||
984 | } | ||
985 | advanceLast = false; | ||
986 | } | ||
987 | lastPivot.isRed = true; | ||
988 | lastPivot.parent = lastParent; | ||
989 | if (lastParent != null) { | ||
990 | lastParent.left = lastPivot; | ||
991 | } | ||
992 | lastPivot.left = node.right; | ||
993 | if (!lastPivot.left.isLeaf()) { | ||
994 | lastPivot.left.parent = lastPivot; | ||
995 | } | ||
996 | lastPivot.right = last; | ||
997 | if (!last.isLeaf()) { | ||
998 | last.parent = lastPivot; | ||
999 | } | ||
1000 | last = lastPivot.left; | ||
1001 | lastParent = lastPivot; | ||
1002 | lastPivot.fixInsertionWithoutGettingRoot(false); | ||
1003 | } | ||
1004 | lastPivot = node; | ||
1005 | node = node.left; | ||
1006 | } else { | ||
1007 | // Right move | ||
1008 | if (firstPivot == null) { | ||
1009 | // The pre-split tree is empty | ||
1010 | first = node.left; | ||
1011 | first.parent = null; | ||
1012 | if (first.isRed) { | ||
1013 | first.isRed = false; | ||
1014 | firstParent = first; | ||
1015 | first = first.right; | ||
1016 | } | ||
1017 | } else { | ||
1018 | // Concatenate the post-split tree and node.left | ||
1019 | if (node.left.isRed) { | ||
1020 | node.left.isRed = false; | ||
1021 | } else if (!node.isRed) { | ||
1022 | firstParent = first; | ||
1023 | first = first.right; | ||
1024 | if (first.isRed) { | ||
1025 | firstParent = first; | ||
1026 | first = first.right; | ||
1027 | } | ||
1028 | advanceFirst = false; | ||
1029 | } | ||
1030 | firstPivot.isRed = true; | ||
1031 | firstPivot.parent = firstParent; | ||
1032 | if (firstParent != null) { | ||
1033 | firstParent.right = firstPivot; | ||
1034 | } | ||
1035 | firstPivot.right = node.left; | ||
1036 | if (!firstPivot.right.isLeaf()) { | ||
1037 | firstPivot.right.parent = firstPivot; | ||
1038 | } | ||
1039 | firstPivot.left = first; | ||
1040 | if (!first.isLeaf()) { | ||
1041 | first.parent = firstPivot; | ||
1042 | } | ||
1043 | first = firstPivot.right; | ||
1044 | firstParent = firstPivot; | ||
1045 | firstPivot.fixInsertionWithoutGettingRoot(false); | ||
1046 | } | ||
1047 | firstPivot = node; | ||
1048 | node = node.right; | ||
1049 | } | ||
1050 | |||
1051 | depth++; | ||
1052 | |||
1053 | // Update "first" and "last" to be the nodes at the proper black height | ||
1054 | if (advanceFirst) { | ||
1055 | firstParent = first; | ||
1056 | first = first.right; | ||
1057 | if (first.isRed) { | ||
1058 | firstParent = first; | ||
1059 | first = first.right; | ||
1060 | } | ||
1061 | } | ||
1062 | if (advanceLast) { | ||
1063 | lastParent = last; | ||
1064 | last = last.left; | ||
1065 | if (last.isRed) { | ||
1066 | lastParent = last; | ||
1067 | last = last.left; | ||
1068 | } | ||
1069 | } | ||
1070 | } | ||
1071 | |||
1072 | // Add firstPivot to the pre-split tree | ||
1073 | N leaf = node; | ||
1074 | if (first == null) { | ||
1075 | first = leaf; | ||
1076 | } else { | ||
1077 | firstPivot.isRed = true; | ||
1078 | firstPivot.parent = firstParent; | ||
1079 | if (firstParent != null) { | ||
1080 | firstParent.right = firstPivot; | ||
1081 | } | ||
1082 | firstPivot.left = leaf; | ||
1083 | firstPivot.right = leaf; | ||
1084 | firstPivot.fixInsertionWithoutGettingRoot(false); | ||
1085 | for (first = firstPivot; first.parent != null; first = first.parent) { | ||
1086 | first.augment(); | ||
1087 | } | ||
1088 | first.augment(); | ||
1089 | } | ||
1090 | |||
1091 | // Add lastPivot to the post-split tree | ||
1092 | lastPivot.isRed = true; | ||
1093 | lastPivot.parent = lastParent; | ||
1094 | if (lastParent != null) { | ||
1095 | lastParent.left = lastPivot; | ||
1096 | } | ||
1097 | lastPivot.left = leaf; | ||
1098 | lastPivot.right = leaf; | ||
1099 | lastPivot.fixInsertionWithoutGettingRoot(false); | ||
1100 | for (last = lastPivot; last.parent != null; last = last.parent) { | ||
1101 | last.augment(); | ||
1102 | } | ||
1103 | last.augment(); | ||
1104 | |||
1105 | @SuppressWarnings("unchecked") | ||
1106 | N[] result = (N[])Array.newInstance(getClass(), 2); | ||
1107 | result[0] = first; | ||
1108 | result[1] = last; | ||
1109 | return result; | ||
1110 | } | ||
1111 | |||
1112 | /** | ||
1113 | * Returns the lowest common ancestor of this node and "other" - the node that is an ancestor of both and is not the | ||
1114 | * parent of a node that is an ancestor of both. Assumes that this is in the same tree as "other". Assumes that | ||
1115 | * neither "this" nor "other" is a leaf node. This method may return "this" or "other". | ||
1116 | * | ||
1117 | * Note that while it is possible to compute the lowest common ancestor in O(P) time, where P is the length of the | ||
1118 | * path from this node to "other", the "lca" method is not guaranteed to take O(P) time. If your application | ||
1119 | * requires this, then you should write your own lowest common ancestor method. | ||
1120 | */ | ||
1121 | public N lca(N other) { | ||
1122 | if (isLeaf() || other.isLeaf()) { | ||
1123 | throw new IllegalArgumentException("One of the nodes is a leaf node"); | ||
1124 | } | ||
1125 | |||
1126 | // Compute the depth of each node | ||
1127 | int depth = 0; | ||
1128 | for (N parent = this.parent; parent != null; parent = parent.parent) { | ||
1129 | depth++; | ||
1130 | } | ||
1131 | int otherDepth = 0; | ||
1132 | for (N parent = other.parent; parent != null; parent = parent.parent) { | ||
1133 | otherDepth++; | ||
1134 | } | ||
1135 | |||
1136 | // Go up to nodes of the same depth | ||
1137 | @SuppressWarnings("unchecked") | ||
1138 | N parent = (N)this; | ||
1139 | N otherParent = other; | ||
1140 | if (depth <= otherDepth) { | ||
1141 | for (int i = otherDepth; i > depth; i--) { | ||
1142 | otherParent = otherParent.parent; | ||
1143 | } | ||
1144 | } else { | ||
1145 | for (int i = depth; i > otherDepth; i--) { | ||
1146 | parent = parent.parent; | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | // Find the LCA | ||
1151 | while (parent != otherParent) { | ||
1152 | parent = parent.parent; | ||
1153 | otherParent = otherParent.parent; | ||
1154 | } | ||
1155 | if (parent != null) { | ||
1156 | return parent; | ||
1157 | } else { | ||
1158 | throw new IllegalArgumentException("The nodes do not belong to the same tree"); | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | /** | ||
1163 | * Returns an integer comparing the position of this node in the tree that contains it with that of "other". Returns | ||
1164 | * a negative number if this is earlier, a positive number if this is later, and 0 if this is at the same position. | ||
1165 | * Assumes that this is in the same tree as "other". Assumes that neither "this" nor "other" is a leaf node. | ||
1166 | * | ||
1167 | * The base class's implementation takes O(log N) time. If a RedBlackNode subclass stores a value used to order the | ||
1168 | * nodes, then it could override compareTo to compare the nodes' values, which would take O(1) time. | ||
1169 | * | ||
1170 | * Note that while it is possible to compare the positions of two nodes in O(P) time, where P is the length of the | ||
1171 | * path from this node to "other", the default implementation of compareTo is not guaranteed to take O(P) time. If | ||
1172 | * your application requires this, then you should write your own comparison method. | ||
1173 | */ | ||
1174 | @Override | ||
1175 | public int compareTo(N other) { | ||
1176 | if (isLeaf() || other.isLeaf()) { | ||
1177 | throw new IllegalArgumentException("One of the nodes is a leaf node"); | ||
1178 | } | ||
1179 | |||
1180 | // The algorithm operates as follows: compare the depth of this node to that of "other". If the depth of | ||
1181 | // "other" is greater, keep moving up from "other" until we find the ancestor at the same depth. Then, keep | ||
1182 | // moving up from "this" and from that node until we reach the lowest common ancestor. The node that arrived | ||
1183 | // from the left child of the common ancestor is earlier. The algorithm is analogous if the depth of "other" is | ||
1184 | // not greater. | ||
1185 | if (this == other) { | ||
1186 | return 0; | ||
1187 | } | ||
1188 | |||
1189 | // Compute the depth of each node | ||
1190 | int depth = 0; | ||
1191 | RedBlackNode<N> parent; | ||
1192 | for (parent = this; parent.parent != null; parent = parent.parent) { | ||
1193 | depth++; | ||
1194 | } | ||
1195 | int otherDepth = 0; | ||
1196 | N otherParent; | ||
1197 | for (otherParent = other; otherParent.parent != null; otherParent = otherParent.parent) { | ||
1198 | otherDepth++; | ||
1199 | } | ||
1200 | |||
1201 | // Go up to nodes of the same depth | ||
1202 | if (depth < otherDepth) { | ||
1203 | otherParent = other; | ||
1204 | for (int i = otherDepth - 1; i > depth; i--) { | ||
1205 | otherParent = otherParent.parent; | ||
1206 | } | ||
1207 | if (otherParent.parent != this) { | ||
1208 | otherParent = otherParent.parent; | ||
1209 | } else if (left == otherParent) { | ||
1210 | return 1; | ||
1211 | } else { | ||
1212 | return -1; | ||
1213 | } | ||
1214 | parent = this; | ||
1215 | } else if (depth > otherDepth) { | ||
1216 | parent = this; | ||
1217 | for (int i = depth - 1; i > otherDepth; i--) { | ||
1218 | parent = parent.parent; | ||
1219 | } | ||
1220 | if (parent.parent != other) { | ||
1221 | parent = parent.parent; | ||
1222 | } else if (other.left == parent) { | ||
1223 | return -1; | ||
1224 | } else { | ||
1225 | return 1; | ||
1226 | } | ||
1227 | otherParent = other; | ||
1228 | } else { | ||
1229 | parent = this; | ||
1230 | otherParent = other; | ||
1231 | } | ||
1232 | |||
1233 | // Keep going up until we reach the lowest common ancestor | ||
1234 | while (parent.parent != otherParent.parent) { | ||
1235 | parent = parent.parent; | ||
1236 | otherParent = otherParent.parent; | ||
1237 | } | ||
1238 | if (parent.parent == null) { | ||
1239 | throw new IllegalArgumentException("The nodes do not belong to the same tree"); | ||
1240 | } | ||
1241 | if (parent.parent.left == parent) { | ||
1242 | return -1; | ||
1243 | } else { | ||
1244 | return 1; | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1248 | /** Throws a RuntimeException if the RedBlackNode fields of this are not correct for a leaf node. */ | ||
1249 | private void assertIsValidLeaf() { | ||
1250 | if (left != null || right != null || parent != null || isRed) { | ||
1251 | throw new RuntimeException("A leaf node's \"left\", \"right\", \"parent\", or isRed field is incorrect"); | ||
1252 | } | ||
1253 | } | ||
1254 | |||
1255 | /** | ||
1256 | * Throws a RuntimeException if the subtree rooted at this node does not satisfy the red-black properties, excluding | ||
1257 | * the requirement that the root be black, or it contains a repeated node other than a leaf node. | ||
1258 | * @param blackHeight The required number of black nodes in each path from this to a leaf node, including this and | ||
1259 | * the leaf node. | ||
1260 | * @param visited The nodes we have reached thus far, other than leaf nodes. This method adds the non-leaf nodes in | ||
1261 | * the subtree rooted at this node to "visited". | ||
1262 | */ | ||
1263 | private void assertSubtreeIsValidRedBlack(int blackHeight, Set<Reference<N>> visited) { | ||
1264 | @SuppressWarnings("unchecked") | ||
1265 | N nThis = (N)this; | ||
1266 | if (left == null || right == null) { | ||
1267 | assertIsValidLeaf(); | ||
1268 | if (blackHeight != 1) { | ||
1269 | throw new RuntimeException("Not all root-to-leaf paths have the same number of black nodes"); | ||
1270 | } | ||
1271 | return; | ||
1272 | } else if (!visited.add(new Reference<N>(nThis))) { | ||
1273 | throw new RuntimeException("The tree contains a repeated non-leaf node"); | ||
1274 | } else { | ||
1275 | int childBlackHeight; | ||
1276 | if (isRed) { | ||
1277 | if ((!left.isLeaf() && left.isRed) || (!right.isLeaf() && right.isRed)) { | ||
1278 | throw new RuntimeException("A red node has a red child"); | ||
1279 | } | ||
1280 | childBlackHeight = blackHeight; | ||
1281 | } else if (blackHeight == 0) { | ||
1282 | throw new RuntimeException("Not all root-to-leaf paths have the same number of black nodes"); | ||
1283 | } else { | ||
1284 | childBlackHeight = blackHeight - 1; | ||
1285 | } | ||
1286 | |||
1287 | if (!left.isLeaf() && left.parent != this) { | ||
1288 | throw new RuntimeException("left.parent != this"); | ||
1289 | } | ||
1290 | if (!right.isLeaf() && right.parent != this) { | ||
1291 | throw new RuntimeException("right.parent != this"); | ||
1292 | } | ||
1293 | RedBlackNode<N> leftNode = left; | ||
1294 | RedBlackNode<N> rightNode = right; | ||
1295 | leftNode.assertSubtreeIsValidRedBlack(childBlackHeight, visited); | ||
1296 | rightNode.assertSubtreeIsValidRedBlack(childBlackHeight, visited); | ||
1297 | } | ||
1298 | } | ||
1299 | |||
1300 | /** Calls assertNodeIsValid() on every node in the subtree rooted at this node. */ | ||
1301 | private void assertNodesAreValid() { | ||
1302 | assertNodeIsValid(); | ||
1303 | if (left != null) { | ||
1304 | RedBlackNode<N> leftNode = left; | ||
1305 | RedBlackNode<N> rightNode = right; | ||
1306 | leftNode.assertNodesAreValid(); | ||
1307 | rightNode.assertNodesAreValid(); | ||
1308 | } | ||
1309 | } | ||
1310 | |||
1311 | /** | ||
1312 | * Throws a RuntimeException if the subtree rooted at this node is not a valid red-black tree, e.g. if a red node | ||
1313 | * has a red child or it contains a non-leaf node "node" for which node.left.parent != node. (If parent != null, | ||
1314 | * it's okay if isRed is true.) This method is useful for debugging. See also assertSubtreeIsValid(). | ||
1315 | */ | ||
1316 | public void assertSubtreeIsValidRedBlack() { | ||
1317 | if (isLeaf()) { | ||
1318 | assertIsValidLeaf(); | ||
1319 | } else { | ||
1320 | if (parent == null && isRed) { | ||
1321 | throw new RuntimeException("The root is red"); | ||
1322 | } | ||
1323 | |||
1324 | // Compute the black height of the tree | ||
1325 | Set<Reference<N>> nodes = new HashSet<Reference<N>>(); | ||
1326 | int blackHeight = 0; | ||
1327 | @SuppressWarnings("unchecked") | ||
1328 | N node = (N)this; | ||
1329 | while (node != null) { | ||
1330 | if (!nodes.add(new Reference<N>(node))) { | ||
1331 | throw new RuntimeException("The tree contains a repeated non-leaf node"); | ||
1332 | } | ||
1333 | if (!node.isRed) { | ||
1334 | blackHeight++; | ||
1335 | } | ||
1336 | node = node.left; | ||
1337 | } | ||
1338 | |||
1339 | assertSubtreeIsValidRedBlack(blackHeight, new HashSet<Reference<N>>()); | ||
1340 | } | ||
1341 | } | ||
1342 | |||
1343 | /** | ||
1344 | * Throws a RuntimeException if we detect a problem with the subtree rooted at this node, such as a red child of a | ||
1345 | * red node or a non-leaf descendant "node" for which node.left.parent != node. This method is useful for | ||
1346 | * debugging. RedBlackNode subclasses may want to override assertSubtreeIsValid() to call assertOrderIsValid. | ||
1347 | */ | ||
1348 | public void assertSubtreeIsValid() { | ||
1349 | assertSubtreeIsValidRedBlack(); | ||
1350 | assertNodesAreValid(); | ||
1351 | } | ||
1352 | |||
1353 | /** | ||
1354 | * Throws a RuntimeException if the nodes in the subtree rooted at this node are not in the specified order or they | ||
1355 | * do not lie in the specified range. Assumes that the subtree rooted at this node is a valid binary tree, i.e. it | ||
1356 | * has no repeated nodes other than leaf nodes. | ||
1357 | * @param comparator A comparator indicating how the nodes should be ordered. | ||
1358 | * @param start The lower limit for nodes in the subtree, if any. | ||
1359 | * @param end The upper limit for nodes in the subtree, if any. | ||
1360 | */ | ||
1361 | private void assertOrderIsValid(Comparator<? super N> comparator, N start, N end) { | ||
1362 | if (!isLeaf()) { | ||
1363 | @SuppressWarnings("unchecked") | ||
1364 | N nThis = (N)this; | ||
1365 | if (start != null && comparator.compare(nThis, start) < 0) { | ||
1366 | throw new RuntimeException("The nodes are not ordered correctly"); | ||
1367 | } | ||
1368 | if (end != null && comparator.compare(nThis, end) > 0) { | ||
1369 | throw new RuntimeException("The nodes are not ordered correctly"); | ||
1370 | } | ||
1371 | RedBlackNode<N> leftNode = left; | ||
1372 | RedBlackNode<N> rightNode = right; | ||
1373 | leftNode.assertOrderIsValid(comparator, start, nThis); | ||
1374 | rightNode.assertOrderIsValid(comparator, nThis, end); | ||
1375 | } | ||
1376 | } | ||
1377 | |||
1378 | /** | ||
1379 | * Throws a RuntimeException if the nodes in the subtree rooted at this node are not in the specified order. | ||
1380 | * Assumes that this is a valid binary tree, i.e. there are no repeated nodes other than leaf nodes. This method is | ||
1381 | * useful for debugging. RedBlackNode subclasses may want to override assertSubtreeIsValid() to call | ||
1382 | * assertOrderIsValid. | ||
1383 | * @param comparator A comparator indicating how the nodes should be ordered. If this is null, we use the nodes' | ||
1384 | * natural order, as in N.compareTo. | ||
1385 | */ | ||
1386 | public void assertOrderIsValid(Comparator<? super N> comparator) { | ||
1387 | if (comparator == null) { | ||
1388 | comparator = naturalOrder(); | ||
1389 | } | ||
1390 | assertOrderIsValid(comparator, null, null); | ||
1391 | } | ||
1392 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/Reference.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/Reference.java new file mode 100644 index 00000000..a25c167d --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/Reference.java | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * The MIT License (MIT) | ||
3 | * | ||
4 | * Copyright (c) 2016 btrekkie | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | * of this software and associated documentation files (the "Software"), to deal | ||
8 | * in the Software without restriction, including without limitation the rights | ||
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | * copies of the Software, and to permit persons to whom the Software is | ||
11 | * furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be included in all | ||
14 | * copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | * SOFTWARE. | ||
23 | */ | ||
24 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval; | ||
25 | |||
26 | /** | ||
27 | * Wraps a value using reference equality. In other words, two references are equal only if their values are the same | ||
28 | * object instance, as in ==. | ||
29 | * @param <T> The type of value. | ||
30 | */ | ||
31 | class Reference<T> { | ||
32 | /** The value this wraps. */ | ||
33 | private final T value; | ||
34 | |||
35 | public Reference(T value) { | ||
36 | this.value = value; | ||
37 | } | ||
38 | |||
39 | public boolean equals(Object obj) { | ||
40 | if (!(obj instanceof Reference)) { | ||
41 | return false; | ||
42 | } | ||
43 | Reference<?> reference = (Reference<?>)obj; | ||
44 | return value == reference.value; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public int hashCode() { | ||
49 | return System.identityHashCode(value); | ||
50 | } | ||
51 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/aggregators/IntervalAggregatorFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/aggregators/IntervalAggregatorFactory.xtend new file mode 100644 index 00000000..dee31f67 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/aggregators/IntervalAggregatorFactory.xtend | |||
@@ -0,0 +1,50 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.aggregators | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.Interval | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.IntervalAggregationMode | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.IntervalAggregationOperator | ||
6 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.AggregatorType | ||
7 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.BoundAggregator | ||
8 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IAggregatorFactory | ||
9 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
10 | |||
11 | @AggregatorType(parameterTypes=#[Interval], returnTypes=#[Interval]) | ||
12 | abstract class IntervalAggregatorFactory implements IAggregatorFactory { | ||
13 | val IntervalAggregationMode mode | ||
14 | |||
15 | @FinalFieldsConstructor | ||
16 | protected new() { | ||
17 | } | ||
18 | |||
19 | override getAggregatorLogic(Class<?> domainClass) { | ||
20 | if (domainClass == Interval) { | ||
21 | new BoundAggregator(new IntervalAggregationOperator(mode), Interval, Interval) | ||
22 | } else { | ||
23 | throw new IllegalArgumentException("Unknown domain class: " + domainClass) | ||
24 | } | ||
25 | } | ||
26 | } | ||
27 | |||
28 | class intervalSum extends IntervalAggregatorFactory { | ||
29 | new() { | ||
30 | super(IntervalAggregationMode.SUM) | ||
31 | } | ||
32 | } | ||
33 | |||
34 | class intervalMin extends IntervalAggregatorFactory { | ||
35 | new() { | ||
36 | super(IntervalAggregationMode.MIN) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | class intervalMax extends IntervalAggregatorFactory { | ||
41 | new() { | ||
42 | super(IntervalAggregationMode.MAX) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | class intervalJoin extends IntervalAggregatorFactory { | ||
47 | new() { | ||
48 | super(IntervalAggregationMode.JOIN) | ||
49 | } | ||
50 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/aggregators/intervalHull.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/aggregators/intervalHull.xtend new file mode 100644 index 00000000..72605f57 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/aggregators/intervalHull.xtend | |||
@@ -0,0 +1,74 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.aggregators | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.Interval | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.IntervalHullAggregatorOperator | ||
5 | import java.math.BigDecimal | ||
6 | import java.math.BigInteger | ||
7 | import java.math.MathContext | ||
8 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.AggregatorType | ||
9 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.BoundAggregator | ||
10 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IAggregatorFactory | ||
11 | |||
12 | @AggregatorType(parameterTypes=#[BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short], returnTypes=#[ | ||
13 | Interval, Interval, Interval, Interval, Interval, Interval, Interval, Interval]) | ||
14 | class intervalHull implements IAggregatorFactory { | ||
15 | |||
16 | override getAggregatorLogic(Class<?> domainClass) { | ||
17 | new BoundAggregator(getAggregationOperator(domainClass), domainClass, Interval) | ||
18 | } | ||
19 | |||
20 | private def getAggregationOperator(Class<?> domainClass) { | ||
21 | switch (domainClass) { | ||
22 | case BigDecimal: | ||
23 | new IntervalHullAggregatorOperator<BigDecimal>() { | ||
24 | override protected toBigDecimal(BigDecimal value, MathContext mc) { | ||
25 | value.round(mc) | ||
26 | } | ||
27 | } | ||
28 | case BigInteger: | ||
29 | new IntervalHullAggregatorOperator<BigInteger>() { | ||
30 | override protected toBigDecimal(BigInteger value, MathContext mc) { | ||
31 | new BigDecimal(value, mc) | ||
32 | } | ||
33 | } | ||
34 | case Byte: | ||
35 | new IntervalHullAggregatorOperator<Byte>() { | ||
36 | override protected toBigDecimal(Byte value, MathContext mc) { | ||
37 | new BigDecimal(value, mc) | ||
38 | } | ||
39 | } | ||
40 | case Double: | ||
41 | new IntervalHullAggregatorOperator<Double>() { | ||
42 | override protected toBigDecimal(Double value, MathContext mc) { | ||
43 | new BigDecimal(value, mc) | ||
44 | } | ||
45 | } | ||
46 | case Float: | ||
47 | new IntervalHullAggregatorOperator<Float>() { | ||
48 | override protected toBigDecimal(Float value, MathContext mc) { | ||
49 | new BigDecimal(value, mc) | ||
50 | } | ||
51 | } | ||
52 | case Integer: | ||
53 | new IntervalHullAggregatorOperator<Integer>() { | ||
54 | override protected toBigDecimal(Integer value, MathContext mc) { | ||
55 | new BigDecimal(value, mc) | ||
56 | } | ||
57 | } | ||
58 | case Long: | ||
59 | new IntervalHullAggregatorOperator<Long>() { | ||
60 | override protected toBigDecimal(Long value, MathContext mc) { | ||
61 | new BigDecimal(value, mc) | ||
62 | } | ||
63 | } | ||
64 | case Short: | ||
65 | new IntervalHullAggregatorOperator<Short>() { | ||
66 | override protected toBigDecimal(Short value, MathContext mc) { | ||
67 | new BigDecimal(value, mc) | ||
68 | } | ||
69 | } | ||
70 | default: | ||
71 | throw new IllegalArgumentException("Unknown domain class: " + domainClass) | ||
72 | } | ||
73 | } | ||
74 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeIndexer.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeIndexer.xtend index d6a15c1a..0e0f1f02 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeIndexer.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeIndexer.xtend | |||
@@ -1,209 +1,150 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns |
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | 3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type |
5 | import org.eclipse.emf.ecore.EClass | 4 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem |
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | 5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality |
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult | 6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult |
9 | 7 | ||
10 | class GenericTypeIndexer extends TypeIndexer { | 8 | class GenericTypeIndexer extends TypeIndexer { |
11 | val PatternGenerator base; | ||
12 | |||
13 | new(PatternGenerator base) { | 9 | new(PatternGenerator base) { |
14 | this.base = base | 10 | super(base) |
15 | } | 11 | } |
12 | |||
16 | override requiresTypeAnalysis() { false } | 13 | override requiresTypeAnalysis() { false } |
17 | 14 | ||
18 | public override getRequiredQueries() ''' | 15 | override getRequiredQueries() ''' |
19 | private pattern newELement(interpretation: PartialInterpretation, element: DefinedElement) { | 16 | «super.requiredQueries» |
20 | PartialInterpretation.newElements(interpretation,element); | 17 | |
21 | } | 18 | /** |
22 | 19 | * Direct supertypes of a type. | |
23 | private pattern typeInterpretation(problem:LogicProblem, interpetation:PartialInterpretation, type:TypeDeclaration, typeInterpretation:PartialComplexTypeInterpretation) { | 20 | */ |
24 | find interpretation(problem,interpetation); | 21 | private pattern supertypeDirect(subtype : Type, supertype : Type) { |
25 | LogicProblem.types(problem,type); | 22 | Type.supertypes(subtype, supertype); |
26 | PartialInterpretation.partialtypeinterpratation(interpetation,typeInterpretation); | 23 | } |
27 | PartialComplexTypeInterpretation.interpretationOf(typeInterpretation,type); | 24 | |
28 | } | 25 | /** |
29 | 26 | * All supertypes of a type. | |
30 | private pattern directInstanceOf(problem:LogicProblem, interpetation:PartialInterpretation, element:DefinedElement, type:Type) { | 27 | */ |
31 | find interpretation(problem,interpetation); | 28 | private pattern supertypeStar(subtype: Type, supertype: Type) { |
32 | find mustExist(problem,interpetation,element); | 29 | subtype == supertype; |
33 | LogicProblem.types(problem,type); | 30 | } or { |
34 | TypeDefinition.elements(type,element); | 31 | find supertypeDirect+(subtype,supertype); |
35 | } or { | 32 | } |
36 | find mustExist(problem,interpetation,element); | 33 | |
37 | find typeInterpretation(problem,interpetation,type,typeInterpretation); | 34 | /// Complex type reasoning patterns /// |
38 | PartialComplexTypeInterpretation.elements(typeInterpretation,element); | 35 | // |
39 | } | 36 | // In a valid type system, for each element e there is exactly one type T where |
40 | 37 | // 1: T(e) - but we dont know this for type declaration | |
41 | /** | 38 | // 2: For the dynamic type D and another type T, where D(e) && D-->T, T(e) is true. |
42 | * Direct supertypes of a type. | 39 | // 2e: A type hierarchy is invalid, if there is a supertype T for a dynamic type D which does no contains e: |
43 | */ | 40 | // D(e) && D-->T && !T(e) |
44 | private pattern supertypeDirect(subtype : Type, supertype : Type) { | 41 | // 3: There is no T' that T'->T and T'(e) |
45 | Type.supertypes(subtype, supertype); | 42 | // 3e: A type hierarcy is invalid, if there is a type T for a dynamic type D, which contains e, but not subtype of T: |
46 | } | 43 | // D(e) && ![T--->D] && T(e) |
47 | |||
48 | /** | ||
49 | * All supertypes of a type. | ||
50 | */ | ||
51 | private pattern supertypeStar(subtype: Type, supertype: Type) { | ||
52 | subtype == supertype; | ||
53 | } or { | ||
54 | find supertypeDirect+(subtype,supertype); | ||
55 | } | ||
56 | |||
57 | /// Complex type reasoning patterns /// | ||
58 | // | ||
59 | // In a valid type system, for each element e there is exactly one type T where | ||
60 | // 1: T(e) - but we dont know this for type declaration | ||
61 | // 2: For the dynamic type D and another type T, where D(e) && D-->T, T(e) is true. | ||
62 | // 2e: A type hierarchy is invalid, if there is a supertype T for a dynamic type D which does no contains e: | ||
63 | // D(e) && D-->T && !T(e) | ||
64 | // 3: There is no T' that T'->T and T'(e) | ||
65 | // 3e: A type hierarcy is invalid, if there is a type T for a dynamic type D, which contains e, but not subtype of T: | ||
66 | // D(e) && ![T--->D] && T(e) | ||
67 | // 4: T is not abstract | ||
68 | // Such type T is called Dynamic type of e, while other types are called static types. | ||
69 | // | ||
70 | // The following patterns checks the possible dynamic types for an element | ||
71 | |||
72 | private pattern wellformedType(problem: LogicProblem, interpretation:PartialInterpretation, dynamic:Type, element:DefinedElement) { | ||
73 | // 1: T(e) | ||
74 | find directInstanceOf(problem,interpretation,element,dynamic); | ||
75 | // 2e is not true: D(e) && D-->T && !T(e) | ||
76 | neg find dynamicTypeNotSubtypeOfADefinition(problem,interpretation,element,dynamic); | ||
77 | // 3e is not true: D(e) && ![T--->D] && T(e) | ||
78 | neg find dynamicTypeIsSubtypeOfANonDefinition(problem,interpretation,element,dynamic); | ||
79 | // 4: T is not abstract | ||
80 | Type.isAbstract(dynamic,false); | ||
81 | } | ||
82 | |||
83 | |||
84 | private pattern isPrimitive(element: PrimitiveElement) { | ||
85 | PrimitiveElement(element); | ||
86 | } | ||
87 | |||
88 | private pattern possibleDynamicType(problem: LogicProblem, interpretation:PartialInterpretation, dynamic:Type, element:DefinedElement) | ||
89 | // case 1: element is defined at least once | ||
90 | { | ||
91 | LogicProblem.types(problem,dynamic); | ||
92 | // select a random definition 'randomType' | ||
93 | find directInstanceOf(problem,interpretation,element,randomType); | ||
94 | // dynamic is a subtype of 'randomType' | ||
95 | find supertypeStar(dynamic,randomType); | ||
96 | // 2e is not true: D(e) && D-->T && !T(e) | ||
97 | neg find dynamicTypeNotSubtypeOfADefinition(problem,interpretation,element,dynamic); | ||
98 | // 3e is not true: D(e) && ![T--->D] && T(e) | ||
99 | neg find dynamicTypeIsSubtypeOfANonDefinition(problem,interpretation,element,dynamic); | ||
100 | // 4: T is not abstract | ||
101 | Type.isAbstract(dynamic,false); | ||
102 | // 5. element is not primitive datatype | ||
103 | neg find isPrimitive(element); | ||
104 | } or | ||
105 | // case 2: element is not defined anywhere | ||
106 | { | ||
107 | find mayExist(problem,interpretation,element); | ||
108 | // there is no definition | ||
109 | neg find directInstanceOf(problem,interpretation,element,_); | ||
110 | // 2e is not true: D(e) && D-->T && !T(e) | ||
111 | // because non of the definition contains element, the type cannot have defined supertype | ||
112 | LogicProblem.types(problem,dynamic); | ||
113 | PartialInterpretation.problem(interpretation,problem); | ||
114 | neg find typeWithDefinedSupertype(dynamic); | ||
115 | // 3e is not true: D(e) && ![T--->D] && T(e) | ||
116 | // because there is no definition, dynamic covers all definition | ||
117 | // 4: T is not abstract | 44 | // 4: T is not abstract |
118 | Type.isAbstract(dynamic,false); | 45 | // Such type T is called Dynamic type of e, while other types are called static types. |
119 | // 5. element is not primitive datatype | 46 | // |
120 | neg find isPrimitive(element); | 47 | // The following patterns checks the possible dynamic types for an element |
121 | } | 48 | |
122 | 49 | private pattern wellformedType(problem: LogicProblem, interpretation:PartialInterpretation, dynamic:Type, element:DefinedElement) { | |
123 | /** | 50 | // 1: T(e) |
124 | * supertype -------> element <------- otherSupertype | 51 | find directInstanceOf(problem,interpretation,element,dynamic); |
125 | * A A | 52 | // 2e is not true: D(e) && D-->T && !T(e) |
126 | * | | | 53 | neg find dynamicTypeNotSubtypeOfADefinition(problem,interpretation,element,dynamic); |
127 | * wrongDynamic -----------------------------X | 54 | // 3e is not true: D(e) && ![T--->D] && T(e) |
128 | */ | 55 | neg find dynamicTypeIsSubtypeOfANonDefinition(problem,interpretation,element,dynamic); |
129 | private pattern dynamicTypeNotSubtypeOfADefinition(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement, wrongDynamic : Type) { | 56 | // 4: T is not abstract |
130 | find directInstanceOf(problem,interpretation,element,supertype); | 57 | Type.isAbstract(dynamic,false); |
131 | find directInstanceOf(problem,interpretation,element,otherSupertype); | 58 | } |
132 | find supertypeStar(wrongDynamic,supertype); | 59 | |
133 | neg find supertypeStar(wrongDynamic,otherSupertype); | 60 | private pattern possibleDynamicType(problem: LogicProblem, interpretation:PartialInterpretation, dynamic:Type, element:DefinedElement) |
134 | } | 61 | // case 1: element is defined at least once |
135 | 62 | { | |
136 | /** | 63 | LogicProblem.types(problem,dynamic); |
137 | * supertype -------> element <---X--- otherSupertype | 64 | // select a random definition 'randomType' |
138 | * A A | 65 | find directInstanceOf(problem,interpretation,element,randomType); |
139 | * | | | 66 | // dynamic is a subtype of 'randomType' |
140 | * wrongDynamic -----------------------------+ | 67 | find supertypeStar(dynamic,randomType); |
141 | */ | 68 | // 2e is not true: D(e) && D-->T && !T(e) |
142 | private pattern dynamicTypeIsSubtypeOfANonDefinition(problem: LogicProblem, interpretation:PartialInterpretation, element:DefinedElement, wrongDynamic:Type) { | 69 | neg find dynamicTypeNotSubtypeOfADefinition(problem,interpretation,element,dynamic); |
143 | find directInstanceOf(problem,interpretation,element,supertype); | 70 | // 3e is not true: D(e) && ![T--->D] && T(e) |
144 | neg find elementInTypeDefinition(element,otherSupertype); | 71 | neg find dynamicTypeIsSubtypeOfANonDefinition(problem,interpretation,element,dynamic); |
145 | TypeDefinition(otherSupertype); | 72 | // 4: T is not abstract |
146 | find supertypeStar(wrongDynamic, supertype); | 73 | Type.isAbstract(dynamic,false); |
147 | find supertypeStar(wrongDynamic, otherSupertype); | 74 | // 5. element is not primitive datatype |
148 | } | 75 | neg find isPrimitive(element); |
149 | 76 | } or | |
150 | private pattern elementInTypeDefinition(element:DefinedElement, definition:TypeDefinition) { | 77 | // case 2: element is not defined anywhere |
151 | TypeDefinition.elements(definition,element); | 78 | { |
152 | } | 79 | find mayExist(problem,interpretation,element); |
153 | 80 | // there is no definition | |
154 | private pattern typeWithDefinedSupertype(type:Type) { | 81 | neg find directInstanceOf(problem,interpretation,element,_); |
155 | find supertypeStar(type,definedSupertype); | 82 | // 2e is not true: D(e) && D-->T && !T(e) |
156 | TypeDefinition(definedSupertype); | 83 | // because non of the definition contains element, the type cannot have defined supertype |
157 | } | 84 | LogicProblem.types(problem,dynamic); |
158 | 85 | PartialInterpretation.problem(interpretation,problem); | |
159 | private pattern scopeDisallowsNewElementsFromType(typeInterpretation:PartialComplexTypeInterpretation) { | 86 | neg find typeWithDefinedSupertype(dynamic); |
160 | Scope.targetTypeInterpretation(scope,typeInterpretation); | 87 | // 3e is not true: D(e) && ![T--->D] && T(e) |
161 | Scope.maxNewElements(scope,0); | 88 | // because there is no definition, dynamic covers all definition |
162 | } | 89 | // 4: T is not abstract |
163 | ''' | 90 | Type.isAbstract(dynamic,false); |
164 | 91 | // 5. element is not primitive datatype | |
165 | public override generateInstanceOfQueries(LogicProblem problem, PartialInterpretation emptySolution,TypeAnalysisResult typeAnalysisResult) { | 92 | neg find isPrimitive(element); |
166 | ''' | 93 | } |
167 | «FOR type:problem.types» | 94 | |
168 | «problem.generateMustInstenceOf(type)» | ||
169 | «problem.generateMayInstanceOf(type)» | ||
170 | «ENDFOR» | ||
171 | ''' | ||
172 | } | ||
173 | |||
174 | private def patternName(Type type, Modality modality) | ||
175 | '''«modality.toString.toLowerCase»InstanceOf«base.canonizeName(type.name)»''' | ||
176 | |||
177 | private def generateMustInstenceOf(LogicProblem problem, Type type) { | ||
178 | ''' | ||
179 | /** | 95 | /** |
180 | * An element must be an instance of type "«type.name»". | 96 | * supertype -------> element <------- otherSupertype |
97 | * A A | ||
98 | * | | | ||
99 | * wrongDynamic -----------------------------X | ||
181 | */ | 100 | */ |
182 | private pattern «patternName(type,Modality.MUST)»(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | 101 | private pattern dynamicTypeNotSubtypeOfADefinition(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement, wrongDynamic : Type) { |
183 | Type.name(type,"«type.name»"); | 102 | find directInstanceOf(problem,interpretation,element,supertype); |
184 | find directInstanceOf(problem,interpretation,element,type); | 103 | find directInstanceOf(problem,interpretation,element,otherSupertype); |
104 | find supertypeStar(wrongDynamic,supertype); | ||
105 | neg find supertypeStar(wrongDynamic,otherSupertype); | ||
185 | } | 106 | } |
186 | ''' | 107 | |
187 | } | ||
188 | |||
189 | private def generateMayInstanceOf(LogicProblem problem, Type type) { | ||
190 | ''' | ||
191 | /** | 108 | /** |
192 | * An element may be an instance of type "«type.name»". | 109 | * supertype -------> element <---X--- otherSupertype |
110 | * A A | ||
111 | * | | | ||
112 | * wrongDynamic -----------------------------+ | ||
193 | */ | 113 | */ |
194 | private pattern «patternName(type,Modality.MAY)»(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | 114 | private pattern dynamicTypeIsSubtypeOfANonDefinition(problem: LogicProblem, interpretation:PartialInterpretation, element:DefinedElement, wrongDynamic:Type) { |
195 | Type.name(type,"«type.name»"); | 115 | find directInstanceOf(problem,interpretation,element,supertype); |
196 | find possibleDynamicType(problem,interpretation,dynamic,element); | 116 | neg find elementInTypeDefinition(element,otherSupertype); |
197 | find supertypeStar(dynamic,type); | 117 | TypeDefinition(otherSupertype); |
198 | neg find scopeDisallowsNewElementsFromType(dynamic); | 118 | find supertypeStar(wrongDynamic, supertype); |
119 | find supertypeStar(wrongDynamic, otherSupertype); | ||
120 | } | ||
121 | |||
122 | private pattern elementInTypeDefinition(element:DefinedElement, definition:TypeDefinition) { | ||
123 | TypeDefinition.elements(definition,element); | ||
124 | } | ||
125 | |||
126 | private pattern typeWithDefinedSupertype(type:Type) { | ||
127 | find supertypeStar(type,definedSupertype); | ||
128 | TypeDefinition(definedSupertype); | ||
129 | } | ||
130 | |||
131 | private pattern scopeDisallowsNewElementsFromType(typeInterpretation:PartialComplexTypeInterpretation) { | ||
132 | Scope.targetTypeInterpretation(scope,typeInterpretation); | ||
133 | Scope.maxNewElements(scope,0); | ||
199 | } | 134 | } |
135 | ''' | ||
136 | |||
137 | protected override generateMayInstanceOf(LogicProblem problem, Type type, TypeAnalysisResult typeAnalysisResult) { | ||
138 | ''' | ||
139 | /** | ||
140 | * An element may be an instance of type "«type.name»". | ||
141 | */ | ||
142 | private pattern «patternName(type,Modality.MAY)»(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | ||
143 | Type.name(type,"«type.name»"); | ||
144 | find possibleDynamicType(problem,interpretation,dynamic,element); | ||
145 | find supertypeStar(dynamic,type); | ||
146 | neg find scopeDisallowsNewElementsFromType(dynamic); | ||
147 | } | ||
200 | ''' | 148 | ''' |
201 | } | 149 | } |
202 | 150 | } | |
203 | public override referInstanceOf(Type type, Modality modality, String variableName) { | ||
204 | '''find «patternName(type,modality)»(problem,interpretation,«variableName»);''' | ||
205 | } | ||
206 | public override referInstanceOf(EClass type, Modality modality, String variableName) { | ||
207 | '''find «modality.toString.toLowerCase»InstanceOf«base.canonizeName('''«type.name» class''')»(problem,interpretation,«variableName»);''' | ||
208 | } | ||
209 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeRefinementGenerator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeRefinementGenerator.xtend index 2e03d6ed..52f0cbea 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeRefinementGenerator.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeRefinementGenerator.xtend | |||
@@ -11,110 +11,114 @@ import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.par | |||
11 | import java.util.HashMap | 11 | import java.util.HashMap |
12 | 12 | ||
13 | class GenericTypeRefinementGenerator extends TypeRefinementGenerator { | 13 | class GenericTypeRefinementGenerator extends TypeRefinementGenerator { |
14 | public new(PatternGenerator base) { | 14 | new(PatternGenerator base) { |
15 | super(base) | 15 | super(base) |
16 | } | 16 | } |
17 | |||
17 | override requiresTypeAnalysis() { false } | 18 | override requiresTypeAnalysis() { false } |
18 | 19 | ||
19 | override generateRefineObjectQueries(LogicProblem p, PartialInterpretation emptySolution, TypeAnalysisResult typeAnalysisResult) { | 20 | override generateRefineObjectQueries(LogicProblem p, PartialInterpretation emptySolution, |
21 | TypeAnalysisResult typeAnalysisResult) { | ||
20 | val containment = p.containmentHierarchies.head | 22 | val containment = p.containmentHierarchies.head |
21 | val newObjectTypes = p.types.filter(TypeDeclaration).filter[!isAbstract] | 23 | val newObjectTypes = p.types.filter(TypeDeclaration).filter[!isAbstract] |
22 | val inverseRelations = new HashMap | 24 | val inverseRelations = new HashMap |
23 | p.annotations.filter(InverseRelationAssertion).forEach[ | 25 | p.annotations.filter(InverseRelationAssertion).forEach [ |
24 | inverseRelations.put(it.inverseA,it.inverseB) | 26 | inverseRelations.put(it.inverseA, it.inverseB) |
25 | inverseRelations.put(it.inverseB,it.inverseA) | 27 | inverseRelations.put(it.inverseB, it.inverseA) |
26 | ] | 28 | ] |
27 | return ''' | 29 | return ''' |
28 | private pattern hasElementInContainment(problem:LogicProblem, interpretation:PartialInterpretation) | 30 | pattern «hasElementInContainmentName»(problem:LogicProblem, interpretation:PartialInterpretation) |
29 | «FOR type :containment.typesOrderedInHierarchy SEPARATOR "or"»{ | 31 | «FOR type : containment.typesOrderedInHierarchy SEPARATOR "or"»{ |
30 | find interpretation(problem,interpretation); | ||
31 | «base.typeIndexer.referInstanceOf(type,Modality.MUST,"root")» | ||
32 | find mustExist(problem, interpretation, root); | ||
33 | }«ENDFOR» | ||
34 | «FOR type:newObjectTypes» | ||
35 | «IF(containment.typesOrderedInHierarchy.contains(type))» | ||
36 | «FOR containmentRelation : containment.containmentRelations.filter[canBeContainedByRelation(it,type)]» | ||
37 | «IF inverseRelations.containsKey(containmentRelation)» | ||
38 | pattern «this.patternName(containmentRelation,inverseRelations.get(containmentRelation),type)»( | ||
39 | problem:LogicProblem, interpretation:PartialInterpretation, | ||
40 | relationInterpretation:PartialRelationInterpretation, inverseInterpretation:PartialRelationInterpretation ,typeInterpretation:PartialComplexTypeInterpretation, | ||
41 | container:DefinedElement) | ||
42 | { | ||
43 | find interpretation(problem,interpretation); | ||
44 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); | ||
45 | PartialComplexTypeInterpretation.interpretationOf.name(typeInterpretation,"«type.name»"); | ||
46 | PartialInterpretation.partialrelationinterpretation(interpretation,relationInterpretation); | ||
47 | PartialRelationInterpretation.interpretationOf.name(relationInterpretation,"«containmentRelation.name»"); | ||
48 | PartialInterpretation.partialrelationinterpretation(interpretation,inverseInterpretation); | ||
49 | PartialRelationInterpretation.interpretationOf.name(inverseInterpretation,"«inverseRelations.get(containmentRelation).name»"); | ||
50 | «base.typeIndexer.referInstanceOf((containmentRelation.parameters.get(0) as ComplexTypeReference).referred,Modality.MUST,"container")» | ||
51 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» | ||
52 | «base.relationDeclarationIndexer.referRelation(containmentRelation as RelationDeclaration,"container","newObject",Modality.MAY)» | ||
53 | find mustExist(problem, interpretation, container); | ||
54 | neg find mustExist(problem, interpretation, newObject); | ||
55 | } | ||
56 | «ELSE» | ||
57 | pattern «this.patternName(containmentRelation,null,type)»( | ||
58 | problem:LogicProblem, interpretation:PartialInterpretation, | ||
59 | relationInterpretation:PartialRelationInterpretation, typeInterpretation:PartialComplexTypeInterpretation, | ||
60 | container:DefinedElement) | ||
61 | { | ||
62 | find interpretation(problem,interpretation); | ||
63 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); | ||
64 | PartialComplexTypeInterpretation.interpretationOf.name(typeInterpretation,"«type.name»"); | ||
65 | PartialInterpretation.partialrelationinterpretation(interpretation,relationInterpretation); | ||
66 | PartialRelationInterpretation.interpretationOf.name(relationInterpretation,"«containmentRelation.name»"); | ||
67 | «base.typeIndexer.referInstanceOf((containmentRelation.parameters.get(0) as ComplexTypeReference).referred,Modality.MUST,"container")» | ||
68 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» | ||
69 | «base.relationDeclarationIndexer.referRelation(containmentRelation as RelationDeclaration,"container","newObject",Modality.MAY)» | ||
70 | find mustExist(problem, interpretation, container); | ||
71 | neg find mustExist(problem, interpretation, newObject); | ||
72 | } | ||
73 | «ENDIF» | ||
74 | «ENDFOR» | ||
75 | pattern «patternName(null,null,type)»( | ||
76 | problem:LogicProblem, interpretation:PartialInterpretation, | ||
77 | typeInterpretation:PartialComplexTypeInterpretation) | ||
78 | { | ||
79 | find interpretation(problem,interpretation); | 32 | find interpretation(problem,interpretation); |
80 | neg find hasElementInContainment(problem,interpretation); | 33 | «base.typeIndexer.referInstanceOf(type,Modality.MUST,"root")» |
81 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); | 34 | find mustExist(problem, interpretation, root); |
82 | PartialComplexTypeInterpretation.interpretationOf.name(type,"«type.name»"); | 35 | }«ENDFOR» |
83 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» | 36 | «FOR type : newObjectTypes» |
84 | find mayExist(problem, interpretation, newObject); | 37 | «IF(containment.typesOrderedInHierarchy.contains(type))» |
85 | neg find mustExist(problem, interpretation, newObject); | 38 | «FOR containmentRelation : containment.containmentRelations.filter[canBeContainedByRelation(it,type)]» |
86 | } | 39 | «IF inverseRelations.containsKey(containmentRelation)» |
87 | «ELSE» | 40 | pattern «this.patternName(containmentRelation,inverseRelations.get(containmentRelation),type)»( |
88 | pattern createObject_«this.patternName(null,null,type)»( | 41 | problem:LogicProblem, interpretation:PartialInterpretation, |
89 | problem:LogicProblem, interpretation:PartialInterpretation, | 42 | relationInterpretation:PartialRelationInterpretation, inverseInterpretation:PartialRelationInterpretation ,typeInterpretation:PartialComplexTypeInterpretation, |
90 | typeInterpretation:PartialComplexTypeInterpretation) | 43 | container:DefinedElement) |
91 | { | 44 | { |
92 | find interpretation(problem,interpretation); | 45 | find interpretation(problem,interpretation); |
93 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); | 46 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); |
94 | PartialComplexTypeInterpretation.interpretationOf.name(typeInterpretation,"«type.name»"); | 47 | PartialComplexTypeInterpretation.interpretationOf.name(typeInterpretation,"«type.name»"); |
95 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» | 48 | PartialInterpretation.partialrelationinterpretation(interpretation,relationInterpretation); |
96 | find mayExist(problem, interpretation, newObject); | 49 | PartialRelationInterpretation.interpretationOf.name(relationInterpretation,"«containmentRelation.name»"); |
97 | neg find mustExist(problem, interpretation, newObject); | 50 | PartialInterpretation.partialrelationinterpretation(interpretation,inverseInterpretation); |
98 | } | 51 | PartialRelationInterpretation.interpretationOf.name(inverseInterpretation,"«inverseRelations.get(containmentRelation).name»"); |
99 | «ENDIF» | 52 | «base.typeIndexer.referInstanceOf((containmentRelation.parameters.get(0) as ComplexTypeReference).referred,Modality.MUST,"container")» |
100 | «ENDFOR» | 53 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» |
54 | «base.relationDeclarationIndexer.referRelation(containmentRelation as RelationDeclaration,"container","newObject",Modality.MAY)» | ||
55 | find mustExist(problem, interpretation, container); | ||
56 | neg find mustExist(problem, interpretation, newObject); | ||
57 | } | ||
58 | «ELSE» | ||
59 | pattern «this.patternName(containmentRelation,null,type)»( | ||
60 | problem:LogicProblem, interpretation:PartialInterpretation, | ||
61 | relationInterpretation:PartialRelationInterpretation, typeInterpretation:PartialComplexTypeInterpretation, | ||
62 | container:DefinedElement) | ||
63 | { | ||
64 | find interpretation(problem,interpretation); | ||
65 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); | ||
66 | PartialComplexTypeInterpretation.interpretationOf.name(typeInterpretation,"«type.name»"); | ||
67 | PartialInterpretation.partialrelationinterpretation(interpretation,relationInterpretation); | ||
68 | PartialRelationInterpretation.interpretationOf.name(relationInterpretation,"«containmentRelation.name»"); | ||
69 | «base.typeIndexer.referInstanceOf((containmentRelation.parameters.get(0) as ComplexTypeReference).referred,Modality.MUST,"container")» | ||
70 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» | ||
71 | «base.relationDeclarationIndexer.referRelation(containmentRelation as RelationDeclaration,"container","newObject",Modality.MAY)» | ||
72 | find mustExist(problem, interpretation, container); | ||
73 | neg find mustExist(problem, interpretation, newObject); | ||
74 | } | ||
75 | «ENDIF» | ||
76 | «ENDFOR» | ||
77 | pattern «patternName(null,null,type)»( | ||
78 | problem:LogicProblem, interpretation:PartialInterpretation, | ||
79 | typeInterpretation:PartialComplexTypeInterpretation) | ||
80 | { | ||
81 | find interpretation(problem,interpretation); | ||
82 | neg find «hasElementInContainmentName»(problem,interpretation); | ||
83 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); | ||
84 | PartialComplexTypeInterpretation.interpretationOf.name(type,"«type.name»"); | ||
85 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» | ||
86 | find mayExist(problem, interpretation, newObject); | ||
87 | neg find mustExist(problem, interpretation, newObject); | ||
88 | } | ||
89 | «ELSE» | ||
90 | pattern createObject_«this.patternName(null,null,type)»( | ||
91 | problem:LogicProblem, interpretation:PartialInterpretation, | ||
92 | typeInterpretation:PartialComplexTypeInterpretation) | ||
93 | { | ||
94 | find interpretation(problem,interpretation); | ||
95 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); | ||
96 | PartialComplexTypeInterpretation.interpretationOf.name(typeInterpretation,"«type.name»"); | ||
97 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» | ||
98 | find mayExist(problem, interpretation, newObject); | ||
99 | neg find mustExist(problem, interpretation, newObject); | ||
100 | } | ||
101 | «ENDIF» | ||
102 | «ENDFOR» | ||
101 | ''' | 103 | ''' |
102 | } | 104 | } |
103 | 105 | ||
104 | override generateRefineTypeQueries(LogicProblem p, PartialInterpretation emptySolution, TypeAnalysisResult typeAnalysisResult) { | 106 | override generateRefineTypeQueries(LogicProblem p, PartialInterpretation emptySolution, |
107 | TypeAnalysisResult typeAnalysisResult) { | ||
105 | return ''' | 108 | return ''' |
106 | «FOR type : p.types.filter(TypeDeclaration).filter[!it.isAbstract]» | 109 | «FOR type : p.types.filter(TypeDeclaration).filter[!it.isAbstract]» |
107 | pattern refineTypeTo_«base.canonizeName(type.name)»(problem:LogicProblem, interpretation:PartialInterpretation, object: DefinedElement) { | 110 | pattern refineTypeTo_«base.canonizeName(type.name)»(problem:LogicProblem, interpretation:PartialInterpretation, object: DefinedElement) { |
108 | find interpretation(problem,interpretation); | 111 | find interpretation(problem,interpretation); |
109 | find mustExist(problem, interpretation, object); | 112 | find mustExist(problem, interpretation, object); |
110 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"object")» | 113 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"object")» |
111 | neg «base.typeIndexer.referInstanceOf(type,Modality.MUST,"object")» | 114 | neg «base.typeIndexer.referInstanceOf(type,Modality.MUST,"object")» |
112 | } | 115 | } |
113 | «ENDFOR» | 116 | «ENDFOR» |
114 | ''' | 117 | ''' |
115 | } | 118 | } |
116 | 119 | ||
117 | override getRefineTypeQueryNames(LogicProblem p, PartialInterpretation emptySolution, TypeAnalysisResult typeAnalysisResult) { | 120 | override getRefineTypeQueryNames(LogicProblem p, PartialInterpretation emptySolution, |
121 | TypeAnalysisResult typeAnalysisResult) { | ||
118 | p.types.filter(TypeDeclaration).toInvertedMap['''refineTypeTo_«base.canonizeName(it.name)»'''] | 122 | p.types.filter(TypeDeclaration).toInvertedMap['''refineTypeTo_«base.canonizeName(it.name)»'''] |
119 | } | 123 | } |
120 | } \ No newline at end of file | 124 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PConstraintTransformer.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PConstraintTransformer.xtend new file mode 100644 index 00000000..dd5cade1 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PConstraintTransformer.xtend | |||
@@ -0,0 +1,275 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatra2logic.XExpressionExtractor | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | ||
5 | import org.eclipse.emf.ecore.EAttribute | ||
6 | import org.eclipse.emf.ecore.EEnumLiteral | ||
7 | import org.eclipse.emf.ecore.EReference | ||
8 | import org.eclipse.viatra.query.runtime.emf.types.EClassTransitiveInstancesKey | ||
9 | import org.eclipse.viatra.query.runtime.emf.types.EDataTypeInSlotsKey | ||
10 | import org.eclipse.viatra.query.runtime.emf.types.EStructuralFeatureInstancesKey | ||
11 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
12 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable | ||
13 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality | ||
14 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter | ||
15 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExpressionEvaluation | ||
16 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality | ||
17 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall | ||
18 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint | ||
19 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure | ||
20 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.ConstantValue | ||
21 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall | ||
22 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint | ||
23 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.VariableMapping | ||
24 | import java.util.List | ||
25 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeReference | ||
26 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.PrimitiveTypeReference | ||
27 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference | ||
28 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference | ||
29 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference | ||
30 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference | ||
31 | import java.util.Map | ||
32 | |||
33 | class PConstraintTransformer { | ||
34 | val extension RelationDefinitionIndexer relationDefinitionIndexer; | ||
35 | val expressionExtractor = new XExpressionExtractor | ||
36 | val expressionGenerator = new PExpressionGenerator | ||
37 | |||
38 | new(RelationDefinitionIndexer relationDefinitionIndexer) { | ||
39 | this.relationDefinitionIndexer = relationDefinitionIndexer | ||
40 | } | ||
41 | |||
42 | dispatch def transformConstraint(TypeConstraint constraint, Modality modality, List<VariableMapping> variableMapping) { | ||
43 | val touple = constraint.variablesTuple | ||
44 | if(touple.size == 1) { | ||
45 | val inputKey = constraint.equivalentJudgement.inputKey | ||
46 | if(inputKey instanceof EClassTransitiveInstancesKey) { | ||
47 | return relationDefinitionIndexer.base.typeIndexer.referInstanceOf(inputKey.emfKey,modality.toMustMay, | ||
48 | constraint.getVariableInTuple(0).canonizeName) | ||
49 | } else if(inputKey instanceof EDataTypeInSlotsKey){ | ||
50 | return '''// type constraint is enforced by construction''' | ||
51 | } | ||
52 | |||
53 | } else if(touple.size == 2){ | ||
54 | val key = (constraint.equivalentJudgement.inputKey as EStructuralFeatureInstancesKey).emfKey | ||
55 | if(key instanceof EReference) { | ||
56 | return base.referRelationByName( | ||
57 | key, | ||
58 | constraint.getVariableInTuple(0).canonizeName, | ||
59 | constraint.getVariableInTuple(1).canonizeName, | ||
60 | modality.toMustMay) | ||
61 | } else if (key instanceof EAttribute) { | ||
62 | return base.referAttributeByName(key, | ||
63 | constraint.getVariableInTuple(0).canonizeName, | ||
64 | constraint.getVariableInTuple(1).canonizeName, | ||
65 | modality.toMustMay) | ||
66 | } else throw new UnsupportedOperationException('''unknown key: «key.class»''') | ||
67 | } else { | ||
68 | throw new UnsupportedOperationException('''Unsupported touple size: «touple.size»''') | ||
69 | } | ||
70 | } | ||
71 | dispatch def transformConstraint(TypeFilterConstraint constraint, Modality modality, List<VariableMapping> variableMapping) { | ||
72 | val touple = constraint.variablesTuple | ||
73 | if(touple.size == 1) { | ||
74 | val inputKey = constraint.equivalentJudgement.inputKey | ||
75 | if(inputKey instanceof EClassTransitiveInstancesKey) { | ||
76 | return base.typeIndexer.referInstanceOf(inputKey.emfKey,modality.toMustMay, | ||
77 | (constraint.getVariablesTuple.get(0) as PVariable).canonizeName) | ||
78 | } else if(inputKey instanceof EDataTypeInSlotsKey){ | ||
79 | return '''// type constraint is enforced by construction''' | ||
80 | } | ||
81 | |||
82 | } else if(touple.size == 2){ | ||
83 | val key = (constraint.equivalentJudgement.inputKey as EStructuralFeatureInstancesKey).emfKey | ||
84 | if(key instanceof EReference) { | ||
85 | return base.referRelationByName( | ||
86 | key, | ||
87 | (constraint.getVariablesTuple.get(0) as PVariable).canonizeName, | ||
88 | (constraint.getVariablesTuple.get(1) as PVariable).canonizeName, | ||
89 | modality.toMustMay) | ||
90 | } else if (key instanceof EAttribute) { | ||
91 | return base.referAttributeByName(key, | ||
92 | (constraint.getVariablesTuple.get(0) as PVariable).canonizeName, | ||
93 | (constraint.getVariablesTuple.get(1) as PVariable).canonizeName, | ||
94 | modality.toMustMay) | ||
95 | } else throw new UnsupportedOperationException('''unknown key: «key.class»''') | ||
96 | } else { | ||
97 | throw new UnsupportedOperationException('''Unsupported touple size: «touple.size»''') | ||
98 | } | ||
99 | } | ||
100 | |||
101 | dispatch def transformConstraint(Equality equality, Modality modality, List<VariableMapping> variableMapping) { | ||
102 | val a = equality.who | ||
103 | val b = equality.withWhom | ||
104 | transformEquality(modality.toMustMay, a, b) | ||
105 | } | ||
106 | |||
107 | private def CharSequence transformEquality(Modality modality, PVariable a, PVariable b) { | ||
108 | if(modality.isMustOrCurrent) '''find mustEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
109 | else '''find mayEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
110 | } | ||
111 | |||
112 | dispatch def transformConstraint(Inequality inequality, Modality modality, List<VariableMapping> variableMapping) { | ||
113 | val a = inequality.who | ||
114 | val b = inequality.withWhom | ||
115 | if(modality.isCurrent) { | ||
116 | return '''neg find mustEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
117 | } else if(modality.isMust) { | ||
118 | return '''neg find mayEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
119 | } else { // modality.isMay | ||
120 | return '''neg find mustEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
121 | } | ||
122 | } | ||
123 | |||
124 | dispatch def transformConstraint(NegativePatternCall pcall, Modality modality, List<VariableMapping> variableMapping) { | ||
125 | val params = (0..<pcall.actualParametersTuple.size).map[index | | ||
126 | val variable = pcall.actualParametersTuple.get(index) as PVariable | ||
127 | return variable.canonizeName | ||
128 | ] | ||
129 | return referPattern(pcall.referredQuery,params,modality.dual,false,false) | ||
130 | } | ||
131 | |||
132 | dispatch def transformConstraint(PositivePatternCall pcall, Modality modality, List<VariableMapping> variableMapping) { | ||
133 | val params = (0..<pcall.variablesTuple.size).map[index | | ||
134 | val variable = pcall.variablesTuple.get(index) as PVariable | ||
135 | return variable.canonizeName | ||
136 | ] | ||
137 | return referPattern(pcall.referredQuery,params,modality,true,false) | ||
138 | } | ||
139 | dispatch def transformConstraint(BinaryTransitiveClosure pcall, Modality modality, List<VariableMapping> variableMapping) { | ||
140 | val params = (0..1).map[index | | ||
141 | val variable = pcall.getVariableInTuple(index) as PVariable | ||
142 | return variable.canonizeName | ||
143 | ] | ||
144 | return referPattern(pcall.referredQuery,params,modality,true,true) | ||
145 | } | ||
146 | dispatch def transformConstraint(ExportedParameter e, Modality modality, List<VariableMapping> variableMapping) { | ||
147 | val v1 = '''var_«e.parameterName»''' | ||
148 | val v2 = e.parameterVariable.canonizeName | ||
149 | if(v1.compareTo(v2) == 0) { | ||
150 | return '''// «v1» exported''' | ||
151 | } else { | ||
152 | return '''«v1» == «v2»;''' | ||
153 | } | ||
154 | } | ||
155 | dispatch def transformConstraint(ConstantValue c, Modality modality, List<VariableMapping> variableMapping) { | ||
156 | val target = c.supplierKey | ||
157 | |||
158 | var String targetString; | ||
159 | var String additionalDefinition; | ||
160 | if(target instanceof EEnumLiteral) { | ||
161 | targetString = '''const_«target.name»_«target.EEnum.name»''' | ||
162 | additionalDefinition = '''DefinedElement.name(«targetString»,"«target.name» «target.EEnum.name»"); //LogicProblem.elements(problem,«targetString»);''' | ||
163 | } else if(target instanceof Integer) { | ||
164 | targetString = '''const_«target»_Integer''' | ||
165 | additionalDefinition = '''PrimitiveElement.valueSet(«targetString»,true); IntegerElement.value(«targetString»,«target»);''' | ||
166 | } else if(target instanceof Boolean) { | ||
167 | targetString = '''const_«target»_Boolean''' | ||
168 | additionalDefinition = '''PrimitiveElement.valueSet(«targetString»,true); BooleanElement.value(«targetString»,«target»);''' | ||
169 | } else if(target instanceof String) { | ||
170 | targetString = '''const_«target»_String''' | ||
171 | additionalDefinition = '''PrimitiveElement.valueSet(«targetString»,true); StringElement.value(«targetString»,"«target»");''' | ||
172 | } else if(target instanceof Double) { | ||
173 | targetString = '''const_«target»_Real''' | ||
174 | additionalDefinition = '''PrimitiveElement.valueSet(«targetString»,true); RealElement.value(«targetString»,«target»);''' | ||
175 | } else if(target instanceof Float) { | ||
176 | targetString = '''const_«target»_Real''' | ||
177 | additionalDefinition = '''PrimitiveElement.valueSet(«targetString»,true); RealElement.value(«targetString»,«target»);''' | ||
178 | } else { | ||
179 | throw new UnsupportedOperationException('''Unknown constant type: «target.class»''') | ||
180 | } | ||
181 | |||
182 | val source = c.variablesTuple | ||
183 | var String sourceName | ||
184 | if(source.size == 1) | ||
185 | sourceName = (source.get(0) as PVariable).canonizeName | ||
186 | else throw new UnsupportedOperationException("unknown source") | ||
187 | return '''«sourceName» == «targetString»;«additionalDefinition»'''; | ||
188 | } | ||
189 | |||
190 | protected def valueVariable(PVariable v) { | ||
191 | "value_"+v.canonizeName | ||
192 | } | ||
193 | protected def valueSetted(PVariable v) { | ||
194 | "setted_"+v.canonizeName | ||
195 | } | ||
196 | def hasValue(PVariable v, String target, Modality m, List<VariableMapping> variableMapping) { | ||
197 | val typeReference = variableMapping.filter[it.sourcePVariable === v].head.targetLogicVariable.range as PrimitiveTypeReference | ||
198 | if(m.isMay) { | ||
199 | '''PrimitiveElement.valueSet(«v.canonizeName»,«v.valueSetted»); «hasValueExpressionByRef(typeReference,v,v.valueVariable)» | ||
200 | ««« check(!«v.valueSetted»||«v.valueVariable»==«target»)); | ||
201 | ''' | ||
202 | } else { // Must or current | ||
203 | '''PrimitiveElement.valueSet(«v.canonizeName»,true);«hasValueExpressionByRef(typeReference,v,target)»''' | ||
204 | } | ||
205 | } | ||
206 | |||
207 | private def hasValueExpression(List<VariableMapping> variableMapping, PVariable v, String target) { | ||
208 | val mapping = variableMapping.filter[ | ||
209 | val v2 = (it.sourcePVariable as PVariable) | ||
210 | v2 === v | ||
211 | ].head | ||
212 | val range = mapping.targetLogicVariable.range | ||
213 | hasValueExpressionByRef( | ||
214 | range, | ||
215 | v, | ||
216 | target | ||
217 | ) | ||
218 | } | ||
219 | private def dispatch hasValueExpressionByRef(BoolTypeReference typeReference, PVariable v, String target) '''BooleanElement.value(«v.canonizeName»,«target»);''' | ||
220 | private def dispatch hasValueExpressionByRef(IntTypeReference typeReference, PVariable v, String target) '''IntegerElement.value(«v.canonizeName»,«target»);''' | ||
221 | private def dispatch hasValueExpressionByRef(RealTypeReference typeReference, PVariable v, String target) '''RealElement.value(«v.canonizeName»,«target»);''' | ||
222 | private def dispatch hasValueExpressionByRef(StringTypeReference typeReference, PVariable v, String target) '''StringElement.value(«v.canonizeName»,«target»);''' | ||
223 | private def dispatch hasValueExpressionByRef(TypeReference typeReference, PVariable v, String target) { | ||
224 | throw new UnsupportedOperationException('''Unsupported primitive type reference: «typeReference.class»''') | ||
225 | } | ||
226 | |||
227 | dispatch def transformConstraint(ExpressionEvaluation e, Modality modality, List<VariableMapping> variableMapping) { | ||
228 | if(e.outputVariable!==null) { | ||
229 | throw new UnsupportedOperationException('''Only check expressions are supported "«e.class.name»"!''') | ||
230 | } else { | ||
231 | val expression = expressionExtractor.extractExpression(e.evaluator) | ||
232 | val Map<PVariable, PrimitiveTypeReference> variable2Type = e.affectedVariables.toInvertedMap[v|variableMapping.filter[it.sourcePVariable === v].head.targetLogicVariable.range as PrimitiveTypeReference] | ||
233 | if(modality.isMay) { | ||
234 | return ''' | ||
235 | «FOR variable: e.affectedVariables» | ||
236 | PrimitiveElement.valueSet(«variable.canonizeName»,«variable.valueSetted»); «hasValueExpression(variableMapping,variable,variable.valueVariable)» | ||
237 | «ENDFOR» | ||
238 | ««« check( | ||
239 | ««« «FOR variable: e.affectedVariables SEPARATOR " || "»!«variable.valueSetted»«ENDFOR» | ||
240 | ««« «IF variable2Type.values.filter(RealTypeReference).empty» | ||
241 | ««« || | ||
242 | ««« («expressionGenerator.translateExpression(expression,e.affectedVariables.toInvertedMap[valueVariable],variable2Type)») | ||
243 | ««« «ENDIF» | ||
244 | ««« ); | ||
245 | ''' | ||
246 | } else { // Must or Current | ||
247 | return ''' | ||
248 | «FOR variable: e.affectedVariables» | ||
249 | PrimitiveElement.valueSet(«variable.canonizeName»,true); «hasValueExpression(variableMapping,variable,variable.valueVariable)» | ||
250 | «ENDFOR» | ||
251 | ««« «IF variable2Type.values.filter(RealTypeReference).empty» | ||
252 | ««« check(«expressionGenerator.translateExpression(expression,e.affectedVariables.toInvertedMap[valueVariable],variable2Type)»); | ||
253 | ««« «ENDIF» | ||
254 | ''' | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | |||
259 | dispatch def transformConstraint(PConstraint c, Modality modality, List<VariableMapping> variableMapping) { | ||
260 | throw new UnsupportedOperationException('''Unknown constraint type: "«c.class.name»"!''') | ||
261 | } | ||
262 | |||
263 | dispatch def transformConstraintUnset(ExpressionEvaluation e, List<VariableMapping> variableMapping) { | ||
264 | return ''' | ||
265 | «FOR variable: e.affectedVariables» | ||
266 | PrimitiveElement.valueSet(«variable.canonizeName»,«variable.valueSetted»); «hasValueExpression(variableMapping,variable,variable.valueVariable)» | ||
267 | «ENDFOR» | ||
268 | ««« check(«FOR variable: e.affectedVariables SEPARATOR " || "»!«variable.valueSetted»«ENDFOR»); | ||
269 | ''' | ||
270 | } | ||
271 | |||
272 | dispatch def transformConstraintUnset(PConstraint c, List<VariableMapping> variableMapping) { | ||
273 | throw new UnsupportedOperationException('''Unknown constraint type: "«c.class.name»"!''') | ||
274 | } | ||
275 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PExpressionGenerator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PExpressionGenerator.xtend new file mode 100644 index 00000000..62ff92b2 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PExpressionGenerator.xtend | |||
@@ -0,0 +1,116 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | ||
2 | |||
3 | import java.util.Map | ||
4 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable | ||
5 | import org.eclipse.xtext.xbase.XBinaryOperation | ||
6 | import org.eclipse.xtext.xbase.XExpression | ||
7 | import org.eclipse.xtext.xbase.XFeatureCall | ||
8 | import org.eclipse.xtext.xbase.XMemberFeatureCall | ||
9 | import org.eclipse.xtext.xbase.XNumberLiteral | ||
10 | import org.eclipse.xtext.xbase.XUnaryOperation | ||
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.PrimitiveTypeReference | ||
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference | ||
13 | |||
14 | class PExpressionGenerator { | ||
15 | static val N_Base = "org.eclipse.xtext.xbase.lib." | ||
16 | |||
17 | static val N_PLUS1 = "operator_plus" | ||
18 | static val N_MINUS1 = "operator_minus" | ||
19 | |||
20 | static val N_MINUS2 = "operator_minus" | ||
21 | static val N_PLUS2 = "operator_plus" | ||
22 | static val N_POWER = "operator_power" | ||
23 | static val N_MULTIPLY = "operator_multiply" | ||
24 | static val N_DIVIDE = "operator_divide" | ||
25 | static val N_MODULO = "operator_modulo" | ||
26 | static val N_LESSTHAN = "operator_lessThan" | ||
27 | static val N_LESSEQUALSTHAN = "operator_lessEqualsThan" | ||
28 | static val N_GREATERTHAN = "operator_greaterThan" | ||
29 | static val N_GREATEREQUALTHAN = "operator_greaterEqualsThan" | ||
30 | static val N_EQUALS = "operator_equals" | ||
31 | static val N_NOTEQUALS = "operator_notEquals" | ||
32 | static val N_EQUALS3 = "operator_tripleEquals" | ||
33 | static val N_NOTEQUALS3 = "operator_tripleNotEquals" | ||
34 | |||
35 | protected def isN(String name, String s) { | ||
36 | val res = name.startsWith(N_Base) && name.endsWith(s) | ||
37 | //println('''[«res»] «name» ?= «N_Base»*«s»''') | ||
38 | return res | ||
39 | } | ||
40 | |||
41 | static val N_POWER2 = "java.lang.Math.pow" | ||
42 | |||
43 | def dispatch CharSequence translateExpression(XBinaryOperation e, Map<PVariable,String> valueName, Map<PVariable, PrimitiveTypeReference> variable2Type) { | ||
44 | val left = e.leftOperand.translateExpression(valueName,variable2Type) | ||
45 | val right = e.rightOperand.translateExpression(valueName,variable2Type) | ||
46 | val feature = e.feature.qualifiedName | ||
47 | if(feature.isN(N_MINUS2)) { return '''(«left»-«right»)'''} | ||
48 | else if(feature.isN(N_PLUS2)) { return '''(«left»+«right»)''' } | ||
49 | else if(feature.isN(N_POWER)) { return '''(«left»^«right»)''' } | ||
50 | else if(feature.isN(N_MULTIPLY)) { return '''(«left»*«right»)''' } | ||
51 | else if(feature.isN(N_DIVIDE)) { return '''(«left»/«right»)''' } | ||
52 | else if(feature.isN(N_MODULO)) { return '''(«left»%«right»)''' } | ||
53 | else if(feature.isN(N_LESSTHAN)) { return '''(«left»<«right»)''' } | ||
54 | else if(feature.isN(N_LESSEQUALSTHAN)) { return '''(«left»<=«right»)''' } | ||
55 | else if(feature.isN(N_GREATERTHAN)) { return '''(«left»>«right»)''' } | ||
56 | else if(feature.isN(N_GREATEREQUALTHAN)) { return '''(«left»>=«right»)''' } | ||
57 | else if(feature.isN(N_EQUALS)) { return '''(«left»==«right»)''' } | ||
58 | else if(feature.isN(N_NOTEQUALS)) { return '''(«left»!=«right»)''' } | ||
59 | else if(feature.isN(N_EQUALS3)) { return '''(«left»===«right»)''' } | ||
60 | else if(feature.isN(N_NOTEQUALS3)) { return '''(«left»!==«right»)''' } | ||
61 | else { | ||
62 | println("-> " + e.feature+","+e.class) | ||
63 | println("-> " + e.leftOperand) | ||
64 | println("-> " + e.rightOperand) | ||
65 | println("-> " + e.feature.qualifiedName) | ||
66 | throw new UnsupportedOperationException('''Unsupported binary operator feature: "«e.feature.class.simpleName»" - «e»''') | ||
67 | } | ||
68 | } | ||
69 | |||
70 | def dispatch CharSequence translateExpression(XUnaryOperation e, Map<PVariable,String> valueName, Map<PVariable, PrimitiveTypeReference> variable2Type) { | ||
71 | val operand = e.operand.translateExpression(valueName,variable2Type) | ||
72 | val feature = e.feature.qualifiedName | ||
73 | if(feature.isN(N_MINUS1)) { return '''(-«operand»)'''} | ||
74 | else if(feature.isN(N_PLUS1)) { return '''(+«operand»)'''} | ||
75 | else{ | ||
76 | println("-> " + e.feature+","+e.class) | ||
77 | println("-> " + e.operand) | ||
78 | println("-> " + e.feature.qualifiedName) | ||
79 | throw new UnsupportedOperationException('''Unsupported unary operator feature: "«e.feature.class.simpleName»" - «e»''') | ||
80 | } | ||
81 | } | ||
82 | |||
83 | def dispatch CharSequence translateExpression(XMemberFeatureCall e, Map<PVariable,String> valueName, Map<PVariable, PrimitiveTypeReference> variable2Type) { | ||
84 | val transformedArguments = e.actualArguments.map[translateExpression(valueName,variable2Type)] | ||
85 | val feature = e.feature.qualifiedName | ||
86 | if(feature == N_POWER2) { | ||
87 | return '''Math.pow(«transformedArguments.get(0)»,«transformedArguments.get(1)»)''' | ||
88 | }else { | ||
89 | println(e.feature+","+e.class) | ||
90 | println(e.actualArguments.join(", ")) | ||
91 | println(e.feature.qualifiedName) | ||
92 | throw new UnsupportedOperationException('''Unsupported feature call: "«e.feature.qualifiedName»" - «e»''') | ||
93 | } | ||
94 | } | ||
95 | |||
96 | def dispatch CharSequence translateExpression(XFeatureCall e, Map<PVariable,String> valueName, Map<PVariable, PrimitiveTypeReference> variable2Type) { | ||
97 | val featureName = e.feature.qualifiedName | ||
98 | val type = variable2Type.entrySet.filter[it.key.name===featureName].head.value | ||
99 | val entryWithName = valueName.entrySet.filter[it.key.name == featureName].head | ||
100 | if(entryWithName !== null) { | ||
101 | if(type instanceof RealTypeReference) { | ||
102 | return '''(«entryWithName.value».doubleValue)''' | ||
103 | } else { | ||
104 | return entryWithName.value | ||
105 | } | ||
106 | } else { | ||
107 | throw new IllegalArgumentException('''Feature call reference to unavailable variable "«featureName»"''') | ||
108 | } | ||
109 | } | ||
110 | |||
111 | def dispatch CharSequence translateExpression(XNumberLiteral l, Map<PVariable,String> valueName, Map<PVariable, PrimitiveTypeReference> variable2Type) '''«l.value»''' | ||
112 | |||
113 | def dispatch CharSequence translateExpression(XExpression expression, Map<PVariable,String> valueName, Map<PVariable, PrimitiveTypeReference> variable2Type) { | ||
114 | throw new UnsupportedOperationException('''Unsupported expression in check or eval: «expression.class.name», «expression»"''') | ||
115 | } | ||
116 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternGenerator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternGenerator.xtend index d4c76bb4..edf92343 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternGenerator.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternGenerator.xtend | |||
@@ -1,7 +1,6 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns |
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion | 3 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion |
4 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference | 4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference | 5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference |
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference |
@@ -17,31 +16,55 @@ import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.Transform | |||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | 16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality |
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult | 17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult |
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod | 18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod |
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraints | ||
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
23 | import java.util.Collection | ||
21 | import java.util.HashMap | 24 | import java.util.HashMap |
22 | import java.util.Map | 25 | import java.util.Map |
23 | import org.eclipse.emf.ecore.EAttribute | 26 | import org.eclipse.emf.ecore.EAttribute |
24 | import org.eclipse.emf.ecore.EReference | 27 | import org.eclipse.emf.ecore.EReference |
28 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
25 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | 29 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery |
26 | import org.eclipse.xtend.lib.annotations.Accessors | 30 | import org.eclipse.xtend.lib.annotations.Accessors |
31 | import org.eclipse.xtend.lib.annotations.Data | ||
32 | import org.eclipse.xtend2.lib.StringConcatenationClient | ||
27 | 33 | ||
28 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 34 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
29 | 35 | ||
36 | @Data class PatternGeneratorResult { | ||
37 | CharSequence patternText | ||
38 | HashMap<PConstraint,String> constraint2MustPreconditionName | ||
39 | HashMap<PConstraint,String> constraint2CurrentPreconditionName | ||
40 | } | ||
41 | |||
42 | interface UnitPropagationPatternGenerator { | ||
43 | def Map<Relation, String> getMustPatterns() | ||
44 | |||
45 | def Map<Relation, String> getMustNotPatterns() | ||
46 | |||
47 | def StringConcatenationClient getAdditionalPatterns(PatternGenerator generator, Map<String, PQuery> fqn2PQuery) | ||
48 | } | ||
49 | |||
30 | class PatternGenerator { | 50 | class PatternGenerator { |
31 | @Accessors(PUBLIC_GETTER) val TypeIndexer typeIndexer //= new TypeIndexer(this) | 51 | @Accessors(PUBLIC_GETTER) val TypeIndexer typeIndexer // = new TypeIndexer(this) |
32 | @Accessors(PUBLIC_GETTER) val RelationDeclarationIndexer relationDeclarationIndexer = new RelationDeclarationIndexer(this) | 52 | @Accessors(PUBLIC_GETTER) val RelationDeclarationIndexer relationDeclarationIndexer = new RelationDeclarationIndexer( |
33 | @Accessors(PUBLIC_GETTER) val RelationDefinitionIndexer relationDefinitionIndexer = new RelationDefinitionIndexer(this) | 53 | this) |
54 | @Accessors(PUBLIC_GETTER) val RelationDefinitionIndexer relationDefinitionIndexer = new RelationDefinitionIndexer( | ||
55 | this) | ||
34 | @Accessors(PUBLIC_GETTER) val ContainmentIndexer containmentIndexer = new ContainmentIndexer(this) | 56 | @Accessors(PUBLIC_GETTER) val ContainmentIndexer containmentIndexer = new ContainmentIndexer(this) |
35 | @Accessors(PUBLIC_GETTER) val InvalidIndexer invalidIndexer = new InvalidIndexer(this) | 57 | @Accessors(PUBLIC_GETTER) val InvalidIndexer invalidIndexer = new InvalidIndexer(this) |
36 | @Accessors(PUBLIC_GETTER) val UnfinishedIndexer unfinishedIndexer = new UnfinishedIndexer(this) | 58 | @Accessors(PUBLIC_GETTER) val UnfinishedIndexer unfinishedIndexer |
37 | @Accessors(PUBLIC_GETTER) val TypeRefinementGenerator typeRefinementGenerator //= new RefinementGenerator(this) | 59 | @Accessors(PUBLIC_GETTER) val TypeRefinementGenerator typeRefinementGenerator //= new RefinementGenerator(this) |
38 | @Accessors(PUBLIC_GETTER) val RelationRefinementGenerator relationRefinementGenerator = new RelationRefinementGenerator(this) | 60 | @Accessors(PUBLIC_GETTER) val RelationRefinementGenerator relationRefinementGenerator = new RelationRefinementGenerator(this) |
61 | @Accessors(PUBLIC_GETTER) val UnitPropagationPreconditionGenerator unitPropagationPreconditionGenerator = new UnitPropagationPreconditionGenerator(this) | ||
39 | 62 | ||
40 | public new(TypeInferenceMethod typeInferenceMethod) { | 63 | new(TypeInferenceMethod typeInferenceMethod, ScopePropagatorStrategy scopePropagatorStrategy) { |
41 | if(typeInferenceMethod == TypeInferenceMethod.Generic) { | 64 | if(typeInferenceMethod == TypeInferenceMethod.Generic) { |
42 | this.typeIndexer = new GenericTypeIndexer(this) | 65 | this.typeIndexer = new GenericTypeIndexer(this) |
43 | this.typeRefinementGenerator = new GenericTypeRefinementGenerator(this) | 66 | this.typeRefinementGenerator = new GenericTypeRefinementGenerator(this) |
44 | } else if(typeInferenceMethod == TypeInferenceMethod.PreliminaryAnalysis) { | 67 | } else if (typeInferenceMethod == TypeInferenceMethod.PreliminaryAnalysis) { |
45 | this.typeIndexer = new TypeIndexerWithPreliminaryTypeAnalysis(this) | 68 | this.typeIndexer = new TypeIndexerWithPreliminaryTypeAnalysis(this) |
46 | this.typeRefinementGenerator = new TypeRefinementWithPreliminaryTypeAnalysis(this) | 69 | this.typeRefinementGenerator = new TypeRefinementWithPreliminaryTypeAnalysis(this) |
47 | } else { | 70 | } else { |
@@ -49,113 +72,105 @@ class PatternGenerator { | |||
49 | this.typeRefinementGenerator = null | 72 | this.typeRefinementGenerator = null |
50 | throw new IllegalArgumentException('''Unknown type indexing technique : «typeInferenceMethod.name»''') | 73 | throw new IllegalArgumentException('''Unknown type indexing technique : «typeInferenceMethod.name»''') |
51 | } | 74 | } |
75 | this.unfinishedIndexer = new UnfinishedIndexer(this, scopePropagatorStrategy.requiresUpperBoundIndexing) | ||
52 | } | 76 | } |
53 | 77 | ||
54 | public def requiresTypeAnalysis() { | 78 | def requiresTypeAnalysis() { |
55 | typeIndexer.requiresTypeAnalysis || typeRefinementGenerator.requiresTypeAnalysis | 79 | typeIndexer.requiresTypeAnalysis || typeRefinementGenerator.requiresTypeAnalysis |
56 | } | 80 | } |
57 | 81 | ||
58 | public dispatch def referRelation( | 82 | dispatch def CharSequence referRelation(RelationDeclaration referred, String sourceVariable, String targetVariable, |
59 | RelationDeclaration referred, | 83 | Modality modality, Map<String, PQuery> fqn2PQuery) { |
60 | String sourceVariable, | 84 | return this.relationDeclarationIndexer.referRelation(referred, sourceVariable, targetVariable, modality) |
61 | String targetVariable, | ||
62 | Modality modality, | ||
63 | Map<String,PQuery> fqn2PQuery) | ||
64 | { | ||
65 | return this.relationDeclarationIndexer.referRelation(referred,sourceVariable,targetVariable,modality) | ||
66 | } | 85 | } |
67 | public dispatch def referRelation( | 86 | |
68 | RelationDefinition referred, | 87 | dispatch def CharSequence referRelation(RelationDefinition referred, String sourceVariable, String targetVariable, |
69 | String sourceVariable, | 88 | Modality modality, Map<String, PQuery> fqn2PQuery) { |
70 | String targetVariable, | 89 | val pattern = referred.annotations.filter(TransfomedViatraQuery).head.patternFullyQualifiedName.lookup( |
71 | Modality modality, | 90 | fqn2PQuery) |
72 | Map<String,PQuery> fqn2PQuery) | 91 | return this.relationDefinitionIndexer.referPattern(pattern, #[sourceVariable, targetVariable], modality, true, |
73 | { | 92 | false) |
74 | val pattern = referred.annotations.filter(TransfomedViatraQuery).head.patternFullyQualifiedName.lookup(fqn2PQuery) | ||
75 | return this.relationDefinitionIndexer.referPattern(pattern,#[sourceVariable,targetVariable],modality,true,false) | ||
76 | } | 93 | } |
77 | 94 | ||
78 | def public referRelationByName(EReference reference, | 95 | def referRelationByName(EReference reference, String sourceVariable, String targetVariable, Modality modality) { |
79 | String sourceVariable, | 96 | '''find «modality.name.toLowerCase»InRelation«canonizeName('''«reference.name» reference «reference.EContainingClass.name»''')»(problem,interpretation,«sourceVariable»,«targetVariable»);''' |
80 | String targetVariable, | ||
81 | Modality modality) | ||
82 | { | ||
83 | '''find «modality.name.toLowerCase»InRelation«canonizeName('''«reference.name» reference «reference.EContainingClass.name»''') | ||
84 | »(problem,interpretation,«sourceVariable»,«targetVariable»);''' | ||
85 | } | 97 | } |
86 | 98 | ||
87 | def public CharSequence referAttributeByName(EAttribute attribute, | 99 | def CharSequence referAttributeByName(EAttribute attribute, String sourceVariable, String targetVariable, |
88 | String sourceVariable, | 100 | Modality modality) { |
89 | String targetVariable, | 101 | '''find «modality.name.toLowerCase»InRelation«canonizeName('''«attribute.name» attribute «attribute.EContainingClass.name»''')»(problem,interpretation,«sourceVariable»,«targetVariable»);''' |
90 | Modality modality) | ||
91 | { | ||
92 | '''find «modality.name.toLowerCase»InRelation«canonizeName('''«attribute.name» attribute «attribute.EContainingClass.name»''') | ||
93 | »(problem,interpretation,«sourceVariable»,«targetVariable»);''' | ||
94 | } | 102 | } |
95 | 103 | ||
96 | public def canonizeName(String name) { | 104 | def canonizeName(String name) { |
97 | name.split(' ').join('_') | 105 | name.split(' ').join('_') |
98 | } | 106 | } |
99 | 107 | ||
100 | public def lowerMultiplicities(LogicProblem problem) { | 108 | def wfQueries(LogicProblem problem) { |
101 | problem.assertions.map[annotations].flatten.filter(LowerMultiplicityAssertion).filter[!it.relation.isDerived] | 109 | problem.assertions.map[it.annotations].flatten.filter(TransformedViatraWellformednessConstraint).map[it.query] |
102 | } | ||
103 | public def wfQueries(LogicProblem problem) { | ||
104 | problem.assertions.map[it.annotations] | ||
105 | .flatten | ||
106 | .filter(TransformedViatraWellformednessConstraint) | ||
107 | .map[it.query] | ||
108 | } | 110 | } |
109 | public def getContainments(LogicProblem p) { | 111 | |
112 | def getContainments(LogicProblem p) { | ||
110 | return p.containmentHierarchies.head.containmentRelations | 113 | return p.containmentHierarchies.head.containmentRelations |
111 | } | 114 | } |
112 | public def getInverseRelations(LogicProblem p) { | 115 | |
116 | def getInverseRelations(LogicProblem p) { | ||
113 | val inverseRelations = new HashMap | 117 | val inverseRelations = new HashMap |
114 | p.annotations.filter(InverseRelationAssertion).forEach[ | 118 | p.annotations.filter(InverseRelationAssertion).forEach [ |
115 | inverseRelations.put(it.inverseA,it.inverseB) | 119 | inverseRelations.put(it.inverseA, it.inverseB) |
116 | inverseRelations.put(it.inverseB,it.inverseA) | 120 | inverseRelations.put(it.inverseB, it.inverseA) |
117 | ] | 121 | ] |
118 | return inverseRelations | 122 | return inverseRelations |
119 | } | 123 | } |
120 | public def isRepresentative(Relation relation, Relation inverse) { | 124 | |
121 | if(inverse == null) { | 125 | def isRepresentative(Relation relation, Relation inverse) { |
126 | if (relation === null) { | ||
127 | return false | ||
128 | } else if (inverse === null) { | ||
122 | return true | 129 | return true |
123 | } else { | 130 | } else { |
124 | relation.name.compareTo(inverse.name)<1 | 131 | relation.name.compareTo(inverse.name) < 1 |
125 | } | 132 | } |
126 | } | 133 | } |
127 | 134 | ||
128 | public def isDerived(Relation relation) { | 135 | def isDerived(Relation relation) { |
129 | relation.annotations.exists[it instanceof DefinedByDerivedFeature] | 136 | relation.annotations.exists[it instanceof DefinedByDerivedFeature] |
130 | } | 137 | } |
131 | public def getDerivedDefinition(RelationDeclaration relation) { | 138 | |
139 | def getDerivedDefinition(RelationDeclaration relation) { | ||
132 | relation.annotations.filter(DefinedByDerivedFeature).head.query | 140 | relation.annotations.filter(DefinedByDerivedFeature).head.query |
133 | } | 141 | } |
134 | 142 | ||
135 | private def allTypeReferences(LogicProblem problem) { | 143 | private def allTypeReferences(LogicProblem problem) { |
136 | problem.eAllContents.filter(TypeReference).toIterable | 144 | problem.eAllContents.filter(TypeReference).toIterable |
137 | } | 145 | } |
146 | |||
138 | protected def hasBoolean(LogicProblem problem) { | 147 | protected def hasBoolean(LogicProblem problem) { |
139 | problem.allTypeReferences.exists[it instanceof BoolTypeReference] | 148 | problem.allTypeReferences.exists[it instanceof BoolTypeReference] |
140 | } | 149 | } |
150 | |||
141 | protected def hasInteger(LogicProblem problem) { | 151 | protected def hasInteger(LogicProblem problem) { |
142 | problem.allTypeReferences.exists[it instanceof IntTypeReference] | 152 | problem.allTypeReferences.exists[it instanceof IntTypeReference] |
143 | } | 153 | } |
154 | |||
144 | protected def hasReal(LogicProblem problem) { | 155 | protected def hasReal(LogicProblem problem) { |
145 | problem.allTypeReferences.exists[it instanceof RealTypeReference] | 156 | problem.allTypeReferences.exists[it instanceof RealTypeReference] |
146 | } | 157 | } |
158 | |||
147 | protected def hasString(LogicProblem problem) { | 159 | protected def hasString(LogicProblem problem) { |
148 | problem.allTypeReferences.exists[it instanceof StringTypeReference] | 160 | problem.allTypeReferences.exists[it instanceof StringTypeReference] |
149 | } | 161 | } |
150 | 162 | ||
151 | public def transformBaseProperties( | 163 | def transformBaseProperties( |
152 | LogicProblem problem, | 164 | LogicProblem problem, |
153 | PartialInterpretation emptySolution, | 165 | PartialInterpretation emptySolution, |
154 | Map<String,PQuery> fqn2PQuery, | 166 | Map<String, PQuery> fqn2PQuery, |
155 | TypeAnalysisResult typeAnalysisResult | 167 | TypeAnalysisResult typeAnalysisResult, |
168 | RelationConstraints constraints, | ||
169 | Collection<LinearTypeConstraintHint> hints, | ||
170 | Collection<UnitPropagationPatternGenerator> unitPropagationPatternGenerators | ||
156 | ) { | 171 | ) { |
157 | 172 | val first = | |
158 | return ''' | 173 | ''' |
159 | import epackage "http://www.bme.hu/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage" | 174 | import epackage "http://www.bme.hu/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage" |
160 | import epackage "http://www.bme.hu/mit/inf/dslreasoner/logic/model/problem" | 175 | import epackage "http://www.bme.hu/mit/inf/dslreasoner/logic/model/problem" |
161 | import epackage "http://www.bme.hu/mit/inf/dslreasoner/logic/model/language" | 176 | import epackage "http://www.bme.hu/mit/inf/dslreasoner/logic/model/language" |
@@ -170,6 +185,7 @@ class PatternGenerator { | |||
170 | ///////////////////////// | 185 | ///////////////////////// |
171 | // 0.1 Existence | 186 | // 0.1 Existence |
172 | ///////////////////////// | 187 | ///////////////////////// |
188 | /** [[exist(element)]]=1 */ | ||
173 | private pattern mustExist(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | 189 | private pattern mustExist(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { |
174 | find interpretation(problem,interpretation); | 190 | find interpretation(problem,interpretation); |
175 | LogicProblem.elements(problem,element); | 191 | LogicProblem.elements(problem,element); |
@@ -178,6 +194,7 @@ class PatternGenerator { | |||
178 | PartialInterpretation.newElements(interpretation,element); | 194 | PartialInterpretation.newElements(interpretation,element); |
179 | } | 195 | } |
180 | 196 | ||
197 | /** [[exist(element)]]>=1/2 */ | ||
181 | private pattern mayExist(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | 198 | private pattern mayExist(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { |
182 | find mustExist(problem,interpretation,element); | 199 | find mustExist(problem,interpretation,element); |
183 | } or { | 200 | } or { |
@@ -188,7 +205,7 @@ class PatternGenerator { | |||
188 | 205 | ||
189 | private pattern elementCloseWorld(element:DefinedElement) { | 206 | private pattern elementCloseWorld(element:DefinedElement) { |
190 | PartialInterpretation.openWorldElements(i,element); | 207 | PartialInterpretation.openWorldElements(i,element); |
191 | PartialInterpretation.maxNewElements(i,0); | 208 | PartialInterpretation.maxNewElements(i,0); |
192 | } or { | 209 | } or { |
193 | Scope.targetTypeInterpretation(scope,interpretation); | 210 | Scope.targetTypeInterpretation(scope,interpretation); |
194 | PartialTypeInterpratation.elements(interpretation,element); | 211 | PartialTypeInterpratation.elements(interpretation,element); |
@@ -198,64 +215,115 @@ class PatternGenerator { | |||
198 | //////////////////////// | 215 | //////////////////////// |
199 | // 0.2 Equivalence | 216 | // 0.2 Equivalence |
200 | //////////////////////// | 217 | //////////////////////// |
201 | pattern mayEquivalent(problem:LogicProblem, interpretation:PartialInterpretation, a: DefinedElement, b: DefinedElement) { | 218 | pattern mayEquivalent(problem:LogicProblem, interpretation:PartialInterpretation, a: DefinedElement, b: DefinedElement) |
219 | // For non-primitive type. Boolean types always must equivalent or cannot equivalent | ||
220 | { | ||
202 | find mayExist(problem,interpretation,a); | 221 | find mayExist(problem,interpretation,a); |
203 | find mayExist(problem,interpretation,b); | 222 | find mayExist(problem,interpretation,b); |
204 | a == b; | 223 | a == b; |
224 | ««« } or { | ||
225 | ««« find mayExist(problem,interpretation,a); | ||
226 | ««« find mayExist(problem,interpretation,b); | ||
227 | ««« IntegerElement(a); | ||
228 | ««« IntegerElement(b); | ||
229 | ««« PrimitiveElement.valueSet(a,false); | ||
230 | ««« } or { | ||
231 | ««« find mayExist(problem,interpretation,a); | ||
232 | ««« find mayExist(problem,interpretation,b); | ||
233 | ««« IntegerElement(a); | ||
234 | ««« IntegerElement(b); | ||
235 | ««« PrimitiveElement.valueSet(b,false); | ||
236 | ««« } or { | ||
237 | ««« find mayExist(problem,interpretation,a); | ||
238 | ««« find mayExist(problem,interpretation,b); | ||
239 | ««« RealElement(a); | ||
240 | ««« RealElement(b); | ||
241 | ««« PrimitiveElement.valueSet(a,false); | ||
242 | ««« } or { | ||
243 | ««« find mayExist(problem,interpretation,a); | ||
244 | ««« find mayExist(problem,interpretation,b); | ||
245 | ««« RealElement(a); | ||
246 | ««« RealElement(b); | ||
247 | ««« PrimitiveElement.valueSet(b,false); | ||
248 | ««« } or { | ||
249 | ««« find mayExist(problem,interpretation,a); | ||
250 | ««« find mayExist(problem,interpretation,b); | ||
251 | ««« StringElement(a); | ||
252 | ««« StringElement(b); | ||
253 | ««« PrimitiveElement.valueSet(a,false); | ||
254 | ««« } or { | ||
255 | ««« find mayExist(problem,interpretation,a); | ||
256 | ««« find mayExist(problem,interpretation,b); | ||
257 | ««« StringElement(a); | ||
258 | ««« StringElement(b); | ||
259 | ««« PrimitiveElement.valueSet(b,false); | ||
205 | } | 260 | } |
261 | |||
206 | pattern mustEquivalent(problem:LogicProblem, interpretation:PartialInterpretation, a: DefinedElement, b: DefinedElement) { | 262 | pattern mustEquivalent(problem:LogicProblem, interpretation:PartialInterpretation, a: DefinedElement, b: DefinedElement) { |
263 | // For non-primitive and Boolean primitive type | ||
207 | find mustExist(problem,interpretation,a); | 264 | find mustExist(problem,interpretation,a); |
208 | find mustExist(problem,interpretation,b); | 265 | find mustExist(problem,interpretation,b); |
209 | a == b; | 266 | a == b; |
267 | ««« } or { | ||
268 | ««« find mustExist(problem,interpretation,a); | ||
269 | ««« find mustExist(problem,interpretation,b); | ||
270 | ««« PrimitiveElement.valueSet(a,true); | ||
271 | ««« PrimitiveElement.valueSet(b,true); | ||
272 | ««« IntegerElement.value(a,value); | ||
273 | ««« IntegerElement.value(b,value); | ||
274 | ««« } or { | ||
275 | ««« find mustExist(problem,interpretation,a); | ||
276 | ««« find mustExist(problem,interpretation,b); | ||
277 | ««« PrimitiveElement.valueSet(a,true); | ||
278 | ««« PrimitiveElement.valueSet(b,true); | ||
279 | ««« RealElement.value(a,value); | ||
280 | ««« RealElement.value(b,value); | ||
281 | ««« } or { | ||
282 | ««« find mustExist(problem,interpretation,a); | ||
283 | ««« find mustExist(problem,interpretation,b); | ||
284 | ««« PrimitiveElement.valueSet(a,true); | ||
285 | ««« PrimitiveElement.valueSet(b,true); | ||
286 | ««« StringElement.value(a,value); | ||
287 | ««« StringElement.value(b,value); | ||
210 | } | 288 | } |
211 | 289 | ||
212 | //////////////////////// | ||
213 | // 0.3 Required Patterns by TypeIndexer | ||
214 | //////////////////////// | ||
215 | «typeIndexer.requiredQueries» | ||
216 | |||
217 | ////////// | 290 | ////////// |
218 | // 1. Problem-Specific Base Indexers | 291 | // 1. Problem-Specific Base Indexers |
219 | ////////// | 292 | ////////// |
220 | // 1.1 Type Indexers | 293 | // 1.1 Type Indexers |
221 | ////////// | 294 | ////////// |
222 | // 1.1.1 primitive Type Indexers | 295 | // 1.1.1 Required Patterns by TypeIndexer |
223 | ////////// | 296 | ////////// |
224 | ««« pattern instanceofBoolean(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | 297 | |
225 | ««« find interpretation(problem,interpretation); | 298 | «typeIndexer.requiredQueries» |
226 | ««« PartialInterpretation.booleanelements(interpretation,element); | ||
227 | ««« } | ||
228 | ««« pattern instanceofInteger(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | ||
229 | ««« find interpretation(problem,interpretation); | ||
230 | ««« PartialInterpretation.integerelements(interpretation,element); | ||
231 | ««« } or { | ||
232 | ««« find interpretation(problem,interpretation); | ||
233 | ««« PartialInterpretation.newIntegers(interpetation,element); | ||
234 | ««« } | ||
235 | ««« pattern instanceofReal(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | ||
236 | ««« find interpretation(problem,interpretation); | ||
237 | ««« PartialInterpretation.realelements(interpretation,element); | ||
238 | ««« } or { | ||
239 | ««« find interpretation(problem,interpretation); | ||
240 | ««« PartialInterpretation.newReals(interpetation,element); | ||
241 | ««« } | ||
242 | ««« pattern instanceofString(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | ||
243 | ««« find interpretation(problem,interpretation); | ||
244 | ««« PartialInterpretation.stringelements(interpretation,element); | ||
245 | ««« } or { | ||
246 | ««« find interpretation(problem,interpretation); | ||
247 | ««« PartialInterpretation.newStrings(interpetation,element); | ||
248 | ««« } | ||
249 | 299 | ||
250 | ////////// | 300 | ////////// |
251 | // 1.1.2 domain-specific Type Indexers | 301 | // 1.1.2 primitive Type Indexers |
302 | ////////// | ||
303 | // Currently unused. Refer primitive types as: | ||
304 | // > PrimitiveElement(element) | ||
305 | // specific types are referred as: | ||
306 | // > BooleanElement(variableName) | ||
307 | // > IntegerElement(variableName) | ||
308 | // > RealElement(variableName) | ||
309 | // > StringElement(variableName) | ||
310 | // And their value as | ||
311 | // > BooleanElement.value(variableName,value) | ||
312 | // > IntegerElement.value(variableName,value) | ||
313 | // > RealElement.value(variableName,value) | ||
314 | // > StringElement.value(variableName,value) | ||
315 | // Whether a value is set is defined by: | ||
316 | // > PrimitiveElement.valueSet(variableName,isFilled); | ||
317 | |||
318 | ////////// | ||
319 | // 1.1.3 domain-specific Type Indexers | ||
252 | ////////// | 320 | ////////// |
253 | «typeIndexer.generateInstanceOfQueries(problem,emptySolution,typeAnalysisResult)» | 321 | «typeIndexer.generateInstanceOfQueries(problem,emptySolution,typeAnalysisResult)» |
254 | 322 | ||
255 | ////////// | 323 | ////////// |
256 | // 1.2 Relation Declaration Indexers | 324 | // 1.2 Relation Declaration Indexers |
257 | ////////// | 325 | ////////// |
258 | «relationDeclarationIndexer.generateRelationIndexers(problem,problem.relations.filter(RelationDeclaration),fqn2PQuery)» | 326 | «relationDeclarationIndexer.generateRelationIndexers(problem,problem.relations.filter(RelationDeclaration),unitPropagationPatternGenerators,fqn2PQuery)» |
259 | 327 | ||
260 | ////////// | 328 | ////////// |
261 | // 1.3 Relation Definition Indexers | 329 | // 1.3 Relation Definition Indexers |
@@ -279,7 +347,7 @@ class PatternGenerator { | |||
279 | ////////// | 347 | ////////// |
280 | // 3.1 Unfinishedness Measured by Multiplicity | 348 | // 3.1 Unfinishedness Measured by Multiplicity |
281 | ////////// | 349 | ////////// |
282 | «unfinishedIndexer.generateUnfinishedMultiplicityQueries(problem,fqn2PQuery)» | 350 | «unfinishedIndexer.generateUnfinishedMultiplicityQueries(constraints.multiplicityConstraints,fqn2PQuery)» |
283 | 351 | ||
284 | ////////// | 352 | ////////// |
285 | // 3.2 Unfinishedness Measured by WF Queries | 353 | // 3.2 Unfinishedness Measured by WF Queries |
@@ -301,7 +369,24 @@ class PatternGenerator { | |||
301 | ////////// | 369 | ////////// |
302 | // 4.3 Relation refinement | 370 | // 4.3 Relation refinement |
303 | ////////// | 371 | ////////// |
304 | «relationRefinementGenerator.generateRefineReference(problem)» | 372 | «relationRefinementGenerator.generateRefineReference(problem, unitPropagationPatternGenerators)» |
373 | |||
374 | ////////// | ||
375 | // 5 Hints | ||
376 | ////////// | ||
377 | «FOR hint : hints» | ||
378 | «hint.getAdditionalPatterns(this, fqn2PQuery)» | ||
379 | «ENDFOR» | ||
380 | «FOR generator : unitPropagationPatternGenerators» | ||
381 | «generator.getAdditionalPatterns(this, fqn2PQuery)» | ||
382 | «ENDFOR» | ||
383 | |||
384 | ////////// | ||
385 | // 6 Unit Propagations | ||
386 | ////////// | ||
305 | ''' | 387 | ''' |
388 | val up = unitPropagationPreconditionGenerator.generateUnitPropagationRules(problem,problem.relations.filter(RelationDefinition),fqn2PQuery) | ||
389 | val second = up.definitions | ||
390 | return new PatternGeneratorResult(first+second,up.constraint2MustPreconditionName,up.constraint2CurrentPreconditionName) | ||
306 | } | 391 | } |
307 | } | 392 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternProvider.xtend index 0e13a5e1..2e786286 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternProvider.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternProvider.xtend | |||
@@ -1,97 +1,171 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns |
2 | 2 | ||
3 | import com.google.common.collect.ImmutableSet | ||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | 4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation |
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | 5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | 7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | 8 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem |
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics | 10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics |
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysis | 11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysis |
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult | 12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult |
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod | 13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod |
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraints | ||
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationMultiplicityConstraint | ||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.util.ParseUtil | 18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.util.ParseUtil |
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
13 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace | 20 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace |
21 | import java.util.Collection | ||
22 | import java.util.HashMap | ||
14 | import java.util.Map | 23 | import java.util.Map |
24 | import java.util.Set | ||
15 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | 25 | import org.eclipse.viatra.query.runtime.api.IPatternMatch |
16 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | 26 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification |
17 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | 27 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher |
28 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
18 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | 29 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery |
19 | import org.eclipse.xtend.lib.annotations.Data | 30 | import org.eclipse.xtend.lib.annotations.Data |
20 | 31 | ||
21 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 32 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
22 | import java.util.Collection | ||
23 | import java.util.Set | ||
24 | 33 | ||
25 | @Data class GeneratedPatterns { | 34 | @Data class GeneratedPatterns { |
26 | public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWFQueries | 35 | public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWFQueries |
27 | public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFQueries | 36 | public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFQueries |
28 | public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedMulticiplicityQueries | 37 | public Map<RelationMultiplicityConstraint, UnifinishedMultiplicityQueries> multiplicityConstraintQueries |
29 | public Map<ObjectCreationPrecondition, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineObjectQueries | 38 | public IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hasElementInContainmentQuery |
30 | public Map<? extends Type, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineTypeQueries | 39 | public Map<ObjectCreationPrecondition, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineObjectQueries |
31 | public Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refinerelationQueries | 40 | public Map<? extends Type, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineTypeQueries |
41 | public Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineRelationQueries | ||
42 | public Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> mustRelationPropagationQueries | ||
43 | public Map<PConstraint, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> mustUnitPropagationPreconditionPatterns | ||
44 | public Map<PConstraint, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> currentUnitPropagationPreconditionPatterns | ||
45 | public Map<RelationDefinition, ModalPatternQueries> modalRelationQueries | ||
32 | public Collection<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allQueries | 46 | public Collection<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allQueries |
33 | } | 47 | } |
34 | 48 | ||
49 | @Data | ||
50 | class ModalPatternQueries { | ||
51 | val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> mayQuery | ||
52 | val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> mustQuery | ||
53 | val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> currentQuery | ||
54 | } | ||
55 | |||
56 | @Data | ||
57 | class UnifinishedMultiplicityQueries { | ||
58 | val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> existingMultiplicityQuery | ||
59 | val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> existingInverseMultiplicityQuery | ||
60 | |||
61 | def Set<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> getAllQueries() { | ||
62 | val builder = ImmutableSet.builder | ||
63 | if (existingMultiplicityQuery !== null) { | ||
64 | builder.add(existingMultiplicityQuery) | ||
65 | } | ||
66 | if (existingInverseMultiplicityQuery !== null) { | ||
67 | builder.add(existingInverseMultiplicityQuery) | ||
68 | } | ||
69 | builder.build | ||
70 | } | ||
71 | } | ||
72 | |||
35 | class PatternProvider { | 73 | class PatternProvider { |
36 | |||
37 | val TypeAnalysis typeAnalysis = new TypeAnalysis | 74 | val TypeAnalysis typeAnalysis = new TypeAnalysis |
38 | 75 | ||
39 | public def generateQueries( | 76 | def generateQueries(LogicProblem problem, PartialInterpretation emptySolution, ModelGenerationStatistics statistics, |
40 | LogicProblem problem, | 77 | Set<PQuery> existingQueries, ReasonerWorkspace workspace, TypeInferenceMethod typeInferenceMethod, |
41 | PartialInterpretation emptySolution, | 78 | ScopePropagatorStrategy scopePropagatorStrategy, RelationConstraints relationConstraints, |
42 | ModelGenerationStatistics statistics, | 79 | Collection<LinearTypeConstraintHint> hints, |
43 | Set<PQuery> existingQueries, | 80 | Collection<UnitPropagationPatternGenerator> unitPropagationPatternGenerators, boolean writeToFile) { |
44 | ReasonerWorkspace workspace, | ||
45 | TypeInferenceMethod typeInferenceMethod, | ||
46 | boolean writeToFile) | ||
47 | { | ||
48 | val fqn2Query = existingQueries.toMap[it.fullyQualifiedName] | 81 | val fqn2Query = existingQueries.toMap[it.fullyQualifiedName] |
49 | val PatternGenerator patternGenerator = new PatternGenerator(typeInferenceMethod) | 82 | val PatternGenerator patternGenerator = new PatternGenerator(typeInferenceMethod, scopePropagatorStrategy) |
50 | val typeAnalysisResult = if(patternGenerator.requiresTypeAnalysis) { | 83 | val typeAnalysisResult = if (patternGenerator.requiresTypeAnalysis) { |
51 | val startTime = System.nanoTime | 84 | val startTime = System.nanoTime |
52 | val result = typeAnalysis.performTypeAnalysis(problem,emptySolution) | 85 | val result = typeAnalysis.performTypeAnalysis(problem, emptySolution) |
53 | val typeAnalysisTime = System.nanoTime - startTime | 86 | val typeAnalysisTime = System.nanoTime - startTime |
54 | statistics.PreliminaryTypeAnalisisTime = typeAnalysisTime | 87 | statistics.preliminaryTypeAnalisisTime = typeAnalysisTime |
55 | result | 88 | result |
56 | } else { | 89 | } else { |
57 | null | 90 | null |
58 | } | 91 | } |
59 | val baseIndexerFile = patternGenerator.transformBaseProperties(problem,emptySolution,fqn2Query,typeAnalysisResult) | 92 | val patternGeneratorResult = patternGenerator.transformBaseProperties(problem, emptySolution, fqn2Query, |
60 | if(writeToFile) { | 93 | typeAnalysisResult, relationConstraints, hints, unitPropagationPatternGenerators) |
61 | workspace.writeText('''generated3valued.vql_deactivated''',baseIndexerFile) | 94 | if (writeToFile) { |
95 | workspace.writeText('''generated3valued.vql_deactivated''', patternGeneratorResult.patternText) | ||
62 | } | 96 | } |
63 | val ParseUtil parseUtil = new ParseUtil | 97 | val ParseUtil parseUtil = new ParseUtil |
64 | val generatedQueries = parseUtil.parse(baseIndexerFile) | 98 | val generatedQueries = parseUtil.parse(patternGeneratorResult.patternText) |
65 | val runtimeQueries = calclulateRuntimeQueries(patternGenerator,problem,emptySolution,typeAnalysisResult,generatedQueries); | 99 | val runtimeQueries = calclulateRuntimeQueries(patternGenerator, problem, emptySolution, typeAnalysisResult, |
100 | patternGeneratorResult.constraint2MustPreconditionName, | ||
101 | patternGeneratorResult.constraint2CurrentPreconditionName, relationConstraints, | ||
102 | unitPropagationPatternGenerators, generatedQueries) | ||
66 | return runtimeQueries | 103 | return runtimeQueries |
67 | } | 104 | } |
68 | 105 | ||
69 | private def GeneratedPatterns calclulateRuntimeQueries( | 106 | private def GeneratedPatterns calclulateRuntimeQueries( |
70 | PatternGenerator patternGenerator, | 107 | PatternGenerator patternGenerator, |
71 | LogicProblem problem, | 108 | LogicProblem problem, |
72 | PartialInterpretation emptySolution, | 109 | PartialInterpretation emptySolution, |
73 | TypeAnalysisResult typeAnalysisResult, | 110 | TypeAnalysisResult typeAnalysisResult, |
74 | Map<String, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> queries | 111 | HashMap<PConstraint, String> mustUnitPropagationTrace, |
112 | HashMap<PConstraint, String> currentUnitPropagationTrace, | ||
113 | RelationConstraints relationConstraints, | ||
114 | Collection<UnitPropagationPatternGenerator> unitPropagationPatternGenerators, | ||
115 | Map<String, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> queries | ||
75 | ) { | 116 | ) { |
76 | val Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> | 117 | val Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWFQueries = patternGenerator. |
77 | invalidWFQueries = patternGenerator.invalidIndexer.getInvalidateByWfQueryNames(problem).mapValues[it.lookup(queries)] | 118 | invalidIndexer.getInvalidateByWfQueryNames(problem).mapValues[it.lookup(queries)] |
78 | val Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> | 119 | val Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFQueries = patternGenerator. |
79 | unfinishedWFQueries = patternGenerator.unfinishedIndexer.getUnfinishedWFQueryNames(problem).mapValues[it.lookup(queries)] | 120 | unfinishedIndexer.getUnfinishedWFQueryNames(problem).mapValues[it.lookup(queries)] |
80 | val Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> | 121 | |
81 | unfinishedMultiplicityQueries = patternGenerator.unfinishedIndexer.getUnfinishedMultiplicityQueries(problem).mapValues[it.lookup(queries)] | 122 | val unfinishedMultiplicities = patternGenerator.unfinishedIndexer.getUnfinishedMultiplicityQueries( |
82 | val Map<ObjectCreationPrecondition, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> | 123 | relationConstraints.multiplicityConstraints) |
83 | refineObjectsQueries = patternGenerator.typeRefinementGenerator.getRefineObjectQueryNames(problem,emptySolution,typeAnalysisResult).mapValues[it.lookup(queries)] | 124 | val multiplicityConstraintQueries = unfinishedMultiplicities.mapValues [ |
84 | val Map<? extends Type, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> | 125 | new UnifinishedMultiplicityQueries(existingMultiplicityQueryName?.lookup(queries), |
85 | refineTypeQueries = patternGenerator.typeRefinementGenerator.getRefineTypeQueryNames(problem,emptySolution,typeAnalysisResult).mapValues[it.lookup(queries)] | 126 | existingInverseMultiplicityQueryName?.lookup(queries)) |
86 | val Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> | 127 | ] |
87 | refineRelationQueries = patternGenerator.relationRefinementGenerator.getRefineRelationQueries(problem).mapValues[it.lookup(queries)] | 128 | val hasElementInContainmentQuery = patternGenerator.typeRefinementGenerator.hasElementInContainmentName.lookup( |
129 | queries) | ||
130 | |||
131 | val Map<ObjectCreationPrecondition, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineObjectsQueries = patternGenerator. | ||
132 | typeRefinementGenerator.getRefineObjectQueryNames(problem, emptySolution, typeAnalysisResult).mapValues [ | ||
133 | it.lookup(queries) | ||
134 | ] | ||
135 | val Map<? extends Type, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineTypeQueries = patternGenerator. | ||
136 | typeRefinementGenerator.getRefineTypeQueryNames(problem, emptySolution, typeAnalysisResult).mapValues [ | ||
137 | it.lookup(queries) | ||
138 | ] | ||
139 | val Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineRelationQueries = patternGenerator. | ||
140 | relationRefinementGenerator.getRefineRelationQueries(problem).mapValues[it.lookup(queries)] | ||
141 | val Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> mustRelationPropagationQueries = patternGenerator. | ||
142 | relationRefinementGenerator.getMustPropagationQueries(problem, unitPropagationPatternGenerators).mapValues[it.lookup(queries)] | ||
143 | val Map<PConstraint, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> mustUnitPropagationPreconditionPatterns = mustUnitPropagationTrace. | ||
144 | mapValues[it.lookup(queries)] | ||
145 | val Map<PConstraint, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> currentUnitPropagationPreconditionPatterns = currentUnitPropagationTrace. | ||
146 | mapValues[it.lookup(queries)] | ||
147 | |||
148 | val modalRelationQueries = problem.relations.filter(RelationDefinition).toMap([it], [ relationDefinition | | ||
149 | val indexer = patternGenerator.relationDefinitionIndexer | ||
150 | new ModalPatternQueries( | ||
151 | indexer.relationDefinitionName(relationDefinition, Modality.MAY).lookup(queries), | ||
152 | indexer.relationDefinitionName(relationDefinition, Modality.MUST).lookup(queries), | ||
153 | indexer.relationDefinitionName(relationDefinition, Modality.CURRENT).lookup(queries) | ||
154 | ) | ||
155 | ]) | ||
156 | |||
88 | return new GeneratedPatterns( | 157 | return new GeneratedPatterns( |
89 | invalidWFQueries, | 158 | invalidWFQueries, |
90 | unfinishedWFQueries, | 159 | unfinishedWFQueries, |
91 | unfinishedMultiplicityQueries, | 160 | multiplicityConstraintQueries, |
161 | hasElementInContainmentQuery, | ||
92 | refineObjectsQueries, | 162 | refineObjectsQueries, |
93 | refineTypeQueries, | 163 | refineTypeQueries, |
94 | refineRelationQueries, | 164 | refineRelationQueries, |
165 | mustRelationPropagationQueries, | ||
166 | mustUnitPropagationPreconditionPatterns, | ||
167 | currentUnitPropagationPreconditionPatterns, | ||
168 | modalRelationQueries, | ||
95 | queries.values | 169 | queries.values |
96 | ) | 170 | ) |
97 | } | 171 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDeclarationIndexer.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDeclarationIndexer.xtend index f384cd50..23ba3cad 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDeclarationIndexer.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDeclarationIndexer.xtend | |||
@@ -1,10 +1,13 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns |
2 | 2 | ||
3 | import com.google.common.collect.ImmutableMap | ||
4 | import com.google.common.collect.ImmutableSet | ||
3 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.UpperMultiplicityAssertion | 5 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.UpperMultiplicityAssertion |
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation |
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | 7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | 8 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem |
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | 9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality |
10 | import java.util.Collection | ||
8 | import java.util.HashMap | 11 | import java.util.HashMap |
9 | import java.util.List | 12 | import java.util.List |
10 | import java.util.Map | 13 | import java.util.Map |
@@ -14,41 +17,40 @@ import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | |||
14 | 17 | ||
15 | class RelationDeclarationIndexer { | 18 | class RelationDeclarationIndexer { |
16 | val PatternGenerator base; | 19 | val PatternGenerator base; |
17 | 20 | ||
18 | new(PatternGenerator base) { | 21 | new(PatternGenerator base) { |
19 | this.base = base | 22 | this.base = base |
20 | } | 23 | } |
21 | 24 | ||
22 | public def generateRelationIndexers(LogicProblem problem, Iterable<RelationDeclaration> relations, Map<String,PQuery> fqn2PQuery) { | 25 | def generateRelationIndexers(LogicProblem problem, Iterable<RelationDeclaration> relations, |
26 | Iterable<UnitPropagationPatternGenerator> unitPropagationPatternGenerators, Map<String, PQuery> fqn2PQuery) { | ||
23 | val upperMultiplicities = new HashMap | 27 | val upperMultiplicities = new HashMap |
24 | problem.annotations.filter(UpperMultiplicityAssertion).forEach[ | 28 | problem.annotations.filter(UpperMultiplicityAssertion).forEach [ |
25 | upperMultiplicities.put(it.relation,it.upper) | 29 | upperMultiplicities.put(it.relation, it.upper) |
26 | ] | 30 | ] |
27 | 31 | val mustNotRelations = ImmutableMap.copyOf(unitPropagationPatternGenerators.flatMap[mustNotPatterns.entrySet]. | |
32 | groupBy[key].mapValues[ImmutableSet.copyOf(map[value])]) | ||
33 | |||
28 | return ''' | 34 | return ''' |
29 | «FOR relation : relations» | 35 | «FOR relation : relations» |
30 | «IF base.isDerived(relation)» | 36 | «IF base.isDerived(relation)» |
31 | «generateDerivedMustRelation(problem,relation,base.getDerivedDefinition(relation).patternFullyQualifiedName.lookup(fqn2PQuery))» | 37 | «generateDerivedMustRelation(problem,relation,base.getDerivedDefinition(relation).patternFullyQualifiedName.lookup(fqn2PQuery))» |
32 | «generateDerivedMayRelation(problem,relation,base.getDerivedDefinition(relation).patternFullyQualifiedName.lookup(fqn2PQuery))» | 38 | «generateDerivedMayRelation(problem,relation,base.getDerivedDefinition(relation).patternFullyQualifiedName.lookup(fqn2PQuery))» |
33 | «ELSE» | 39 | «ELSE» |
34 | «generateMustRelation(problem,relation)» | 40 | «generateMustRelation(problem, relation)» |
35 | «generateMayRelation(problem,relation,upperMultiplicities,base.getContainments(problem),base.getInverseRelations(problem),fqn2PQuery)» | 41 | «generateMayRelation(problem, relation, upperMultiplicities, base.getContainments(problem), base.getInverseRelations(problem), mustNotRelations.get(relation) ?: emptySet, fqn2PQuery)» |
36 | «ENDIF» | 42 | «ENDIF» |
37 | «ENDFOR» | 43 | «ENDFOR» |
38 | ''' | 44 | ''' |
39 | } | 45 | } |
40 | 46 | ||
41 | def private patternName(RelationDeclaration r, Modality modality) { | 47 | def private patternName(RelationDeclaration r, Modality modality) { |
42 | '''«modality.name.toLowerCase»InRelation«base.canonizeName(r.name)»''' | 48 | '''«modality.name.toLowerCase»InRelation«base.canonizeName(r.name)»''' |
43 | } | 49 | } |
44 | 50 | ||
45 | public def referRelation( | 51 | def referRelation(RelationDeclaration referred, String sourceVariable, String targetVariable, |
46 | RelationDeclaration referred, | 52 | Modality modality) '''find «referred.patternName(modality)»(problem,interpretation,«sourceVariable»,«targetVariable»);''' |
47 | String sourceVariable, | 53 | |
48 | String targetVariable, | ||
49 | Modality modality) | ||
50 | '''find «referred.patternName(modality)»(problem,interpretation,«sourceVariable»,«targetVariable»);''' | ||
51 | |||
52 | def generateMustRelation(LogicProblem problem, RelationDeclaration relation) ''' | 54 | def generateMustRelation(LogicProblem problem, RelationDeclaration relation) ''' |
53 | /** | 55 | /** |
54 | * Matcher for detecting tuples t where []«relation.name»(source,target) | 56 | * Matcher for detecting tuples t where []«relation.name»(source,target) |
@@ -65,59 +67,64 @@ class RelationDeclarationIndexer { | |||
65 | BinaryElementRelationLink.param2(link,target); | 67 | BinaryElementRelationLink.param2(link,target); |
66 | } | 68 | } |
67 | ''' | 69 | ''' |
70 | |||
68 | def generateMayRelation(LogicProblem problem, RelationDeclaration relation, | 71 | def generateMayRelation(LogicProblem problem, RelationDeclaration relation, |
69 | Map<Relation, Integer> upperMultiplicities, | 72 | Map<Relation, Integer> upperMultiplicities, List<Relation> containments, |
70 | List<Relation> containments, | 73 | HashMap<Relation, Relation> inverseRelations, Collection<String> mustNotRelations, |
71 | HashMap<Relation, Relation> inverseRelations, | 74 | Map<String, PQuery> fqn2PQuery) { |
72 | Map<String,PQuery> fqn2PQuery) | ||
73 | { | ||
74 | return ''' | 75 | return ''' |
75 | /** | 76 | /** |
76 | * Matcher for detecting tuples t where <>«relation.name»(source,target) | 77 | * Matcher for detecting tuples t where <>«relation.name»(source,target) |
77 | */ | 78 | */ |
78 | private pattern «relation.patternName(Modality.MAY)»( | 79 | private pattern «relation.patternName(Modality.MAY)»( |
79 | problem:LogicProblem, interpretation:PartialInterpretation, | 80 | problem:LogicProblem, interpretation:PartialInterpretation, |
80 | source: DefinedElement, target:DefinedElement) | 81 | source: DefinedElement, target:DefinedElement) |
81 | { | 82 | { |
82 | find interpretation(problem,interpretation); | 83 | find interpretation(problem,interpretation); |
83 | // The two endpoint of the link have to exist | 84 | // The two endpoint of the link have to exist |
84 | find mayExist(problem, interpretation, source); | 85 | find mayExist(problem, interpretation, source); |
85 | find mayExist(problem, interpretation, target); | 86 | find mayExist(problem, interpretation, target); |
86 | // Type consistency | 87 | // Type consistency |
87 | «base.typeIndexer.referInstanceOfByReference(relation.parameters.get(0),Modality.MAY,"source")» | 88 | «base.typeIndexer.referInstanceOfByReference(relation.parameters.get(0),Modality.MAY,"source")» |
88 | «base.typeIndexer.referInstanceOfByReference(relation.parameters.get(1),Modality.MAY,"target")» | 89 | «base.typeIndexer.referInstanceOfByReference(relation.parameters.get(1),Modality.MAY,"target")» |
89 | «IF upperMultiplicities.containsKey(relation)» | 90 | «IF upperMultiplicities.containsKey(relation)» |
90 | // There are "numberOfExistingReferences" currently existing instances of the reference from the source, | 91 | // There are "numberOfExistingReferences" currently existing instances of the reference from the source, |
91 | // the upper bound of the multiplicity should be considered. | 92 | // the upper bound of the multiplicity should be considered. |
92 | numberOfExistingReferences == count «referRelation(relation,"source","_",Modality.MUST)» | 93 | numberOfExistingReferences == count «referRelation(relation,"source","_",Modality.MUST)» |
93 | check(numberOfExistingReferences < «upperMultiplicities.get(relation)»); | 94 | numberOfExistingReferences != «upperMultiplicities.get(relation)»; |
94 | «ENDIF» | 95 | «ENDIF» |
95 | «IF inverseRelations.containsKey(relation) && upperMultiplicities.containsKey(inverseRelations.get(relation))» | 96 | «IF inverseRelations.containsKey(relation) && upperMultiplicities.containsKey(inverseRelations.get(relation))» |
96 | // There are "numberOfExistingReferences" currently existing instances of the reference to the target, | 97 | // There are "numberOfExistingReferences" currently existing instances of the reference to the target, |
97 | // the upper bound of the opposite reference multiplicity should be considered. | 98 | // the upper bound of the opposite reference multiplicity should be considered. |
98 | numberOfExistingOppositeReferences == count «base.referRelation(inverseRelations.get(relation),"target","_",Modality.MUST,fqn2PQuery)» | 99 | numberOfExistingOppositeReferences == count «base.referRelation(inverseRelations.get(relation),"target","_",Modality.MUST,fqn2PQuery)» |
99 | check(numberOfExistingOppositeReferences < «upperMultiplicities.get(inverseRelations.get(relation))»); | 100 | numberOfExistingOppositeReferences != «upperMultiplicities.get(inverseRelations.get(relation))»; |
100 | «ENDIF» | 101 | «ENDIF» |
101 | «IF containments.contains(relation)» | 102 | «IF containments.contains(relation)» |
102 | // The reference is containment, then a new reference cannot be create if: | 103 | // The reference is containment, then a new reference cannot be create if: |
103 | // 1. Multiple parents | 104 | // 1. Multiple parents |
104 | neg «base.containmentIndexer.referMustContaint("_","target")» | 105 | neg «base.containmentIndexer.referMustContaint("_","target")» |
105 | // 2. Circle in the containment hierarchy | 106 | // 2. Circle in the containment hierarchy |
106 | neg «base.containmentIndexer.referTransitiveMustContains("target","source")» | 107 | neg «base.containmentIndexer.referTransitiveMustContains("target","source")» |
107 | «ENDIF» | 108 | «ENDIF» |
108 | «IF inverseRelations.containsKey(relation) && containments.contains(inverseRelations.get(relation))» | 109 | «IF inverseRelations.containsKey(relation) && containments.contains(inverseRelations.get(relation))» |
109 | // The eOpposite of the reference is containment, then a referene cannot be created if | 110 | // The eOpposite of the reference is containment, then a referene cannot be created if |
110 | // 1. Multiple parents | 111 | // 1. Multiple parents |
111 | neg «base.containmentIndexer.referMustContaint("source","_")» | 112 | neg «base.containmentIndexer.referMustContaint("source","_")» |
112 | // 2. Circle in the containment hierarchy | 113 | // 2. Circle in the containment hierarchy |
113 | neg «base.containmentIndexer.referTransitiveMustContains("source","target")» | 114 | neg «base.containmentIndexer.referTransitiveMustContains("source","target")» |
114 | «ENDIF» | 115 | «ENDIF» |
115 | } or { | 116 | «IF !mustNotRelations.empty» |
116 | «relation.referRelation("source","target",Modality.MUST)» | 117 | // ![] unit propagation relations |
117 | } | 118 | «FOR mustNotRelation : mustNotRelations» |
118 | ''' | 119 | neg find «mustNotRelation»(problem, interpretation, source, target); |
120 | «ENDFOR» | ||
121 | «ENDIF» | ||
122 | } or { | ||
123 | «relation.referRelation("source","target",Modality.MUST)» | ||
124 | } | ||
125 | ''' | ||
119 | } | 126 | } |
120 | 127 | ||
121 | def generateDerivedMustRelation(LogicProblem problem, RelationDeclaration relation, PQuery definition) ''' | 128 | def generateDerivedMustRelation(LogicProblem problem, RelationDeclaration relation, PQuery definition) ''' |
122 | /** | 129 | /** |
123 | * Matcher for detecting tuples t where []«relation.name»(source,target) | 130 | * Matcher for detecting tuples t where []«relation.name»(source,target) |
@@ -129,6 +136,7 @@ class RelationDeclarationIndexer { | |||
129 | «base.relationDefinitionIndexer.referPattern(definition,#["source","target"],Modality::MUST,true,false)» | 136 | «base.relationDefinitionIndexer.referPattern(definition,#["source","target"],Modality::MUST,true,false)» |
130 | } | 137 | } |
131 | ''' | 138 | ''' |
139 | |||
132 | def generateDerivedMayRelation(LogicProblem problem, RelationDeclaration relation, PQuery definition) ''' | 140 | def generateDerivedMayRelation(LogicProblem problem, RelationDeclaration relation, PQuery definition) ''' |
133 | /** | 141 | /** |
134 | * Matcher for detecting tuples t where []«relation.name»(source,target) | 142 | * Matcher for detecting tuples t where []«relation.name»(source,target) |
@@ -140,4 +148,4 @@ class RelationDeclarationIndexer { | |||
140 | «base.relationDefinitionIndexer.referPattern(definition,#["source","target"],Modality::MAY,true,false)» | 148 | «base.relationDefinitionIndexer.referPattern(definition,#["source","target"],Modality::MAY,true,false)» |
141 | } | 149 | } |
142 | ''' | 150 | ''' |
143 | } \ No newline at end of file | 151 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDefinitionIndexer.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDefinitionIndexer.xtend index 9723373f..338a9af2 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDefinitionIndexer.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDefinitionIndexer.xtend | |||
@@ -5,38 +5,27 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | |||
5 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery | 5 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery |
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | 6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality |
7 | import java.util.Map | 7 | import java.util.Map |
8 | import org.eclipse.emf.ecore.EAttribute | ||
9 | import org.eclipse.emf.ecore.EEnumLiteral | ||
10 | import org.eclipse.emf.ecore.EReference | ||
11 | import org.eclipse.viatra.query.runtime.emf.types.EClassTransitiveInstancesKey | ||
12 | import org.eclipse.viatra.query.runtime.emf.types.EDataTypeInSlotsKey | ||
13 | import org.eclipse.viatra.query.runtime.emf.types.EStructuralFeatureInstancesKey | ||
14 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
15 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable | 8 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable |
16 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality | ||
17 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter | ||
18 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality | ||
19 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall | ||
20 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure | 9 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure |
21 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.ConstantValue | 10 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction |
22 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall | ||
23 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint | ||
24 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | 11 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery |
25 | 12 | ||
26 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 13 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
27 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint | ||
28 | 14 | ||
29 | class RelationDefinitionIndexer { | 15 | class RelationDefinitionIndexer { |
30 | val PatternGenerator base; | 16 | public val PatternGenerator base; |
17 | val PConstraintTransformer constraintTransformer; | ||
31 | 18 | ||
32 | new(PatternGenerator base) { | 19 | new(PatternGenerator base) { |
33 | this.base = base | 20 | this.base = base |
21 | this.constraintTransformer = new PConstraintTransformer(this); | ||
34 | } | 22 | } |
35 | 23 | ||
36 | public def generateRelationDefinitions( | 24 | def generateRelationDefinitions( |
37 | LogicProblem problem, | 25 | LogicProblem problem, |
38 | Iterable<RelationDefinition> relations, | 26 | Iterable<RelationDefinition> relations, |
39 | Map<String,PQuery> fqn2PQuery) { | 27 | Map<String,PQuery> fqn2PQuery) |
28 | { | ||
40 | val relation2PQuery = relations.toInvertedMap[ | 29 | val relation2PQuery = relations.toInvertedMap[ |
41 | annotations.filter(TransfomedViatraQuery).head.patternFullyQualifiedName.lookup(fqn2PQuery) | 30 | annotations.filter(TransfomedViatraQuery).head.patternFullyQualifiedName.lookup(fqn2PQuery) |
42 | ] | 31 | ] |
@@ -71,23 +60,24 @@ class RelationDefinitionIndexer { | |||
71 | ] | 60 | ] |
72 | } | 61 | } |
73 | 62 | ||
74 | private def relationDefinitionName(RelationDefinition relation, Modality modality) | 63 | def String relationDefinitionName(RelationDefinition relation, Modality modality) |
75 | '''«modality.name.toLowerCase»InRelation_«base.canonizeName(relation.name)»''' | 64 | '''«modality.name.toLowerCase»InRelation_«base.canonizeName(relation.name)»''' |
76 | 65 | ||
77 | private def canonizeName(PVariable v) { | 66 | def canonizeName(PVariable v) { |
78 | return '''«IF v.referringConstraints.size == 1»_«ENDIF»var_«v.name.replaceAll("\\W","")»''' | 67 | return '''«IF v.referringConstraints.size == 1»_«ENDIF»var_«v.name.replaceAll("\\W","")»''' |
79 | } | 68 | } |
80 | 69 | ||
81 | private def transformPattern(RelationDefinition relation, PQuery p, Modality modality) { | 70 | private def transformPattern(RelationDefinition relation, PQuery p, Modality modality) { |
82 | try { | 71 | try { |
72 | val bodies = (relation.annotations.filter(TransfomedViatraQuery).head.optimizedDisjunction as PDisjunction).bodies | ||
83 | return ''' | 73 | return ''' |
84 | private pattern «relationDefinitionName(relation,modality)»( | 74 | private pattern «relationDefinitionName(relation,modality)»( |
85 | problem:LogicProblem, interpretation:PartialInterpretation, | 75 | problem:LogicProblem, interpretation:PartialInterpretation, |
86 | «FOR param : p.parameters SEPARATOR ', '»var_«param.name»«ENDFOR») | 76 | «FOR param : p.parameters SEPARATOR ', '»var_«param.name»«ENDFOR») |
87 | «FOR body : p.disjunctBodies.bodies SEPARATOR "or"»{ | 77 | «FOR body : bodies SEPARATOR "or"»{ |
88 | find interpretation(problem,interpretation); | 78 | find interpretation(problem,interpretation); |
89 | «FOR constraint : body.constraints» | 79 | «FOR constraint : body.constraints» |
90 | «constraint.transformConstraint(modality)» | 80 | «this.constraintTransformer.transformConstraint(constraint,modality,relation.annotations.filter(TransfomedViatraQuery).head.variableTrace)» |
91 | «ENDFOR» | 81 | «ENDFOR» |
92 | }«ENDFOR» | 82 | }«ENDFOR» |
93 | ''' | 83 | ''' |
@@ -104,158 +94,12 @@ class RelationDefinitionIndexer { | |||
104 | ''' | 94 | ''' |
105 | } | 95 | } |
106 | 96 | ||
107 | private def toMustMay(Modality modality) { | 97 | def toMustMay(Modality modality) { |
108 | if(modality == Modality::MAY) return Modality::MAY | 98 | if(modality == Modality::MAY) return Modality::MAY |
109 | else return Modality::MUST | 99 | else return Modality::MUST |
110 | } | 100 | } |
111 | 101 | ||
112 | def public referPattern(PQuery p, String[] variables, Modality modality, boolean positive, boolean transitive) ''' | 102 | def referPattern(PQuery p, String[] variables, Modality modality, boolean positive, boolean transitive) ''' |
113 | «IF !positive»neg «ENDIF»find «IF transitive»twoParam_«ENDIF»«modality.name.toLowerCase»InRelation_pattern_«p.fullyQualifiedName.replace('.','_')»«IF transitive»+«ENDIF»(«IF !transitive»problem,interpretation,«ENDIF»«variables.join(',')»); | 103 | «IF !positive»neg «ENDIF»find «IF transitive»twoParam_«ENDIF»«modality.name.toLowerCase»InRelation_pattern_«p.fullyQualifiedName.replace('.','_')»«IF transitive»+«ENDIF»(«IF !transitive»problem,interpretation,«ENDIF»«variables.join(',')»); |
114 | ''' | 104 | ''' |
115 | |||
116 | private dispatch def transformConstraint(TypeConstraint constraint, Modality modality) { | ||
117 | val touple = constraint.variablesTuple | ||
118 | if(touple.size == 1) { | ||
119 | val inputKey = constraint.equivalentJudgement.inputKey | ||
120 | if(inputKey instanceof EClassTransitiveInstancesKey) { | ||
121 | return base.typeIndexer.referInstanceOf(inputKey.emfKey,modality.toMustMay, | ||
122 | constraint.getVariableInTuple(0).canonizeName) | ||
123 | } else if(inputKey instanceof EDataTypeInSlotsKey){ | ||
124 | return '''// type constraint is enforced by construction''' | ||
125 | } | ||
126 | |||
127 | } else if(touple.size == 2){ | ||
128 | val key = (constraint.equivalentJudgement.inputKey as EStructuralFeatureInstancesKey).emfKey | ||
129 | if(key instanceof EReference) { | ||
130 | return base.referRelationByName( | ||
131 | key, | ||
132 | constraint.getVariableInTuple(0).canonizeName, | ||
133 | constraint.getVariableInTuple(1).canonizeName, | ||
134 | modality.toMustMay) | ||
135 | } else if (key instanceof EAttribute) { | ||
136 | return base.referAttributeByName(key, | ||
137 | constraint.getVariableInTuple(0).canonizeName, | ||
138 | constraint.getVariableInTuple(1).canonizeName, | ||
139 | modality.toMustMay) | ||
140 | } else throw new UnsupportedOperationException('''unknown key: «key.class»''') | ||
141 | } else { | ||
142 | throw new UnsupportedOperationException('''Unsupported touple size: «touple.size»''') | ||
143 | } | ||
144 | } | ||
145 | private dispatch def transformConstraint(TypeFilterConstraint constraint, Modality modality) { | ||
146 | val touple = constraint.variablesTuple | ||
147 | if(touple.size == 1) { | ||
148 | val inputKey = constraint.equivalentJudgement.inputKey | ||
149 | if(inputKey instanceof EClassTransitiveInstancesKey) { | ||
150 | return base.typeIndexer.referInstanceOf(inputKey.emfKey,modality.toMustMay, | ||
151 | (constraint.getVariablesTuple.get(0) as PVariable).canonizeName) | ||
152 | } else if(inputKey instanceof EDataTypeInSlotsKey){ | ||
153 | return '''// type constraint is enforced by construction''' | ||
154 | } | ||
155 | |||
156 | } else if(touple.size == 2){ | ||
157 | val key = (constraint.equivalentJudgement.inputKey as EStructuralFeatureInstancesKey).emfKey | ||
158 | if(key instanceof EReference) { | ||
159 | return base.referRelationByName( | ||
160 | key, | ||
161 | (constraint.getVariablesTuple.get(0) as PVariable).canonizeName, | ||
162 | (constraint.getVariablesTuple.get(1) as PVariable).canonizeName, | ||
163 | modality.toMustMay) | ||
164 | } else if (key instanceof EAttribute) { | ||
165 | return base.referAttributeByName(key, | ||
166 | (constraint.getVariablesTuple.get(0) as PVariable).canonizeName, | ||
167 | (constraint.getVariablesTuple.get(1) as PVariable).canonizeName, | ||
168 | modality.toMustMay) | ||
169 | } else throw new UnsupportedOperationException('''unknown key: «key.class»''') | ||
170 | } else { | ||
171 | throw new UnsupportedOperationException('''Unsupported touple size: «touple.size»''') | ||
172 | } | ||
173 | } | ||
174 | |||
175 | private dispatch def transformConstraint(Equality equality, Modality modality) { | ||
176 | val a = equality.who | ||
177 | val b = equality.withWhom | ||
178 | transformEquality(modality.toMustMay, a, b) | ||
179 | } | ||
180 | |||
181 | private def CharSequence transformEquality(Modality modality, PVariable a, PVariable b) { | ||
182 | if(modality.isMustOrCurrent) '''find mustEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
183 | else '''find mayEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
184 | } | ||
185 | |||
186 | private dispatch def transformConstraint(Inequality inequality, Modality modality) { | ||
187 | val a = inequality.who | ||
188 | val b = inequality.withWhom | ||
189 | if(modality.isCurrent) { | ||
190 | return '''neg find mustEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
191 | } else if(modality.isMust) { | ||
192 | return '''neg find mayEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
193 | } else { // modality.isMay | ||
194 | return '''neg find mustEquivalent(problem, interpretation, «a.canonizeName», «b.canonizeName»);''' | ||
195 | } | ||
196 | } | ||
197 | |||
198 | private dispatch def transformConstraint(NegativePatternCall pcall, Modality modality) { | ||
199 | val params = (0..<pcall.actualParametersTuple.size).map[index | | ||
200 | val variable = pcall.actualParametersTuple.get(index) as PVariable | ||
201 | return variable.canonizeName | ||
202 | ] | ||
203 | return referPattern(pcall.referredQuery,params,modality.dual,false,false) | ||
204 | } | ||
205 | |||
206 | private dispatch def transformConstraint(PositivePatternCall pcall, Modality modality) { | ||
207 | val params = (0..<pcall.variablesTuple.size).map[index | | ||
208 | val variable = pcall.variablesTuple.get(index) as PVariable | ||
209 | return variable.canonizeName | ||
210 | ] | ||
211 | return referPattern(pcall.referredQuery,params,modality,true,false) | ||
212 | } | ||
213 | private dispatch def transformConstraint(BinaryTransitiveClosure pcall, Modality modality) { | ||
214 | val params = (0..1).map[index | | ||
215 | val variable = pcall.getVariableInTuple(index) as PVariable | ||
216 | return variable.canonizeName | ||
217 | ] | ||
218 | return referPattern(pcall.referredQuery,params,modality,true,true) | ||
219 | } | ||
220 | private dispatch def transformConstraint(ExportedParameter e, Modality modality) { | ||
221 | return '''// «e.parameterName» is exported''' | ||
222 | } | ||
223 | private dispatch def transformConstraint(ConstantValue c, Modality modality) { | ||
224 | val target = c.supplierKey | ||
225 | |||
226 | var String targetString; | ||
227 | var String additionalDefinition; | ||
228 | if(target instanceof EEnumLiteral) { | ||
229 | targetString = '''const_«target.name»_«target.EEnum.name»''' | ||
230 | additionalDefinition = '''DefinedElement.name(«targetString»,"«target.name» «target.EEnum.name»"); //LogicProblem.elements(problem,«targetString»);''' | ||
231 | } else if(target instanceof Integer) { | ||
232 | targetString = '''const_«target»_Integer''' | ||
233 | additionalDefinition = '''IntegerElement.value(«targetString»,«target»);''' | ||
234 | } else if(target instanceof Boolean) { | ||
235 | targetString = '''const_«target»_Boolean''' | ||
236 | additionalDefinition = '''BooleanElement.value(«targetString»,«target»);''' | ||
237 | } else if(target instanceof String) { | ||
238 | targetString = '''const_«target»_String''' | ||
239 | additionalDefinition = '''StringElement.value(«targetString»,"«target»");''' | ||
240 | } else if(target instanceof Double) { | ||
241 | targetString = '''const_«target»_Number''' | ||
242 | additionalDefinition = '''RealElement.value(«targetString»,"«target»");''' | ||
243 | } else if(target instanceof Float) { | ||
244 | targetString = '''const_«target»_Number''' | ||
245 | additionalDefinition = '''RealElement.value(«targetString»,"«target»");''' | ||
246 | } else { | ||
247 | throw new UnsupportedOperationException('''Unknown constant type: «target.class»''') | ||
248 | } | ||
249 | |||
250 | val source = c.variablesTuple | ||
251 | var String sourceName | ||
252 | if(source.size == 1) | ||
253 | sourceName = (source.get(0) as PVariable).canonizeName | ||
254 | else throw new UnsupportedOperationException("unknown source") | ||
255 | return '''«sourceName» == «targetString»;«additionalDefinition»'''; | ||
256 | } | ||
257 | |||
258 | private dispatch def transformConstraint(PConstraint c, Modality modality) { | ||
259 | throw new UnsupportedOperationException('''Unknown constraint type: "«c.class.name»"!''') | ||
260 | } | ||
261 | } \ No newline at end of file | 105 | } \ No newline at end of file |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationRefinementGenerator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationRefinementGenerator.xtend index f9e9baea..6f5f2402 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationRefinementGenerator.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationRefinementGenerator.xtend | |||
@@ -1,85 +1,93 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns |
2 | 2 | ||
3 | import com.google.common.collect.ImmutableList | ||
4 | import com.google.common.collect.ImmutableMap | ||
5 | import com.google.common.collect.ImmutableSet | ||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation |
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | 7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration |
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | 8 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem |
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | 9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality |
10 | import java.util.Collection | ||
7 | import java.util.LinkedList | 11 | import java.util.LinkedList |
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | 12 | import java.util.Map |
13 | import java.util.Set | ||
14 | import org.eclipse.xtend2.lib.StringConcatenationClient | ||
9 | 15 | ||
10 | class RelationRefinementGenerator { | 16 | class RelationRefinementGenerator { |
11 | PatternGenerator base; | 17 | PatternGenerator base; |
12 | public new(PatternGenerator base) { | 18 | |
19 | new(PatternGenerator base) { | ||
13 | this.base = base | 20 | this.base = base |
14 | } | 21 | } |
15 | 22 | ||
16 | def CharSequence generateRefineReference(LogicProblem p) { | 23 | def CharSequence generateRefineReference(LogicProblem p, |
17 | return ''' | 24 | Collection<UnitPropagationPatternGenerator> unitPropagationPatternGenerators) { |
18 | «FOR relationRefinement: this.getRelationRefinements(p)» | 25 | val mustRelations = getMustRelations(unitPropagationPatternGenerators) |
19 | pattern «relationRefinementQueryName(relationRefinement.key,relationRefinement.value)»( | 26 | |
20 | problem:LogicProblem, interpretation:PartialInterpretation, | 27 | ''' |
21 | relationIterpretation:PartialRelationInterpretation«IF relationRefinement.value != null», oppositeInterpretation:PartialRelationInterpretation«ENDIF», | 28 | «FOR relationRefinement : this.getRelationRefinements(p)» |
22 | from: DefinedElement, to: DefinedElement) | 29 | pattern «relationRefinementQueryName(relationRefinement.key,relationRefinement.value)»( |
23 | { | 30 | problem:LogicProblem, interpretation:PartialInterpretation, |
24 | find interpretation(problem,interpretation); | 31 | relationIterpretation:PartialRelationInterpretation«IF relationRefinement.value !== null», oppositeInterpretation:PartialRelationInterpretation«ENDIF», |
25 | PartialInterpretation.partialrelationinterpretation(interpretation,relationIterpretation); | 32 | from: DefinedElement, to: DefinedElement) |
26 | PartialRelationInterpretation.interpretationOf.name(relationIterpretation,"«relationRefinement.key.name»"); | 33 | { |
27 | «IF relationRefinement.value != null» | 34 | find interpretation(problem,interpretation); |
28 | PartialInterpretation.partialrelationinterpretation(interpretation,oppositeInterpretation); | 35 | PartialInterpretation.partialrelationinterpretation(interpretation,relationIterpretation); |
29 | PartialRelationInterpretation.interpretationOf.name(oppositeInterpretation,"«relationRefinement.value.name»"); | 36 | PartialRelationInterpretation.interpretationOf.name(relationIterpretation,"«relationRefinement.key.name»"); |
30 | «ENDIF» | 37 | «IF relationRefinement.value !== null» |
31 | find mustExist(problem, interpretation, from); | 38 | PartialInterpretation.partialrelationinterpretation(interpretation,oppositeInterpretation); |
32 | find mustExist(problem, interpretation, to); | 39 | PartialRelationInterpretation.interpretationOf.name(oppositeInterpretation,"«relationRefinement.value.name»"); |
33 | «base.typeIndexer.referInstanceOfByReference(relationRefinement.key.parameters.get(0), Modality::MUST,"from")» | 40 | «ENDIF» |
34 | «base.typeIndexer.referInstanceOfByReference(relationRefinement.key.parameters.get(1), Modality::MUST,"to")» | 41 | find mustExist(problem, interpretation, from); |
35 | «base.relationDeclarationIndexer.referRelation(relationRefinement.key,"from","to",Modality.MAY)» | 42 | find mustExist(problem, interpretation, to); |
36 | neg «base.relationDeclarationIndexer.referRelation(relationRefinement.key,"from","to",Modality.MUST)» | 43 | «base.typeIndexer.referInstanceOfByReference(relationRefinement.key.parameters.get(0), Modality::MUST,"from")» |
37 | } | 44 | «base.typeIndexer.referInstanceOfByReference(relationRefinement.key.parameters.get(1), Modality::MUST,"to")» |
38 | «ENDFOR» | 45 | «base.relationDeclarationIndexer.referRelation(relationRefinement.key,"from","to",Modality.MAY)» |
46 | neg «base.relationDeclarationIndexer.referRelation(relationRefinement.key,"from","to",Modality.MUST)» | ||
47 | } | ||
48 | |||
49 | «IF isMustPropagationQueryNeeded(relationRefinement.key, relationRefinement.value, mustRelations)» | ||
50 | pattern «mustPropagationQueryName(relationRefinement.key)»( | ||
51 | problem:LogicProblem, interpretation:PartialInterpretation, | ||
52 | relationIterpretation:PartialRelationInterpretation«IF relationRefinement.value !== null», oppositeInterpretation:PartialRelationInterpretation«ENDIF», | ||
53 | from: DefinedElement, to: DefinedElement) | ||
54 | «FOR body : getMustPropagationBodies(relationRefinement.key, relationRefinement.value, mustRelations) SEPARATOR " or "» | ||
55 | { | ||
56 | «referRefinementQuery(relationRefinement.key, relationRefinement.value, "relationIterpretation", "oppositeInterpretation", "from", "to")» | ||
57 | «body» | ||
58 | } | ||
59 | «ENDFOR» | ||
60 | «ENDIF» | ||
61 | «ENDFOR» | ||
39 | ''' | 62 | ''' |
40 | } | 63 | } |
41 | 64 | ||
42 | def String relationRefinementQueryName(RelationDeclaration relation, Relation inverseRelation) { | 65 | def String relationRefinementQueryName(RelationDeclaration relation, Relation inverseRelation) { |
43 | '''«IF inverseRelation != null | 66 | '''«IF inverseRelation !== null»refineRelation_«base.canonizeName(relation.name)»_and_«base.canonizeName(inverseRelation.name)»«ELSE»refineRelation_«base.canonizeName(relation.name)»«ENDIF»''' |
44 | »refineRelation_«base.canonizeName(relation.name)»_and_«base.canonizeName(inverseRelation.name)»« | ||
45 | ELSE | ||
46 | »refineRelation_«base.canonizeName(relation.name)»«ENDIF»''' | ||
47 | } | 67 | } |
48 | 68 | ||
69 | def String mustPropagationQueryName(RelationDeclaration relation) { | ||
70 | '''mustPropagation_«base.canonizeName(relation.name)»''' | ||
71 | } | ||
72 | |||
49 | def referRefinementQuery(RelationDeclaration relation, Relation inverseRelation, String relInterpretationName, | 73 | def referRefinementQuery(RelationDeclaration relation, Relation inverseRelation, String relInterpretationName, |
50 | String inverseInterpretationName, String sourceName, String targetName) | 74 | String inverseInterpretationName, String sourceName, |
51 | '''find «this.relationRefinementQueryName(relation,inverseRelation)»(problem, interpretation, «relInterpretationName», «IF inverseRelation != null»inverseInterpretationName, «ENDIF»«sourceName», «targetName»);''' | 75 | String targetName) '''find «this.relationRefinementQueryName(relation,inverseRelation)»(problem, interpretation, «relInterpretationName», «IF inverseRelation !== null»«inverseInterpretationName», «ENDIF»«sourceName», «targetName»);''' |
52 | 76 | ||
53 | def getRefineRelationQueries(LogicProblem p) { | 77 | def getRefineRelationQueries(LogicProblem p) { |
54 | // val containmentRelations = p.containmentHierarchies.map[containmentRelations].flatten.toSet | 78 | getRelationRefinements(p).toInvertedMap[relationRefinementQueryName(it.key, it.value)] |
55 | // p.relations.filter(RelationDeclaration).filter[!containmentRelations.contains(it)].toInvertedMap['''refineRelation_«base.canonizeName(it.name)»'''] | ||
56 | /* | ||
57 | val res = new LinkedHashMap | ||
58 | for(relation: getRelationRefinements(p)) { | ||
59 | if(inverseRelations.containsKey(relation)) { | ||
60 | val name = '''refineRelation_«base.canonizeName(relation.name)»_and_«base.canonizeName(inverseRelations.get(relation).name)»''' | ||
61 | res.put(relation -> inverseRelations.get(relation),name) | ||
62 | } else { | ||
63 | val name = '''refineRelation_«base.canonizeName(relation.name)»''' | ||
64 | res.put(relation -> null,name) | ||
65 | } | ||
66 | } | ||
67 | return res*/ | ||
68 | |||
69 | getRelationRefinements(p).toInvertedMap[relationRefinementQueryName(it.key,it.value)] | ||
70 | } | 79 | } |
71 | |||
72 | 80 | ||
73 | def getRelationRefinements(LogicProblem p) { | 81 | def getRelationRefinements(LogicProblem p) { |
74 | val inverses = base.getInverseRelations(p) | 82 | val inverses = base.getInverseRelations(p) |
75 | val containments = base.getContainments(p) | 83 | val containments = base.getContainments(p) |
76 | val list = new LinkedList | 84 | val list = new LinkedList |
77 | for(relation : p.relations.filter(RelationDeclaration)) { | 85 | for (relation : p.relations.filter(RelationDeclaration)) { |
78 | if(!containments.contains(relation)) { | 86 | if (!containments.contains(relation)) { |
79 | if(inverses.containsKey(relation)) { | 87 | if (inverses.containsKey(relation)) { |
80 | val inverse = inverses.get(relation) | 88 | val inverse = inverses.get(relation) |
81 | if(!containments.contains(inverse)) { | 89 | if (!containments.contains(inverse)) { |
82 | if(base.isRepresentative(relation,inverse)) { | 90 | if (base.isRepresentative(relation, inverse)) { |
83 | list += (relation -> inverse) | 91 | list += (relation -> inverse) |
84 | } | 92 | } |
85 | } | 93 | } |
@@ -90,4 +98,54 @@ class RelationRefinementGenerator { | |||
90 | } | 98 | } |
91 | return list | 99 | return list |
92 | } | 100 | } |
93 | } \ No newline at end of file | 101 | |
102 | def getMustPropagationQueries(LogicProblem p, | ||
103 | Collection<UnitPropagationPatternGenerator> unitPropagationPatternGenerators) { | ||
104 | val refinements = getRelationRefinements(p) | ||
105 | val mustRelations = getMustRelations(unitPropagationPatternGenerators) | ||
106 | refinements.filter[isMustPropagationQueryNeeded(key, value, mustRelations)].toInvertedMap [ | ||
107 | mustPropagationQueryName(key) | ||
108 | ] | ||
109 | } | ||
110 | |||
111 | private def getMustRelations(Collection<UnitPropagationPatternGenerator> unitPropagationPatternGenerators) { | ||
112 | ImmutableMap.copyOf(unitPropagationPatternGenerators.flatMap[mustPatterns.entrySet].groupBy[key].mapValues [ | ||
113 | ImmutableSet.copyOf(map[value]) | ||
114 | ]) | ||
115 | } | ||
116 | |||
117 | private def isMustPropagationQueryNeeded(Relation relation, Relation inverseRelation, | ||
118 | Map<Relation, ? extends Set<String>> mustRelations) { | ||
119 | val mustSet = mustRelations.get(relation) | ||
120 | if (mustSet !== null && !mustSet.empty) { | ||
121 | return true | ||
122 | } | ||
123 | if (inverseRelation !== null) { | ||
124 | val inverseMustSet = mustRelations.get(inverseRelation) | ||
125 | if (inverseMustSet !== null && !inverseMustSet.empty) { | ||
126 | return true | ||
127 | } | ||
128 | } | ||
129 | false | ||
130 | } | ||
131 | |||
132 | private def getMustPropagationBodies(Relation relation, Relation inverseRelation, | ||
133 | Map<Relation, ? extends Set<String>> mustRelations) { | ||
134 | val builder = ImmutableList.<StringConcatenationClient>builder() | ||
135 | val mustSet = mustRelations.get(relation) | ||
136 | if (mustSet !== null) { | ||
137 | for (refinementQuery : mustSet) { | ||
138 | builder.add('''find «refinementQuery»(problem, interpretation, from, to);''') | ||
139 | } | ||
140 | } | ||
141 | if (inverseRelation !== null && inverseRelation != relation) { | ||
142 | val inverseMustSet = mustRelations.get(inverseRelation) | ||
143 | if (inverseMustSet !== null) { | ||
144 | for (refinementQuery : inverseMustSet) { | ||
145 | builder.add('''find «refinementQuery»(problem, interpretation, to, from);''') | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | builder.build | ||
150 | } | ||
151 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexer.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexer.xtend index d1d57189..e4e2aa30 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexer.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexer.xtend | |||
@@ -1,52 +1,126 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns |
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
5 | import org.eclipse.emf.ecore.EClass | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult | ||
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | ||
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference | 3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference |
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | ||
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference | 5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference |
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference |
13 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference | 7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference |
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | ||
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
14 | import java.math.BigDecimal | 13 | import java.math.BigDecimal |
14 | import org.eclipse.emf.ecore.EClass | ||
15 | import org.eclipse.xtend.lib.annotations.Accessors | ||
16 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
15 | 17 | ||
18 | @FinalFieldsConstructor | ||
16 | abstract class TypeIndexer { | 19 | abstract class TypeIndexer { |
17 | public def CharSequence getRequiredQueries() | 20 | @Accessors(PROTECTED_GETTER) val PatternGenerator base |
18 | public def boolean requiresTypeAnalysis() | 21 | |
19 | public def CharSequence generateInstanceOfQueries(LogicProblem problem,PartialInterpretation emptySolution,TypeAnalysisResult typeAnalysisResult) | 22 | def CharSequence getRequiredQueries() ''' |
20 | public def CharSequence referInstanceOf(Type type, Modality modality, String variableName) | 23 | private pattern typeInterpretation(problem:LogicProblem, interpretation:PartialInterpretation, type:TypeDeclaration, typeInterpretation:PartialComplexTypeInterpretation) { |
21 | public def CharSequence referInstanceOf(EClass type, Modality modality, String variableName) | 24 | find interpretation(problem,interpretation); |
22 | 25 | LogicProblem.types(problem,type); | |
23 | public def dispatch CharSequence referInstanceOfByReference(ComplexTypeReference reference, Modality modality, String variableName) { | 26 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); |
24 | reference.referred.referInstanceOf(modality,variableName) | 27 | PartialComplexTypeInterpretation.interpretationOf(typeInterpretation,type); |
25 | } | 28 | } |
26 | public def dispatch CharSequence referInstanceOfByReference(BoolTypeReference reference, Modality modality, String variableName) { | 29 | |
30 | private pattern directInstanceOf(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement, type:Type) { | ||
31 | find interpretation(problem,interpretation); | ||
32 | LogicProblem.types(problem,type); | ||
33 | TypeDefinition.elements(type,element); | ||
34 | } or { | ||
35 | find interpretation(problem,interpretation); | ||
36 | find typeInterpretation(problem,interpretation,type,typeInterpretation); | ||
37 | PartialComplexTypeInterpretation.elements(typeInterpretation,element); | ||
38 | } | ||
39 | |||
40 | private pattern isPrimitive(element: PrimitiveElement) { | ||
41 | PrimitiveElement(element); | ||
42 | } | ||
43 | ''' | ||
44 | |||
45 | def boolean requiresTypeAnalysis() | ||
46 | |||
47 | def CharSequence generateInstanceOfQueries(LogicProblem problem, PartialInterpretation emptySolution, | ||
48 | TypeAnalysisResult typeAnalysisResult) ''' | ||
49 | «FOR type : problem.types» | ||
50 | «problem.generateMustInstenceOf(type, typeAnalysisResult)» | ||
51 | «problem.generateMayInstanceOf(type, typeAnalysisResult)» | ||
52 | «ENDFOR» | ||
53 | ''' | ||
54 | |||
55 | protected def CharSequence generateMustInstenceOf(LogicProblem problem, Type type, | ||
56 | TypeAnalysisResult typeAnalysisResult) ''' | ||
57 | /** | ||
58 | * An element must be an instance of type "«type.name»". | ||
59 | */ | ||
60 | private pattern «patternName(type,Modality.MUST)»(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | ||
61 | Type.name(type,"«type.name»"); | ||
62 | find directInstanceOf(problem,interpretation,element,type); | ||
63 | } | ||
64 | ''' | ||
65 | |||
66 | protected def CharSequence generateMayInstanceOf(LogicProblem problem, Type type, | ||
67 | TypeAnalysisResult typeAnalysisResult) | ||
68 | |||
69 | protected def patternName(Type type, | ||
70 | Modality modality) '''«modality.toBase»InstanceOf«base.canonizeName(type.name)»''' | ||
71 | |||
72 | def referInstanceOf(Type type, Modality modality, String variableName) { | ||
73 | '''find «patternName(type,modality)»(problem,interpretation,«variableName»);''' | ||
74 | } | ||
75 | |||
76 | def referInstanceOf(EClass type, Modality modality, String variableName) { | ||
77 | '''find «modality.toBase»InstanceOf«base.canonizeName('''«type.name» class''')»(problem,interpretation,«variableName»);''' | ||
78 | } | ||
79 | |||
80 | def dispatch CharSequence referInstanceOfByReference(ComplexTypeReference reference, Modality modality, | ||
81 | String variableName) { | ||
82 | reference.referred.referInstanceOf(modality, variableName) | ||
83 | } | ||
84 | |||
85 | def dispatch CharSequence referInstanceOfByReference(BoolTypeReference reference, Modality modality, | ||
86 | String variableName) { | ||
27 | '''BooleanElement(«variableName»);''' | 87 | '''BooleanElement(«variableName»);''' |
28 | } | 88 | } |
29 | public def dispatch CharSequence referInstanceOfByReference(IntTypeReference reference, Modality modality, String variableName) { | 89 | |
90 | def dispatch CharSequence referInstanceOfByReference(IntTypeReference reference, Modality modality, | ||
91 | String variableName) { | ||
30 | '''IntegerElement(«variableName»);''' | 92 | '''IntegerElement(«variableName»);''' |
31 | } | 93 | } |
32 | public def dispatch CharSequence referInstanceOfByReference(RealTypeReference reference, Modality modality, String variableName) { | 94 | |
95 | def dispatch CharSequence referInstanceOfByReference(RealTypeReference reference, Modality modality, | ||
96 | String variableName) { | ||
33 | '''RealElement(«variableName»);''' | 97 | '''RealElement(«variableName»);''' |
34 | } | 98 | } |
35 | public def dispatch CharSequence referInstanceOfByReference(StringTypeReference reference, Modality modality, String variableName) { | 99 | |
100 | def dispatch CharSequence referInstanceOfByReference(StringTypeReference reference, Modality modality, | ||
101 | String variableName) { | ||
36 | '''StringElement(«variableName»);''' | 102 | '''StringElement(«variableName»);''' |
37 | } | 103 | } |
38 | public def dispatch CharSequence referPrimitiveValue(String variableName, Boolean value) { | 104 | |
105 | def dispatch CharSequence referPrimitiveValue(String variableName, Boolean value) { | ||
39 | '''BooleanElement.value(«variableName»,«value»);''' | 106 | '''BooleanElement.value(«variableName»,«value»);''' |
40 | } | 107 | } |
41 | public def dispatch CharSequence referPrimitiveValue(String variableName, Integer value) { | 108 | |
109 | def dispatch CharSequence referPrimitiveValue(String variableName, Integer value) { | ||
42 | '''IntegerElement.value(«variableName»,«value»);''' | 110 | '''IntegerElement.value(«variableName»,«value»);''' |
43 | } | 111 | } |
44 | public def dispatch CharSequence referPrimitiveValue(String variableName, BigDecimal value) { | 112 | |
113 | def dispatch CharSequence referPrimitiveValue(String variableName, BigDecimal value) { | ||
45 | '''RealElement.value(«variableName»,«value»);''' | 114 | '''RealElement.value(«variableName»,«value»);''' |
46 | } | 115 | } |
47 | ///TODO: de-escaping string literals | 116 | |
48 | public def dispatch CharSequence referPrimitiveValue(String variableName, String value) { | 117 | def dispatch CharSequence referPrimitiveValue(String variableName, String value) { |
118 | // /TODO: de-escaping string literals | ||
49 | '''StringElement.value(«variableName»,"«value»");''' | 119 | '''StringElement.value(«variableName»,"«value»");''' |
50 | } | 120 | } |
51 | 121 | ||
52 | } \ No newline at end of file | 122 | def CharSequence referPrimitiveFilled(String variableName, boolean isFilled) { |
123 | '''PrimitiveElement.valueSet(«variableName»,«isFilled»);''' | ||
124 | } | ||
125 | } | ||
126 | |||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexerWithPreliminaryTypeAnalysis.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexerWithPreliminaryTypeAnalysis.xtend index d3af0426..0393b803 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexerWithPreliminaryTypeAnalysis.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexerWithPreliminaryTypeAnalysis.xtend | |||
@@ -4,113 +4,51 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | |||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | 4 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem |
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | 5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality |
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult | 6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult |
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeRefinementPrecondition | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
9 | import org.eclipse.emf.ecore.EClass | ||
10 | 7 | ||
11 | class TypeIndexerWithPreliminaryTypeAnalysis extends TypeIndexer{ | 8 | class TypeIndexerWithPreliminaryTypeAnalysis extends TypeIndexer { |
12 | val PatternGenerator base; | ||
13 | |||
14 | new(PatternGenerator base) { | 9 | new(PatternGenerator base) { |
15 | this.base = base | 10 | super(base) |
16 | } | 11 | } |
12 | |||
17 | override requiresTypeAnalysis() { true } | 13 | override requiresTypeAnalysis() { true } |
18 | 14 | ||
19 | override getRequiredQueries() ''' | 15 | protected override generateMayInstanceOf(LogicProblem problem, Type type, TypeAnalysisResult typeAnalysisResult) { |
20 | private pattern typeInterpretation(problem:LogicProblem, interpretation:PartialInterpretation, type:TypeDeclaration, typeInterpretation:PartialComplexTypeInterpretation) { | 16 | val precondition = typeAnalysisResult?.mayNewTypePreconditions?.get(type) |
21 | find interpretation(problem,interpretation); | 17 | val inhibitorTypes = precondition?.inhibitorTypes |
22 | LogicProblem.types(problem,type); | ||
23 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); | ||
24 | PartialComplexTypeInterpretation.interpretationOf(typeInterpretation,type); | ||
25 | } | ||
26 | |||
27 | private pattern directInstanceOf(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement, type:Type) { | ||
28 | find interpretation(problem,interpretation); | ||
29 | LogicProblem.types(problem,type); | ||
30 | TypeDefinition.elements(type,element); | ||
31 | } or { | ||
32 | find interpretation(problem,interpretation); | ||
33 | find typeInterpretation(problem,interpretation,type,typeInterpretation); | ||
34 | PartialComplexTypeInterpretation.elements(typeInterpretation,element); | ||
35 | } | ||
36 | |||
37 | private pattern isPrimitive(element: PrimitiveElement) { | ||
38 | PrimitiveElement(element); | ||
39 | } | ||
40 | ''' | ||
41 | |||
42 | override generateInstanceOfQueries(LogicProblem problem, PartialInterpretation emptySolution, TypeAnalysisResult typeAnalysisResult) { | ||
43 | val mayNewTypePreconditions = typeAnalysisResult.mayNewTypePreconditions | ||
44 | |||
45 | return ''' | ||
46 | «FOR type:problem.types» | ||
47 | «problem.generateMustInstenceOf(type)» | ||
48 | «problem.generateMayInstanceOf(type,mayNewTypePreconditions.get(type))» | ||
49 | «ENDFOR» | ||
50 | ''' | ||
51 | } | ||
52 | |||
53 | private def patternName(Type type, Modality modality) | ||
54 | '''«modality.toString.toLowerCase»InstanceOf«base.canonizeName(type.name)»''' | ||
55 | |||
56 | private def generateMustInstenceOf(LogicProblem problem, Type type) { | ||
57 | ''' | ||
58 | /** | ||
59 | * An element must be an instance of type "«type.name»". | ||
60 | */ | ||
61 | private pattern «patternName(type,Modality.MUST)»(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { | ||
62 | Type.name(type,"«type.name»"); | ||
63 | find directInstanceOf(problem,interpretation,element,type); | ||
64 | } | ||
65 | ''' | ||
66 | } | ||
67 | |||
68 | private def generateMayInstanceOf(LogicProblem problem, Type type, TypeRefinementPrecondition precondition) { | ||
69 | val inhibitorTypes = if(precondition!=null) { | ||
70 | precondition.inhibitorTypes | ||
71 | } else { | ||
72 | null | ||
73 | } | ||
74 | ''' | 18 | ''' |
75 | private pattern scopeDisallowsNew«base.canonizeName(type.name)»(problem:LogicProblem, interpretation:PartialInterpretation) { | 19 | private pattern scopeDisallowsNew«base.canonizeName(type.name)»(problem:LogicProblem, interpretation:PartialInterpretation) { |
76 | find interpretation(problem,interpretation); | 20 | find interpretation(problem,interpretation); |
77 | PartialInterpretation.scopes(interpretation,scope); | 21 | PartialInterpretation.scopes(interpretation,scope); |
78 | Scope.targetTypeInterpretation(scope,typeInterpretation); | 22 | Scope.targetTypeInterpretation(scope,typeInterpretation); |
79 | Scope.maxNewElements(scope,0); | 23 | Scope.maxNewElements(scope,0); |
80 | PartialComplexTypeInterpretation.interpretationOf(typeInterpretation,type); | 24 | PartialComplexTypeInterpretation.interpretationOf(typeInterpretation,type); |
81 | Type.name(type,"«type.name»"); | 25 | Type.name(type,"«type.name»"); |
82 | } | 26 | } |
83 | 27 | ||
84 | /** | 28 | /** |
85 | * An element may be an instance of type "«type.name»". | 29 | * An element may be an instance of type "«type.name»". |
86 | */ | 30 | */ |
87 | private pattern «patternName(type,Modality.MAY)»(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) | 31 | private pattern «patternName(type,Modality.MAY)»(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) |
88 | «IF inhibitorTypes !== null»{ | 32 | «IF inhibitorTypes !== null» |
89 | find interpretation(problem,interpretation); | 33 | { |
90 | PartialInterpretation.newElements(interpretation,element); | 34 | find interpretation(problem,interpretation); |
91 | «FOR inhibitorType : inhibitorTypes» | 35 | PartialInterpretation.newElements(interpretation,element); |
92 | neg «referInstanceOf(inhibitorType,Modality.MUST,"element")» | 36 | «FOR inhibitorType : inhibitorTypes» |
93 | «ENDFOR» | 37 | neg «referInstanceOf(inhibitorType,Modality.MUST,"element")» |
94 | neg find scopeDisallowsNew«base.canonizeName(type.name)»(problem, interpretation); | 38 | «ENDFOR» |
95 | neg find isPrimitive(element); | 39 | neg find scopeDisallowsNew«base.canonizeName(type.name)»(problem, interpretation); |
96 | } or { | 40 | neg find isPrimitive(element); |
97 | find interpretation(problem,interpretation); | 41 | } or { |
98 | PartialInterpretation.openWorldElements(interpretation,element); | 42 | find interpretation(problem,interpretation); |
99 | «FOR inhibitorType : inhibitorTypes» | 43 | PartialInterpretation.openWorldElements(interpretation,element); |
100 | neg «referInstanceOf(inhibitorType,Modality.MUST,"element")» | 44 | «FOR inhibitorType : inhibitorTypes» |
101 | «ENDFOR» | 45 | neg «referInstanceOf(inhibitorType,Modality.MUST,"element")» |
102 | neg find scopeDisallowsNew«base.canonizeName(type.name)»(problem, interpretation); | 46 | «ENDFOR» |
103 | neg find isPrimitive(element); | 47 | neg find scopeDisallowsNew«base.canonizeName(type.name)»(problem, interpretation); |
104 | } or | 48 | neg find isPrimitive(element); |
105 | «ENDIF» | 49 | } or |
106 | { «referInstanceOf(type,Modality.MUST,"element")» } | 50 | «ENDIF» |
51 | { «referInstanceOf(type,Modality.MUST,"element")» } | ||
107 | ''' | 52 | ''' |
108 | } | 53 | } |
109 | 54 | } | |
110 | public override referInstanceOf(Type type, Modality modality, String variableName) { | ||
111 | '''find «patternName(type,modality)»(problem,interpretation,«variableName»);''' | ||
112 | } | ||
113 | public override referInstanceOf(EClass type, Modality modality, String variableName) { | ||
114 | '''find «modality.toString.toLowerCase»InstanceOf«base.canonizeName('''«type.name» class''')»(problem,interpretation,«variableName»);''' | ||
115 | } | ||
116 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementGenerator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementGenerator.xtend index 7e3fad91..4ef336ae 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementGenerator.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementGenerator.xtend | |||
@@ -25,69 +25,76 @@ class ObjectCreationPrecondition { | |||
25 | 25 | ||
26 | abstract class TypeRefinementGenerator { | 26 | abstract class TypeRefinementGenerator { |
27 | val protected PatternGenerator base; | 27 | val protected PatternGenerator base; |
28 | public new(PatternGenerator base) { | 28 | |
29 | new(PatternGenerator base) { | ||
29 | this.base = base | 30 | this.base = base |
30 | } | 31 | } |
31 | 32 | ||
32 | public def boolean requiresTypeAnalysis() | 33 | def boolean requiresTypeAnalysis() |
33 | public def CharSequence generateRefineObjectQueries(LogicProblem p, PartialInterpretation emptySolution, TypeAnalysisResult typeAnalysisResult) | 34 | |
34 | public def CharSequence generateRefineTypeQueries(LogicProblem p, PartialInterpretation emptySolution, TypeAnalysisResult typeAnalysisResult) | 35 | def CharSequence generateRefineObjectQueries(LogicProblem p, PartialInterpretation emptySolution, |
35 | public def Map<? extends Type, String> getRefineTypeQueryNames(LogicProblem p, PartialInterpretation emptySolution, TypeAnalysisResult typeAnalysisResult) | 36 | TypeAnalysisResult typeAnalysisResult) |
36 | 37 | ||
37 | public def getRefineObjectQueryNames(LogicProblem p, PartialInterpretation emptySolution, TypeAnalysisResult typeAnalysisResult) { | 38 | def CharSequence generateRefineTypeQueries(LogicProblem p, PartialInterpretation emptySolution, |
38 | val Map<ObjectCreationPrecondition,String> objectCreationQueries = new LinkedHashMap | 39 | TypeAnalysisResult typeAnalysisResult) |
40 | |||
41 | def Map<? extends Type, String> getRefineTypeQueryNames(LogicProblem p, PartialInterpretation emptySolution, | ||
42 | TypeAnalysisResult typeAnalysisResult) | ||
43 | |||
44 | def getRefineObjectQueryNames(LogicProblem p, PartialInterpretation emptySolution, | ||
45 | TypeAnalysisResult typeAnalysisResult) { | ||
46 | val Map<ObjectCreationPrecondition, String> objectCreationQueries = new LinkedHashMap | ||
39 | val containment = p.containmentHierarchies.head | 47 | val containment = p.containmentHierarchies.head |
40 | val inverseRelations = new HashMap | 48 | val inverseRelations = new HashMap |
41 | p.annotations.filter(InverseRelationAssertion).forEach[ | 49 | p.annotations.filter(InverseRelationAssertion).forEach [ |
42 | inverseRelations.put(it.inverseA,it.inverseB) | 50 | inverseRelations.put(it.inverseA, it.inverseB) |
43 | inverseRelations.put(it.inverseB,it.inverseA) | 51 | inverseRelations.put(it.inverseB, it.inverseA) |
44 | ] | 52 | ] |
45 | for(type: p.types.filter(TypeDeclaration).filter[!it.isAbstract]) { | 53 | for (type : p.types.filter(TypeDeclaration).filter[!it.isAbstract]) { |
46 | if(containment.typeInContainment(type)) { | 54 | if (containment.typeInContainment(type)) { |
47 | for(containmentRelation : containment.containmentRelations.filter[canBeContainedByRelation(it,type)]) { | 55 | for (containmentRelation : containment.containmentRelations. |
48 | if(inverseRelations.containsKey(containmentRelation)) { | 56 | filter[canBeContainedByRelation(it, type)]) { |
57 | if (inverseRelations.containsKey(containmentRelation)) { | ||
49 | objectCreationQueries.put( | 58 | objectCreationQueries.put( |
50 | new ObjectCreationPrecondition(containmentRelation,inverseRelations.get(containmentRelation),type), | 59 | new ObjectCreationPrecondition(containmentRelation, |
51 | this.patternName(containmentRelation,inverseRelations.get(containmentRelation),type)) | 60 | inverseRelations.get(containmentRelation), type), |
61 | this.patternName(containmentRelation, inverseRelations.get(containmentRelation), type)) | ||
52 | } else { | 62 | } else { |
53 | objectCreationQueries.put( | 63 | objectCreationQueries.put(new ObjectCreationPrecondition(containmentRelation, null, type), |
54 | new ObjectCreationPrecondition(containmentRelation,null,type), | 64 | patternName(containmentRelation, null, type)) |
55 | patternName(containmentRelation,null,type)) | ||
56 | } | 65 | } |
57 | } | 66 | } |
58 | objectCreationQueries.put( | 67 | objectCreationQueries.put(new ObjectCreationPrecondition(null, null, type), |
59 | new ObjectCreationPrecondition(null,null,type), | 68 | patternName(null, null, type)) |
60 | patternName(null,null,type)) | ||
61 | } else { | 69 | } else { |
62 | objectCreationQueries.put( | 70 | objectCreationQueries.put(new ObjectCreationPrecondition(null, null, type), |
63 | new ObjectCreationPrecondition(null,null,type), | 71 | this.patternName(null, null, type)) |
64 | this.patternName(null,null,type)) | ||
65 | } | 72 | } |
66 | } | 73 | } |
67 | return objectCreationQueries | 74 | return objectCreationQueries |
68 | } | 75 | } |
69 | 76 | ||
70 | protected def canBeContainedByRelation(Relation r, Type t) { | 77 | protected def canBeContainedByRelation(Relation r, Type t) { |
71 | if(r.parameters.size==2) { | 78 | if (r.parameters.size == 2) { |
72 | val param = r.parameters.get(1) | 79 | val param = r.parameters.get(1) |
73 | if(param instanceof ComplexTypeReference) { | 80 | if (param instanceof ComplexTypeReference) { |
74 | val allSuperTypes = t.transitiveClosureStar[it.supertypes] | 81 | val allSuperTypes = t.transitiveClosureStar[it.supertypes] |
75 | for(superType : allSuperTypes) { | 82 | for (superType : allSuperTypes) { |
76 | if(param.referred == superType) return true | 83 | if(param.referred == superType) return true |
77 | } | 84 | } |
78 | } | 85 | } |
79 | } | 86 | } |
80 | return false | 87 | return false |
81 | } | 88 | } |
82 | 89 | ||
83 | private def typeInContainment(ContainmentHierarchy hierarchy, Type type) { | 90 | private def typeInContainment(ContainmentHierarchy hierarchy, Type type) { |
84 | val allSuperTypes = type.transitiveClosureStar[it.supertypes] | 91 | val allSuperTypes = type.transitiveClosureStar[it.supertypes] |
85 | return allSuperTypes.exists[hierarchy.typesOrderedInHierarchy.contains(it)] | 92 | return allSuperTypes.exists[hierarchy.typesOrderedInHierarchy.contains(it)] |
86 | } | 93 | } |
87 | 94 | ||
88 | protected def String patternName(Relation containmentRelation, Relation inverseContainment, Type newType) { | 95 | protected def String patternName(Relation containmentRelation, Relation inverseContainment, Type newType) { |
89 | if(containmentRelation != null) { | 96 | if (containmentRelation !== null) { |
90 | if(inverseContainment != null) { | 97 | if (inverseContainment !== null) { |
91 | '''createObject_«base.canonizeName(newType.name)»_by_«base.canonizeName(containmentRelation.name)»_with_«base.canonizeName(inverseContainment.name)»''' | 98 | '''createObject_«base.canonizeName(newType.name)»_by_«base.canonizeName(containmentRelation.name)»_with_«base.canonizeName(inverseContainment.name)»''' |
92 | } else { | 99 | } else { |
93 | '''createObject_«base.canonizeName(newType.name)»_by_«base.canonizeName(containmentRelation.name)»''' | 100 | '''createObject_«base.canonizeName(newType.name)»_by_«base.canonizeName(containmentRelation.name)»''' |
@@ -96,4 +103,8 @@ abstract class TypeRefinementGenerator { | |||
96 | '''createObject_«base.canonizeName(newType.name)»''' | 103 | '''createObject_«base.canonizeName(newType.name)»''' |
97 | } | 104 | } |
98 | } | 105 | } |
99 | } \ No newline at end of file | 106 | |
107 | def hasElementInContainmentName() { | ||
108 | "hasElementInContainment" | ||
109 | } | ||
110 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementWithPreliminaryTypeAnalysis.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementWithPreliminaryTypeAnalysis.xtend index cbbbcb08..1a81695e 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementWithPreliminaryTypeAnalysis.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementWithPreliminaryTypeAnalysis.xtend | |||
@@ -10,7 +10,7 @@ import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.par | |||
10 | import java.util.HashMap | 10 | import java.util.HashMap |
11 | 11 | ||
12 | class TypeRefinementWithPreliminaryTypeAnalysis extends TypeRefinementGenerator{ | 12 | class TypeRefinementWithPreliminaryTypeAnalysis extends TypeRefinementGenerator{ |
13 | public new(PatternGenerator base) { | 13 | new(PatternGenerator base) { |
14 | super(base) | 14 | super(base) |
15 | } | 15 | } |
16 | override requiresTypeAnalysis() { true } | 16 | override requiresTypeAnalysis() { true } |
@@ -24,7 +24,7 @@ class TypeRefinementWithPreliminaryTypeAnalysis extends TypeRefinementGenerator{ | |||
24 | inverseRelations.put(it.inverseB,it.inverseA) | 24 | inverseRelations.put(it.inverseB,it.inverseA) |
25 | ] | 25 | ] |
26 | return ''' | 26 | return ''' |
27 | private pattern hasElementInContainment(problem:LogicProblem, interpretation:PartialInterpretation) | 27 | pattern «hasElementInContainmentName»(problem:LogicProblem, interpretation:PartialInterpretation) |
28 | «FOR type :containment.typesOrderedInHierarchy SEPARATOR "or"»{ | 28 | «FOR type :containment.typesOrderedInHierarchy SEPARATOR "or"»{ |
29 | find interpretation(problem,interpretation); | 29 | find interpretation(problem,interpretation); |
30 | «base.typeIndexer.referInstanceOf(type,Modality.MUST,"root")» | 30 | «base.typeIndexer.referInstanceOf(type,Modality.MUST,"root")» |
@@ -76,7 +76,7 @@ class TypeRefinementWithPreliminaryTypeAnalysis extends TypeRefinementGenerator{ | |||
76 | typeInterpretation:PartialComplexTypeInterpretation) | 76 | typeInterpretation:PartialComplexTypeInterpretation) |
77 | { | 77 | { |
78 | find interpretation(problem,interpretation); | 78 | find interpretation(problem,interpretation); |
79 | neg find hasElementInContainment(problem,interpretation); | 79 | neg find «hasElementInContainmentName»(problem,interpretation); |
80 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); | 80 | PartialInterpretation.partialtypeinterpratation(interpretation,typeInterpretation); |
81 | PartialComplexTypeInterpretation.interpretationOf.name(typeInterpretation,"«type.name»"); | 81 | PartialComplexTypeInterpretation.interpretationOf.name(typeInterpretation,"«type.name»"); |
82 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» | 82 | «base.typeIndexer.referInstanceOf(type,Modality.MAY,"newObject")» |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/UnfinishedIndexer.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/UnfinishedIndexer.xtend index ad1c9033..65ad3d48 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/UnfinishedIndexer.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/UnfinishedIndexer.xtend | |||
@@ -1,85 +1,149 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns |
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion | 3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration |
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | 4 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem |
5 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransformedViatraWellformednessConstraint | 5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality |
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationMultiplicityConstraint | ||
7 | import java.util.LinkedHashMap | ||
8 | import java.util.List | ||
6 | import java.util.Map | 9 | import java.util.Map |
7 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | 10 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery |
11 | import org.eclipse.xtend.lib.annotations.Data | ||
8 | 12 | ||
9 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 13 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
10 | import java.util.LinkedHashMap | 14 | |
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | 15 | @Data |
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | 16 | class UnifinishedMultiplicityQueryNames { |
17 | val String existingMultiplicityQueryName | ||
18 | val String existingInverseMultiplicityQueryName | ||
19 | } | ||
13 | 20 | ||
14 | class UnfinishedIndexer { | 21 | class UnfinishedIndexer { |
15 | val PatternGenerator base | 22 | val PatternGenerator base |
16 | 23 | val boolean indexUpperMultiplicities | |
17 | new(PatternGenerator patternGenerator) { | 24 | |
25 | new(PatternGenerator patternGenerator, boolean indexUpperMultiplicities) { | ||
18 | this.base = patternGenerator | 26 | this.base = patternGenerator |
27 | this.indexUpperMultiplicities = indexUpperMultiplicities | ||
19 | } | 28 | } |
20 | 29 | ||
21 | def generateUnfinishedWfQueries(LogicProblem problem, Map<String,PQuery> fqn2PQuery) { | 30 | def generateUnfinishedWfQueries(LogicProblem problem, Map<String, PQuery> fqn2PQuery) { |
22 | val wfQueries = base.wfQueries(problem) | 31 | val wfQueries = base.wfQueries(problem) |
23 | ''' | 32 | ''' |
24 | «FOR wfQuery: wfQueries» | 33 | «FOR wfQuery : wfQueries» |
25 | pattern unfinishedBy_«base.canonizeName(wfQuery.target.name)»(problem:LogicProblem, interpretation:PartialInterpretation, | 34 | pattern unfinishedBy_«base.canonizeName(wfQuery.target.name)»(problem:LogicProblem, interpretation:PartialInterpretation, |
26 | «FOR param : wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery).parameters SEPARATOR ', '»var_«param.name»«ENDFOR») | 35 | «FOR param : wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery).parameters SEPARATOR ', '»var_«param.name»«ENDFOR») |
27 | { | 36 | { |
28 | «base.relationDefinitionIndexer.referPattern( | 37 | «base.relationDefinitionIndexer.referPattern( |
29 | wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery), | 38 | wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery), |
30 | wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery).parameters.map['''var_«it.name»'''], | 39 | wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery).parameters.map['''var_«it.name»'''], |
31 | Modality.CURRENT, | 40 | Modality.CURRENT, |
32 | true,false)» | 41 | true,false)» |
33 | } | 42 | } |
34 | «ENDFOR» | 43 | «ENDFOR» |
35 | ''' | 44 | ''' |
36 | } | 45 | } |
46 | |||
37 | def getUnfinishedWFQueryNames(LogicProblem problem) { | 47 | def getUnfinishedWFQueryNames(LogicProblem problem) { |
38 | val wfQueries = base.wfQueries(problem) | 48 | val wfQueries = base.wfQueries(problem) |
39 | val map = new LinkedHashMap | 49 | val map = new LinkedHashMap |
40 | for(wfQuery : wfQueries) { | 50 | for (wfQuery : wfQueries) { |
41 | map.put(wfQuery.target,'''unfinishedBy_«base.canonizeName(wfQuery.target.name)»''') | 51 | map.put(wfQuery.target, '''unfinishedBy_«base.canonizeName(wfQuery.target.name)»''') |
42 | } | 52 | } |
43 | return map | 53 | return map |
44 | } | 54 | } |
45 | def generateUnfinishedMultiplicityQueries(LogicProblem problem, Map<String,PQuery> fqn2PQuery) { | 55 | |
46 | val lowerMultiplicities = base.lowerMultiplicities(problem) | 56 | def generateUnfinishedMultiplicityQueries(List<RelationMultiplicityConstraint> constraints, |
47 | return ''' | 57 | Map<String, PQuery> fqn2PQuery) ''' |
48 | «FOR lowerMultiplicity : lowerMultiplicities» | 58 | «FOR constraint : constraints» |
49 | pattern «unfinishedMultiplicityName(lowerMultiplicity)»(problem:LogicProblem, interpretation:PartialInterpretation, relationIterpretation:PartialRelationInterpretation, object:DefinedElement,missingMultiplicity) { | 59 | «IF constraint.shouldIndexExistingMultiplicites(indexUpperMultiplicities)» |
50 | find interpretation(problem,interpretation); | 60 | private pattern «existingMultiplicityName(constraint)»(problem:LogicProblem, interpretation:PartialInterpretation, object:DefinedElement, numberOfExistingReferences:java Integer«IF constraint.shouldIndexRepairMultiplcities(indexUpperMultiplicities)», numberOfRepairMatches: java Integer«ENDIF») { |
51 | PartialInterpretation.partialrelationinterpretation(interpretation,relationIterpretation); | 61 | find interpretation(problem,interpretation); |
52 | PartialRelationInterpretation.interpretationOf.name(relationIterpretation,"«lowerMultiplicity.relation.name»"); | 62 | find mustExist(problem,interpretation,object); |
53 | «base.typeIndexer.referInstanceOf(lowerMultiplicity.firstParamTypeOfRelation,Modality::MUST,"object")» | 63 | «base.typeIndexer.referInstanceOf(constraint.sourceType,Modality::MUST,"object")» |
54 | numberOfExistingReferences == count «base.referRelation(lowerMultiplicity.relation,"object","_",Modality.MUST,fqn2PQuery)» | 64 | numberOfExistingReferences == count «base.referRelation(constraint.relation,"object","_",Modality.MUST,fqn2PQuery)» |
55 | check(numberOfExistingReferences < «lowerMultiplicity.lower»); | 65 | «IF constraint.shouldIndexRepairMultiplcities(indexUpperMultiplicities)» |
56 | missingMultiplicity == eval(«lowerMultiplicity.lower»-numberOfExistingReferences); | 66 | numberOfRepairMatches == count find «repairMatchName(constraint)»(problem, interpretation, object, _); |
57 | } | 67 | «ENDIF» |
68 | } | ||
69 | «ENDIF» | ||
70 | |||
71 | «IF constraint.shouldIndexRepairMatches(indexUpperMultiplicities)» | ||
72 | private pattern «repairMatchName(constraint)»(problem:LogicProblem, interpretation:PartialInterpretation, source:DefinedElement, target:DefinedElement) { | ||
73 | «IF constraint.containment || constraint.container» | ||
74 | «repairMatchFallback(constraint, fqn2PQuery)» | ||
75 | «ELSEIF base.isRepresentative(constraint.relation, constraint.inverseRelation) && constraint.relation instanceof RelationDeclaration» | ||
76 | «base.relationRefinementGenerator.referRefinementQuery(constraint.relation as RelationDeclaration, constraint.inverseRelation, "_", "_", "source", "target")» | ||
77 | «ELSEIF base.isRepresentative(constraint.inverseRelation, constraint.relation) && constraint.inverseRelation instanceof RelationDeclaration» | ||
78 | «base.relationRefinementGenerator.referRefinementQuery(constraint.inverseRelation as RelationDeclaration, constraint.relation, "_", "_", "target", "source")» | ||
79 | «ELSE» | ||
80 | «repairMatchFallback(constraint, fqn2PQuery)» | ||
81 | «ENDIF» | ||
82 | } | ||
83 | «ENDIF» | ||
84 | |||
85 | «IF constraint.shouldIndexInverseMultiplicites(indexUpperMultiplicities)» | ||
86 | private pattern «existingInverseMultiplicityName(constraint)»(problem:LogicProblem, interpretation:PartialInterpretation, object:DefinedElement, numberOfExistingReferences:java Integer, numberOfRepairMatches: java Integer) { | ||
87 | find interpretation(problem,interpretation); | ||
88 | find mustExist(problem,interpretation,object); | ||
89 | «base.typeIndexer.referInstanceOf(constraint.targetType,Modality::MUST,"object")» | ||
90 | numberOfExistingReferences == count «base.referRelation(constraint.relation,"_","object",Modality.MUST,fqn2PQuery)» | ||
91 | numberOfRepairMatches == count find «repairMatchName(constraint)»(problem, interpretation, _, object); | ||
92 | } | ||
93 | «ENDIF» | ||
58 | «ENDFOR» | 94 | «ENDFOR» |
59 | ''' | 95 | ''' |
96 | |||
97 | private def repairMatchFallback(RelationMultiplicityConstraint constraint, Map<String, PQuery> fqn2PQuery) ''' | ||
98 | find interpretation(problem,interpretation); | ||
99 | find mustExist(problem,interpretation,source); | ||
100 | «base.typeIndexer.referInstanceOf(constraint.sourceType,Modality::MUST,"source")» | ||
101 | find mustExist(problem,interpretation,target); | ||
102 | «base.typeIndexer.referInstanceOf(constraint.targetType,Modality::MUST,"target")» | ||
103 | neg «base.referRelation(constraint.relation,"source","target",Modality.MUST,fqn2PQuery)» | ||
104 | «base.referRelation(constraint.relation,"source","target",Modality.MAY,fqn2PQuery)» | ||
105 | ''' | ||
106 | |||
107 | def String existingMultiplicityName( | ||
108 | RelationMultiplicityConstraint constraint) '''existingMultiplicity_«base.canonizeName(constraint.relation.name)»''' | ||
109 | |||
110 | def String existingInverseMultiplicityName( | ||
111 | RelationMultiplicityConstraint constraint) '''existingInverseMultiplicity_«base.canonizeName(constraint.relation.name)»''' | ||
112 | |||
113 | private def String repairMatchName( | ||
114 | RelationMultiplicityConstraint constraint) '''repair_«base.canonizeName(constraint.relation.name)»''' | ||
115 | |||
116 | def getUnfinishedMultiplicityQueries(List<RelationMultiplicityConstraint> constraints) { | ||
117 | constraints.toInvertedMap [ constraint | | ||
118 | new UnifinishedMultiplicityQueryNames( | ||
119 | if (constraint.shouldIndexExistingMultiplicites(indexUpperMultiplicities)) { | ||
120 | existingMultiplicityName(constraint) | ||
121 | } else { | ||
122 | null | ||
123 | }, | ||
124 | if (constraint.shouldIndexInverseMultiplicites(indexUpperMultiplicities)) { | ||
125 | existingInverseMultiplicityName(constraint) | ||
126 | } else { | ||
127 | null | ||
128 | } | ||
129 | ) | ||
130 | ] | ||
60 | } | 131 | } |
61 | def String unfinishedMultiplicityName(LowerMultiplicityAssertion lowerMultiplicityAssertion) | 132 | |
62 | '''unfinishedLowerMultiplicity_«base.canonizeName(lowerMultiplicityAssertion.relation.name)»''' | 133 | static def shouldIndexExistingMultiplicites(RelationMultiplicityConstraint it, boolean indexUpperMultiplicities) { |
63 | 134 | constrainsUnfinished || (indexUpperMultiplicities && constrainsRemainingContents) | |
64 | def public referUnfinishedMultiplicityQuery(LowerMultiplicityAssertion lowerMultiplicityAssertion) | ||
65 | '''find «unfinishedMultiplicityName(lowerMultiplicityAssertion)»(problem, interpretation ,object, missingMultiplicity);''' | ||
66 | |||
67 | def getFirstParamTypeOfRelation(LowerMultiplicityAssertion lowerMultiplicityAssertion) { | ||
68 | val parameters = lowerMultiplicityAssertion.relation.parameters | ||
69 | if(parameters.size == 2) { | ||
70 | val firstParam = parameters.get(0) | ||
71 | if(firstParam instanceof ComplexTypeReference) { | ||
72 | return firstParam.referred | ||
73 | } | ||
74 | } | ||
75 | } | 135 | } |
76 | 136 | ||
77 | def getUnfinishedMultiplicityQueries(LogicProblem problem) { | 137 | static def shouldIndexRepairMultiplcities(RelationMultiplicityConstraint it, boolean indexUpperMultiplicities) { |
78 | val lowerMultiplicities = base.lowerMultiplicities(problem) | 138 | shouldIndexExistingMultiplicites(indexUpperMultiplicities) && constrainsUnrepairable |
79 | val map = new LinkedHashMap | 139 | } |
80 | for(lowerMultiplicity : lowerMultiplicities) { | 140 | |
81 | map.put(lowerMultiplicity.relation,unfinishedMultiplicityName(lowerMultiplicity)) | 141 | static def shouldIndexInverseMultiplicites(RelationMultiplicityConstraint it, boolean indexUpperMultiplicities) { |
82 | } | 142 | indexUpperMultiplicities && constrainsRemainingInverse |
83 | return map | 143 | } |
144 | |||
145 | static def shouldIndexRepairMatches(RelationMultiplicityConstraint it, boolean indexUpperMultiplicities) { | ||
146 | shouldIndexRepairMultiplcities(indexUpperMultiplicities) || | ||
147 | shouldIndexInverseMultiplicites(indexUpperMultiplicities) | ||
84 | } | 148 | } |
85 | } | 149 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/UnitPropagationPreconditionGenerator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/UnitPropagationPreconditionGenerator.xtend new file mode 100644 index 00000000..400f47bc --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/UnitPropagationPreconditionGenerator.xtend | |||
@@ -0,0 +1,302 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
6 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.PropagationModality | ||
9 | import java.util.Map | ||
10 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
11 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable | ||
12 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExpressionEvaluation | ||
13 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | ||
14 | |||
15 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | ||
16 | import java.util.LinkedList | ||
17 | import java.util.List | ||
18 | import org.eclipse.xtend.lib.annotations.Data | ||
19 | import java.util.HashMap | ||
20 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall | ||
21 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall | ||
22 | import java.util.Comparator | ||
23 | import java.util.ArrayList | ||
24 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction | ||
25 | import java.util.LinkedHashSet | ||
26 | |||
27 | @Data class UnitPropagation { | ||
28 | val PQuery q | ||
29 | val PConstraint c | ||
30 | val PropagationModality pm | ||
31 | val Modality m3 | ||
32 | } | ||
33 | @Data | ||
34 | class UnitPropagationPreconditionGenerationResult { | ||
35 | List<CharSequence> definitions= new LinkedList | ||
36 | Map<UnitPropagation,String> unitPropagation2PatternName = new HashMap | ||
37 | Map<PConstraint,String> constraintOccurence2Name = new HashMap | ||
38 | |||
39 | def registerQuery(PQuery q, PConstraint c, PropagationModality pm, Modality m3, String patternName, CharSequence definition) { | ||
40 | val key = new UnitPropagation(q,c,pm,m3) | ||
41 | definitions += definition | ||
42 | unitPropagation2PatternName.put(key,patternName) | ||
43 | } | ||
44 | def registerUnsatQuery(PQuery q, PConstraint c, PropagationModality pm, Modality m3) { | ||
45 | val key = new UnitPropagation(q,c,pm,m3) | ||
46 | unitPropagation2PatternName.put(key,null) | ||
47 | } | ||
48 | def contains(PQuery q, PConstraint c, PropagationModality pm, Modality m3) { | ||
49 | val key = new UnitPropagation(q,c,pm,m3) | ||
50 | return unitPropagation2PatternName.containsKey(key) | ||
51 | } | ||
52 | def getName(PQuery q, PConstraint c, PropagationModality pm, Modality m3) { | ||
53 | val key = new UnitPropagation(q,c,pm,m3) | ||
54 | return key.lookup(unitPropagation2PatternName) | ||
55 | } | ||
56 | def isDefined(PQuery q, PConstraint c, PropagationModality pm, Modality m3) { | ||
57 | val key = new UnitPropagation(q,c,pm,m3) | ||
58 | return unitPropagation2PatternName.get(key) !== null | ||
59 | } | ||
60 | } | ||
61 | @Data | ||
62 | class UnitPropagationPreconditionFinalResult { | ||
63 | CharSequence definitions | ||
64 | HashMap<PConstraint,String> constraint2MustPreconditionName | ||
65 | HashMap<PConstraint,String> constraint2CurrentPreconditionName | ||
66 | } | ||
67 | |||
68 | class UnitPropagationPreconditionGenerator { | ||
69 | val PatternGenerator base | ||
70 | val PConstraintTransformer constraintTransformer; | ||
71 | |||
72 | new(PatternGenerator patternGenerator) { | ||
73 | this.base = patternGenerator | ||
74 | this.constraintTransformer = new PConstraintTransformer(base.relationDefinitionIndexer) | ||
75 | } | ||
76 | |||
77 | def generateUnitPropagationRules( | ||
78 | LogicProblem problem, | ||
79 | Iterable<RelationDefinition> relations, | ||
80 | Map<String,PQuery> fqn2PQuery) | ||
81 | { | ||
82 | // Create an empty result | ||
83 | val res = new UnitPropagationPreconditionGenerationResult | ||
84 | val wfs = base.wfQueries(problem)//.map[it.patternPQuery] | ||
85 | val Map<PConstraint,List<Pair<String,Integer>>> mainMustPropagationNames = new HashMap | ||
86 | val Map<PConstraint,List<Pair<String,Integer>>> mainCurrentPropagationNames = new HashMap | ||
87 | for(wf : wfs) { | ||
88 | val query = wf.patternPQuery as PQuery | ||
89 | val relation = wf.target | ||
90 | val allReferredChecks = allReferredConstraints(relation,query).filter(ExpressionEvaluation) | ||
91 | |||
92 | for(referredCheck : allReferredChecks) { | ||
93 | val mustPropagationPrecondition = getOrGeneratePropagationRule(res,relation,query,referredCheck,PropagationModality::UP, Modality::MUST) | ||
94 | val currentPropagationPrecondition = getOrGeneratePropagationRule(res,relation,query,referredCheck,PropagationModality::UP, Modality::CURRENT) | ||
95 | if(!mainMustPropagationNames.containsKey(referredCheck)) { | ||
96 | mainMustPropagationNames.put(referredCheck,new LinkedList) | ||
97 | } | ||
98 | if(!mainCurrentPropagationNames.containsKey(referredCheck)) { | ||
99 | mainCurrentPropagationNames.put(referredCheck,new LinkedList) | ||
100 | } | ||
101 | if(mustPropagationPrecondition !== null) { | ||
102 | mainMustPropagationNames.get(referredCheck).add(mustPropagationPrecondition->query.parameterNames.size) | ||
103 | } | ||
104 | if(currentPropagationPrecondition !== null) { | ||
105 | mainCurrentPropagationNames.get(referredCheck).add(currentPropagationPrecondition->query.parameterNames.size) | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | val preconditions = new LinkedList | ||
110 | val constraint2MustPrecondition = new HashMap | ||
111 | val constraint2CurrentPrecondition = new HashMap | ||
112 | for(entry : mainMustPropagationNames.entrySet) { | ||
113 | val name = '''UPMUSTPropagate_«res.getOrGenerateConstraintName(entry.key)»'''; | ||
114 | val def = ''' | ||
115 | pattern «name»(«FOR index : 1..entry.key.arity SEPARATOR ", "»«canonizeName(index,PropagationModality::UP)»«ENDFOR») | ||
116 | «FOR propagation : entry.value SEPARATOR " or "» | ||
117 | { find «propagation.key»(problem,interpretation,«FOR index : 0..<propagation.value SEPARATOR ','»_«ENDFOR»,«FOR index : 1..entry.key.arity SEPARATOR ", "»«canonizeName(index,PropagationModality::UP)»«ENDFOR»); } | ||
118 | «ENDFOR»''' | ||
119 | preconditions+=def | ||
120 | constraint2MustPrecondition.put(entry.key,name) | ||
121 | } | ||
122 | for(entry : mainCurrentPropagationNames.entrySet) { | ||
123 | val name = '''UPCurrentPropagate_«res.getOrGenerateConstraintName(entry.key)»'''; | ||
124 | val def = ''' | ||
125 | pattern «name»(«FOR index : 1..entry.key.arity SEPARATOR ", "»«canonizeName(index,PropagationModality::UP)»«ENDFOR») | ||
126 | «FOR propagation : entry.value SEPARATOR " or "» | ||
127 | { find «propagation.key»(problem,interpretation,«FOR index : 0..<propagation.value SEPARATOR ','»_«ENDFOR»,«FOR index : 1..entry.key.arity SEPARATOR ", "»«canonizeName(index,PropagationModality::UP)»«ENDFOR»); } | ||
128 | «ENDFOR»''' | ||
129 | preconditions+=def | ||
130 | constraint2CurrentPrecondition.put(entry.key,name) | ||
131 | } | ||
132 | |||
133 | val definitions = ''' | ||
134 | «FOR def : res.definitions» | ||
135 | «def» | ||
136 | «ENDFOR» | ||
137 | |||
138 | // Collected propagation preconditions: | ||
139 | |||
140 | «FOR predondition : preconditions» | ||
141 | «predondition» | ||
142 | «ENDFOR» | ||
143 | ''' | ||
144 | return new UnitPropagationPreconditionFinalResult(definitions,constraint2MustPrecondition,constraint2CurrentPrecondition) | ||
145 | } | ||
146 | def allReferredConstraints(Relation relation, PQuery query) { | ||
147 | val allReferredQueries = query.allReferredQueries | ||
148 | val problem = relation.eContainer as LogicProblem | ||
149 | val constraints = new LinkedHashSet | ||
150 | for(referredQuery: #[query]+allReferredQueries) { | ||
151 | val referredRelation = problem.annotations.filter(TransfomedViatraQuery).filter[it.patternPQuery === referredQuery].head.target | ||
152 | val bodies = (referredRelation.annotations.filter(TransfomedViatraQuery).head.optimizedDisjunction as PDisjunction).bodies | ||
153 | constraints.addAll(bodies.map[getConstraints].flatten) | ||
154 | } | ||
155 | |||
156 | return constraints | ||
157 | } | ||
158 | |||
159 | def getOrGeneratePropagationRule(UnitPropagationPreconditionGenerationResult res, Relation relation, PQuery q, PConstraint c, PropagationModality pm, Modality m3) { | ||
160 | if(res.contains(q,c,pm,m3)) { | ||
161 | return res.getName(q,c,pm,m3) | ||
162 | } else { | ||
163 | res.generatePropagationRule(relation,q,c,pm,m3) | ||
164 | return res.getName(q,c,pm,m3) | ||
165 | } | ||
166 | } | ||
167 | def getOrGenerateConstraintName(UnitPropagationPreconditionGenerationResult res, PConstraint c){ | ||
168 | if(res.constraintOccurence2Name.containsKey(c)) { | ||
169 | return res.constraintOccurence2Name.get(c) | ||
170 | } else { | ||
171 | val constraintName = '''Constraint«res.constraintOccurence2Name.size»''' | ||
172 | res.constraintOccurence2Name.put(c,constraintName) | ||
173 | return constraintName | ||
174 | } | ||
175 | } | ||
176 | |||
177 | def void generatePropagationRule(UnitPropagationPreconditionGenerationResult res, Relation relation, PQuery q, PConstraint c, PropagationModality pm, Modality m3) { | ||
178 | val name = relationDefinitionName(res,relation,q,c,pm,m3) | ||
179 | val constraintArity = c.arity | ||
180 | val bodies = (relation.annotations.filter(TransfomedViatraQuery).head.optimizedDisjunction as PDisjunction).bodies | ||
181 | val generatedBodies = new LinkedList | ||
182 | for(body : bodies) { | ||
183 | if(body.constraints.contains(c)) { | ||
184 | if(pm === PropagationModality::UP) { | ||
185 | generatedBodies += ''' | ||
186 | // Original Constraints | ||
187 | «FOR constraint : body.constraints.filter[it !== c]» | ||
188 | «this.constraintTransformer.transformConstraint(constraint,m3,relation.annotations.filter(TransfomedViatraQuery).head.variableTrace)» | ||
189 | «ENDFOR» | ||
190 | // Propagation for constraint | ||
191 | «this.constraintTransformer.transformConstraintUnset(c as ExpressionEvaluation,relation.annotations.filter(TransfomedViatraQuery).head.variableTrace)» | ||
192 | // Matching variables | ||
193 | «this.propagateVariables(c,pm)» | ||
194 | ''' | ||
195 | } | ||
196 | // Otherwise, for PropagationModality::DOWN, the body cannot be satisfied | ||
197 | } else { | ||
198 | val positives = body.constraints.filter(PositivePatternCall) | ||
199 | for(positive: positives) { | ||
200 | val referredPQuery = positive.referredQuery | ||
201 | val referredRelation = (relation.eContainer as LogicProblem) | ||
202 | .annotations.filter(TransfomedViatraQuery).filter[it.patternPQuery === referredPQuery].head.target | ||
203 | if(allReferredConstraints(referredRelation,referredPQuery).toSet.contains(c)) { | ||
204 | val referredName = getOrGeneratePropagationRule(res,referredRelation,referredPQuery,c,pm,m3) | ||
205 | if(referredName !== null) { | ||
206 | generatedBodies += ''' | ||
207 | // Original Constraints | ||
208 | «FOR constraint : body.constraints.filter[it !== positive]» | ||
209 | «this.constraintTransformer.transformConstraint(constraint,m3,relation.annotations.filter(TransfomedViatraQuery).head.variableTrace)» | ||
210 | «ENDFOR» | ||
211 | // Propagation for constraint referred indirectly from this pattern through «referredName» | ||
212 | find «referredName»(problem, interpretation, | ||
213 | «FOR index : 0..<referredPQuery.parameters.size SEPARATOR ", "»«positive.getVariableInTuple(index).canonizeName»«ENDFOR», | ||
214 | «FOR index : 1..c.arity SEPARATOR ", "»«canonizeName(index,pm)»«ENDFOR»); | ||
215 | ''' | ||
216 | } | ||
217 | // Otherwise, if the referred pattern is not satisfiable, this pattern is not satisfiable either | ||
218 | } | ||
219 | } | ||
220 | |||
221 | val negatives = body.constraints.filter(NegativePatternCall) | ||
222 | for(negative : negatives) { | ||
223 | val referredPQuery = negative.referredQuery | ||
224 | val referredRelation = (relation.eContainer as LogicProblem) | ||
225 | .annotations.filter(TransfomedViatraQuery).filter[it.patternPQuery === referredPQuery].head.target | ||
226 | if(allReferredConstraints(referredRelation,referredPQuery).toSet.contains(c)) { | ||
227 | val referredName = getOrGeneratePropagationRule(res,referredRelation,referredPQuery,c,pm,m3.dual) | ||
228 | if(referredName !== null) { | ||
229 | generatedBodies += ''' | ||
230 | // Original Constraints | ||
231 | «FOR constraint : body.constraints.filter[it !== negative]» | ||
232 | «this.constraintTransformer.transformConstraint(constraint,m3,relation.annotations.filter(TransfomedViatraQuery).head.variableTrace)» | ||
233 | «ENDFOR» | ||
234 | // Propagation for constraint referred indirectly from this pattern through «referredName» | ||
235 | find «referredName»(problem, interpretation, | ||
236 | «FOR index : 0..<referredPQuery.parameters.size SEPARATOR ", "»«(negative.actualParametersTuple.get(index) as PVariable).canonizeName»«ENDFOR», | ||
237 | «FOR index : 1..c.arity SEPARATOR ", "»«canonizeName(index,pm)»«ENDFOR»); | ||
238 | ''' | ||
239 | } else { | ||
240 | generatedBodies += ''' | ||
241 | // Original Constraints | ||
242 | «FOR constraint : body.constraints.filter[it !== negative]» | ||
243 | «this.constraintTransformer.transformConstraint(constraint,m3,relation.annotations.filter(TransfomedViatraQuery).head.variableTrace)» | ||
244 | «ENDFOR» | ||
245 | // Propagation for constraint referred indirectly from this pattern through «referredName», | ||
246 | // which was unsatisfiable | ||
247 | ''' | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | |||
254 | // Register the result | ||
255 | if(generatedBodies.empty) { | ||
256 | res.registerUnsatQuery(q,c,pm,m3) | ||
257 | } else { | ||
258 | val definition = ''' | ||
259 | private pattern «name»( | ||
260 | problem:LogicProblem, interpretation:PartialInterpretation, | ||
261 | «FOR param : q.parameters SEPARATOR ', '»var_«param.name»«ENDFOR», | ||
262 | «FOR arity : 1..constraintArity SEPARATOR ', '»«canonizeName(arity,pm)»«ENDFOR») | ||
263 | «FOR generatedBody: generatedBodies SEPARATOR " or "»{ | ||
264 | «generatedBody» | ||
265 | }«ENDFOR» | ||
266 | ''' | ||
267 | res.registerQuery(q,c,pm,m3,name,definition) | ||
268 | } | ||
269 | } | ||
270 | |||
271 | private def String relationDefinitionName(UnitPropagationPreconditionGenerationResult res, Relation relation, PQuery q, PConstraint c, PropagationModality pm, Modality m3) | ||
272 | '''«pm.name»«m3.name»Propagate«res.getOrGenerateConstraintName(c)»_«base.canonizeName(relation.name)»''' | ||
273 | |||
274 | def canonizeName(PVariable v) { | ||
275 | return '''«IF v.referringConstraints.size == 1»_«ENDIF»var_«v.name.replaceAll("\\W","")»''' | ||
276 | } | ||
277 | |||
278 | def canonizeName(int index, PropagationModality m) { | ||
279 | return '''«m.name.toLowerCase»_«index»''' | ||
280 | } | ||
281 | |||
282 | def dispatch propagateVariables(ExpressionEvaluation c, PropagationModality m) { | ||
283 | val comparator = new Comparator<PVariable>(){ | ||
284 | override compare(PVariable o1, PVariable o2) { | ||
285 | o1.name.compareTo(o2.name) | ||
286 | } | ||
287 | } | ||
288 | val variablesInOrder = new ArrayList(c.affectedVariables) | ||
289 | variablesInOrder.toList.sort(comparator) | ||
290 | return '''«FOR variableIndex : 1..variablesInOrder.size»«variablesInOrder.get(variableIndex-1).canonizeName»==«canonizeName(variableIndex,m)»;«ENDFOR»''' | ||
291 | } | ||
292 | def dispatch propagateVariables(PConstraint c, PropagationModality m) { | ||
293 | throw new UnsupportedOperationException('''Constraint not supported: «c.class.simpleName»''') | ||
294 | } | ||
295 | |||
296 | def dispatch arity(ExpressionEvaluation c) { | ||
297 | c.affectedVariables.size | ||
298 | } | ||
299 | def dispatch arity(PConstraint c) { | ||
300 | throw new UnsupportedOperationException('''Constraint not supported: «c.class.simpleName»''') | ||
301 | } | ||
302 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/GoalConstraintProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/GoalConstraintProvider.xtend index e1be2742..732c135d 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/GoalConstraintProvider.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/GoalConstraintProvider.xtend | |||
@@ -1,18 +1,89 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules |
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.MultiplicityGoalConstraintCalculator | 3 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion |
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns | 8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns |
5 | import java.util.ArrayList | 9 | import java.util.ArrayList |
10 | import java.util.HashMap | ||
11 | import java.util.LinkedList | ||
12 | import java.util.List | ||
13 | import java.util.Map | ||
6 | 14 | ||
7 | class GoalConstraintProvider { | 15 | class GoalConstraintProvider { |
8 | def public getUnfinishedMultiplicityQueries(GeneratedPatterns patterns) { | 16 | |
9 | val multiplicityQueries = patterns.unfinishedMulticiplicityQueries | 17 | def getUnfinishedMultiplicityQueries(LogicProblem p, GeneratedPatterns patterns, boolean calculateObjectCost) { |
10 | val res = new ArrayList(multiplicityQueries.size) | 18 | val objectCosts = if (calculateObjectCost) { |
11 | for(multiplicityQuery : multiplicityQueries.entrySet) { | 19 | calculateMissingObjectCost(p) |
12 | val targetRelationName = multiplicityQuery.key.name | 20 | } else { |
13 | val query = multiplicityQuery.value | 21 | emptyMap |
14 | res += new MultiplicityGoalConstraintCalculator(targetRelationName,query); | 22 | } |
23 | val res = new ArrayList() | ||
24 | for (entry : patterns.multiplicityConstraintQueries.entrySet) { | ||
25 | val constraint = entry.key | ||
26 | if (constraint.constrainsUnfinished) { | ||
27 | val queries = entry.value | ||
28 | val targetRelationName = constraint.relation.name | ||
29 | val query = queries.existingMultiplicityQuery | ||
30 | val containment = constraint.containment | ||
31 | val lowerBound = constraint.lowerBound | ||
32 | val cost = objectCosts.getOrDefault(constraint.relation, 1) | ||
33 | res += new MultiplicityGoalConstraintCalculator( | ||
34 | targetRelationName, | ||
35 | query, | ||
36 | containment, | ||
37 | lowerBound, | ||
38 | cost | ||
39 | ) | ||
40 | } | ||
15 | } | 41 | } |
16 | return res | 42 | return res |
17 | } | 43 | } |
18 | } \ No newline at end of file | 44 | |
45 | private def calculateMissingObjectCost(LogicProblem p) { | ||
46 | val containments = p.containmentHierarchies.head.containmentRelations | ||
47 | val containment2Lower = containments.toInvertedMap [ containment | | ||
48 | val lower = p.annotations.filter(LowerMultiplicityAssertion).filter[it.relation === containment].head | ||
49 | if (lower !== null) { | ||
50 | lower.lower | ||
51 | } else { | ||
52 | 0 | ||
53 | } | ||
54 | ] | ||
55 | val types = p.types | ||
56 | val Map<Type, List<? extends Pair<Type, Integer>>> type2NewCost = new HashMap | ||
57 | for (type : types) { | ||
58 | val allSupertypes = (#[type] + type.supertypes).toSet | ||
59 | val allOutgoingContainments = containments.filter [ | ||
60 | allSupertypes.contains((it.parameters.get(0) as ComplexTypeReference).referred) | ||
61 | ] | ||
62 | val list = new LinkedList | ||
63 | for (outgoingContainment : allOutgoingContainments) { | ||
64 | val value = containment2Lower.get(outgoingContainment) | ||
65 | if (value > 0) { | ||
66 | list.add((outgoingContainment.parameters.get(1) as ComplexTypeReference).referred -> value) | ||
67 | } | ||
68 | } | ||
69 | type2NewCost.put(type, list) | ||
70 | } | ||
71 | val res = new HashMap | ||
72 | for (containment : containments) { | ||
73 | val key = containment | ||
74 | val value = (containment.parameters.get(1) as ComplexTypeReference).referred.count(type2NewCost) | ||
75 | // println('''«key.name» --> «value» new''') | ||
76 | res.put(key, value) | ||
77 | } | ||
78 | return res | ||
79 | } | ||
80 | |||
81 | private def int count(Type t, Map<Type, List<? extends Pair<Type, Integer>>> containments) { | ||
82 | val list = containments.get(t) | ||
83 | var r = 1 | ||
84 | for (element : list) { | ||
85 | r += element.value * element.key.count(containments) | ||
86 | } | ||
87 | return r | ||
88 | } | ||
89 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/RefinementRuleProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/RefinementRuleProvider.xtend index 20d24b77..dca10baf 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/RefinementRuleProvider.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/RefinementRuleProvider.xtend | |||
@@ -1,226 +1,743 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules |
2 | 2 | ||
3 | import com.google.common.collect.ImmutableList | ||
4 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion | ||
5 | import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference | ||
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | ||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement | 8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement |
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.LogiclanguageFactory | 10 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.LogiclanguageFactory |
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.PrimitiveTypeReference | ||
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | 13 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | 14 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration |
15 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference | ||
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | 16 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type |
17 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics | 18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics |
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator | 19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator |
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns | 20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns |
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ObjectCreationPrecondition | 21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ObjectCreationPrecondition |
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialBooleanInterpretation | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | 23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation |
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialIntegerInterpretation | ||
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRealInterpretation | ||
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation | 27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation |
28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialStringInterpretation | ||
29 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationFactory | 30 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationFactory |
31 | import java.lang.reflect.Field | ||
32 | import java.util.HashMap | ||
33 | import java.util.Iterator | ||
16 | import java.util.LinkedHashMap | 34 | import java.util.LinkedHashMap |
35 | import java.util.LinkedList | ||
36 | import java.util.List | ||
37 | import java.util.Map | ||
38 | import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine | ||
17 | import org.eclipse.viatra.query.runtime.api.GenericPatternMatch | 39 | import org.eclipse.viatra.query.runtime.api.GenericPatternMatch |
40 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
18 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | 41 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification |
42 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
19 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | 43 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher |
44 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
45 | import org.eclipse.viatra.query.runtime.rete.matcher.ReteBackendFactory | ||
20 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule | 46 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule |
21 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRuleFactory | 47 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRuleFactory |
48 | import org.eclipse.xtend.lib.annotations.Data | ||
49 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
50 | import org.eclipse.xtext.xbase.lib.Functions.Function0 | ||
22 | 51 | ||
23 | class RefinementRuleProvider { | 52 | class RefinementRuleProvider { |
24 | private extension BatchTransformationRuleFactory factory = new BatchTransformationRuleFactory | 53 | val extension BatchTransformationRuleFactory factory = new BatchTransformationRuleFactory |
25 | private extension PartialinterpretationFactory factory2 = PartialinterpretationFactory.eINSTANCE | 54 | val extension PartialinterpretationFactory factory2 = PartialinterpretationFactory.eINSTANCE |
26 | private extension LogiclanguageFactory factory3 = LogiclanguageFactory.eINSTANCE | 55 | val extension LogiclanguageFactory factory3 = LogiclanguageFactory.eINSTANCE |
27 | 56 | ||
28 | def canonizeName(String name) { | 57 | def canonizeName(String name) { |
29 | return name.replace(' ','_') | 58 | return name.replace(' ', '_') |
30 | } | 59 | } |
31 | 60 | ||
32 | def LinkedHashMap<ObjectCreationPrecondition, BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>>> | 61 | def createUnitPrulePropagator(LogicProblem p, PartialInterpretation i, GeneratedPatterns patterns, |
33 | createObjectRefinementRules( | 62 | ScopePropagator scopePropagator, ModelGenerationStatistics statistics) { |
34 | GeneratedPatterns patterns, | 63 | new UnitRulePropagator(p, i, this, scopePropagator, patterns.mustRelationPropagationQueries, statistics) |
35 | ScopePropagator scopePropagator, | 64 | } |
36 | boolean nameNewElement, | 65 | |
37 | ModelGenerationStatistics statistics | 66 | def LinkedHashMap<ObjectCreationPrecondition, BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>>> createObjectRefinementRules( |
38 | ) | 67 | LogicProblem p, |
39 | { | 68 | PartialInterpretation i, |
69 | GeneratedPatterns patterns, | ||
70 | UnitRulePropagator unitRulePropagator, | ||
71 | boolean nameNewElement, | ||
72 | ModelGenerationStatistics statistics | ||
73 | ) { | ||
40 | val res = new LinkedHashMap | 74 | val res = new LinkedHashMap |
41 | for(LHSEntry: patterns.refineObjectQueries.entrySet) { | 75 | val recursiveObjectCreation = recursiveObjectCreation(p, i) |
76 | for (LHSEntry : patterns.refineObjectQueries.entrySet) { | ||
42 | val containmentRelation = LHSEntry.key.containmentRelation | 77 | val containmentRelation = LHSEntry.key.containmentRelation |
43 | val inverseRelation = LHSEntry.key.inverseContainment | 78 | val inverseRelation = LHSEntry.key.inverseContainment |
44 | val type = LHSEntry.key.newType | 79 | val type = LHSEntry.key.newType |
45 | val lhs = LHSEntry.value as IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> | 80 | val lhs = LHSEntry.value as IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> |
46 | val rule = createObjectCreationRule(containmentRelation,inverseRelation,type,lhs,nameNewElement,scopePropagator,statistics) | 81 | val rule = createObjectCreationRule(p, containmentRelation, inverseRelation, type, |
47 | res.put(LHSEntry.key,rule) | 82 | recursiveObjectCreation.get(type), lhs, nameNewElement, unitRulePropagator, statistics) |
83 | res.put(LHSEntry.key, rule) | ||
48 | } | 84 | } |
49 | return res | 85 | return res |
50 | } | 86 | } |
51 | 87 | ||
52 | def private createObjectCreationRule( | 88 | def private createObjectCreationRule(LogicProblem p, Relation containmentRelation, Relation inverseRelation, |
53 | Relation containmentRelation, | 89 | Type type, List<ObjectCreationInterpretationData> recursiveObjectCreations, |
54 | Relation inverseRelation, | 90 | IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> lhs, boolean nameNewElement, |
55 | Type type, | 91 | UnitRulePropagator unitRulePropagator, ModelGenerationStatistics statistics) { |
56 | IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> lhs, | 92 | val name = '''addObject_«type.name.canonizeName»«IF containmentRelation!==null»_by_«containmentRelation.name.canonizeName»«ENDIF»''' |
57 | boolean nameNewElement, | 93 | val ruleBuilder = factory.createRule(lhs).name(name) |
58 | ScopePropagator scopePropagator, | 94 | if (containmentRelation !== null) { |
59 | ModelGenerationStatistics statistics) | 95 | if (inverseRelation !== null) { |
60 | { | 96 | ruleBuilder.action [ match | |
61 | val name = '''addObject_«type.name.canonizeName»« | 97 | statistics.incrementTransformationCount |
62 | IF containmentRelation!=null»_by_«containmentRelation.name.canonizeName»«ENDIF»''' | 98 | // println(name) |
63 | //println("Rule created: " + name + "> " + lhs.fullyQualifiedName) | ||
64 | val ruleBuilder = factory.createRule | ||
65 | .name(name) | ||
66 | .precondition(lhs) | ||
67 | if(containmentRelation != null) { | ||
68 | if(inverseRelation!= null) { | ||
69 | ruleBuilder.action[match | | ||
70 | //println(name) | ||
71 | val startTime = System.nanoTime | 99 | val startTime = System.nanoTime |
72 | //val problem = match.get(0) as LogicProblem | 100 | // val problem = match.get(0) as LogicProblem |
73 | val interpretation = match.get(1) as PartialInterpretation | 101 | val interpretation = match.get(1) as PartialInterpretation |
74 | val relationInterpretation = match.get(2) as PartialRelationInterpretation | 102 | val relationInterpretation = match.get(2) as PartialRelationInterpretation |
75 | val inverseRelationInterpretation = match.get(3) as PartialRelationInterpretation | 103 | val inverseRelationInterpretation = match.get(3) as PartialRelationInterpretation |
76 | val typeInterpretation = match.get(4) as PartialComplexTypeInterpretation | 104 | val typeInterpretation = match.get(4) as PartialComplexTypeInterpretation |
77 | val container = match.get(5) as DefinedElement | 105 | val container = match.get(5) as DefinedElement |
78 | 106 | createObjectActionWithContainmentAndInverse( | |
79 | val newElement = createDefinedElement | 107 | nameNewElement, |
80 | if(nameNewElement) { | 108 | interpretation, |
81 | newElement.name = '''new «interpretation.newElements.size»''' | 109 | typeInterpretation, |
82 | } | 110 | container, |
83 | 111 | relationInterpretation, | |
84 | // Existence | 112 | inverseRelationInterpretation, |
85 | interpretation.newElements+=newElement | 113 | [createDefinedElement], |
86 | /*interpretation.maxNewElements=interpretation.maxNewElements-1 | 114 | recursiveObjectCreations, |
87 | if(interpretation.minNewElements > 0) { | 115 | unitRulePropagator |
88 | interpretation.minNewElements=interpretation.minNewElements-1 | 116 | ) |
89 | }*/ | 117 | statistics.addExecutionTime(System.nanoTime - startTime) |
90 | 118 | ||
91 | // Types | 119 | unitRulePropagator.propagate |
92 | typeInterpretation.elements += newElement | ||
93 | typeInterpretation.supertypeInterpretation.forEach[it.elements += newElement] | ||
94 | // ContainmentRelation | ||
95 | val newLink1 = factory2.createBinaryElementRelationLink => [it.param1 = container it.param2 = newElement] | ||
96 | relationInterpretation.relationlinks+=newLink1 | ||
97 | // Inverse Containment | ||
98 | val newLink2 = factory2.createBinaryElementRelationLink => [it.param1 = newElement it.param2 = container] | ||
99 | inverseRelationInterpretation.relationlinks+=newLink2 | ||
100 | |||
101 | // Scope propagation | ||
102 | scopePropagator.propagateAdditionToType(typeInterpretation) | ||
103 | |||
104 | statistics.addExecutionTime(System.nanoTime-startTime) | ||
105 | ] | 120 | ] |
106 | } else { | 121 | } else { |
107 | ruleBuilder.action[match | | 122 | ruleBuilder.action [ match | |
108 | //println(name) | 123 | statistics.incrementTransformationCount |
124 | // println(name) | ||
109 | val startTime = System.nanoTime | 125 | val startTime = System.nanoTime |
110 | //val problem = match.get(0) as LogicProblem | 126 | // val problem = match.get(0) as LogicProblem |
111 | val interpretation = match.get(1) as PartialInterpretation | 127 | val interpretation = match.get(1) as PartialInterpretation |
112 | val relationInterpretation = match.get(2) as PartialRelationInterpretation | 128 | val relationInterpretation = match.get(2) as PartialRelationInterpretation |
113 | val typeInterpretation = match.get(3) as PartialComplexTypeInterpretation | 129 | val typeInterpretation = match.get(3) as PartialComplexTypeInterpretation |
114 | val container = match.get(4) as DefinedElement | 130 | val container = match.get(4) as DefinedElement |
115 | 131 | ||
116 | val newElement = createDefinedElement | 132 | createObjectActionWithContainment( |
117 | if(nameNewElement) { | 133 | nameNewElement, |
118 | newElement.name = '''new «interpretation.newElements.size»''' | 134 | interpretation, |
119 | } | 135 | typeInterpretation, |
120 | 136 | container, | |
121 | // Existence | 137 | relationInterpretation, |
122 | interpretation.newElements+=newElement | 138 | [createDefinedElement], |
123 | /*interpretation.maxNewElements=interpretation.maxNewElements-1 | 139 | recursiveObjectCreations, |
124 | if(interpretation.minNewElements > 0) { | 140 | unitRulePropagator |
125 | interpretation.minNewElements=interpretation.minNewElements-1 | 141 | ) |
126 | }*/ | 142 | statistics.addExecutionTime(System.nanoTime - startTime) |
127 | 143 | ||
128 | // Types | 144 | unitRulePropagator.propagate |
129 | typeInterpretation.elements += newElement | ||
130 | typeInterpretation.supertypeInterpretation.forEach[it.elements += newElement] | ||
131 | // ContainmentRelation | ||
132 | val newLink = factory2.createBinaryElementRelationLink => [it.param1 = container it.param2 = newElement] | ||
133 | relationInterpretation.relationlinks+=newLink | ||
134 | |||
135 | // Scope propagation | ||
136 | scopePropagator.propagateAdditionToType(typeInterpretation) | ||
137 | |||
138 | statistics.addExecutionTime(System.nanoTime-startTime) | ||
139 | ] | 145 | ] |
140 | } | 146 | } |
141 | } else { | 147 | } else { |
142 | ruleBuilder.action[match | | 148 | ruleBuilder.action [ match | |
149 | statistics.incrementTransformationCount | ||
150 | // println(name) | ||
143 | val startTime = System.nanoTime | 151 | val startTime = System.nanoTime |
144 | //val problem = match.get(0) as LogicProblem | 152 | // val problem = match.get(0) as LogicProblem |
145 | val interpretation = match.get(1) as PartialInterpretation | 153 | val interpretation = match.get(1) as PartialInterpretation |
146 | val typeInterpretation = match.get(2) as PartialComplexTypeInterpretation | 154 | val typeInterpretation = match.get(2) as PartialComplexTypeInterpretation |
147 | 155 | ||
148 | val newElement = createDefinedElement | 156 | createObjectAction( |
149 | if(nameNewElement) { | 157 | nameNewElement, |
150 | newElement.name = '''new «interpretation.newElements.size»''' | 158 | interpretation, |
151 | } | 159 | typeInterpretation, |
152 | 160 | [createDefinedElement], | |
153 | // Existence | 161 | recursiveObjectCreations, |
154 | interpretation.newElements+=newElement | 162 | unitRulePropagator |
155 | /* | 163 | ) |
156 | interpretation.maxNewElements=interpretation.maxNewElements-1 | 164 | statistics.addExecutionTime(System.nanoTime - startTime) |
157 | if(interpretation.minNewElements > 0) { | 165 | |
158 | interpretation.minNewElements=interpretation.minNewElements-1 | 166 | unitRulePropagator.propagate |
159 | }*/ | ||
160 | |||
161 | // Types | ||
162 | typeInterpretation.elements += newElement | ||
163 | typeInterpretation.supertypeInterpretation.forEach[it.elements += newElement] | ||
164 | |||
165 | // Scope propagation | ||
166 | scopePropagator.propagateAdditionToType(typeInterpretation) | ||
167 | |||
168 | statistics.addExecutionTime(System.nanoTime-startTime) | ||
169 | ] | 167 | ] |
170 | } | 168 | } |
171 | return ruleBuilder.build | 169 | return ruleBuilder.build |
172 | } | 170 | } |
173 | 171 | ||
174 | def createRelationRefinementRules(GeneratedPatterns patterns, ModelGenerationStatistics statistics) { | 172 | def private recursiveObjectCreation(LogicProblem p, PartialInterpretation i) { |
173 | val Map<Type, List<ObjectCreationInterpretationData>> recursiveObjectCreation = new HashMap | ||
174 | for (type : p.types) { | ||
175 | recursiveObjectCreation.put(type, new LinkedList) | ||
176 | } | ||
177 | |||
178 | val containmentReferences = p.containmentHierarchies.head.containmentRelations | ||
179 | |||
180 | for (relationInterpretation : i.partialrelationinterpretation) { | ||
181 | val relation = relationInterpretation.interpretationOf | ||
182 | val lowermultiplicities = p.annotations.filter(LowerMultiplicityAssertion).filter[it.relation === relation] | ||
183 | if ((!lowermultiplicities.empty)) { | ||
184 | val number = lowermultiplicities.head.lower | ||
185 | if (number > 0) { | ||
186 | val sourceTypeInterpretation = getTypeInterpretation(i, relation, | ||
187 | 0) as PartialComplexTypeInterpretation | ||
188 | val subtypeInterpretations = i.partialtypeinterpratation.filter(PartialComplexTypeInterpretation). | ||
189 | filter [ | ||
190 | it === sourceTypeInterpretation || | ||
191 | it.supertypeInterpretation.contains(sourceTypeInterpretation) | ||
192 | ] | ||
193 | |||
194 | if (containmentReferences.contains(relation)) { | ||
195 | val targetTypeInterpretation = getTypeInterpretation(i, relation, 1) | ||
196 | val targetType = (targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf | ||
197 | if ((!targetType.isIsAbstract) && (targetType.supertypes.empty)) { | ||
198 | val inverseAnnotation = p.annotations.filter(InverseRelationAssertion).filter [ | ||
199 | it.inverseA === relation || it.inverseB === relation | ||
200 | ] | ||
201 | if (!inverseAnnotation.empty) { | ||
202 | val onlyInverseAnnotation = if (inverseAnnotation.head.inverseA === relation) { | ||
203 | inverseAnnotation.head.inverseB | ||
204 | } else { | ||
205 | inverseAnnotation.head.inverseA | ||
206 | } | ||
207 | val inverseRelationInterpretation = i.partialrelationinterpretation.filter [ | ||
208 | it.interpretationOf === onlyInverseAnnotation | ||
209 | ].head | ||
210 | for (subTypeInterpretation : subtypeInterpretations) { | ||
211 | for (var times = 0; times < number; times++) { | ||
212 | recursiveObjectCreation.get(subTypeInterpretation.interpretationOf) += | ||
213 | new ObjectCreationInterpretationData( | ||
214 | i, | ||
215 | targetTypeInterpretation, | ||
216 | relationInterpretation, | ||
217 | inverseRelationInterpretation, | ||
218 | targetTypeInterpretation.getTypeConstructor | ||
219 | ) | ||
220 | } | ||
221 | } | ||
222 | } else { | ||
223 | for (subTypeInterpretation : subtypeInterpretations) { | ||
224 | for (var times = 0; times < number; times++) { | ||
225 | recursiveObjectCreation.get(subTypeInterpretation.interpretationOf) += | ||
226 | new ObjectCreationInterpretationData( | ||
227 | i, | ||
228 | targetTypeInterpretation, | ||
229 | relationInterpretation, | ||
230 | null, | ||
231 | targetTypeInterpretation.getTypeConstructor | ||
232 | ) | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | } else if (relation.parameters.get(1) instanceof PrimitiveTypeReference) { | ||
238 | val targetTypeInterpretation = getTypeInterpretation(i, relation, 1) | ||
239 | for (subTypeInterpretation : subtypeInterpretations) { | ||
240 | for (var times = 0; times < number; times++) { | ||
241 | recursiveObjectCreation.get(subTypeInterpretation.interpretationOf) += | ||
242 | new ObjectCreationInterpretationData( | ||
243 | i, | ||
244 | targetTypeInterpretation, | ||
245 | relationInterpretation, | ||
246 | null, | ||
247 | targetTypeInterpretation.getTypeConstructor | ||
248 | ) | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | } | ||
255 | |||
256 | // Doing the recursion | ||
257 | var objectCreations = new LinkedList(recursiveObjectCreation.values.flatten.toList) | ||
258 | for (objectCreation : objectCreations) { | ||
259 | val newInterpretation = objectCreation.typeInterpretation | ||
260 | if (newInterpretation instanceof PartialComplexTypeInterpretation) { | ||
261 | val newlyCreatedType = newInterpretation.interpretationOf | ||
262 | if (recursiveObjectCreation.containsKey(newlyCreatedType)) { | ||
263 | val actionsWhenTypeCreated = recursiveObjectCreation.get(newlyCreatedType) | ||
264 | objectCreation.recursiveConstructors += actionsWhenTypeCreated | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | |||
269 | // checking acyclicity | ||
270 | for (objectCreation : objectCreations) { | ||
271 | var reachable = objectCreation.recursiveConstructors | ||
272 | do { | ||
273 | if (reachable.contains(objectCreation)) { | ||
274 | throw new IllegalArgumentException('''Cicrle in the containment!''') | ||
275 | } else { | ||
276 | reachable = reachable.map[it.recursiveConstructors].flatten.toList | ||
277 | } | ||
278 | } while (!reachable.empty) | ||
279 | } | ||
280 | |||
281 | return recursiveObjectCreation | ||
282 | } | ||
283 | |||
284 | private def getTypeInterpretation(PartialInterpretation i, RelationDeclaration relation, int index) { | ||
285 | val typeReference = relation.parameters.get(index) | ||
286 | return getTypeInterpretation(i, typeReference) | ||
287 | |||
288 | } | ||
289 | |||
290 | private dispatch def getTypeInterpretation(PartialInterpretation i, ComplexTypeReference reference) { | ||
291 | return i.partialtypeinterpratation.filter(PartialComplexTypeInterpretation).filter [ | ||
292 | it.getInterpretationOf == reference.referred | ||
293 | ].head | ||
294 | } | ||
295 | |||
296 | private dispatch def getTypeInterpretation(PartialInterpretation i, BoolTypeReference reference) { | ||
297 | return i.partialtypeinterpratation.filter(PartialBooleanInterpretation).head | ||
298 | } | ||
299 | |||
300 | private dispatch def getTypeInterpretation(PartialInterpretation i, IntTypeReference reference) { | ||
301 | return i.partialtypeinterpratation.filter(PartialIntegerInterpretation).head | ||
302 | } | ||
303 | |||
304 | private dispatch def getTypeInterpretation(PartialInterpretation i, RealTypeReference reference) { | ||
305 | return i.partialtypeinterpratation.filter(PartialRealInterpretation).head | ||
306 | } | ||
307 | |||
308 | private dispatch def getTypeInterpretation(PartialInterpretation i, StringTypeReference reference) { | ||
309 | return i.partialtypeinterpratation.filter(PartialStringInterpretation).head | ||
310 | } | ||
311 | |||
312 | private dispatch def Function0<DefinedElement> getTypeConstructor(PartialComplexTypeInterpretation reference) { | ||
313 | [createDefinedElement] | ||
314 | } | ||
315 | |||
316 | private dispatch def Function0<DefinedElement> getTypeConstructor(PartialBooleanInterpretation reference) { | ||
317 | [createBooleanElement] | ||
318 | } | ||
319 | |||
320 | private dispatch def Function0<DefinedElement> getTypeConstructor(PartialIntegerInterpretation reference) { | ||
321 | [createIntegerElement] | ||
322 | } | ||
323 | |||
324 | private dispatch def Function0<DefinedElement> getTypeConstructor(PartialRealInterpretation reference) { | ||
325 | [createRealElement] | ||
326 | } | ||
327 | |||
328 | private dispatch def Function0<DefinedElement> getTypeConstructor(PartialStringInterpretation reference) { | ||
329 | [createStringElement] | ||
330 | } | ||
331 | |||
332 | def createRelationRefinementRules(GeneratedPatterns patterns, UnitRulePropagator unitRulePropagator, | ||
333 | ModelGenerationStatistics statistics) { | ||
175 | val res = new LinkedHashMap | 334 | val res = new LinkedHashMap |
176 | for(LHSEntry: patterns.refinerelationQueries.entrySet) { | 335 | for (LHSEntry : patterns.refineRelationQueries.entrySet) { |
177 | val declaration = LHSEntry.key.key | 336 | val declaration = LHSEntry.key.key |
178 | val inverseReference = LHSEntry.key.value | 337 | val inverseReference = LHSEntry.key.value |
179 | val lhs = LHSEntry.value as IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> | 338 | val lhs = LHSEntry.value as IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> |
180 | val rule = createRelationRefinementRule(declaration,inverseReference,lhs,statistics) | 339 | val rule = createRelationRefinementRule(declaration, inverseReference, lhs, unitRulePropagator, statistics) |
181 | res.put(LHSEntry.key,rule) | 340 | res.put(LHSEntry.key, rule) |
182 | } | 341 | } |
183 | return res | 342 | return res |
184 | } | 343 | } |
185 | 344 | ||
186 | def private BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>> | 345 | def private BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>> createRelationRefinementRule( |
187 | createRelationRefinementRule(RelationDeclaration declaration, Relation inverseRelation, IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> lhs, ModelGenerationStatistics statistics) | 346 | RelationDeclaration declaration, Relation inverseRelation, |
188 | { | 347 | IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> lhs, UnitRulePropagator unitRulePropagator, |
189 | val name = '''addRelation_«declaration.name.canonizeName»«IF inverseRelation != null»_and_«inverseRelation.name.canonizeName»«ENDIF»''' | 348 | ModelGenerationStatistics statistics) { |
190 | val ruleBuilder = factory.createRule | 349 | val name = '''addRelation_«declaration.name.canonizeName»«IF inverseRelation !== null»_and_«inverseRelation.name.canonizeName»«ENDIF»''' |
191 | .name(name) | 350 | val ruleBuilder = factory.createRule(lhs).name(name) |
192 | .precondition(lhs) | 351 | if (inverseRelation === null) { |
193 | if (inverseRelation == null) { | ||
194 | ruleBuilder.action [ match | | 352 | ruleBuilder.action [ match | |
195 | val startTime = System.nanoTime | 353 | statistics.incrementTransformationCount |
196 | //println(name) | 354 | // println(name) |
197 | // val problem = match.get(0) as LogicProblem | 355 | val startTime = System.nanoTime |
198 | // val interpretation = match.get(1) as PartialInterpretation | 356 | createRelationLinkAction(match, unitRulePropagator) |
199 | val relationInterpretation = match.get(2) as PartialRelationInterpretation | 357 | statistics.addExecutionTime(System.nanoTime - startTime) |
200 | val src = match.get(3) as DefinedElement | 358 | |
201 | val trg = match.get(4) as DefinedElement | 359 | unitRulePropagator.propagate |
202 | val link = createBinaryElementRelationLink => [it.param1 = src it.param2 = trg] | ||
203 | relationInterpretation.relationlinks += link | ||
204 | statistics.addExecutionTime(System.nanoTime-startTime) | ||
205 | ] | 360 | ] |
206 | } else { | 361 | } else { |
207 | ruleBuilder.action [ match | | 362 | ruleBuilder.action [ match | |
208 | val startTime = System.nanoTime | 363 | statistics.incrementTransformationCount |
209 | //println(name) | 364 | // println(name) |
210 | // val problem = match.get(0) as LogicProblem | 365 | val startTime = System.nanoTime |
211 | // val interpretation = match.get(1) as PartialInterpretation | 366 | createRelationLinkWithInverse(match, unitRulePropagator) |
212 | val relationInterpretation = match.get(2) as PartialRelationInterpretation | 367 | statistics.addExecutionTime(System.nanoTime - startTime) |
213 | val inverseInterpretation = match.get(3) as PartialRelationInterpretation | 368 | |
214 | val src = match.get(4) as DefinedElement | 369 | unitRulePropagator.propagate |
215 | val trg = match.get(5) as DefinedElement | ||
216 | val link = createBinaryElementRelationLink => [it.param1 = src it.param2 = trg] | ||
217 | relationInterpretation.relationlinks += link | ||
218 | val inverseLink = createBinaryElementRelationLink => [it.param1 = trg it.param2 = src] | ||
219 | inverseInterpretation.relationlinks += inverseLink | ||
220 | statistics.addExecutionTime(System.nanoTime-startTime) | ||
221 | ] | 370 | ] |
222 | } | 371 | } |
223 | 372 | ||
224 | return ruleBuilder.build | 373 | return ruleBuilder.build |
225 | } | 374 | } |
375 | |||
376 | // /////////////////////// | ||
377 | // Actions | ||
378 | // /////////////////////// | ||
379 | protected def void createObjectAction(boolean nameNewElement, ObjectCreationInterpretationData data, | ||
380 | DefinedElement container, UnitRulePropagator unitRulePropagator) { | ||
381 | if (data.containerInterpretation !== null) { | ||
382 | if (data.containerInverseInterpretation !== null) { | ||
383 | createObjectActionWithContainmentAndInverse( | ||
384 | nameNewElement, | ||
385 | data.interpretation, | ||
386 | data.typeInterpretation, | ||
387 | container, | ||
388 | data.containerInterpretation, | ||
389 | data.containerInverseInterpretation, | ||
390 | data.constructor, | ||
391 | data.recursiveConstructors, | ||
392 | unitRulePropagator | ||
393 | ) | ||
394 | } else { | ||
395 | createObjectActionWithContainment( | ||
396 | nameNewElement, | ||
397 | data.interpretation, | ||
398 | data.typeInterpretation, | ||
399 | container, | ||
400 | data.containerInterpretation, | ||
401 | data.constructor, | ||
402 | data.recursiveConstructors, | ||
403 | unitRulePropagator | ||
404 | ) | ||
405 | } | ||
406 | } else { | ||
407 | createObjectAction( | ||
408 | nameNewElement, | ||
409 | data.interpretation, | ||
410 | data.typeInterpretation, | ||
411 | data.constructor, | ||
412 | data.recursiveConstructors, | ||
413 | unitRulePropagator | ||
414 | ) | ||
415 | } | ||
416 | |||
417 | } | ||
418 | |||
419 | protected def createObjectActionWithContainmentAndInverse( | ||
420 | boolean nameNewElement, | ||
421 | PartialInterpretation interpretation, | ||
422 | PartialTypeInterpratation typeInterpretation, | ||
423 | DefinedElement container, | ||
424 | PartialRelationInterpretation relationInterpretation, | ||
425 | PartialRelationInterpretation inverseRelationInterpretation, | ||
426 | Function0<DefinedElement> constructor, | ||
427 | List<ObjectCreationInterpretationData> recursiceObjectCreations, | ||
428 | UnitRulePropagator unitRulePropagator | ||
429 | ) { | ||
430 | val newElement = constructor.apply | ||
431 | if (nameNewElement) { | ||
432 | newElement.name = '''new «interpretation.newElements.size»''' | ||
433 | } | ||
434 | |||
435 | // Types | ||
436 | typeInterpretation.elements += newElement | ||
437 | if (typeInterpretation instanceof PartialComplexTypeInterpretation) { | ||
438 | typeInterpretation.supertypeInterpretation.forEach[it.elements += newElement] | ||
439 | } | ||
440 | // ContainmentRelation | ||
441 | val newLink1 = factory2.createBinaryElementRelationLink => [it.param1 = container it.param2 = newElement] | ||
442 | relationInterpretation.relationlinks += newLink1 | ||
443 | // Inverse Containment | ||
444 | val newLink2 = factory2.createBinaryElementRelationLink => [it.param1 = newElement it.param2 = container] | ||
445 | inverseRelationInterpretation.relationlinks += newLink2 | ||
446 | |||
447 | // Scope propagation | ||
448 | unitRulePropagator.decrementTypeScope(typeInterpretation) | ||
449 | unitRulePropagator.addedToRelation(relationInterpretation.interpretationOf) | ||
450 | unitRulePropagator.addedToRelation(inverseRelationInterpretation.interpretationOf) | ||
451 | |||
452 | // Existence | ||
453 | interpretation.newElements += newElement | ||
454 | |||
455 | // Do recursive object creation | ||
456 | for (newConstructor : recursiceObjectCreations) { | ||
457 | createObjectAction(nameNewElement, newConstructor, newElement, unitRulePropagator) | ||
458 | } | ||
459 | |||
460 | return newElement | ||
461 | } | ||
462 | |||
463 | protected def createObjectActionWithContainment( | ||
464 | boolean nameNewElement, | ||
465 | PartialInterpretation interpretation, | ||
466 | PartialTypeInterpratation typeInterpretation, | ||
467 | DefinedElement container, | ||
468 | PartialRelationInterpretation relationInterpretation, | ||
469 | Function0<DefinedElement> constructor, | ||
470 | List<ObjectCreationInterpretationData> recursiceObjectCreations, | ||
471 | UnitRulePropagator unitRulePropagator | ||
472 | ) { | ||
473 | val newElement = constructor.apply | ||
474 | if (nameNewElement) { | ||
475 | newElement.name = '''new «interpretation.newElements.size»''' | ||
476 | } | ||
477 | |||
478 | // Types | ||
479 | typeInterpretation.elements += newElement | ||
480 | if (typeInterpretation instanceof PartialComplexTypeInterpretation) { | ||
481 | typeInterpretation.supertypeInterpretation.forEach[it.elements += newElement] | ||
482 | } | ||
483 | // ContainmentRelation | ||
484 | val newLink = factory2.createBinaryElementRelationLink => [it.param1 = container it.param2 = newElement] | ||
485 | relationInterpretation.relationlinks += newLink | ||
486 | unitRulePropagator.addedToRelation(relationInterpretation.interpretationOf) | ||
487 | |||
488 | // Scope propagation | ||
489 | unitRulePropagator.decrementTypeScope(typeInterpretation) | ||
490 | |||
491 | // Existence | ||
492 | interpretation.newElements += newElement | ||
493 | |||
494 | // Do recursive object creation | ||
495 | for (newConstructor : recursiceObjectCreations) { | ||
496 | createObjectAction(nameNewElement, newConstructor, newElement, unitRulePropagator) | ||
497 | } | ||
498 | |||
499 | return newElement | ||
500 | } | ||
501 | |||
502 | protected def createObjectAction(boolean nameNewElement, PartialInterpretation interpretation, | ||
503 | PartialTypeInterpratation typeInterpretation, Function0<DefinedElement> constructor, | ||
504 | List<ObjectCreationInterpretationData> recursiceObjectCreations, UnitRulePropagator unitRulePropagator) { | ||
505 | val newElement = constructor.apply | ||
506 | if (nameNewElement) { | ||
507 | newElement.name = '''new «interpretation.newElements.size»''' | ||
508 | } | ||
509 | |||
510 | // Types | ||
511 | typeInterpretation.elements += newElement | ||
512 | if (typeInterpretation instanceof PartialComplexTypeInterpretation) { | ||
513 | typeInterpretation.supertypeInterpretation.forEach[it.elements += newElement] | ||
514 | } | ||
515 | |||
516 | // Scope propagation | ||
517 | unitRulePropagator.decrementTypeScope(typeInterpretation) | ||
518 | |||
519 | // Existence | ||
520 | interpretation.newElements += newElement | ||
521 | |||
522 | // Do recursive object creation | ||
523 | for (newConstructor : recursiceObjectCreations) { | ||
524 | createObjectAction(nameNewElement, newConstructor, newElement, unitRulePropagator) | ||
525 | } | ||
526 | |||
527 | return newElement | ||
528 | } | ||
529 | |||
530 | protected def createRelationLinkAction(IPatternMatch match, UnitRulePropagator unitRulePropagator) { | ||
531 | // val problem = match.get(0) as LogicProblem | ||
532 | // val interpretation = match.get(1) as PartialInterpretation | ||
533 | val relationInterpretation = match.get(2) as PartialRelationInterpretation | ||
534 | val src = match.get(3) as DefinedElement | ||
535 | val trg = match.get(4) as DefinedElement | ||
536 | createRelationLinkAction(src, trg, relationInterpretation, unitRulePropagator) | ||
537 | } | ||
538 | |||
539 | protected def void createRelationLinkAction(DefinedElement src, DefinedElement trg, | ||
540 | PartialRelationInterpretation relationInterpretation, UnitRulePropagator unitRulePropagator) { | ||
541 | val link = createBinaryElementRelationLink => [it.param1 = src it.param2 = trg] | ||
542 | relationInterpretation.relationlinks += link | ||
543 | unitRulePropagator.addedToRelation(relationInterpretation.interpretationOf) | ||
544 | } | ||
545 | |||
546 | protected def void createRelationLinkWithInverse(IPatternMatch match, UnitRulePropagator unitRulePropagator) { | ||
547 | // val problem = match.get(0) as LogicProblem | ||
548 | // val interpretation = match.get(1) as PartialInterpretation | ||
549 | val relationInterpretation = match.get(2) as PartialRelationInterpretation | ||
550 | val inverseInterpretation = match.get(3) as PartialRelationInterpretation | ||
551 | val src = match.get(4) as DefinedElement | ||
552 | val trg = match.get(5) as DefinedElement | ||
553 | createRelationLinkWithInverse(src, trg, relationInterpretation, inverseInterpretation, unitRulePropagator) | ||
554 | } | ||
555 | |||
556 | protected def void createRelationLinkWithInverse(DefinedElement src, DefinedElement trg, | ||
557 | PartialRelationInterpretation relationInterpretation, PartialRelationInterpretation inverseInterpretation, | ||
558 | UnitRulePropagator unitRulePropagator) { | ||
559 | val link = createBinaryElementRelationLink => [it.param1 = src it.param2 = trg] | ||
560 | relationInterpretation.relationlinks += link | ||
561 | val inverseLink = createBinaryElementRelationLink => [it.param1 = trg it.param2 = src] | ||
562 | inverseInterpretation.relationlinks += inverseLink | ||
563 | unitRulePropagator.addedToRelation(relationInterpretation.interpretationOf) | ||
564 | unitRulePropagator.addedToRelation(inverseInterpretation.interpretationOf) | ||
565 | } | ||
566 | |||
567 | static class UnitRulePropagator { | ||
568 | val LogicProblem p | ||
569 | val PartialInterpretation i | ||
570 | val RefinementRuleProvider refinementRuleProvider | ||
571 | var AdvancedViatraQueryEngine queryEngine | ||
572 | var Field delayMessageDelivery | ||
573 | val ScopePropagator scopePropagator | ||
574 | val List<AbstractMustRelationPropagator<? extends IPatternMatch>> propagators | ||
575 | val ModelGenerationStatistics statistics | ||
576 | |||
577 | new(LogicProblem p, PartialInterpretation i, RefinementRuleProvider refinementRuleProvider, | ||
578 | ScopePropagator scopePropagator, | ||
579 | Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> mustRelationPropagationQueries, | ||
580 | ModelGenerationStatistics statistics) { | ||
581 | this.p = p | ||
582 | this.i = i | ||
583 | this.refinementRuleProvider = refinementRuleProvider | ||
584 | queryEngine = ViatraQueryEngine.on(new EMFScope(i)) as AdvancedViatraQueryEngine | ||
585 | delayMessageDelivery = queryEngine.class.getDeclaredField("delayMessageDelivery") | ||
586 | delayMessageDelivery.accessible = true | ||
587 | this.scopePropagator = scopePropagator | ||
588 | propagators = ImmutableList.copyOf(mustRelationPropagationQueries.entrySet.map [ entry | | ||
589 | val matcher = queryEngine.getMatcher(entry.value) | ||
590 | getPropagator(entry.key.key, entry.key.value, matcher) | ||
591 | ]) | ||
592 | this.statistics = statistics | ||
593 | } | ||
594 | |||
595 | def decrementTypeScope(PartialTypeInterpratation partialTypeInterpratation) { | ||
596 | scopePropagator.decrementTypeScope(partialTypeInterpratation) | ||
597 | } | ||
598 | |||
599 | def addedToRelation(Relation r) { | ||
600 | scopePropagator.addedToRelation(r) | ||
601 | } | ||
602 | |||
603 | def propagate() { | ||
604 | var boolean changed | ||
605 | do { | ||
606 | val scopeChanged = propagateScope() | ||
607 | val mustChanged = propagateMustRelations() | ||
608 | changed = scopeChanged || mustChanged | ||
609 | } while (changed) | ||
610 | } | ||
611 | |||
612 | protected def flushQueryEngine() { | ||
613 | if (queryEngine.updatePropagationDelayed) { | ||
614 | delayMessageDelivery.setBoolean(queryEngine, false) | ||
615 | queryEngine.getQueryBackend(ReteBackendFactory.INSTANCE).flushUpdates | ||
616 | delayMessageDelivery.setBoolean(queryEngine, true) | ||
617 | } | ||
618 | } | ||
619 | |||
620 | protected def propagateScope() { | ||
621 | if (scopePropagator.scopePropagationNeeded) { | ||
622 | if (scopePropagator.queryEngineFlushRequiredBeforePropagation) { | ||
623 | flushQueryEngine() | ||
624 | } | ||
625 | val propagatorStartTime = System.nanoTime | ||
626 | scopePropagator.propagateAllScopeConstraints() | ||
627 | statistics.addScopePropagationTime(System.nanoTime - propagatorStartTime) | ||
628 | true | ||
629 | } else { | ||
630 | false | ||
631 | } | ||
632 | } | ||
633 | |||
634 | protected def propagateMustRelations() { | ||
635 | if (propagators.empty) { | ||
636 | return false | ||
637 | } | ||
638 | flushQueryEngine() | ||
639 | val propagatorStartTime = System.nanoTime | ||
640 | var changed = false | ||
641 | for (propagator : propagators) { | ||
642 | changed = propagator.propagate(p, i, refinementRuleProvider, this) || changed | ||
643 | } | ||
644 | statistics.addMustRelationPropagationTime(System.nanoTime - propagatorStartTime) | ||
645 | changed | ||
646 | } | ||
647 | |||
648 | private static def <T extends IPatternMatch> getPropagator(Relation relation, Relation inverseRelation, | ||
649 | ViatraQueryMatcher<T> matcher) { | ||
650 | if (inverseRelation === null) { | ||
651 | new MustRelationPropagator(matcher) | ||
652 | } else if (relation == inverseRelation) { | ||
653 | new MustRelationPropagatorWithSelfInverse(matcher) | ||
654 | } else { | ||
655 | new MustRelationPropagatorWithInverse(matcher) | ||
656 | } | ||
657 | } | ||
658 | |||
659 | @FinalFieldsConstructor | ||
660 | private static abstract class AbstractMustRelationPropagator<T extends IPatternMatch> { | ||
661 | val ViatraQueryMatcher<T> matcher | ||
662 | |||
663 | def propagate(LogicProblem p, PartialInterpretation i, RefinementRuleProvider refinementRuleProvider, | ||
664 | UnitRulePropagator unitRulePropagator) { | ||
665 | val iterator = getIterator(p, i) | ||
666 | if (!iterator.hasNext) { | ||
667 | return false | ||
668 | } | ||
669 | iterate(iterator, refinementRuleProvider, unitRulePropagator) | ||
670 | true | ||
671 | } | ||
672 | |||
673 | def iterate(Iterator<T> iterator, RefinementRuleProvider refinementRuleProvider, | ||
674 | UnitRulePropagator unitRulePropagator) { | ||
675 | while (iterator.hasNext) { | ||
676 | doPropagate(iterator.next, refinementRuleProvider, unitRulePropagator) | ||
677 | } | ||
678 | } | ||
679 | |||
680 | protected def getIterator(LogicProblem p, PartialInterpretation i) { | ||
681 | val partialMatch = matcher.newEmptyMatch | ||
682 | partialMatch.set(0, p) | ||
683 | partialMatch.set(1, i) | ||
684 | matcher.streamAllMatches(partialMatch).iterator | ||
685 | } | ||
686 | |||
687 | protected def void doPropagate(T match, RefinementRuleProvider refinementRuleProvider, | ||
688 | UnitRulePropagator unitRulePropagator) | ||
689 | } | ||
690 | |||
691 | private static class MustRelationPropagator<T extends IPatternMatch> extends AbstractMustRelationPropagator<T> { | ||
692 | new(ViatraQueryMatcher<T> matcher) { | ||
693 | super(matcher) | ||
694 | } | ||
695 | |||
696 | override protected doPropagate(T match, RefinementRuleProvider refinementRuleProvider, | ||
697 | UnitRulePropagator unitRulePropagator) { | ||
698 | refinementRuleProvider.createRelationLinkAction(match, unitRulePropagator) | ||
699 | } | ||
700 | } | ||
701 | |||
702 | private static class MustRelationPropagatorWithInverse<T extends IPatternMatch> extends AbstractMustRelationPropagator<T> { | ||
703 | new(ViatraQueryMatcher<T> matcher) { | ||
704 | super(matcher) | ||
705 | } | ||
706 | |||
707 | override protected doPropagate(T match, RefinementRuleProvider refinementRuleProvider, | ||
708 | UnitRulePropagator unitRulePropagator) { | ||
709 | refinementRuleProvider.createRelationLinkWithInverse(match, unitRulePropagator) | ||
710 | } | ||
711 | } | ||
712 | |||
713 | private static class MustRelationPropagatorWithSelfInverse<T extends IPatternMatch> extends MustRelationPropagatorWithInverse<T> { | ||
714 | new(ViatraQueryMatcher<T> matcher) { | ||
715 | super(matcher) | ||
716 | } | ||
717 | |||
718 | override iterate(Iterator<T> iterator, RefinementRuleProvider refinementRuleProvider, | ||
719 | UnitRulePropagator unitRulePropagator) { | ||
720 | val pairs = newHashSet | ||
721 | while (iterator.hasNext) { | ||
722 | val match = iterator.next | ||
723 | val src = match.get(4) as DefinedElement | ||
724 | val trg = match.get(5) as DefinedElement | ||
725 | if (!pairs.contains(trg -> src)) { | ||
726 | pairs.add(src -> trg) | ||
727 | doPropagate(match, refinementRuleProvider, unitRulePropagator) | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | } | ||
732 | } | ||
733 | } | ||
734 | |||
735 | @Data | ||
736 | class ObjectCreationInterpretationData { | ||
737 | PartialInterpretation interpretation | ||
738 | PartialTypeInterpratation typeInterpretation | ||
739 | PartialRelationInterpretation containerInterpretation | ||
740 | PartialRelationInterpretation containerInverseInterpretation | ||
741 | Function0<DefinedElement> constructor | ||
742 | List<ObjectCreationInterpretationData> recursiveConstructors = new LinkedList | ||
226 | } | 743 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/util/ParseUtil.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/util/ParseUtil.xtend index 8e264488..26ec7091 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/util/ParseUtil.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/util/ParseUtil.xtend | |||
@@ -196,8 +196,20 @@ class ParseUtil { | |||
196 | } | 196 | } |
197 | 197 | ||
198 | class FixedMetamodelProvider implements IMetamodelProvider { | 198 | class FixedMetamodelProvider implements IMetamodelProvider { |
199 | |||
200 | static val EPACKAGE_TO_PLUGIN_MAP = #{ | ||
201 | PartialinterpretationPackage.eINSTANCE -> "hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage", | ||
202 | LogicproblemPackage.eINSTANCE -> "hu.bme.mit.inf.dslreasoner.logic.model", | ||
203 | LogiclanguagePackage.eINSTANCE -> "hu.bme.mit.inf.dslreasoner.logic.model" | ||
204 | } | ||
205 | |||
206 | static val EPACKAGE_TO_JAVA_PACKAGE_MAP = #{ | ||
207 | PartialinterpretationPackage.eINSTANCE -> "hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation", | ||
208 | LogicproblemPackage.eINSTANCE -> "hu.bme.mit.inf.dslreasoner.logic.model.logicproblem", | ||
209 | LogiclanguagePackage.eINSTANCE -> "hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage" | ||
210 | } | ||
199 | 211 | ||
200 | protected val List<EPackage> packages = new LinkedList | 212 | val List<EPackage> packages = new LinkedList |
201 | 213 | ||
202 | new() { | 214 | new() { |
203 | packages += PartialinterpretationPackage.eINSTANCE | 215 | packages += PartialinterpretationPackage.eINSTANCE |
@@ -213,15 +225,24 @@ class FixedMetamodelProvider implements IMetamodelProvider { | |||
213 | } | 225 | } |
214 | 226 | ||
215 | override boolean isGeneratedCodeAvailable(EPackage ePackage, ResourceSet set) { | 227 | override boolean isGeneratedCodeAvailable(EPackage ePackage, ResourceSet set) { |
216 | true | 228 | EPACKAGE_TO_PLUGIN_MAP.containsKey(ePackage) |
217 | } | 229 | } |
218 | 230 | ||
219 | override String getModelPluginId(EPackage ePackage, ResourceSet set) { | 231 | override String getModelPluginId(EPackage ePackage, ResourceSet set) { |
220 | return "hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage" | 232 | EPACKAGE_TO_PLUGIN_MAP.get(ePackage) |
221 | } | 233 | } |
222 | 234 | ||
223 | override String getQualifiedClassName(EClassifier classifier, EObject context) { | 235 | override String getQualifiedClassName(EClassifier classifier, EObject context) { |
224 | classifier.name | 236 | val instanceClassName = classifier.instanceClassName |
237 | if (instanceClassName !== null) { | ||
238 | return instanceClassName | ||
239 | } | ||
240 | val javaPackage = EPACKAGE_TO_JAVA_PACKAGE_MAP.get(classifier.EPackage) | ||
241 | if (javaPackage !== null) { | ||
242 | javaPackage + "." + classifier.name | ||
243 | } else { | ||
244 | null | ||
245 | } | ||
225 | } | 246 | } |
226 | 247 | ||
227 | override loadEPackage(String uri, ResourceSet resourceSet) { | 248 | override loadEPackage(String uri, ResourceSet resourceSet) { |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/META-INF/MANIFEST.MF b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/META-INF/MANIFEST.MF index 83c90829..639a8a9c 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/META-INF/MANIFEST.MF +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/META-INF/MANIFEST.MF | |||
@@ -28,7 +28,8 @@ Require-Bundle: org.eclipse.core.runtime, | |||
28 | org.eclipse.xtend.lib.macro, | 28 | org.eclipse.xtend.lib.macro, |
29 | org.eclipse.viatra.query.runtime;bundle-version="1.5.0", | 29 | org.eclipse.viatra.query.runtime;bundle-version="1.5.0", |
30 | org.eclipse.viatra.dse;bundle-version="0.15.0", | 30 | org.eclipse.viatra.dse;bundle-version="0.15.0", |
31 | hu.bme.mit.inf.dslreasoner.ecore2logic;bundle-version="1.0.0" | 31 | hu.bme.mit.inf.dslreasoner.ecore2logic;bundle-version="1.0.0", |
32 | org.eclipse.collections;bundle-version="10.1.0" | ||
32 | Bundle-ActivationPolicy: lazy | 33 | Bundle-ActivationPolicy: lazy |
33 | Automatic-Module-Name: hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage | 34 | Automatic-Module-Name: hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage |
34 | 35 | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/PartialInterpretation.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/PartialInterpretation.java index 098cc15b..9d0c3fea 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/PartialInterpretation.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/PartialInterpretation.java | |||
@@ -30,6 +30,7 @@ import org.eclipse.emf.ecore.EObject; | |||
30 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getScopes <em>Scopes</em>}</li> | 30 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getScopes <em>Scopes</em>}</li> |
31 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getMinNewElements <em>Min New Elements</em>}</li> | 31 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getMinNewElements <em>Min New Elements</em>}</li> |
32 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getMaxNewElements <em>Max New Elements</em>}</li> | 32 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getMaxNewElements <em>Max New Elements</em>}</li> |
33 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getMinNewElementsHeuristic <em>Min New Elements Heuristic</em>}</li> | ||
33 | * </ul> | 34 | * </ul> |
34 | * | 35 | * |
35 | * @see hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage#getPartialInterpretation() | 36 | * @see hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage#getPartialInterpretation() |
@@ -255,4 +256,27 @@ public interface PartialInterpretation extends EObject { | |||
255 | */ | 256 | */ |
256 | void setMaxNewElements(int value); | 257 | void setMaxNewElements(int value); |
257 | 258 | ||
259 | /** | ||
260 | * Returns the value of the '<em><b>Min New Elements Heuristic</b></em>' attribute. | ||
261 | * The default value is <code>"0"</code>. | ||
262 | * <!-- begin-user-doc --> | ||
263 | * <!-- end-user-doc --> | ||
264 | * @return the value of the '<em>Min New Elements Heuristic</em>' attribute. | ||
265 | * @see #setMinNewElementsHeuristic(int) | ||
266 | * @see hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage#getPartialInterpretation_MinNewElementsHeuristic() | ||
267 | * @model default="0" required="true" | ||
268 | * @generated | ||
269 | */ | ||
270 | int getMinNewElementsHeuristic(); | ||
271 | |||
272 | /** | ||
273 | * Sets the value of the '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getMinNewElementsHeuristic <em>Min New Elements Heuristic</em>}' attribute. | ||
274 | * <!-- begin-user-doc --> | ||
275 | * <!-- end-user-doc --> | ||
276 | * @param value the new value of the '<em>Min New Elements Heuristic</em>' attribute. | ||
277 | * @see #getMinNewElementsHeuristic() | ||
278 | * @generated | ||
279 | */ | ||
280 | void setMinNewElementsHeuristic(int value); | ||
281 | |||
258 | } // PartialInterpretation | 282 | } // PartialInterpretation |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/PartialinterpretationPackage.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/PartialinterpretationPackage.java index 4f34b9b7..f462ebe4 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/PartialinterpretationPackage.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/PartialinterpretationPackage.java | |||
@@ -167,13 +167,22 @@ public interface PartialinterpretationPackage extends EPackage { | |||
167 | int PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS = 10; | 167 | int PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS = 10; |
168 | 168 | ||
169 | /** | 169 | /** |
170 | * The feature id for the '<em><b>Min New Elements Heuristic</b></em>' attribute. | ||
171 | * <!-- begin-user-doc --> | ||
172 | * <!-- end-user-doc --> | ||
173 | * @generated | ||
174 | * @ordered | ||
175 | */ | ||
176 | int PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS_HEURISTIC = 11; | ||
177 | |||
178 | /** | ||
170 | * The number of structural features of the '<em>Partial Interpretation</em>' class. | 179 | * The number of structural features of the '<em>Partial Interpretation</em>' class. |
171 | * <!-- begin-user-doc --> | 180 | * <!-- begin-user-doc --> |
172 | * <!-- end-user-doc --> | 181 | * <!-- end-user-doc --> |
173 | * @generated | 182 | * @generated |
174 | * @ordered | 183 | * @ordered |
175 | */ | 184 | */ |
176 | int PARTIAL_INTERPRETATION_FEATURE_COUNT = 11; | 185 | int PARTIAL_INTERPRETATION_FEATURE_COUNT = 12; |
177 | 186 | ||
178 | /** | 187 | /** |
179 | * The number of operations of the '<em>Partial Interpretation</em>' class. | 188 | * The number of operations of the '<em>Partial Interpretation</em>' class. |
@@ -913,13 +922,22 @@ public interface PartialinterpretationPackage extends EPackage { | |||
913 | int SCOPE__TARGET_TYPE_INTERPRETATION = 2; | 922 | int SCOPE__TARGET_TYPE_INTERPRETATION = 2; |
914 | 923 | ||
915 | /** | 924 | /** |
925 | * The feature id for the '<em><b>Min New Elements Heuristic</b></em>' attribute. | ||
926 | * <!-- begin-user-doc --> | ||
927 | * <!-- end-user-doc --> | ||
928 | * @generated | ||
929 | * @ordered | ||
930 | */ | ||
931 | int SCOPE__MIN_NEW_ELEMENTS_HEURISTIC = 3; | ||
932 | |||
933 | /** | ||
916 | * The number of structural features of the '<em>Scope</em>' class. | 934 | * The number of structural features of the '<em>Scope</em>' class. |
917 | * <!-- begin-user-doc --> | 935 | * <!-- begin-user-doc --> |
918 | * <!-- end-user-doc --> | 936 | * <!-- end-user-doc --> |
919 | * @generated | 937 | * @generated |
920 | * @ordered | 938 | * @ordered |
921 | */ | 939 | */ |
922 | int SCOPE_FEATURE_COUNT = 3; | 940 | int SCOPE_FEATURE_COUNT = 4; |
923 | 941 | ||
924 | /** | 942 | /** |
925 | * The number of operations of the '<em>Scope</em>' class. | 943 | * The number of operations of the '<em>Scope</em>' class. |
@@ -1358,6 +1376,17 @@ public interface PartialinterpretationPackage extends EPackage { | |||
1358 | EAttribute getPartialInterpretation_MaxNewElements(); | 1376 | EAttribute getPartialInterpretation_MaxNewElements(); |
1359 | 1377 | ||
1360 | /** | 1378 | /** |
1379 | * Returns the meta object for the attribute '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getMinNewElementsHeuristic <em>Min New Elements Heuristic</em>}'. | ||
1380 | * <!-- begin-user-doc --> | ||
1381 | * <!-- end-user-doc --> | ||
1382 | * @return the meta object for the attribute '<em>Min New Elements Heuristic</em>'. | ||
1383 | * @see hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation#getMinNewElementsHeuristic() | ||
1384 | * @see #getPartialInterpretation() | ||
1385 | * @generated | ||
1386 | */ | ||
1387 | EAttribute getPartialInterpretation_MinNewElementsHeuristic(); | ||
1388 | |||
1389 | /** | ||
1361 | * Returns the meta object for class '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialConstantInterpretation <em>Partial Constant Interpretation</em>}'. | 1390 | * Returns the meta object for class '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialConstantInterpretation <em>Partial Constant Interpretation</em>}'. |
1362 | * <!-- begin-user-doc --> | 1391 | * <!-- begin-user-doc --> |
1363 | * <!-- end-user-doc --> | 1392 | * <!-- end-user-doc --> |
@@ -1750,6 +1779,17 @@ public interface PartialinterpretationPackage extends EPackage { | |||
1750 | EReference getScope_TargetTypeInterpretation(); | 1779 | EReference getScope_TargetTypeInterpretation(); |
1751 | 1780 | ||
1752 | /** | 1781 | /** |
1782 | * Returns the meta object for the attribute '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getMinNewElementsHeuristic <em>Min New Elements Heuristic</em>}'. | ||
1783 | * <!-- begin-user-doc --> | ||
1784 | * <!-- end-user-doc --> | ||
1785 | * @return the meta object for the attribute '<em>Min New Elements Heuristic</em>'. | ||
1786 | * @see hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getMinNewElementsHeuristic() | ||
1787 | * @see #getScope() | ||
1788 | * @generated | ||
1789 | */ | ||
1790 | EAttribute getScope_MinNewElementsHeuristic(); | ||
1791 | |||
1792 | /** | ||
1753 | * Returns the meta object for class '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation <em>Partial Primitive Interpretation</em>}'. | 1793 | * Returns the meta object for class '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation <em>Partial Primitive Interpretation</em>}'. |
1754 | * <!-- begin-user-doc --> | 1794 | * <!-- begin-user-doc --> |
1755 | * <!-- end-user-doc --> | 1795 | * <!-- end-user-doc --> |
@@ -1953,6 +1993,14 @@ public interface PartialinterpretationPackage extends EPackage { | |||
1953 | EAttribute PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS = eINSTANCE.getPartialInterpretation_MaxNewElements(); | 1993 | EAttribute PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS = eINSTANCE.getPartialInterpretation_MaxNewElements(); |
1954 | 1994 | ||
1955 | /** | 1995 | /** |
1996 | * The meta object literal for the '<em><b>Min New Elements Heuristic</b></em>' attribute feature. | ||
1997 | * <!-- begin-user-doc --> | ||
1998 | * <!-- end-user-doc --> | ||
1999 | * @generated | ||
2000 | */ | ||
2001 | EAttribute PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS_HEURISTIC = eINSTANCE.getPartialInterpretation_MinNewElementsHeuristic(); | ||
2002 | |||
2003 | /** | ||
1956 | * The meta object literal for the '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialConstantInterpretationImpl <em>Partial Constant Interpretation</em>}' class. | 2004 | * The meta object literal for the '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialConstantInterpretationImpl <em>Partial Constant Interpretation</em>}' class. |
1957 | * <!-- begin-user-doc --> | 2005 | * <!-- begin-user-doc --> |
1958 | * <!-- end-user-doc --> | 2006 | * <!-- end-user-doc --> |
@@ -2279,6 +2327,14 @@ public interface PartialinterpretationPackage extends EPackage { | |||
2279 | EReference SCOPE__TARGET_TYPE_INTERPRETATION = eINSTANCE.getScope_TargetTypeInterpretation(); | 2327 | EReference SCOPE__TARGET_TYPE_INTERPRETATION = eINSTANCE.getScope_TargetTypeInterpretation(); |
2280 | 2328 | ||
2281 | /** | 2329 | /** |
2330 | * The meta object literal for the '<em><b>Min New Elements Heuristic</b></em>' attribute feature. | ||
2331 | * <!-- begin-user-doc --> | ||
2332 | * <!-- end-user-doc --> | ||
2333 | * @generated | ||
2334 | */ | ||
2335 | EAttribute SCOPE__MIN_NEW_ELEMENTS_HEURISTIC = eINSTANCE.getScope_MinNewElementsHeuristic(); | ||
2336 | |||
2337 | /** | ||
2282 | * The meta object literal for the '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialPrimitiveInterpretationImpl <em>Partial Primitive Interpretation</em>}' class. | 2338 | * The meta object literal for the '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialPrimitiveInterpretationImpl <em>Partial Primitive Interpretation</em>}' class. |
2283 | * <!-- begin-user-doc --> | 2339 | * <!-- begin-user-doc --> |
2284 | * <!-- end-user-doc --> | 2340 | * <!-- end-user-doc --> |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/Scope.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/Scope.java index 155b9f00..a0b58615 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/Scope.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/Scope.java | |||
@@ -16,6 +16,7 @@ import org.eclipse.emf.ecore.EObject; | |||
16 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getMinNewElements <em>Min New Elements</em>}</li> | 16 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getMinNewElements <em>Min New Elements</em>}</li> |
17 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getMaxNewElements <em>Max New Elements</em>}</li> | 17 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getMaxNewElements <em>Max New Elements</em>}</li> |
18 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getTargetTypeInterpretation <em>Target Type Interpretation</em>}</li> | 18 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getTargetTypeInterpretation <em>Target Type Interpretation</em>}</li> |
19 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getMinNewElementsHeuristic <em>Min New Elements Heuristic</em>}</li> | ||
19 | * </ul> | 20 | * </ul> |
20 | * | 21 | * |
21 | * @see hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage#getScope() | 22 | * @see hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage#getScope() |
@@ -105,4 +106,27 @@ public interface Scope extends EObject { | |||
105 | */ | 106 | */ |
106 | void setTargetTypeInterpretation(PartialTypeInterpratation value); | 107 | void setTargetTypeInterpretation(PartialTypeInterpratation value); |
107 | 108 | ||
109 | /** | ||
110 | * Returns the value of the '<em><b>Min New Elements Heuristic</b></em>' attribute. | ||
111 | * The default value is <code>"0"</code>. | ||
112 | * <!-- begin-user-doc --> | ||
113 | * <!-- end-user-doc --> | ||
114 | * @return the value of the '<em>Min New Elements Heuristic</em>' attribute. | ||
115 | * @see #setMinNewElementsHeuristic(int) | ||
116 | * @see hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage#getScope_MinNewElementsHeuristic() | ||
117 | * @model default="0" required="true" | ||
118 | * @generated | ||
119 | */ | ||
120 | int getMinNewElementsHeuristic(); | ||
121 | |||
122 | /** | ||
123 | * Sets the value of the '{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope#getMinNewElementsHeuristic <em>Min New Elements Heuristic</em>}' attribute. | ||
124 | * <!-- begin-user-doc --> | ||
125 | * <!-- end-user-doc --> | ||
126 | * @param value the new value of the '<em>Min New Elements Heuristic</em>' attribute. | ||
127 | * @see #getMinNewElementsHeuristic() | ||
128 | * @generated | ||
129 | */ | ||
130 | void setMinNewElementsHeuristic(int value); | ||
131 | |||
108 | } // Scope | 132 | } // Scope |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/BinaryElementRelationLinkImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/BinaryElementRelationLinkImpl.java index f5efe02a..ca33dd65 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/BinaryElementRelationLinkImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/BinaryElementRelationLinkImpl.java | |||
@@ -73,6 +73,7 @@ public class BinaryElementRelationLinkImpl extends RelationLinkImpl implements B | |||
73 | * <!-- end-user-doc --> | 73 | * <!-- end-user-doc --> |
74 | * @generated | 74 | * @generated |
75 | */ | 75 | */ |
76 | @Override | ||
76 | public DefinedElement getParam1() { | 77 | public DefinedElement getParam1() { |
77 | if (param1 != null && param1.eIsProxy()) { | 78 | if (param1 != null && param1.eIsProxy()) { |
78 | InternalEObject oldParam1 = (InternalEObject)param1; | 79 | InternalEObject oldParam1 = (InternalEObject)param1; |
@@ -99,6 +100,7 @@ public class BinaryElementRelationLinkImpl extends RelationLinkImpl implements B | |||
99 | * <!-- end-user-doc --> | 100 | * <!-- end-user-doc --> |
100 | * @generated | 101 | * @generated |
101 | */ | 102 | */ |
103 | @Override | ||
102 | public void setParam1(DefinedElement newParam1) { | 104 | public void setParam1(DefinedElement newParam1) { |
103 | DefinedElement oldParam1 = param1; | 105 | DefinedElement oldParam1 = param1; |
104 | param1 = newParam1; | 106 | param1 = newParam1; |
@@ -111,6 +113,7 @@ public class BinaryElementRelationLinkImpl extends RelationLinkImpl implements B | |||
111 | * <!-- end-user-doc --> | 113 | * <!-- end-user-doc --> |
112 | * @generated | 114 | * @generated |
113 | */ | 115 | */ |
116 | @Override | ||
114 | public DefinedElement getParam2() { | 117 | public DefinedElement getParam2() { |
115 | if (param2 != null && param2.eIsProxy()) { | 118 | if (param2 != null && param2.eIsProxy()) { |
116 | InternalEObject oldParam2 = (InternalEObject)param2; | 119 | InternalEObject oldParam2 = (InternalEObject)param2; |
@@ -137,6 +140,7 @@ public class BinaryElementRelationLinkImpl extends RelationLinkImpl implements B | |||
137 | * <!-- end-user-doc --> | 140 | * <!-- end-user-doc --> |
138 | * @generated | 141 | * @generated |
139 | */ | 142 | */ |
143 | @Override | ||
140 | public void setParam2(DefinedElement newParam2) { | 144 | public void setParam2(DefinedElement newParam2) { |
141 | DefinedElement oldParam2 = param2; | 145 | DefinedElement oldParam2 = param2; |
142 | param2 = newParam2; | 146 | param2 = newParam2; |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/BooleanElementImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/BooleanElementImpl.java index e906e07d..5f12d9e4 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/BooleanElementImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/BooleanElementImpl.java | |||
@@ -69,6 +69,7 @@ public class BooleanElementImpl extends PrimitiveElementImpl implements BooleanE | |||
69 | * <!-- end-user-doc --> | 69 | * <!-- end-user-doc --> |
70 | * @generated | 70 | * @generated |
71 | */ | 71 | */ |
72 | @Override | ||
72 | public boolean isValue() { | 73 | public boolean isValue() { |
73 | return value; | 74 | return value; |
74 | } | 75 | } |
@@ -78,6 +79,7 @@ public class BooleanElementImpl extends PrimitiveElementImpl implements BooleanE | |||
78 | * <!-- end-user-doc --> | 79 | * <!-- end-user-doc --> |
79 | * @generated | 80 | * @generated |
80 | */ | 81 | */ |
82 | @Override | ||
81 | public void setValue(boolean newValue) { | 83 | public void setValue(boolean newValue) { |
82 | boolean oldValue = value; | 84 | boolean oldValue = value; |
83 | value = newValue; | 85 | value = newValue; |
@@ -152,7 +154,7 @@ public class BooleanElementImpl extends PrimitiveElementImpl implements BooleanE | |||
152 | public String toString() { | 154 | public String toString() { |
153 | if (eIsProxy()) return super.toString(); | 155 | if (eIsProxy()) return super.toString(); |
154 | 156 | ||
155 | StringBuffer result = new StringBuffer(super.toString()); | 157 | StringBuilder result = new StringBuilder(super.toString()); |
156 | result.append(" (value: "); | 158 | result.append(" (value: "); |
157 | result.append(value); | 159 | result.append(value); |
158 | result.append(')'); | 160 | result.append(')'); |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/IntegerElementImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/IntegerElementImpl.java index ef1a4b96..c8fbe1dd 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/IntegerElementImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/IntegerElementImpl.java | |||
@@ -69,6 +69,7 @@ public class IntegerElementImpl extends PrimitiveElementImpl implements IntegerE | |||
69 | * <!-- end-user-doc --> | 69 | * <!-- end-user-doc --> |
70 | * @generated | 70 | * @generated |
71 | */ | 71 | */ |
72 | @Override | ||
72 | public int getValue() { | 73 | public int getValue() { |
73 | return value; | 74 | return value; |
74 | } | 75 | } |
@@ -78,6 +79,7 @@ public class IntegerElementImpl extends PrimitiveElementImpl implements IntegerE | |||
78 | * <!-- end-user-doc --> | 79 | * <!-- end-user-doc --> |
79 | * @generated | 80 | * @generated |
80 | */ | 81 | */ |
82 | @Override | ||
81 | public void setValue(int newValue) { | 83 | public void setValue(int newValue) { |
82 | int oldValue = value; | 84 | int oldValue = value; |
83 | value = newValue; | 85 | value = newValue; |
@@ -152,7 +154,7 @@ public class IntegerElementImpl extends PrimitiveElementImpl implements IntegerE | |||
152 | public String toString() { | 154 | public String toString() { |
153 | if (eIsProxy()) return super.toString(); | 155 | if (eIsProxy()) return super.toString(); |
154 | 156 | ||
155 | StringBuffer result = new StringBuffer(super.toString()); | 157 | StringBuilder result = new StringBuilder(super.toString()); |
156 | result.append(" (value: "); | 158 | result.append(" (value: "); |
157 | result.append(value); | 159 | result.append(value); |
158 | result.append(')'); | 160 | result.append(')'); |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/NaryRelationLinkElementImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/NaryRelationLinkElementImpl.java index 749a03c5..c319a3f4 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/NaryRelationLinkElementImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/NaryRelationLinkElementImpl.java | |||
@@ -83,6 +83,7 @@ public class NaryRelationLinkElementImpl extends MinimalEObjectImpl.Container im | |||
83 | * <!-- end-user-doc --> | 83 | * <!-- end-user-doc --> |
84 | * @generated | 84 | * @generated |
85 | */ | 85 | */ |
86 | @Override | ||
86 | public int getIndex() { | 87 | public int getIndex() { |
87 | return index; | 88 | return index; |
88 | } | 89 | } |
@@ -92,6 +93,7 @@ public class NaryRelationLinkElementImpl extends MinimalEObjectImpl.Container im | |||
92 | * <!-- end-user-doc --> | 93 | * <!-- end-user-doc --> |
93 | * @generated | 94 | * @generated |
94 | */ | 95 | */ |
96 | @Override | ||
95 | public void setIndex(int newIndex) { | 97 | public void setIndex(int newIndex) { |
96 | int oldIndex = index; | 98 | int oldIndex = index; |
97 | index = newIndex; | 99 | index = newIndex; |
@@ -104,6 +106,7 @@ public class NaryRelationLinkElementImpl extends MinimalEObjectImpl.Container im | |||
104 | * <!-- end-user-doc --> | 106 | * <!-- end-user-doc --> |
105 | * @generated | 107 | * @generated |
106 | */ | 108 | */ |
109 | @Override | ||
107 | public DefinedElement getParam() { | 110 | public DefinedElement getParam() { |
108 | if (param != null && param.eIsProxy()) { | 111 | if (param != null && param.eIsProxy()) { |
109 | InternalEObject oldParam = (InternalEObject)param; | 112 | InternalEObject oldParam = (InternalEObject)param; |
@@ -130,6 +133,7 @@ public class NaryRelationLinkElementImpl extends MinimalEObjectImpl.Container im | |||
130 | * <!-- end-user-doc --> | 133 | * <!-- end-user-doc --> |
131 | * @generated | 134 | * @generated |
132 | */ | 135 | */ |
136 | @Override | ||
133 | public void setParam(DefinedElement newParam) { | 137 | public void setParam(DefinedElement newParam) { |
134 | DefinedElement oldParam = param; | 138 | DefinedElement oldParam = param; |
135 | param = newParam; | 139 | param = newParam; |
@@ -215,7 +219,7 @@ public class NaryRelationLinkElementImpl extends MinimalEObjectImpl.Container im | |||
215 | public String toString() { | 219 | public String toString() { |
216 | if (eIsProxy()) return super.toString(); | 220 | if (eIsProxy()) return super.toString(); |
217 | 221 | ||
218 | StringBuffer result = new StringBuffer(super.toString()); | 222 | StringBuilder result = new StringBuilder(super.toString()); |
219 | result.append(" (index: "); | 223 | result.append(" (index: "); |
220 | result.append(index); | 224 | result.append(index); |
221 | result.append(')'); | 225 | result.append(')'); |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/NaryRelationLinkImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/NaryRelationLinkImpl.java index f387ee06..9f7628cf 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/NaryRelationLinkImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/NaryRelationLinkImpl.java | |||
@@ -66,6 +66,7 @@ public class NaryRelationLinkImpl extends RelationLinkImpl implements NaryRelati | |||
66 | * <!-- end-user-doc --> | 66 | * <!-- end-user-doc --> |
67 | * @generated | 67 | * @generated |
68 | */ | 68 | */ |
69 | @Override | ||
69 | public EList<NaryRelationLinkElement> getElements() { | 70 | public EList<NaryRelationLinkElement> getElements() { |
70 | if (elements == null) { | 71 | if (elements == null) { |
71 | elements = new EObjectContainmentEList<NaryRelationLinkElement>(NaryRelationLinkElement.class, this, PartialinterpretationPackage.NARY_RELATION_LINK__ELEMENTS); | 72 | elements = new EObjectContainmentEList<NaryRelationLinkElement>(NaryRelationLinkElement.class, this, PartialinterpretationPackage.NARY_RELATION_LINK__ELEMENTS); |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialComplexTypeInterpretationImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialComplexTypeInterpretationImpl.java index 07ee282d..c00b4278 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialComplexTypeInterpretationImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialComplexTypeInterpretationImpl.java | |||
@@ -79,6 +79,7 @@ public class PartialComplexTypeInterpretationImpl extends PartialTypeInterpratat | |||
79 | * <!-- end-user-doc --> | 79 | * <!-- end-user-doc --> |
80 | * @generated | 80 | * @generated |
81 | */ | 81 | */ |
82 | @Override | ||
82 | public EList<PartialComplexTypeInterpretation> getSupertypeInterpretation() { | 83 | public EList<PartialComplexTypeInterpretation> getSupertypeInterpretation() { |
83 | if (supertypeInterpretation == null) { | 84 | if (supertypeInterpretation == null) { |
84 | supertypeInterpretation = new EObjectResolvingEList<PartialComplexTypeInterpretation>(PartialComplexTypeInterpretation.class, this, PartialinterpretationPackage.PARTIAL_COMPLEX_TYPE_INTERPRETATION__SUPERTYPE_INTERPRETATION); | 85 | supertypeInterpretation = new EObjectResolvingEList<PartialComplexTypeInterpretation>(PartialComplexTypeInterpretation.class, this, PartialinterpretationPackage.PARTIAL_COMPLEX_TYPE_INTERPRETATION__SUPERTYPE_INTERPRETATION); |
@@ -91,6 +92,7 @@ public class PartialComplexTypeInterpretationImpl extends PartialTypeInterpratat | |||
91 | * <!-- end-user-doc --> | 92 | * <!-- end-user-doc --> |
92 | * @generated | 93 | * @generated |
93 | */ | 94 | */ |
95 | @Override | ||
94 | public TypeDeclaration getInterpretationOf() { | 96 | public TypeDeclaration getInterpretationOf() { |
95 | if (interpretationOf != null && interpretationOf.eIsProxy()) { | 97 | if (interpretationOf != null && interpretationOf.eIsProxy()) { |
96 | InternalEObject oldInterpretationOf = (InternalEObject)interpretationOf; | 98 | InternalEObject oldInterpretationOf = (InternalEObject)interpretationOf; |
@@ -117,6 +119,7 @@ public class PartialComplexTypeInterpretationImpl extends PartialTypeInterpratat | |||
117 | * <!-- end-user-doc --> | 119 | * <!-- end-user-doc --> |
118 | * @generated | 120 | * @generated |
119 | */ | 121 | */ |
122 | @Override | ||
120 | public void setInterpretationOf(TypeDeclaration newInterpretationOf) { | 123 | public void setInterpretationOf(TypeDeclaration newInterpretationOf) { |
121 | TypeDeclaration oldInterpretationOf = interpretationOf; | 124 | TypeDeclaration oldInterpretationOf = interpretationOf; |
122 | interpretationOf = newInterpretationOf; | 125 | interpretationOf = newInterpretationOf; |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialConstantInterpretationImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialConstantInterpretationImpl.java index 81b2ce8d..6d51f0db 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialConstantInterpretationImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialConstantInterpretationImpl.java | |||
@@ -63,6 +63,7 @@ public class PartialConstantInterpretationImpl extends MinimalEObjectImpl.Contai | |||
63 | * <!-- end-user-doc --> | 63 | * <!-- end-user-doc --> |
64 | * @generated | 64 | * @generated |
65 | */ | 65 | */ |
66 | @Override | ||
66 | public ConstantDeclaration getInterpretationOf() { | 67 | public ConstantDeclaration getInterpretationOf() { |
67 | if (interpretationOf != null && interpretationOf.eIsProxy()) { | 68 | if (interpretationOf != null && interpretationOf.eIsProxy()) { |
68 | InternalEObject oldInterpretationOf = (InternalEObject)interpretationOf; | 69 | InternalEObject oldInterpretationOf = (InternalEObject)interpretationOf; |
@@ -89,6 +90,7 @@ public class PartialConstantInterpretationImpl extends MinimalEObjectImpl.Contai | |||
89 | * <!-- end-user-doc --> | 90 | * <!-- end-user-doc --> |
90 | * @generated | 91 | * @generated |
91 | */ | 92 | */ |
93 | @Override | ||
92 | public void setInterpretationOf(ConstantDeclaration newInterpretationOf) { | 94 | public void setInterpretationOf(ConstantDeclaration newInterpretationOf) { |
93 | ConstantDeclaration oldInterpretationOf = interpretationOf; | 95 | ConstantDeclaration oldInterpretationOf = interpretationOf; |
94 | interpretationOf = newInterpretationOf; | 96 | interpretationOf = newInterpretationOf; |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialFunctionInterpretationImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialFunctionInterpretationImpl.java index 2d361e8e..855c4abc 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialFunctionInterpretationImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialFunctionInterpretationImpl.java | |||
@@ -63,6 +63,7 @@ public class PartialFunctionInterpretationImpl extends MinimalEObjectImpl.Contai | |||
63 | * <!-- end-user-doc --> | 63 | * <!-- end-user-doc --> |
64 | * @generated | 64 | * @generated |
65 | */ | 65 | */ |
66 | @Override | ||
66 | public FunctionDeclaration getInterpretationOf() { | 67 | public FunctionDeclaration getInterpretationOf() { |
67 | if (interpretationOf != null && interpretationOf.eIsProxy()) { | 68 | if (interpretationOf != null && interpretationOf.eIsProxy()) { |
68 | InternalEObject oldInterpretationOf = (InternalEObject)interpretationOf; | 69 | InternalEObject oldInterpretationOf = (InternalEObject)interpretationOf; |
@@ -89,6 +90,7 @@ public class PartialFunctionInterpretationImpl extends MinimalEObjectImpl.Contai | |||
89 | * <!-- end-user-doc --> | 90 | * <!-- end-user-doc --> |
90 | * @generated | 91 | * @generated |
91 | */ | 92 | */ |
93 | @Override | ||
92 | public void setInterpretationOf(FunctionDeclaration newInterpretationOf) { | 94 | public void setInterpretationOf(FunctionDeclaration newInterpretationOf) { |
93 | FunctionDeclaration oldInterpretationOf = interpretationOf; | 95 | FunctionDeclaration oldInterpretationOf = interpretationOf; |
94 | interpretationOf = newInterpretationOf; | 96 | interpretationOf = newInterpretationOf; |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialInterpretationImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialInterpretationImpl.java index bce3e2e0..9afdd8d2 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialInterpretationImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialInterpretationImpl.java | |||
@@ -47,6 +47,7 @@ import org.eclipse.emf.ecore.util.InternalEList; | |||
47 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialInterpretationImpl#getScopes <em>Scopes</em>}</li> | 47 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialInterpretationImpl#getScopes <em>Scopes</em>}</li> |
48 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialInterpretationImpl#getMinNewElements <em>Min New Elements</em>}</li> | 48 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialInterpretationImpl#getMinNewElements <em>Min New Elements</em>}</li> |
49 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialInterpretationImpl#getMaxNewElements <em>Max New Elements</em>}</li> | 49 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialInterpretationImpl#getMaxNewElements <em>Max New Elements</em>}</li> |
50 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.PartialInterpretationImpl#getMinNewElementsHeuristic <em>Min New Elements Heuristic</em>}</li> | ||
50 | * </ul> | 51 | * </ul> |
51 | * | 52 | * |
52 | * @generated | 53 | * @generated |
@@ -183,6 +184,26 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
183 | protected int maxNewElements = MAX_NEW_ELEMENTS_EDEFAULT; | 184 | protected int maxNewElements = MAX_NEW_ELEMENTS_EDEFAULT; |
184 | 185 | ||
185 | /** | 186 | /** |
187 | * The default value of the '{@link #getMinNewElementsHeuristic() <em>Min New Elements Heuristic</em>}' attribute. | ||
188 | * <!-- begin-user-doc --> | ||
189 | * <!-- end-user-doc --> | ||
190 | * @see #getMinNewElementsHeuristic() | ||
191 | * @generated | ||
192 | * @ordered | ||
193 | */ | ||
194 | protected static final int MIN_NEW_ELEMENTS_HEURISTIC_EDEFAULT = 0; | ||
195 | |||
196 | /** | ||
197 | * The cached value of the '{@link #getMinNewElementsHeuristic() <em>Min New Elements Heuristic</em>}' attribute. | ||
198 | * <!-- begin-user-doc --> | ||
199 | * <!-- end-user-doc --> | ||
200 | * @see #getMinNewElementsHeuristic() | ||
201 | * @generated | ||
202 | * @ordered | ||
203 | */ | ||
204 | protected int minNewElementsHeuristic = MIN_NEW_ELEMENTS_HEURISTIC_EDEFAULT; | ||
205 | |||
206 | /** | ||
186 | * <!-- begin-user-doc --> | 207 | * <!-- begin-user-doc --> |
187 | * <!-- end-user-doc --> | 208 | * <!-- end-user-doc --> |
188 | * @generated | 209 | * @generated |
@@ -206,6 +227,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
206 | * <!-- end-user-doc --> | 227 | * <!-- end-user-doc --> |
207 | * @generated | 228 | * @generated |
208 | */ | 229 | */ |
230 | @Override | ||
209 | public LogicProblem getProblem() { | 231 | public LogicProblem getProblem() { |
210 | if (problem != null && problem.eIsProxy()) { | 232 | if (problem != null && problem.eIsProxy()) { |
211 | InternalEObject oldProblem = (InternalEObject)problem; | 233 | InternalEObject oldProblem = (InternalEObject)problem; |
@@ -232,6 +254,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
232 | * <!-- end-user-doc --> | 254 | * <!-- end-user-doc --> |
233 | * @generated | 255 | * @generated |
234 | */ | 256 | */ |
257 | @Override | ||
235 | public void setProblem(LogicProblem newProblem) { | 258 | public void setProblem(LogicProblem newProblem) { |
236 | LogicProblem oldProblem = problem; | 259 | LogicProblem oldProblem = problem; |
237 | problem = newProblem; | 260 | problem = newProblem; |
@@ -244,6 +267,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
244 | * <!-- end-user-doc --> | 267 | * <!-- end-user-doc --> |
245 | * @generated | 268 | * @generated |
246 | */ | 269 | */ |
270 | @Override | ||
247 | public EList<PartialConstantInterpretation> getPartialconstantinterpretation() { | 271 | public EList<PartialConstantInterpretation> getPartialconstantinterpretation() { |
248 | if (partialconstantinterpretation == null) { | 272 | if (partialconstantinterpretation == null) { |
249 | partialconstantinterpretation = new EObjectContainmentEList<PartialConstantInterpretation>(PartialConstantInterpretation.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALCONSTANTINTERPRETATION); | 273 | partialconstantinterpretation = new EObjectContainmentEList<PartialConstantInterpretation>(PartialConstantInterpretation.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALCONSTANTINTERPRETATION); |
@@ -256,6 +280,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
256 | * <!-- end-user-doc --> | 280 | * <!-- end-user-doc --> |
257 | * @generated | 281 | * @generated |
258 | */ | 282 | */ |
283 | @Override | ||
259 | public EList<PartialRelationInterpretation> getPartialrelationinterpretation() { | 284 | public EList<PartialRelationInterpretation> getPartialrelationinterpretation() { |
260 | if (partialrelationinterpretation == null) { | 285 | if (partialrelationinterpretation == null) { |
261 | partialrelationinterpretation = new EObjectContainmentEList<PartialRelationInterpretation>(PartialRelationInterpretation.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALRELATIONINTERPRETATION); | 286 | partialrelationinterpretation = new EObjectContainmentEList<PartialRelationInterpretation>(PartialRelationInterpretation.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALRELATIONINTERPRETATION); |
@@ -268,6 +293,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
268 | * <!-- end-user-doc --> | 293 | * <!-- end-user-doc --> |
269 | * @generated | 294 | * @generated |
270 | */ | 295 | */ |
296 | @Override | ||
271 | public EList<PartialFunctionInterpretation> getPartialfunctioninterpretation() { | 297 | public EList<PartialFunctionInterpretation> getPartialfunctioninterpretation() { |
272 | if (partialfunctioninterpretation == null) { | 298 | if (partialfunctioninterpretation == null) { |
273 | partialfunctioninterpretation = new EObjectContainmentEList<PartialFunctionInterpretation>(PartialFunctionInterpretation.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALFUNCTIONINTERPRETATION); | 299 | partialfunctioninterpretation = new EObjectContainmentEList<PartialFunctionInterpretation>(PartialFunctionInterpretation.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALFUNCTIONINTERPRETATION); |
@@ -280,6 +306,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
280 | * <!-- end-user-doc --> | 306 | * <!-- end-user-doc --> |
281 | * @generated | 307 | * @generated |
282 | */ | 308 | */ |
309 | @Override | ||
283 | public EList<DefinedElement> getNewElements() { | 310 | public EList<DefinedElement> getNewElements() { |
284 | if (newElements == null) { | 311 | if (newElements == null) { |
285 | newElements = new EObjectContainmentEList<DefinedElement>(DefinedElement.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__NEW_ELEMENTS); | 312 | newElements = new EObjectContainmentEList<DefinedElement>(DefinedElement.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__NEW_ELEMENTS); |
@@ -292,6 +319,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
292 | * <!-- end-user-doc --> | 319 | * <!-- end-user-doc --> |
293 | * @generated | 320 | * @generated |
294 | */ | 321 | */ |
322 | @Override | ||
295 | public EList<PartialTypeInterpratation> getPartialtypeinterpratation() { | 323 | public EList<PartialTypeInterpratation> getPartialtypeinterpratation() { |
296 | if (partialtypeinterpratation == null) { | 324 | if (partialtypeinterpratation == null) { |
297 | partialtypeinterpratation = new EObjectContainmentEList<PartialTypeInterpratation>(PartialTypeInterpratation.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALTYPEINTERPRATATION); | 325 | partialtypeinterpratation = new EObjectContainmentEList<PartialTypeInterpratation>(PartialTypeInterpratation.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALTYPEINTERPRATATION); |
@@ -304,6 +332,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
304 | * <!-- end-user-doc --> | 332 | * <!-- end-user-doc --> |
305 | * @generated | 333 | * @generated |
306 | */ | 334 | */ |
335 | @Override | ||
307 | public EList<DefinedElement> getOpenWorldElements() { | 336 | public EList<DefinedElement> getOpenWorldElements() { |
308 | if (openWorldElements == null) { | 337 | if (openWorldElements == null) { |
309 | openWorldElements = new EObjectContainmentEList<DefinedElement>(DefinedElement.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__OPEN_WORLD_ELEMENTS); | 338 | openWorldElements = new EObjectContainmentEList<DefinedElement>(DefinedElement.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__OPEN_WORLD_ELEMENTS); |
@@ -316,6 +345,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
316 | * <!-- end-user-doc --> | 345 | * <!-- end-user-doc --> |
317 | * @generated | 346 | * @generated |
318 | */ | 347 | */ |
348 | @Override | ||
319 | public LogicProblem getProblemConainer() { | 349 | public LogicProblem getProblemConainer() { |
320 | return problemConainer; | 350 | return problemConainer; |
321 | } | 351 | } |
@@ -340,6 +370,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
340 | * <!-- end-user-doc --> | 370 | * <!-- end-user-doc --> |
341 | * @generated | 371 | * @generated |
342 | */ | 372 | */ |
373 | @Override | ||
343 | public void setProblemConainer(LogicProblem newProblemConainer) { | 374 | public void setProblemConainer(LogicProblem newProblemConainer) { |
344 | if (newProblemConainer != problemConainer) { | 375 | if (newProblemConainer != problemConainer) { |
345 | NotificationChain msgs = null; | 376 | NotificationChain msgs = null; |
@@ -359,6 +390,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
359 | * <!-- end-user-doc --> | 390 | * <!-- end-user-doc --> |
360 | * @generated | 391 | * @generated |
361 | */ | 392 | */ |
393 | @Override | ||
362 | public EList<Scope> getScopes() { | 394 | public EList<Scope> getScopes() { |
363 | if (scopes == null) { | 395 | if (scopes == null) { |
364 | scopes = new EObjectContainmentEList<Scope>(Scope.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__SCOPES); | 396 | scopes = new EObjectContainmentEList<Scope>(Scope.class, this, PartialinterpretationPackage.PARTIAL_INTERPRETATION__SCOPES); |
@@ -371,6 +403,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
371 | * <!-- end-user-doc --> | 403 | * <!-- end-user-doc --> |
372 | * @generated | 404 | * @generated |
373 | */ | 405 | */ |
406 | @Override | ||
374 | public int getMinNewElements() { | 407 | public int getMinNewElements() { |
375 | return minNewElements; | 408 | return minNewElements; |
376 | } | 409 | } |
@@ -380,6 +413,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
380 | * <!-- end-user-doc --> | 413 | * <!-- end-user-doc --> |
381 | * @generated | 414 | * @generated |
382 | */ | 415 | */ |
416 | @Override | ||
383 | public void setMinNewElements(int newMinNewElements) { | 417 | public void setMinNewElements(int newMinNewElements) { |
384 | int oldMinNewElements = minNewElements; | 418 | int oldMinNewElements = minNewElements; |
385 | minNewElements = newMinNewElements; | 419 | minNewElements = newMinNewElements; |
@@ -392,6 +426,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
392 | * <!-- end-user-doc --> | 426 | * <!-- end-user-doc --> |
393 | * @generated | 427 | * @generated |
394 | */ | 428 | */ |
429 | @Override | ||
395 | public int getMaxNewElements() { | 430 | public int getMaxNewElements() { |
396 | return maxNewElements; | 431 | return maxNewElements; |
397 | } | 432 | } |
@@ -401,6 +436,7 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
401 | * <!-- end-user-doc --> | 436 | * <!-- end-user-doc --> |
402 | * @generated | 437 | * @generated |
403 | */ | 438 | */ |
439 | @Override | ||
404 | public void setMaxNewElements(int newMaxNewElements) { | 440 | public void setMaxNewElements(int newMaxNewElements) { |
405 | int oldMaxNewElements = maxNewElements; | 441 | int oldMaxNewElements = maxNewElements; |
406 | maxNewElements = newMaxNewElements; | 442 | maxNewElements = newMaxNewElements; |
@@ -414,6 +450,29 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
414 | * @generated | 450 | * @generated |
415 | */ | 451 | */ |
416 | @Override | 452 | @Override |
453 | public int getMinNewElementsHeuristic() { | ||
454 | return minNewElementsHeuristic; | ||
455 | } | ||
456 | |||
457 | /** | ||
458 | * <!-- begin-user-doc --> | ||
459 | * <!-- end-user-doc --> | ||
460 | * @generated | ||
461 | */ | ||
462 | @Override | ||
463 | public void setMinNewElementsHeuristic(int newMinNewElementsHeuristic) { | ||
464 | int oldMinNewElementsHeuristic = minNewElementsHeuristic; | ||
465 | minNewElementsHeuristic = newMinNewElementsHeuristic; | ||
466 | if (eNotificationRequired()) | ||
467 | eNotify(new ENotificationImpl(this, Notification.SET, PartialinterpretationPackage.PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS_HEURISTIC, oldMinNewElementsHeuristic, minNewElementsHeuristic)); | ||
468 | } | ||
469 | |||
470 | /** | ||
471 | * <!-- begin-user-doc --> | ||
472 | * <!-- end-user-doc --> | ||
473 | * @generated | ||
474 | */ | ||
475 | @Override | ||
417 | public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { | 476 | public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { |
418 | switch (featureID) { | 477 | switch (featureID) { |
419 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALCONSTANTINTERPRETATION: | 478 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__PARTIALCONSTANTINTERPRETATION: |
@@ -467,6 +526,8 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
467 | return getMinNewElements(); | 526 | return getMinNewElements(); |
468 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS: | 527 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS: |
469 | return getMaxNewElements(); | 528 | return getMaxNewElements(); |
529 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS_HEURISTIC: | ||
530 | return getMinNewElementsHeuristic(); | ||
470 | } | 531 | } |
471 | return super.eGet(featureID, resolve, coreType); | 532 | return super.eGet(featureID, resolve, coreType); |
472 | } | 533 | } |
@@ -520,6 +581,9 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
520 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS: | 581 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS: |
521 | setMaxNewElements((Integer)newValue); | 582 | setMaxNewElements((Integer)newValue); |
522 | return; | 583 | return; |
584 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS_HEURISTIC: | ||
585 | setMinNewElementsHeuristic((Integer)newValue); | ||
586 | return; | ||
523 | } | 587 | } |
524 | super.eSet(featureID, newValue); | 588 | super.eSet(featureID, newValue); |
525 | } | 589 | } |
@@ -565,6 +629,9 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
565 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS: | 629 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS: |
566 | setMaxNewElements(MAX_NEW_ELEMENTS_EDEFAULT); | 630 | setMaxNewElements(MAX_NEW_ELEMENTS_EDEFAULT); |
567 | return; | 631 | return; |
632 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS_HEURISTIC: | ||
633 | setMinNewElementsHeuristic(MIN_NEW_ELEMENTS_HEURISTIC_EDEFAULT); | ||
634 | return; | ||
568 | } | 635 | } |
569 | super.eUnset(featureID); | 636 | super.eUnset(featureID); |
570 | } | 637 | } |
@@ -599,6 +666,8 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
599 | return minNewElements != MIN_NEW_ELEMENTS_EDEFAULT; | 666 | return minNewElements != MIN_NEW_ELEMENTS_EDEFAULT; |
600 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS: | 667 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS: |
601 | return maxNewElements != MAX_NEW_ELEMENTS_EDEFAULT; | 668 | return maxNewElements != MAX_NEW_ELEMENTS_EDEFAULT; |
669 | case PartialinterpretationPackage.PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS_HEURISTIC: | ||
670 | return minNewElementsHeuristic != MIN_NEW_ELEMENTS_HEURISTIC_EDEFAULT; | ||
602 | } | 671 | } |
603 | return super.eIsSet(featureID); | 672 | return super.eIsSet(featureID); |
604 | } | 673 | } |
@@ -612,11 +681,13 @@ public class PartialInterpretationImpl extends MinimalEObjectImpl.Container impl | |||
612 | public String toString() { | 681 | public String toString() { |
613 | if (eIsProxy()) return super.toString(); | 682 | if (eIsProxy()) return super.toString(); |
614 | 683 | ||
615 | StringBuffer result = new StringBuffer(super.toString()); | 684 | StringBuilder result = new StringBuilder(super.toString()); |
616 | result.append(" (minNewElements: "); | 685 | result.append(" (minNewElements: "); |
617 | result.append(minNewElements); | 686 | result.append(minNewElements); |
618 | result.append(", maxNewElements: "); | 687 | result.append(", maxNewElements: "); |
619 | result.append(maxNewElements); | 688 | result.append(maxNewElements); |
689 | result.append(", minNewElementsHeuristic: "); | ||
690 | result.append(minNewElementsHeuristic); | ||
620 | result.append(')'); | 691 | result.append(')'); |
621 | return result.toString(); | 692 | return result.toString(); |
622 | } | 693 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialRelationInterpretationImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialRelationInterpretationImpl.java index 71aef9af..7ad06504 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialRelationInterpretationImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialRelationInterpretationImpl.java | |||
@@ -106,6 +106,7 @@ public class PartialRelationInterpretationImpl extends MinimalEObjectImpl.Contai | |||
106 | * <!-- end-user-doc --> | 106 | * <!-- end-user-doc --> |
107 | * @generated | 107 | * @generated |
108 | */ | 108 | */ |
109 | @Override | ||
109 | public RelationDeclaration getInterpretationOf() { | 110 | public RelationDeclaration getInterpretationOf() { |
110 | if (interpretationOf != null && interpretationOf.eIsProxy()) { | 111 | if (interpretationOf != null && interpretationOf.eIsProxy()) { |
111 | InternalEObject oldInterpretationOf = (InternalEObject)interpretationOf; | 112 | InternalEObject oldInterpretationOf = (InternalEObject)interpretationOf; |
@@ -132,6 +133,7 @@ public class PartialRelationInterpretationImpl extends MinimalEObjectImpl.Contai | |||
132 | * <!-- end-user-doc --> | 133 | * <!-- end-user-doc --> |
133 | * @generated | 134 | * @generated |
134 | */ | 135 | */ |
136 | @Override | ||
135 | public void setInterpretationOf(RelationDeclaration newInterpretationOf) { | 137 | public void setInterpretationOf(RelationDeclaration newInterpretationOf) { |
136 | RelationDeclaration oldInterpretationOf = interpretationOf; | 138 | RelationDeclaration oldInterpretationOf = interpretationOf; |
137 | interpretationOf = newInterpretationOf; | 139 | interpretationOf = newInterpretationOf; |
@@ -144,6 +146,7 @@ public class PartialRelationInterpretationImpl extends MinimalEObjectImpl.Contai | |||
144 | * <!-- end-user-doc --> | 146 | * <!-- end-user-doc --> |
145 | * @generated | 147 | * @generated |
146 | */ | 148 | */ |
149 | @Override | ||
147 | public EList<RelationLink> getRelationlinks() { | 150 | public EList<RelationLink> getRelationlinks() { |
148 | if (relationlinks == null) { | 151 | if (relationlinks == null) { |
149 | relationlinks = new EObjectContainmentEList<RelationLink>(RelationLink.class, this, PartialinterpretationPackage.PARTIAL_RELATION_INTERPRETATION__RELATIONLINKS); | 152 | relationlinks = new EObjectContainmentEList<RelationLink>(RelationLink.class, this, PartialinterpretationPackage.PARTIAL_RELATION_INTERPRETATION__RELATIONLINKS); |
@@ -156,6 +159,7 @@ public class PartialRelationInterpretationImpl extends MinimalEObjectImpl.Contai | |||
156 | * <!-- end-user-doc --> | 159 | * <!-- end-user-doc --> |
157 | * @generated | 160 | * @generated |
158 | */ | 161 | */ |
162 | @Override | ||
159 | public TypeReference getParam1() { | 163 | public TypeReference getParam1() { |
160 | if (param1 != null && param1.eIsProxy()) { | 164 | if (param1 != null && param1.eIsProxy()) { |
161 | InternalEObject oldParam1 = (InternalEObject)param1; | 165 | InternalEObject oldParam1 = (InternalEObject)param1; |
@@ -182,6 +186,7 @@ public class PartialRelationInterpretationImpl extends MinimalEObjectImpl.Contai | |||
182 | * <!-- end-user-doc --> | 186 | * <!-- end-user-doc --> |
183 | * @generated | 187 | * @generated |
184 | */ | 188 | */ |
189 | @Override | ||
185 | public void setParam1(TypeReference newParam1) { | 190 | public void setParam1(TypeReference newParam1) { |
186 | TypeReference oldParam1 = param1; | 191 | TypeReference oldParam1 = param1; |
187 | param1 = newParam1; | 192 | param1 = newParam1; |
@@ -194,6 +199,7 @@ public class PartialRelationInterpretationImpl extends MinimalEObjectImpl.Contai | |||
194 | * <!-- end-user-doc --> | 199 | * <!-- end-user-doc --> |
195 | * @generated | 200 | * @generated |
196 | */ | 201 | */ |
202 | @Override | ||
197 | public TypeReference getParam2() { | 203 | public TypeReference getParam2() { |
198 | if (param2 != null && param2.eIsProxy()) { | 204 | if (param2 != null && param2.eIsProxy()) { |
199 | InternalEObject oldParam2 = (InternalEObject)param2; | 205 | InternalEObject oldParam2 = (InternalEObject)param2; |
@@ -220,6 +226,7 @@ public class PartialRelationInterpretationImpl extends MinimalEObjectImpl.Contai | |||
220 | * <!-- end-user-doc --> | 226 | * <!-- end-user-doc --> |
221 | * @generated | 227 | * @generated |
222 | */ | 228 | */ |
229 | @Override | ||
223 | public void setParam2(TypeReference newParam2) { | 230 | public void setParam2(TypeReference newParam2) { |
224 | TypeReference oldParam2 = param2; | 231 | TypeReference oldParam2 = param2; |
225 | param2 = newParam2; | 232 | param2 = newParam2; |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialTypeInterpratationImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialTypeInterpratationImpl.java index da9b1472..51eabd2c 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialTypeInterpratationImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialTypeInterpratationImpl.java | |||
@@ -76,6 +76,7 @@ public abstract class PartialTypeInterpratationImpl extends MinimalEObjectImpl.C | |||
76 | * <!-- end-user-doc --> | 76 | * <!-- end-user-doc --> |
77 | * @generated | 77 | * @generated |
78 | */ | 78 | */ |
79 | @Override | ||
79 | public EList<DefinedElement> getElements() { | 80 | public EList<DefinedElement> getElements() { |
80 | if (elements == null) { | 81 | if (elements == null) { |
81 | elements = new EObjectResolvingEList<DefinedElement>(DefinedElement.class, this, PartialinterpretationPackage.PARTIAL_TYPE_INTERPRATATION__ELEMENTS); | 82 | elements = new EObjectResolvingEList<DefinedElement>(DefinedElement.class, this, PartialinterpretationPackage.PARTIAL_TYPE_INTERPRATATION__ELEMENTS); |
@@ -88,6 +89,7 @@ public abstract class PartialTypeInterpratationImpl extends MinimalEObjectImpl.C | |||
88 | * <!-- end-user-doc --> | 89 | * <!-- end-user-doc --> |
89 | * @generated | 90 | * @generated |
90 | */ | 91 | */ |
92 | @Override | ||
91 | public EList<Scope> getScopes() { | 93 | public EList<Scope> getScopes() { |
92 | if (scopes == null) { | 94 | if (scopes == null) { |
93 | scopes = new EObjectWithInverseResolvingEList<Scope>(Scope.class, this, PartialinterpretationPackage.PARTIAL_TYPE_INTERPRATATION__SCOPES, PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION); | 95 | scopes = new EObjectWithInverseResolvingEList<Scope>(Scope.class, this, PartialinterpretationPackage.PARTIAL_TYPE_INTERPRATATION__SCOPES, PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION); |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialinterpretationFactoryImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialinterpretationFactoryImpl.java index af1db8a1..06ca4e37 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialinterpretationFactoryImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialinterpretationFactoryImpl.java | |||
@@ -84,6 +84,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
84 | * <!-- end-user-doc --> | 84 | * <!-- end-user-doc --> |
85 | * @generated | 85 | * @generated |
86 | */ | 86 | */ |
87 | @Override | ||
87 | public PartialInterpretation createPartialInterpretation() { | 88 | public PartialInterpretation createPartialInterpretation() { |
88 | PartialInterpretationImpl partialInterpretation = new PartialInterpretationImpl(); | 89 | PartialInterpretationImpl partialInterpretation = new PartialInterpretationImpl(); |
89 | return partialInterpretation; | 90 | return partialInterpretation; |
@@ -94,6 +95,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
94 | * <!-- end-user-doc --> | 95 | * <!-- end-user-doc --> |
95 | * @generated | 96 | * @generated |
96 | */ | 97 | */ |
98 | @Override | ||
97 | public PartialConstantInterpretation createPartialConstantInterpretation() { | 99 | public PartialConstantInterpretation createPartialConstantInterpretation() { |
98 | PartialConstantInterpretationImpl partialConstantInterpretation = new PartialConstantInterpretationImpl(); | 100 | PartialConstantInterpretationImpl partialConstantInterpretation = new PartialConstantInterpretationImpl(); |
99 | return partialConstantInterpretation; | 101 | return partialConstantInterpretation; |
@@ -104,6 +106,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
104 | * <!-- end-user-doc --> | 106 | * <!-- end-user-doc --> |
105 | * @generated | 107 | * @generated |
106 | */ | 108 | */ |
109 | @Override | ||
107 | public PartialRelationInterpretation createPartialRelationInterpretation() { | 110 | public PartialRelationInterpretation createPartialRelationInterpretation() { |
108 | PartialRelationInterpretationImpl partialRelationInterpretation = new PartialRelationInterpretationImpl(); | 111 | PartialRelationInterpretationImpl partialRelationInterpretation = new PartialRelationInterpretationImpl(); |
109 | return partialRelationInterpretation; | 112 | return partialRelationInterpretation; |
@@ -114,6 +117,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
114 | * <!-- end-user-doc --> | 117 | * <!-- end-user-doc --> |
115 | * @generated | 118 | * @generated |
116 | */ | 119 | */ |
120 | @Override | ||
117 | public PartialFunctionInterpretation createPartialFunctionInterpretation() { | 121 | public PartialFunctionInterpretation createPartialFunctionInterpretation() { |
118 | PartialFunctionInterpretationImpl partialFunctionInterpretation = new PartialFunctionInterpretationImpl(); | 122 | PartialFunctionInterpretationImpl partialFunctionInterpretation = new PartialFunctionInterpretationImpl(); |
119 | return partialFunctionInterpretation; | 123 | return partialFunctionInterpretation; |
@@ -124,6 +128,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
124 | * <!-- end-user-doc --> | 128 | * <!-- end-user-doc --> |
125 | * @generated | 129 | * @generated |
126 | */ | 130 | */ |
131 | @Override | ||
127 | public UnaryElementRelationLink createUnaryElementRelationLink() { | 132 | public UnaryElementRelationLink createUnaryElementRelationLink() { |
128 | UnaryElementRelationLinkImpl unaryElementRelationLink = new UnaryElementRelationLinkImpl(); | 133 | UnaryElementRelationLinkImpl unaryElementRelationLink = new UnaryElementRelationLinkImpl(); |
129 | return unaryElementRelationLink; | 134 | return unaryElementRelationLink; |
@@ -134,6 +139,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
134 | * <!-- end-user-doc --> | 139 | * <!-- end-user-doc --> |
135 | * @generated | 140 | * @generated |
136 | */ | 141 | */ |
142 | @Override | ||
137 | public BinaryElementRelationLink createBinaryElementRelationLink() { | 143 | public BinaryElementRelationLink createBinaryElementRelationLink() { |
138 | BinaryElementRelationLinkImpl binaryElementRelationLink = new BinaryElementRelationLinkImpl(); | 144 | BinaryElementRelationLinkImpl binaryElementRelationLink = new BinaryElementRelationLinkImpl(); |
139 | return binaryElementRelationLink; | 145 | return binaryElementRelationLink; |
@@ -144,6 +150,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
144 | * <!-- end-user-doc --> | 150 | * <!-- end-user-doc --> |
145 | * @generated | 151 | * @generated |
146 | */ | 152 | */ |
153 | @Override | ||
147 | public NaryRelationLink createNaryRelationLink() { | 154 | public NaryRelationLink createNaryRelationLink() { |
148 | NaryRelationLinkImpl naryRelationLink = new NaryRelationLinkImpl(); | 155 | NaryRelationLinkImpl naryRelationLink = new NaryRelationLinkImpl(); |
149 | return naryRelationLink; | 156 | return naryRelationLink; |
@@ -154,6 +161,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
154 | * <!-- end-user-doc --> | 161 | * <!-- end-user-doc --> |
155 | * @generated | 162 | * @generated |
156 | */ | 163 | */ |
164 | @Override | ||
157 | public NaryRelationLinkElement createNaryRelationLinkElement() { | 165 | public NaryRelationLinkElement createNaryRelationLinkElement() { |
158 | NaryRelationLinkElementImpl naryRelationLinkElement = new NaryRelationLinkElementImpl(); | 166 | NaryRelationLinkElementImpl naryRelationLinkElement = new NaryRelationLinkElementImpl(); |
159 | return naryRelationLinkElement; | 167 | return naryRelationLinkElement; |
@@ -164,6 +172,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
164 | * <!-- end-user-doc --> | 172 | * <!-- end-user-doc --> |
165 | * @generated | 173 | * @generated |
166 | */ | 174 | */ |
175 | @Override | ||
167 | public BooleanElement createBooleanElement() { | 176 | public BooleanElement createBooleanElement() { |
168 | BooleanElementImpl booleanElement = new BooleanElementImpl(); | 177 | BooleanElementImpl booleanElement = new BooleanElementImpl(); |
169 | return booleanElement; | 178 | return booleanElement; |
@@ -174,6 +183,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
174 | * <!-- end-user-doc --> | 183 | * <!-- end-user-doc --> |
175 | * @generated | 184 | * @generated |
176 | */ | 185 | */ |
186 | @Override | ||
177 | public IntegerElement createIntegerElement() { | 187 | public IntegerElement createIntegerElement() { |
178 | IntegerElementImpl integerElement = new IntegerElementImpl(); | 188 | IntegerElementImpl integerElement = new IntegerElementImpl(); |
179 | return integerElement; | 189 | return integerElement; |
@@ -184,6 +194,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
184 | * <!-- end-user-doc --> | 194 | * <!-- end-user-doc --> |
185 | * @generated | 195 | * @generated |
186 | */ | 196 | */ |
197 | @Override | ||
187 | public RealElement createRealElement() { | 198 | public RealElement createRealElement() { |
188 | RealElementImpl realElement = new RealElementImpl(); | 199 | RealElementImpl realElement = new RealElementImpl(); |
189 | return realElement; | 200 | return realElement; |
@@ -194,6 +205,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
194 | * <!-- end-user-doc --> | 205 | * <!-- end-user-doc --> |
195 | * @generated | 206 | * @generated |
196 | */ | 207 | */ |
208 | @Override | ||
197 | public StringElement createStringElement() { | 209 | public StringElement createStringElement() { |
198 | StringElementImpl stringElement = new StringElementImpl(); | 210 | StringElementImpl stringElement = new StringElementImpl(); |
199 | return stringElement; | 211 | return stringElement; |
@@ -204,6 +216,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
204 | * <!-- end-user-doc --> | 216 | * <!-- end-user-doc --> |
205 | * @generated | 217 | * @generated |
206 | */ | 218 | */ |
219 | @Override | ||
207 | public Scope createScope() { | 220 | public Scope createScope() { |
208 | ScopeImpl scope = new ScopeImpl(); | 221 | ScopeImpl scope = new ScopeImpl(); |
209 | return scope; | 222 | return scope; |
@@ -214,6 +227,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
214 | * <!-- end-user-doc --> | 227 | * <!-- end-user-doc --> |
215 | * @generated | 228 | * @generated |
216 | */ | 229 | */ |
230 | @Override | ||
217 | public PartialBooleanInterpretation createPartialBooleanInterpretation() { | 231 | public PartialBooleanInterpretation createPartialBooleanInterpretation() { |
218 | PartialBooleanInterpretationImpl partialBooleanInterpretation = new PartialBooleanInterpretationImpl(); | 232 | PartialBooleanInterpretationImpl partialBooleanInterpretation = new PartialBooleanInterpretationImpl(); |
219 | return partialBooleanInterpretation; | 233 | return partialBooleanInterpretation; |
@@ -224,6 +238,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
224 | * <!-- end-user-doc --> | 238 | * <!-- end-user-doc --> |
225 | * @generated | 239 | * @generated |
226 | */ | 240 | */ |
241 | @Override | ||
227 | public PartialIntegerInterpretation createPartialIntegerInterpretation() { | 242 | public PartialIntegerInterpretation createPartialIntegerInterpretation() { |
228 | PartialIntegerInterpretationImpl partialIntegerInterpretation = new PartialIntegerInterpretationImpl(); | 243 | PartialIntegerInterpretationImpl partialIntegerInterpretation = new PartialIntegerInterpretationImpl(); |
229 | return partialIntegerInterpretation; | 244 | return partialIntegerInterpretation; |
@@ -234,6 +249,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
234 | * <!-- end-user-doc --> | 249 | * <!-- end-user-doc --> |
235 | * @generated | 250 | * @generated |
236 | */ | 251 | */ |
252 | @Override | ||
237 | public PartialRealInterpretation createPartialRealInterpretation() { | 253 | public PartialRealInterpretation createPartialRealInterpretation() { |
238 | PartialRealInterpretationImpl partialRealInterpretation = new PartialRealInterpretationImpl(); | 254 | PartialRealInterpretationImpl partialRealInterpretation = new PartialRealInterpretationImpl(); |
239 | return partialRealInterpretation; | 255 | return partialRealInterpretation; |
@@ -244,6 +260,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
244 | * <!-- end-user-doc --> | 260 | * <!-- end-user-doc --> |
245 | * @generated | 261 | * @generated |
246 | */ | 262 | */ |
263 | @Override | ||
247 | public PartialStringInterpretation createPartialStringInterpretation() { | 264 | public PartialStringInterpretation createPartialStringInterpretation() { |
248 | PartialStringInterpretationImpl partialStringInterpretation = new PartialStringInterpretationImpl(); | 265 | PartialStringInterpretationImpl partialStringInterpretation = new PartialStringInterpretationImpl(); |
249 | return partialStringInterpretation; | 266 | return partialStringInterpretation; |
@@ -254,6 +271,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
254 | * <!-- end-user-doc --> | 271 | * <!-- end-user-doc --> |
255 | * @generated | 272 | * @generated |
256 | */ | 273 | */ |
274 | @Override | ||
257 | public PartialComplexTypeInterpretation createPartialComplexTypeInterpretation() { | 275 | public PartialComplexTypeInterpretation createPartialComplexTypeInterpretation() { |
258 | PartialComplexTypeInterpretationImpl partialComplexTypeInterpretation = new PartialComplexTypeInterpretationImpl(); | 276 | PartialComplexTypeInterpretationImpl partialComplexTypeInterpretation = new PartialComplexTypeInterpretationImpl(); |
259 | return partialComplexTypeInterpretation; | 277 | return partialComplexTypeInterpretation; |
@@ -264,6 +282,7 @@ public class PartialinterpretationFactoryImpl extends EFactoryImpl implements Pa | |||
264 | * <!-- end-user-doc --> | 282 | * <!-- end-user-doc --> |
265 | * @generated | 283 | * @generated |
266 | */ | 284 | */ |
285 | @Override | ||
267 | public PartialinterpretationPackage getPartialinterpretationPackage() { | 286 | public PartialinterpretationPackage getPartialinterpretationPackage() { |
268 | return (PartialinterpretationPackage)getEPackage(); | 287 | return (PartialinterpretationPackage)getEPackage(); |
269 | } | 288 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialinterpretationPackageImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialinterpretationPackageImpl.java index a21dc306..1ea3a11d 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialinterpretationPackageImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PartialinterpretationPackageImpl.java | |||
@@ -227,7 +227,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
227 | 227 | ||
228 | /** | 228 | /** |
229 | * Creates, registers, and initializes the <b>Package</b> for this model, and for any others upon which it depends. | 229 | * Creates, registers, and initializes the <b>Package</b> for this model, and for any others upon which it depends. |
230 | * | 230 | * |
231 | * <p>This method is used to initialize {@link PartialinterpretationPackage#eINSTANCE} when that field is accessed. | 231 | * <p>This method is used to initialize {@link PartialinterpretationPackage#eINSTANCE} when that field is accessed. |
232 | * Clients should not invoke it directly. Instead, they should simply access that field to obtain the package. | 232 | * Clients should not invoke it directly. Instead, they should simply access that field to obtain the package. |
233 | * <!-- begin-user-doc --> | 233 | * <!-- begin-user-doc --> |
@@ -241,7 +241,8 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
241 | if (isInited) return (PartialinterpretationPackage)EPackage.Registry.INSTANCE.getEPackage(PartialinterpretationPackage.eNS_URI); | 241 | if (isInited) return (PartialinterpretationPackage)EPackage.Registry.INSTANCE.getEPackage(PartialinterpretationPackage.eNS_URI); |
242 | 242 | ||
243 | // Obtain or create and register package | 243 | // Obtain or create and register package |
244 | PartialinterpretationPackageImpl thePartialinterpretationPackage = (PartialinterpretationPackageImpl)(EPackage.Registry.INSTANCE.get(eNS_URI) instanceof PartialinterpretationPackageImpl ? EPackage.Registry.INSTANCE.get(eNS_URI) : new PartialinterpretationPackageImpl()); | 244 | Object registeredPartialinterpretationPackage = EPackage.Registry.INSTANCE.get(eNS_URI); |
245 | PartialinterpretationPackageImpl thePartialinterpretationPackage = registeredPartialinterpretationPackage instanceof PartialinterpretationPackageImpl ? (PartialinterpretationPackageImpl)registeredPartialinterpretationPackage : new PartialinterpretationPackageImpl(); | ||
245 | 246 | ||
246 | isInited = true; | 247 | isInited = true; |
247 | 248 | ||
@@ -258,7 +259,6 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
258 | // Mark meta-data to indicate it can't be changed | 259 | // Mark meta-data to indicate it can't be changed |
259 | thePartialinterpretationPackage.freeze(); | 260 | thePartialinterpretationPackage.freeze(); |
260 | 261 | ||
261 | |||
262 | // Update the registry and return the package | 262 | // Update the registry and return the package |
263 | EPackage.Registry.INSTANCE.put(PartialinterpretationPackage.eNS_URI, thePartialinterpretationPackage); | 263 | EPackage.Registry.INSTANCE.put(PartialinterpretationPackage.eNS_URI, thePartialinterpretationPackage); |
264 | return thePartialinterpretationPackage; | 264 | return thePartialinterpretationPackage; |
@@ -269,6 +269,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
269 | * <!-- end-user-doc --> | 269 | * <!-- end-user-doc --> |
270 | * @generated | 270 | * @generated |
271 | */ | 271 | */ |
272 | @Override | ||
272 | public EClass getPartialInterpretation() { | 273 | public EClass getPartialInterpretation() { |
273 | return partialInterpretationEClass; | 274 | return partialInterpretationEClass; |
274 | } | 275 | } |
@@ -278,6 +279,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
278 | * <!-- end-user-doc --> | 279 | * <!-- end-user-doc --> |
279 | * @generated | 280 | * @generated |
280 | */ | 281 | */ |
282 | @Override | ||
281 | public EReference getPartialInterpretation_Problem() { | 283 | public EReference getPartialInterpretation_Problem() { |
282 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(0); | 284 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(0); |
283 | } | 285 | } |
@@ -287,6 +289,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
287 | * <!-- end-user-doc --> | 289 | * <!-- end-user-doc --> |
288 | * @generated | 290 | * @generated |
289 | */ | 291 | */ |
292 | @Override | ||
290 | public EReference getPartialInterpretation_Partialconstantinterpretation() { | 293 | public EReference getPartialInterpretation_Partialconstantinterpretation() { |
291 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(1); | 294 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(1); |
292 | } | 295 | } |
@@ -296,6 +299,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
296 | * <!-- end-user-doc --> | 299 | * <!-- end-user-doc --> |
297 | * @generated | 300 | * @generated |
298 | */ | 301 | */ |
302 | @Override | ||
299 | public EReference getPartialInterpretation_Partialrelationinterpretation() { | 303 | public EReference getPartialInterpretation_Partialrelationinterpretation() { |
300 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(2); | 304 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(2); |
301 | } | 305 | } |
@@ -305,6 +309,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
305 | * <!-- end-user-doc --> | 309 | * <!-- end-user-doc --> |
306 | * @generated | 310 | * @generated |
307 | */ | 311 | */ |
312 | @Override | ||
308 | public EReference getPartialInterpretation_Partialfunctioninterpretation() { | 313 | public EReference getPartialInterpretation_Partialfunctioninterpretation() { |
309 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(3); | 314 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(3); |
310 | } | 315 | } |
@@ -314,6 +319,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
314 | * <!-- end-user-doc --> | 319 | * <!-- end-user-doc --> |
315 | * @generated | 320 | * @generated |
316 | */ | 321 | */ |
322 | @Override | ||
317 | public EReference getPartialInterpretation_NewElements() { | 323 | public EReference getPartialInterpretation_NewElements() { |
318 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(4); | 324 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(4); |
319 | } | 325 | } |
@@ -323,6 +329,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
323 | * <!-- end-user-doc --> | 329 | * <!-- end-user-doc --> |
324 | * @generated | 330 | * @generated |
325 | */ | 331 | */ |
332 | @Override | ||
326 | public EReference getPartialInterpretation_Partialtypeinterpratation() { | 333 | public EReference getPartialInterpretation_Partialtypeinterpratation() { |
327 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(5); | 334 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(5); |
328 | } | 335 | } |
@@ -332,6 +339,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
332 | * <!-- end-user-doc --> | 339 | * <!-- end-user-doc --> |
333 | * @generated | 340 | * @generated |
334 | */ | 341 | */ |
342 | @Override | ||
335 | public EReference getPartialInterpretation_OpenWorldElements() { | 343 | public EReference getPartialInterpretation_OpenWorldElements() { |
336 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(6); | 344 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(6); |
337 | } | 345 | } |
@@ -341,6 +349,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
341 | * <!-- end-user-doc --> | 349 | * <!-- end-user-doc --> |
342 | * @generated | 350 | * @generated |
343 | */ | 351 | */ |
352 | @Override | ||
344 | public EReference getPartialInterpretation_ProblemConainer() { | 353 | public EReference getPartialInterpretation_ProblemConainer() { |
345 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(7); | 354 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(7); |
346 | } | 355 | } |
@@ -350,6 +359,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
350 | * <!-- end-user-doc --> | 359 | * <!-- end-user-doc --> |
351 | * @generated | 360 | * @generated |
352 | */ | 361 | */ |
362 | @Override | ||
353 | public EReference getPartialInterpretation_Scopes() { | 363 | public EReference getPartialInterpretation_Scopes() { |
354 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(8); | 364 | return (EReference)partialInterpretationEClass.getEStructuralFeatures().get(8); |
355 | } | 365 | } |
@@ -359,6 +369,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
359 | * <!-- end-user-doc --> | 369 | * <!-- end-user-doc --> |
360 | * @generated | 370 | * @generated |
361 | */ | 371 | */ |
372 | @Override | ||
362 | public EAttribute getPartialInterpretation_MinNewElements() { | 373 | public EAttribute getPartialInterpretation_MinNewElements() { |
363 | return (EAttribute)partialInterpretationEClass.getEStructuralFeatures().get(9); | 374 | return (EAttribute)partialInterpretationEClass.getEStructuralFeatures().get(9); |
364 | } | 375 | } |
@@ -368,6 +379,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
368 | * <!-- end-user-doc --> | 379 | * <!-- end-user-doc --> |
369 | * @generated | 380 | * @generated |
370 | */ | 381 | */ |
382 | @Override | ||
371 | public EAttribute getPartialInterpretation_MaxNewElements() { | 383 | public EAttribute getPartialInterpretation_MaxNewElements() { |
372 | return (EAttribute)partialInterpretationEClass.getEStructuralFeatures().get(10); | 384 | return (EAttribute)partialInterpretationEClass.getEStructuralFeatures().get(10); |
373 | } | 385 | } |
@@ -377,6 +389,17 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
377 | * <!-- end-user-doc --> | 389 | * <!-- end-user-doc --> |
378 | * @generated | 390 | * @generated |
379 | */ | 391 | */ |
392 | @Override | ||
393 | public EAttribute getPartialInterpretation_MinNewElementsHeuristic() { | ||
394 | return (EAttribute)partialInterpretationEClass.getEStructuralFeatures().get(11); | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * <!-- begin-user-doc --> | ||
399 | * <!-- end-user-doc --> | ||
400 | * @generated | ||
401 | */ | ||
402 | @Override | ||
380 | public EClass getPartialConstantInterpretation() { | 403 | public EClass getPartialConstantInterpretation() { |
381 | return partialConstantInterpretationEClass; | 404 | return partialConstantInterpretationEClass; |
382 | } | 405 | } |
@@ -386,6 +409,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
386 | * <!-- end-user-doc --> | 409 | * <!-- end-user-doc --> |
387 | * @generated | 410 | * @generated |
388 | */ | 411 | */ |
412 | @Override | ||
389 | public EReference getPartialConstantInterpretation_InterpretationOf() { | 413 | public EReference getPartialConstantInterpretation_InterpretationOf() { |
390 | return (EReference)partialConstantInterpretationEClass.getEStructuralFeatures().get(0); | 414 | return (EReference)partialConstantInterpretationEClass.getEStructuralFeatures().get(0); |
391 | } | 415 | } |
@@ -395,6 +419,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
395 | * <!-- end-user-doc --> | 419 | * <!-- end-user-doc --> |
396 | * @generated | 420 | * @generated |
397 | */ | 421 | */ |
422 | @Override | ||
398 | public EClass getPartialRelationInterpretation() { | 423 | public EClass getPartialRelationInterpretation() { |
399 | return partialRelationInterpretationEClass; | 424 | return partialRelationInterpretationEClass; |
400 | } | 425 | } |
@@ -404,6 +429,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
404 | * <!-- end-user-doc --> | 429 | * <!-- end-user-doc --> |
405 | * @generated | 430 | * @generated |
406 | */ | 431 | */ |
432 | @Override | ||
407 | public EReference getPartialRelationInterpretation_InterpretationOf() { | 433 | public EReference getPartialRelationInterpretation_InterpretationOf() { |
408 | return (EReference)partialRelationInterpretationEClass.getEStructuralFeatures().get(0); | 434 | return (EReference)partialRelationInterpretationEClass.getEStructuralFeatures().get(0); |
409 | } | 435 | } |
@@ -413,6 +439,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
413 | * <!-- end-user-doc --> | 439 | * <!-- end-user-doc --> |
414 | * @generated | 440 | * @generated |
415 | */ | 441 | */ |
442 | @Override | ||
416 | public EReference getPartialRelationInterpretation_Relationlinks() { | 443 | public EReference getPartialRelationInterpretation_Relationlinks() { |
417 | return (EReference)partialRelationInterpretationEClass.getEStructuralFeatures().get(1); | 444 | return (EReference)partialRelationInterpretationEClass.getEStructuralFeatures().get(1); |
418 | } | 445 | } |
@@ -422,6 +449,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
422 | * <!-- end-user-doc --> | 449 | * <!-- end-user-doc --> |
423 | * @generated | 450 | * @generated |
424 | */ | 451 | */ |
452 | @Override | ||
425 | public EReference getPartialRelationInterpretation_Param1() { | 453 | public EReference getPartialRelationInterpretation_Param1() { |
426 | return (EReference)partialRelationInterpretationEClass.getEStructuralFeatures().get(2); | 454 | return (EReference)partialRelationInterpretationEClass.getEStructuralFeatures().get(2); |
427 | } | 455 | } |
@@ -431,6 +459,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
431 | * <!-- end-user-doc --> | 459 | * <!-- end-user-doc --> |
432 | * @generated | 460 | * @generated |
433 | */ | 461 | */ |
462 | @Override | ||
434 | public EReference getPartialRelationInterpretation_Param2() { | 463 | public EReference getPartialRelationInterpretation_Param2() { |
435 | return (EReference)partialRelationInterpretationEClass.getEStructuralFeatures().get(3); | 464 | return (EReference)partialRelationInterpretationEClass.getEStructuralFeatures().get(3); |
436 | } | 465 | } |
@@ -440,6 +469,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
440 | * <!-- end-user-doc --> | 469 | * <!-- end-user-doc --> |
441 | * @generated | 470 | * @generated |
442 | */ | 471 | */ |
472 | @Override | ||
443 | public EClass getPartialFunctionInterpretation() { | 473 | public EClass getPartialFunctionInterpretation() { |
444 | return partialFunctionInterpretationEClass; | 474 | return partialFunctionInterpretationEClass; |
445 | } | 475 | } |
@@ -449,6 +479,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
449 | * <!-- end-user-doc --> | 479 | * <!-- end-user-doc --> |
450 | * @generated | 480 | * @generated |
451 | */ | 481 | */ |
482 | @Override | ||
452 | public EReference getPartialFunctionInterpretation_InterpretationOf() { | 483 | public EReference getPartialFunctionInterpretation_InterpretationOf() { |
453 | return (EReference)partialFunctionInterpretationEClass.getEStructuralFeatures().get(0); | 484 | return (EReference)partialFunctionInterpretationEClass.getEStructuralFeatures().get(0); |
454 | } | 485 | } |
@@ -458,6 +489,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
458 | * <!-- end-user-doc --> | 489 | * <!-- end-user-doc --> |
459 | * @generated | 490 | * @generated |
460 | */ | 491 | */ |
492 | @Override | ||
461 | public EClass getPartialTypeInterpratation() { | 493 | public EClass getPartialTypeInterpratation() { |
462 | return partialTypeInterpratationEClass; | 494 | return partialTypeInterpratationEClass; |
463 | } | 495 | } |
@@ -467,6 +499,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
467 | * <!-- end-user-doc --> | 499 | * <!-- end-user-doc --> |
468 | * @generated | 500 | * @generated |
469 | */ | 501 | */ |
502 | @Override | ||
470 | public EReference getPartialTypeInterpratation_Elements() { | 503 | public EReference getPartialTypeInterpratation_Elements() { |
471 | return (EReference)partialTypeInterpratationEClass.getEStructuralFeatures().get(0); | 504 | return (EReference)partialTypeInterpratationEClass.getEStructuralFeatures().get(0); |
472 | } | 505 | } |
@@ -476,6 +509,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
476 | * <!-- end-user-doc --> | 509 | * <!-- end-user-doc --> |
477 | * @generated | 510 | * @generated |
478 | */ | 511 | */ |
512 | @Override | ||
479 | public EReference getPartialTypeInterpratation_Scopes() { | 513 | public EReference getPartialTypeInterpratation_Scopes() { |
480 | return (EReference)partialTypeInterpratationEClass.getEStructuralFeatures().get(1); | 514 | return (EReference)partialTypeInterpratationEClass.getEStructuralFeatures().get(1); |
481 | } | 515 | } |
@@ -485,6 +519,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
485 | * <!-- end-user-doc --> | 519 | * <!-- end-user-doc --> |
486 | * @generated | 520 | * @generated |
487 | */ | 521 | */ |
522 | @Override | ||
488 | public EClass getRelationLink() { | 523 | public EClass getRelationLink() { |
489 | return relationLinkEClass; | 524 | return relationLinkEClass; |
490 | } | 525 | } |
@@ -494,6 +529,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
494 | * <!-- end-user-doc --> | 529 | * <!-- end-user-doc --> |
495 | * @generated | 530 | * @generated |
496 | */ | 531 | */ |
532 | @Override | ||
497 | public EClass getUnaryElementRelationLink() { | 533 | public EClass getUnaryElementRelationLink() { |
498 | return unaryElementRelationLinkEClass; | 534 | return unaryElementRelationLinkEClass; |
499 | } | 535 | } |
@@ -503,6 +539,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
503 | * <!-- end-user-doc --> | 539 | * <!-- end-user-doc --> |
504 | * @generated | 540 | * @generated |
505 | */ | 541 | */ |
542 | @Override | ||
506 | public EReference getUnaryElementRelationLink_Param1() { | 543 | public EReference getUnaryElementRelationLink_Param1() { |
507 | return (EReference)unaryElementRelationLinkEClass.getEStructuralFeatures().get(0); | 544 | return (EReference)unaryElementRelationLinkEClass.getEStructuralFeatures().get(0); |
508 | } | 545 | } |
@@ -512,6 +549,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
512 | * <!-- end-user-doc --> | 549 | * <!-- end-user-doc --> |
513 | * @generated | 550 | * @generated |
514 | */ | 551 | */ |
552 | @Override | ||
515 | public EClass getBinaryElementRelationLink() { | 553 | public EClass getBinaryElementRelationLink() { |
516 | return binaryElementRelationLinkEClass; | 554 | return binaryElementRelationLinkEClass; |
517 | } | 555 | } |
@@ -521,6 +559,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
521 | * <!-- end-user-doc --> | 559 | * <!-- end-user-doc --> |
522 | * @generated | 560 | * @generated |
523 | */ | 561 | */ |
562 | @Override | ||
524 | public EReference getBinaryElementRelationLink_Param1() { | 563 | public EReference getBinaryElementRelationLink_Param1() { |
525 | return (EReference)binaryElementRelationLinkEClass.getEStructuralFeatures().get(0); | 564 | return (EReference)binaryElementRelationLinkEClass.getEStructuralFeatures().get(0); |
526 | } | 565 | } |
@@ -530,6 +569,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
530 | * <!-- end-user-doc --> | 569 | * <!-- end-user-doc --> |
531 | * @generated | 570 | * @generated |
532 | */ | 571 | */ |
572 | @Override | ||
533 | public EReference getBinaryElementRelationLink_Param2() { | 573 | public EReference getBinaryElementRelationLink_Param2() { |
534 | return (EReference)binaryElementRelationLinkEClass.getEStructuralFeatures().get(1); | 574 | return (EReference)binaryElementRelationLinkEClass.getEStructuralFeatures().get(1); |
535 | } | 575 | } |
@@ -539,6 +579,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
539 | * <!-- end-user-doc --> | 579 | * <!-- end-user-doc --> |
540 | * @generated | 580 | * @generated |
541 | */ | 581 | */ |
582 | @Override | ||
542 | public EClass getNaryRelationLink() { | 583 | public EClass getNaryRelationLink() { |
543 | return naryRelationLinkEClass; | 584 | return naryRelationLinkEClass; |
544 | } | 585 | } |
@@ -548,6 +589,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
548 | * <!-- end-user-doc --> | 589 | * <!-- end-user-doc --> |
549 | * @generated | 590 | * @generated |
550 | */ | 591 | */ |
592 | @Override | ||
551 | public EReference getNaryRelationLink_Elements() { | 593 | public EReference getNaryRelationLink_Elements() { |
552 | return (EReference)naryRelationLinkEClass.getEStructuralFeatures().get(0); | 594 | return (EReference)naryRelationLinkEClass.getEStructuralFeatures().get(0); |
553 | } | 595 | } |
@@ -557,6 +599,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
557 | * <!-- end-user-doc --> | 599 | * <!-- end-user-doc --> |
558 | * @generated | 600 | * @generated |
559 | */ | 601 | */ |
602 | @Override | ||
560 | public EClass getNaryRelationLinkElement() { | 603 | public EClass getNaryRelationLinkElement() { |
561 | return naryRelationLinkElementEClass; | 604 | return naryRelationLinkElementEClass; |
562 | } | 605 | } |
@@ -566,6 +609,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
566 | * <!-- end-user-doc --> | 609 | * <!-- end-user-doc --> |
567 | * @generated | 610 | * @generated |
568 | */ | 611 | */ |
612 | @Override | ||
569 | public EAttribute getNaryRelationLinkElement_Index() { | 613 | public EAttribute getNaryRelationLinkElement_Index() { |
570 | return (EAttribute)naryRelationLinkElementEClass.getEStructuralFeatures().get(0); | 614 | return (EAttribute)naryRelationLinkElementEClass.getEStructuralFeatures().get(0); |
571 | } | 615 | } |
@@ -575,6 +619,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
575 | * <!-- end-user-doc --> | 619 | * <!-- end-user-doc --> |
576 | * @generated | 620 | * @generated |
577 | */ | 621 | */ |
622 | @Override | ||
578 | public EReference getNaryRelationLinkElement_Param() { | 623 | public EReference getNaryRelationLinkElement_Param() { |
579 | return (EReference)naryRelationLinkElementEClass.getEStructuralFeatures().get(1); | 624 | return (EReference)naryRelationLinkElementEClass.getEStructuralFeatures().get(1); |
580 | } | 625 | } |
@@ -584,6 +629,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
584 | * <!-- end-user-doc --> | 629 | * <!-- end-user-doc --> |
585 | * @generated | 630 | * @generated |
586 | */ | 631 | */ |
632 | @Override | ||
587 | public EClass getPrimitiveElement() { | 633 | public EClass getPrimitiveElement() { |
588 | return primitiveElementEClass; | 634 | return primitiveElementEClass; |
589 | } | 635 | } |
@@ -593,6 +639,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
593 | * <!-- end-user-doc --> | 639 | * <!-- end-user-doc --> |
594 | * @generated | 640 | * @generated |
595 | */ | 641 | */ |
642 | @Override | ||
596 | public EAttribute getPrimitiveElement_ValueSet() { | 643 | public EAttribute getPrimitiveElement_ValueSet() { |
597 | return (EAttribute)primitiveElementEClass.getEStructuralFeatures().get(0); | 644 | return (EAttribute)primitiveElementEClass.getEStructuralFeatures().get(0); |
598 | } | 645 | } |
@@ -602,6 +649,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
602 | * <!-- end-user-doc --> | 649 | * <!-- end-user-doc --> |
603 | * @generated | 650 | * @generated |
604 | */ | 651 | */ |
652 | @Override | ||
605 | public EClass getBooleanElement() { | 653 | public EClass getBooleanElement() { |
606 | return booleanElementEClass; | 654 | return booleanElementEClass; |
607 | } | 655 | } |
@@ -611,6 +659,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
611 | * <!-- end-user-doc --> | 659 | * <!-- end-user-doc --> |
612 | * @generated | 660 | * @generated |
613 | */ | 661 | */ |
662 | @Override | ||
614 | public EAttribute getBooleanElement_Value() { | 663 | public EAttribute getBooleanElement_Value() { |
615 | return (EAttribute)booleanElementEClass.getEStructuralFeatures().get(0); | 664 | return (EAttribute)booleanElementEClass.getEStructuralFeatures().get(0); |
616 | } | 665 | } |
@@ -620,6 +669,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
620 | * <!-- end-user-doc --> | 669 | * <!-- end-user-doc --> |
621 | * @generated | 670 | * @generated |
622 | */ | 671 | */ |
672 | @Override | ||
623 | public EClass getIntegerElement() { | 673 | public EClass getIntegerElement() { |
624 | return integerElementEClass; | 674 | return integerElementEClass; |
625 | } | 675 | } |
@@ -629,6 +679,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
629 | * <!-- end-user-doc --> | 679 | * <!-- end-user-doc --> |
630 | * @generated | 680 | * @generated |
631 | */ | 681 | */ |
682 | @Override | ||
632 | public EAttribute getIntegerElement_Value() { | 683 | public EAttribute getIntegerElement_Value() { |
633 | return (EAttribute)integerElementEClass.getEStructuralFeatures().get(0); | 684 | return (EAttribute)integerElementEClass.getEStructuralFeatures().get(0); |
634 | } | 685 | } |
@@ -638,6 +689,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
638 | * <!-- end-user-doc --> | 689 | * <!-- end-user-doc --> |
639 | * @generated | 690 | * @generated |
640 | */ | 691 | */ |
692 | @Override | ||
641 | public EClass getRealElement() { | 693 | public EClass getRealElement() { |
642 | return realElementEClass; | 694 | return realElementEClass; |
643 | } | 695 | } |
@@ -647,6 +699,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
647 | * <!-- end-user-doc --> | 699 | * <!-- end-user-doc --> |
648 | * @generated | 700 | * @generated |
649 | */ | 701 | */ |
702 | @Override | ||
650 | public EAttribute getRealElement_Value() { | 703 | public EAttribute getRealElement_Value() { |
651 | return (EAttribute)realElementEClass.getEStructuralFeatures().get(0); | 704 | return (EAttribute)realElementEClass.getEStructuralFeatures().get(0); |
652 | } | 705 | } |
@@ -656,6 +709,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
656 | * <!-- end-user-doc --> | 709 | * <!-- end-user-doc --> |
657 | * @generated | 710 | * @generated |
658 | */ | 711 | */ |
712 | @Override | ||
659 | public EClass getStringElement() { | 713 | public EClass getStringElement() { |
660 | return stringElementEClass; | 714 | return stringElementEClass; |
661 | } | 715 | } |
@@ -665,6 +719,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
665 | * <!-- end-user-doc --> | 719 | * <!-- end-user-doc --> |
666 | * @generated | 720 | * @generated |
667 | */ | 721 | */ |
722 | @Override | ||
668 | public EAttribute getStringElement_Value() { | 723 | public EAttribute getStringElement_Value() { |
669 | return (EAttribute)stringElementEClass.getEStructuralFeatures().get(0); | 724 | return (EAttribute)stringElementEClass.getEStructuralFeatures().get(0); |
670 | } | 725 | } |
@@ -674,6 +729,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
674 | * <!-- end-user-doc --> | 729 | * <!-- end-user-doc --> |
675 | * @generated | 730 | * @generated |
676 | */ | 731 | */ |
732 | @Override | ||
677 | public EClass getScope() { | 733 | public EClass getScope() { |
678 | return scopeEClass; | 734 | return scopeEClass; |
679 | } | 735 | } |
@@ -683,6 +739,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
683 | * <!-- end-user-doc --> | 739 | * <!-- end-user-doc --> |
684 | * @generated | 740 | * @generated |
685 | */ | 741 | */ |
742 | @Override | ||
686 | public EAttribute getScope_MinNewElements() { | 743 | public EAttribute getScope_MinNewElements() { |
687 | return (EAttribute)scopeEClass.getEStructuralFeatures().get(0); | 744 | return (EAttribute)scopeEClass.getEStructuralFeatures().get(0); |
688 | } | 745 | } |
@@ -692,6 +749,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
692 | * <!-- end-user-doc --> | 749 | * <!-- end-user-doc --> |
693 | * @generated | 750 | * @generated |
694 | */ | 751 | */ |
752 | @Override | ||
695 | public EAttribute getScope_MaxNewElements() { | 753 | public EAttribute getScope_MaxNewElements() { |
696 | return (EAttribute)scopeEClass.getEStructuralFeatures().get(1); | 754 | return (EAttribute)scopeEClass.getEStructuralFeatures().get(1); |
697 | } | 755 | } |
@@ -701,6 +759,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
701 | * <!-- end-user-doc --> | 759 | * <!-- end-user-doc --> |
702 | * @generated | 760 | * @generated |
703 | */ | 761 | */ |
762 | @Override | ||
704 | public EReference getScope_TargetTypeInterpretation() { | 763 | public EReference getScope_TargetTypeInterpretation() { |
705 | return (EReference)scopeEClass.getEStructuralFeatures().get(2); | 764 | return (EReference)scopeEClass.getEStructuralFeatures().get(2); |
706 | } | 765 | } |
@@ -710,6 +769,17 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
710 | * <!-- end-user-doc --> | 769 | * <!-- end-user-doc --> |
711 | * @generated | 770 | * @generated |
712 | */ | 771 | */ |
772 | @Override | ||
773 | public EAttribute getScope_MinNewElementsHeuristic() { | ||
774 | return (EAttribute)scopeEClass.getEStructuralFeatures().get(3); | ||
775 | } | ||
776 | |||
777 | /** | ||
778 | * <!-- begin-user-doc --> | ||
779 | * <!-- end-user-doc --> | ||
780 | * @generated | ||
781 | */ | ||
782 | @Override | ||
713 | public EClass getPartialPrimitiveInterpretation() { | 783 | public EClass getPartialPrimitiveInterpretation() { |
714 | return partialPrimitiveInterpretationEClass; | 784 | return partialPrimitiveInterpretationEClass; |
715 | } | 785 | } |
@@ -719,6 +789,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
719 | * <!-- end-user-doc --> | 789 | * <!-- end-user-doc --> |
720 | * @generated | 790 | * @generated |
721 | */ | 791 | */ |
792 | @Override | ||
722 | public EClass getPartialBooleanInterpretation() { | 793 | public EClass getPartialBooleanInterpretation() { |
723 | return partialBooleanInterpretationEClass; | 794 | return partialBooleanInterpretationEClass; |
724 | } | 795 | } |
@@ -728,6 +799,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
728 | * <!-- end-user-doc --> | 799 | * <!-- end-user-doc --> |
729 | * @generated | 800 | * @generated |
730 | */ | 801 | */ |
802 | @Override | ||
731 | public EClass getPartialIntegerInterpretation() { | 803 | public EClass getPartialIntegerInterpretation() { |
732 | return partialIntegerInterpretationEClass; | 804 | return partialIntegerInterpretationEClass; |
733 | } | 805 | } |
@@ -737,6 +809,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
737 | * <!-- end-user-doc --> | 809 | * <!-- end-user-doc --> |
738 | * @generated | 810 | * @generated |
739 | */ | 811 | */ |
812 | @Override | ||
740 | public EClass getPartialRealInterpretation() { | 813 | public EClass getPartialRealInterpretation() { |
741 | return partialRealInterpretationEClass; | 814 | return partialRealInterpretationEClass; |
742 | } | 815 | } |
@@ -746,6 +819,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
746 | * <!-- end-user-doc --> | 819 | * <!-- end-user-doc --> |
747 | * @generated | 820 | * @generated |
748 | */ | 821 | */ |
822 | @Override | ||
749 | public EClass getPartialStringInterpretation() { | 823 | public EClass getPartialStringInterpretation() { |
750 | return partialStringInterpretationEClass; | 824 | return partialStringInterpretationEClass; |
751 | } | 825 | } |
@@ -755,6 +829,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
755 | * <!-- end-user-doc --> | 829 | * <!-- end-user-doc --> |
756 | * @generated | 830 | * @generated |
757 | */ | 831 | */ |
832 | @Override | ||
758 | public EClass getPartialComplexTypeInterpretation() { | 833 | public EClass getPartialComplexTypeInterpretation() { |
759 | return partialComplexTypeInterpretationEClass; | 834 | return partialComplexTypeInterpretationEClass; |
760 | } | 835 | } |
@@ -764,6 +839,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
764 | * <!-- end-user-doc --> | 839 | * <!-- end-user-doc --> |
765 | * @generated | 840 | * @generated |
766 | */ | 841 | */ |
842 | @Override | ||
767 | public EReference getPartialComplexTypeInterpretation_SupertypeInterpretation() { | 843 | public EReference getPartialComplexTypeInterpretation_SupertypeInterpretation() { |
768 | return (EReference)partialComplexTypeInterpretationEClass.getEStructuralFeatures().get(0); | 844 | return (EReference)partialComplexTypeInterpretationEClass.getEStructuralFeatures().get(0); |
769 | } | 845 | } |
@@ -773,6 +849,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
773 | * <!-- end-user-doc --> | 849 | * <!-- end-user-doc --> |
774 | * @generated | 850 | * @generated |
775 | */ | 851 | */ |
852 | @Override | ||
776 | public EReference getPartialComplexTypeInterpretation_InterpretationOf() { | 853 | public EReference getPartialComplexTypeInterpretation_InterpretationOf() { |
777 | return (EReference)partialComplexTypeInterpretationEClass.getEStructuralFeatures().get(1); | 854 | return (EReference)partialComplexTypeInterpretationEClass.getEStructuralFeatures().get(1); |
778 | } | 855 | } |
@@ -782,6 +859,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
782 | * <!-- end-user-doc --> | 859 | * <!-- end-user-doc --> |
783 | * @generated | 860 | * @generated |
784 | */ | 861 | */ |
862 | @Override | ||
785 | public PartialinterpretationFactory getPartialinterpretationFactory() { | 863 | public PartialinterpretationFactory getPartialinterpretationFactory() { |
786 | return (PartialinterpretationFactory)getEFactoryInstance(); | 864 | return (PartialinterpretationFactory)getEFactoryInstance(); |
787 | } | 865 | } |
@@ -817,6 +895,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
817 | createEReference(partialInterpretationEClass, PARTIAL_INTERPRETATION__SCOPES); | 895 | createEReference(partialInterpretationEClass, PARTIAL_INTERPRETATION__SCOPES); |
818 | createEAttribute(partialInterpretationEClass, PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS); | 896 | createEAttribute(partialInterpretationEClass, PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS); |
819 | createEAttribute(partialInterpretationEClass, PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS); | 897 | createEAttribute(partialInterpretationEClass, PARTIAL_INTERPRETATION__MAX_NEW_ELEMENTS); |
898 | createEAttribute(partialInterpretationEClass, PARTIAL_INTERPRETATION__MIN_NEW_ELEMENTS_HEURISTIC); | ||
820 | 899 | ||
821 | partialConstantInterpretationEClass = createEClass(PARTIAL_CONSTANT_INTERPRETATION); | 900 | partialConstantInterpretationEClass = createEClass(PARTIAL_CONSTANT_INTERPRETATION); |
822 | createEReference(partialConstantInterpretationEClass, PARTIAL_CONSTANT_INTERPRETATION__INTERPRETATION_OF); | 901 | createEReference(partialConstantInterpretationEClass, PARTIAL_CONSTANT_INTERPRETATION__INTERPRETATION_OF); |
@@ -869,6 +948,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
869 | createEAttribute(scopeEClass, SCOPE__MIN_NEW_ELEMENTS); | 948 | createEAttribute(scopeEClass, SCOPE__MIN_NEW_ELEMENTS); |
870 | createEAttribute(scopeEClass, SCOPE__MAX_NEW_ELEMENTS); | 949 | createEAttribute(scopeEClass, SCOPE__MAX_NEW_ELEMENTS); |
871 | createEReference(scopeEClass, SCOPE__TARGET_TYPE_INTERPRETATION); | 950 | createEReference(scopeEClass, SCOPE__TARGET_TYPE_INTERPRETATION); |
951 | createEAttribute(scopeEClass, SCOPE__MIN_NEW_ELEMENTS_HEURISTIC); | ||
872 | 952 | ||
873 | partialPrimitiveInterpretationEClass = createEClass(PARTIAL_PRIMITIVE_INTERPRETATION); | 953 | partialPrimitiveInterpretationEClass = createEClass(PARTIAL_PRIMITIVE_INTERPRETATION); |
874 | 954 | ||
@@ -945,6 +1025,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
945 | initEReference(getPartialInterpretation_Scopes(), this.getScope(), null, "scopes", null, 0, -1, PartialInterpretation.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); | 1025 | initEReference(getPartialInterpretation_Scopes(), this.getScope(), null, "scopes", null, 0, -1, PartialInterpretation.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); |
946 | initEAttribute(getPartialInterpretation_MinNewElements(), ecorePackage.getEInt(), "minNewElements", "0", 1, 1, PartialInterpretation.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); | 1026 | initEAttribute(getPartialInterpretation_MinNewElements(), ecorePackage.getEInt(), "minNewElements", "0", 1, 1, PartialInterpretation.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); |
947 | initEAttribute(getPartialInterpretation_MaxNewElements(), ecorePackage.getEInt(), "maxNewElements", "-1", 1, 1, PartialInterpretation.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); | 1027 | initEAttribute(getPartialInterpretation_MaxNewElements(), ecorePackage.getEInt(), "maxNewElements", "-1", 1, 1, PartialInterpretation.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); |
1028 | initEAttribute(getPartialInterpretation_MinNewElementsHeuristic(), ecorePackage.getEInt(), "minNewElementsHeuristic", "0", 1, 1, PartialInterpretation.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); | ||
948 | 1029 | ||
949 | initEClass(partialConstantInterpretationEClass, PartialConstantInterpretation.class, "PartialConstantInterpretation", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); | 1030 | initEClass(partialConstantInterpretationEClass, PartialConstantInterpretation.class, "PartialConstantInterpretation", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); |
950 | initEReference(getPartialConstantInterpretation_InterpretationOf(), theLogiclanguagePackage.getConstantDeclaration(), null, "interpretationOf", null, 1, 1, PartialConstantInterpretation.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); | 1031 | initEReference(getPartialConstantInterpretation_InterpretationOf(), theLogiclanguagePackage.getConstantDeclaration(), null, "interpretationOf", null, 1, 1, PartialConstantInterpretation.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); |
@@ -997,6 +1078,7 @@ public class PartialinterpretationPackageImpl extends EPackageImpl implements Pa | |||
997 | initEAttribute(getScope_MinNewElements(), ecorePackage.getEInt(), "minNewElements", "0", 1, 1, Scope.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); | 1078 | initEAttribute(getScope_MinNewElements(), ecorePackage.getEInt(), "minNewElements", "0", 1, 1, Scope.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); |
998 | initEAttribute(getScope_MaxNewElements(), ecorePackage.getEInt(), "maxNewElements", "-1", 1, 1, Scope.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); | 1079 | initEAttribute(getScope_MaxNewElements(), ecorePackage.getEInt(), "maxNewElements", "-1", 1, 1, Scope.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); |
999 | initEReference(getScope_TargetTypeInterpretation(), this.getPartialTypeInterpratation(), this.getPartialTypeInterpratation_Scopes(), "targetTypeInterpretation", null, 1, 1, Scope.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); | 1080 | initEReference(getScope_TargetTypeInterpretation(), this.getPartialTypeInterpratation(), this.getPartialTypeInterpratation_Scopes(), "targetTypeInterpretation", null, 1, 1, Scope.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); |
1081 | initEAttribute(getScope_MinNewElementsHeuristic(), ecorePackage.getEInt(), "minNewElementsHeuristic", "0", 1, 1, Scope.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); | ||
1000 | 1082 | ||
1001 | initEClass(partialPrimitiveInterpretationEClass, PartialPrimitiveInterpretation.class, "PartialPrimitiveInterpretation", IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); | 1083 | initEClass(partialPrimitiveInterpretationEClass, PartialPrimitiveInterpretation.class, "PartialPrimitiveInterpretation", IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); |
1002 | 1084 | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PrimitiveElementImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PrimitiveElementImpl.java index 29a1e1be..a8ef81b0 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PrimitiveElementImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/PrimitiveElementImpl.java | |||
@@ -71,6 +71,7 @@ public abstract class PrimitiveElementImpl extends DefinedElementImpl implements | |||
71 | * <!-- end-user-doc --> | 71 | * <!-- end-user-doc --> |
72 | * @generated | 72 | * @generated |
73 | */ | 73 | */ |
74 | @Override | ||
74 | public boolean isValueSet() { | 75 | public boolean isValueSet() { |
75 | return valueSet; | 76 | return valueSet; |
76 | } | 77 | } |
@@ -80,6 +81,7 @@ public abstract class PrimitiveElementImpl extends DefinedElementImpl implements | |||
80 | * <!-- end-user-doc --> | 81 | * <!-- end-user-doc --> |
81 | * @generated | 82 | * @generated |
82 | */ | 83 | */ |
84 | @Override | ||
83 | public void setValueSet(boolean newValueSet) { | 85 | public void setValueSet(boolean newValueSet) { |
84 | boolean oldValueSet = valueSet; | 86 | boolean oldValueSet = valueSet; |
85 | valueSet = newValueSet; | 87 | valueSet = newValueSet; |
@@ -154,7 +156,7 @@ public abstract class PrimitiveElementImpl extends DefinedElementImpl implements | |||
154 | public String toString() { | 156 | public String toString() { |
155 | if (eIsProxy()) return super.toString(); | 157 | if (eIsProxy()) return super.toString(); |
156 | 158 | ||
157 | StringBuffer result = new StringBuffer(super.toString()); | 159 | StringBuilder result = new StringBuilder(super.toString()); |
158 | result.append(" (valueSet: "); | 160 | result.append(" (valueSet: "); |
159 | result.append(valueSet); | 161 | result.append(valueSet); |
160 | result.append(')'); | 162 | result.append(')'); |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/RealElementImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/RealElementImpl.java index 0361a3e9..67cff5a2 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/RealElementImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/RealElementImpl.java | |||
@@ -71,6 +71,7 @@ public class RealElementImpl extends PrimitiveElementImpl implements RealElement | |||
71 | * <!-- end-user-doc --> | 71 | * <!-- end-user-doc --> |
72 | * @generated | 72 | * @generated |
73 | */ | 73 | */ |
74 | @Override | ||
74 | public BigDecimal getValue() { | 75 | public BigDecimal getValue() { |
75 | return value; | 76 | return value; |
76 | } | 77 | } |
@@ -80,6 +81,7 @@ public class RealElementImpl extends PrimitiveElementImpl implements RealElement | |||
80 | * <!-- end-user-doc --> | 81 | * <!-- end-user-doc --> |
81 | * @generated | 82 | * @generated |
82 | */ | 83 | */ |
84 | @Override | ||
83 | public void setValue(BigDecimal newValue) { | 85 | public void setValue(BigDecimal newValue) { |
84 | BigDecimal oldValue = value; | 86 | BigDecimal oldValue = value; |
85 | value = newValue; | 87 | value = newValue; |
@@ -154,7 +156,7 @@ public class RealElementImpl extends PrimitiveElementImpl implements RealElement | |||
154 | public String toString() { | 156 | public String toString() { |
155 | if (eIsProxy()) return super.toString(); | 157 | if (eIsProxy()) return super.toString(); |
156 | 158 | ||
157 | StringBuffer result = new StringBuffer(super.toString()); | 159 | StringBuilder result = new StringBuilder(super.toString()); |
158 | result.append(" (value: "); | 160 | result.append(" (value: "); |
159 | result.append(value); | 161 | result.append(value); |
160 | result.append(')'); | 162 | result.append(')'); |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/ScopeImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/ScopeImpl.java index d8ade871..a1b6de35 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/ScopeImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/ScopeImpl.java | |||
@@ -26,6 +26,7 @@ import org.eclipse.emf.ecore.impl.MinimalEObjectImpl; | |||
26 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.ScopeImpl#getMinNewElements <em>Min New Elements</em>}</li> | 26 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.ScopeImpl#getMinNewElements <em>Min New Elements</em>}</li> |
27 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.ScopeImpl#getMaxNewElements <em>Max New Elements</em>}</li> | 27 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.ScopeImpl#getMaxNewElements <em>Max New Elements</em>}</li> |
28 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.ScopeImpl#getTargetTypeInterpretation <em>Target Type Interpretation</em>}</li> | 28 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.ScopeImpl#getTargetTypeInterpretation <em>Target Type Interpretation</em>}</li> |
29 | * <li>{@link hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.impl.ScopeImpl#getMinNewElementsHeuristic <em>Min New Elements Heuristic</em>}</li> | ||
29 | * </ul> | 30 | * </ul> |
30 | * | 31 | * |
31 | * @generated | 32 | * @generated |
@@ -82,6 +83,26 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
82 | protected PartialTypeInterpratation targetTypeInterpretation; | 83 | protected PartialTypeInterpratation targetTypeInterpretation; |
83 | 84 | ||
84 | /** | 85 | /** |
86 | * The default value of the '{@link #getMinNewElementsHeuristic() <em>Min New Elements Heuristic</em>}' attribute. | ||
87 | * <!-- begin-user-doc --> | ||
88 | * <!-- end-user-doc --> | ||
89 | * @see #getMinNewElementsHeuristic() | ||
90 | * @generated | ||
91 | * @ordered | ||
92 | */ | ||
93 | protected static final int MIN_NEW_ELEMENTS_HEURISTIC_EDEFAULT = 0; | ||
94 | |||
95 | /** | ||
96 | * The cached value of the '{@link #getMinNewElementsHeuristic() <em>Min New Elements Heuristic</em>}' attribute. | ||
97 | * <!-- begin-user-doc --> | ||
98 | * <!-- end-user-doc --> | ||
99 | * @see #getMinNewElementsHeuristic() | ||
100 | * @generated | ||
101 | * @ordered | ||
102 | */ | ||
103 | protected int minNewElementsHeuristic = MIN_NEW_ELEMENTS_HEURISTIC_EDEFAULT; | ||
104 | |||
105 | /** | ||
85 | * <!-- begin-user-doc --> | 106 | * <!-- begin-user-doc --> |
86 | * <!-- end-user-doc --> | 107 | * <!-- end-user-doc --> |
87 | * @generated | 108 | * @generated |
@@ -105,6 +126,7 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
105 | * <!-- end-user-doc --> | 126 | * <!-- end-user-doc --> |
106 | * @generated | 127 | * @generated |
107 | */ | 128 | */ |
129 | @Override | ||
108 | public int getMinNewElements() { | 130 | public int getMinNewElements() { |
109 | return minNewElements; | 131 | return minNewElements; |
110 | } | 132 | } |
@@ -114,6 +136,7 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
114 | * <!-- end-user-doc --> | 136 | * <!-- end-user-doc --> |
115 | * @generated | 137 | * @generated |
116 | */ | 138 | */ |
139 | @Override | ||
117 | public void setMinNewElements(int newMinNewElements) { | 140 | public void setMinNewElements(int newMinNewElements) { |
118 | int oldMinNewElements = minNewElements; | 141 | int oldMinNewElements = minNewElements; |
119 | minNewElements = newMinNewElements; | 142 | minNewElements = newMinNewElements; |
@@ -126,6 +149,7 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
126 | * <!-- end-user-doc --> | 149 | * <!-- end-user-doc --> |
127 | * @generated | 150 | * @generated |
128 | */ | 151 | */ |
152 | @Override | ||
129 | public int getMaxNewElements() { | 153 | public int getMaxNewElements() { |
130 | return maxNewElements; | 154 | return maxNewElements; |
131 | } | 155 | } |
@@ -135,6 +159,7 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
135 | * <!-- end-user-doc --> | 159 | * <!-- end-user-doc --> |
136 | * @generated | 160 | * @generated |
137 | */ | 161 | */ |
162 | @Override | ||
138 | public void setMaxNewElements(int newMaxNewElements) { | 163 | public void setMaxNewElements(int newMaxNewElements) { |
139 | int oldMaxNewElements = maxNewElements; | 164 | int oldMaxNewElements = maxNewElements; |
140 | maxNewElements = newMaxNewElements; | 165 | maxNewElements = newMaxNewElements; |
@@ -147,6 +172,7 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
147 | * <!-- end-user-doc --> | 172 | * <!-- end-user-doc --> |
148 | * @generated | 173 | * @generated |
149 | */ | 174 | */ |
175 | @Override | ||
150 | public PartialTypeInterpratation getTargetTypeInterpretation() { | 176 | public PartialTypeInterpratation getTargetTypeInterpretation() { |
151 | if (targetTypeInterpretation != null && targetTypeInterpretation.eIsProxy()) { | 177 | if (targetTypeInterpretation != null && targetTypeInterpretation.eIsProxy()) { |
152 | InternalEObject oldTargetTypeInterpretation = (InternalEObject)targetTypeInterpretation; | 178 | InternalEObject oldTargetTypeInterpretation = (InternalEObject)targetTypeInterpretation; |
@@ -188,6 +214,7 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
188 | * <!-- end-user-doc --> | 214 | * <!-- end-user-doc --> |
189 | * @generated | 215 | * @generated |
190 | */ | 216 | */ |
217 | @Override | ||
191 | public void setTargetTypeInterpretation(PartialTypeInterpratation newTargetTypeInterpretation) { | 218 | public void setTargetTypeInterpretation(PartialTypeInterpratation newTargetTypeInterpretation) { |
192 | if (newTargetTypeInterpretation != targetTypeInterpretation) { | 219 | if (newTargetTypeInterpretation != targetTypeInterpretation) { |
193 | NotificationChain msgs = null; | 220 | NotificationChain msgs = null; |
@@ -208,6 +235,29 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
208 | * @generated | 235 | * @generated |
209 | */ | 236 | */ |
210 | @Override | 237 | @Override |
238 | public int getMinNewElementsHeuristic() { | ||
239 | return minNewElementsHeuristic; | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * <!-- begin-user-doc --> | ||
244 | * <!-- end-user-doc --> | ||
245 | * @generated | ||
246 | */ | ||
247 | @Override | ||
248 | public void setMinNewElementsHeuristic(int newMinNewElementsHeuristic) { | ||
249 | int oldMinNewElementsHeuristic = minNewElementsHeuristic; | ||
250 | minNewElementsHeuristic = newMinNewElementsHeuristic; | ||
251 | if (eNotificationRequired()) | ||
252 | eNotify(new ENotificationImpl(this, Notification.SET, PartialinterpretationPackage.SCOPE__MIN_NEW_ELEMENTS_HEURISTIC, oldMinNewElementsHeuristic, minNewElementsHeuristic)); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * <!-- begin-user-doc --> | ||
257 | * <!-- end-user-doc --> | ||
258 | * @generated | ||
259 | */ | ||
260 | @Override | ||
211 | public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) { | 261 | public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) { |
212 | switch (featureID) { | 262 | switch (featureID) { |
213 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: | 263 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: |
@@ -247,6 +297,8 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
247 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: | 297 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: |
248 | if (resolve) return getTargetTypeInterpretation(); | 298 | if (resolve) return getTargetTypeInterpretation(); |
249 | return basicGetTargetTypeInterpretation(); | 299 | return basicGetTargetTypeInterpretation(); |
300 | case PartialinterpretationPackage.SCOPE__MIN_NEW_ELEMENTS_HEURISTIC: | ||
301 | return getMinNewElementsHeuristic(); | ||
250 | } | 302 | } |
251 | return super.eGet(featureID, resolve, coreType); | 303 | return super.eGet(featureID, resolve, coreType); |
252 | } | 304 | } |
@@ -268,6 +320,9 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
268 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: | 320 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: |
269 | setTargetTypeInterpretation((PartialTypeInterpratation)newValue); | 321 | setTargetTypeInterpretation((PartialTypeInterpratation)newValue); |
270 | return; | 322 | return; |
323 | case PartialinterpretationPackage.SCOPE__MIN_NEW_ELEMENTS_HEURISTIC: | ||
324 | setMinNewElementsHeuristic((Integer)newValue); | ||
325 | return; | ||
271 | } | 326 | } |
272 | super.eSet(featureID, newValue); | 327 | super.eSet(featureID, newValue); |
273 | } | 328 | } |
@@ -289,6 +344,9 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
289 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: | 344 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: |
290 | setTargetTypeInterpretation((PartialTypeInterpratation)null); | 345 | setTargetTypeInterpretation((PartialTypeInterpratation)null); |
291 | return; | 346 | return; |
347 | case PartialinterpretationPackage.SCOPE__MIN_NEW_ELEMENTS_HEURISTIC: | ||
348 | setMinNewElementsHeuristic(MIN_NEW_ELEMENTS_HEURISTIC_EDEFAULT); | ||
349 | return; | ||
292 | } | 350 | } |
293 | super.eUnset(featureID); | 351 | super.eUnset(featureID); |
294 | } | 352 | } |
@@ -307,6 +365,8 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
307 | return maxNewElements != MAX_NEW_ELEMENTS_EDEFAULT; | 365 | return maxNewElements != MAX_NEW_ELEMENTS_EDEFAULT; |
308 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: | 366 | case PartialinterpretationPackage.SCOPE__TARGET_TYPE_INTERPRETATION: |
309 | return targetTypeInterpretation != null; | 367 | return targetTypeInterpretation != null; |
368 | case PartialinterpretationPackage.SCOPE__MIN_NEW_ELEMENTS_HEURISTIC: | ||
369 | return minNewElementsHeuristic != MIN_NEW_ELEMENTS_HEURISTIC_EDEFAULT; | ||
310 | } | 370 | } |
311 | return super.eIsSet(featureID); | 371 | return super.eIsSet(featureID); |
312 | } | 372 | } |
@@ -320,11 +380,13 @@ public class ScopeImpl extends MinimalEObjectImpl.Container implements Scope { | |||
320 | public String toString() { | 380 | public String toString() { |
321 | if (eIsProxy()) return super.toString(); | 381 | if (eIsProxy()) return super.toString(); |
322 | 382 | ||
323 | StringBuffer result = new StringBuffer(super.toString()); | 383 | StringBuilder result = new StringBuilder(super.toString()); |
324 | result.append(" (minNewElements: "); | 384 | result.append(" (minNewElements: "); |
325 | result.append(minNewElements); | 385 | result.append(minNewElements); |
326 | result.append(", maxNewElements: "); | 386 | result.append(", maxNewElements: "); |
327 | result.append(maxNewElements); | 387 | result.append(maxNewElements); |
388 | result.append(", minNewElementsHeuristic: "); | ||
389 | result.append(minNewElementsHeuristic); | ||
328 | result.append(')'); | 390 | result.append(')'); |
329 | return result.toString(); | 391 | return result.toString(); |
330 | } | 392 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/StringElementImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/StringElementImpl.java index f207401d..0242c9b2 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/StringElementImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/StringElementImpl.java | |||
@@ -69,6 +69,7 @@ public class StringElementImpl extends PrimitiveElementImpl implements StringEle | |||
69 | * <!-- end-user-doc --> | 69 | * <!-- end-user-doc --> |
70 | * @generated | 70 | * @generated |
71 | */ | 71 | */ |
72 | @Override | ||
72 | public String getValue() { | 73 | public String getValue() { |
73 | return value; | 74 | return value; |
74 | } | 75 | } |
@@ -78,6 +79,7 @@ public class StringElementImpl extends PrimitiveElementImpl implements StringEle | |||
78 | * <!-- end-user-doc --> | 79 | * <!-- end-user-doc --> |
79 | * @generated | 80 | * @generated |
80 | */ | 81 | */ |
82 | @Override | ||
81 | public void setValue(String newValue) { | 83 | public void setValue(String newValue) { |
82 | String oldValue = value; | 84 | String oldValue = value; |
83 | value = newValue; | 85 | value = newValue; |
@@ -152,7 +154,7 @@ public class StringElementImpl extends PrimitiveElementImpl implements StringEle | |||
152 | public String toString() { | 154 | public String toString() { |
153 | if (eIsProxy()) return super.toString(); | 155 | if (eIsProxy()) return super.toString(); |
154 | 156 | ||
155 | StringBuffer result = new StringBuffer(super.toString()); | 157 | StringBuilder result = new StringBuilder(super.toString()); |
156 | result.append(" (value: "); | 158 | result.append(" (value: "); |
157 | result.append(value); | 159 | result.append(value); |
158 | result.append(')'); | 160 | result.append(')'); |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/UnaryElementRelationLinkImpl.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/UnaryElementRelationLinkImpl.java index 2cb56323..e76a89b7 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/UnaryElementRelationLinkImpl.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/ecore-gen/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/partialinterpretation/impl/UnaryElementRelationLinkImpl.java | |||
@@ -62,6 +62,7 @@ public class UnaryElementRelationLinkImpl extends RelationLinkImpl implements Un | |||
62 | * <!-- end-user-doc --> | 62 | * <!-- end-user-doc --> |
63 | * @generated | 63 | * @generated |
64 | */ | 64 | */ |
65 | @Override | ||
65 | public DefinedElement getParam1() { | 66 | public DefinedElement getParam1() { |
66 | if (param1 != null && param1.eIsProxy()) { | 67 | if (param1 != null && param1.eIsProxy()) { |
67 | InternalEObject oldParam1 = (InternalEObject)param1; | 68 | InternalEObject oldParam1 = (InternalEObject)param1; |
@@ -88,6 +89,7 @@ public class UnaryElementRelationLinkImpl extends RelationLinkImpl implements Un | |||
88 | * <!-- end-user-doc --> | 89 | * <!-- end-user-doc --> |
89 | * @generated | 90 | * @generated |
90 | */ | 91 | */ |
92 | @Override | ||
91 | public void setParam1(DefinedElement newParam1) { | 93 | public void setParam1(DefinedElement newParam1) { |
92 | DefinedElement oldParam1 = param1; | 94 | DefinedElement oldParam1 = param1; |
93 | param1 = newParam1; | 95 | param1 = newParam1; |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/model/PartialInterpretation.ecore b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/model/PartialInterpretation.ecore index acf82a3f..47d54258 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/model/PartialInterpretation.ecore +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/model/PartialInterpretation.ecore | |||
@@ -27,6 +27,9 @@ | |||
27 | eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="0"/> | 27 | eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="0"/> |
28 | <eStructuralFeatures xsi:type="ecore:EAttribute" name="maxNewElements" lowerBound="1" | 28 | <eStructuralFeatures xsi:type="ecore:EAttribute" name="maxNewElements" lowerBound="1" |
29 | eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="-1"/> | 29 | eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="-1"/> |
30 | <eStructuralFeatures xsi:type="ecore:EAttribute" name="minNewElementsHeuristic" | ||
31 | lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" | ||
32 | defaultValueLiteral="0"/> | ||
30 | </eClassifiers> | 33 | </eClassifiers> |
31 | <eClassifiers xsi:type="ecore:EClass" name="PartialConstantInterpretation"> | 34 | <eClassifiers xsi:type="ecore:EClass" name="PartialConstantInterpretation"> |
32 | <eStructuralFeatures xsi:type="ecore:EReference" name="interpretationOf" lowerBound="1" | 35 | <eStructuralFeatures xsi:type="ecore:EReference" name="interpretationOf" lowerBound="1" |
@@ -92,6 +95,9 @@ | |||
92 | eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="-1"/> | 95 | eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" defaultValueLiteral="-1"/> |
93 | <eStructuralFeatures xsi:type="ecore:EReference" name="targetTypeInterpretation" | 96 | <eStructuralFeatures xsi:type="ecore:EReference" name="targetTypeInterpretation" |
94 | lowerBound="1" eType="#//PartialTypeInterpratation" eOpposite="#//PartialTypeInterpratation/scopes"/> | 97 | lowerBound="1" eType="#//PartialTypeInterpratation" eOpposite="#//PartialTypeInterpratation/scopes"/> |
98 | <eStructuralFeatures xsi:type="ecore:EAttribute" name="minNewElementsHeuristic" | ||
99 | lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt" | ||
100 | defaultValueLiteral="0"/> | ||
95 | </eClassifiers> | 101 | </eClassifiers> |
96 | <eClassifiers xsi:type="ecore:EClass" name="PartialPrimitiveInterpretation" abstract="true" | 102 | <eClassifiers xsi:type="ecore:EClass" name="PartialPrimitiveInterpretation" abstract="true" |
97 | eSuperTypes="#//PartialTypeInterpratation"/> | 103 | eSuperTypes="#//PartialTypeInterpratation"/> |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/model/PartialInterpretation.genmodel b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/model/PartialInterpretation.genmodel index 2ac0a4f3..daeaf594 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/model/PartialInterpretation.genmodel +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/model/PartialInterpretation.genmodel | |||
@@ -18,7 +18,10 @@ | |||
18 | <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialInterpretation/partialtypeinterpratation"/> | 18 | <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialInterpretation/partialtypeinterpratation"/> |
19 | <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialInterpretation/openWorldElements"/> | 19 | <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialInterpretation/openWorldElements"/> |
20 | <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialInterpretation/problemConainer"/> | 20 | <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialInterpretation/problemConainer"/> |
21 | <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialInterpretation/scope"/> | 21 | <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialInterpretation/scopes"/> |
22 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//PartialInterpretation/minNewElements"/> | ||
23 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//PartialInterpretation/maxNewElements"/> | ||
24 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//PartialInterpretation/minNewElementsHeuristic"/> | ||
22 | </genClasses> | 25 | </genClasses> |
23 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialConstantInterpretation"> | 26 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialConstantInterpretation"> |
24 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialConstantInterpretation/interpretationOf"/> | 27 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialConstantInterpretation/interpretationOf"/> |
@@ -33,9 +36,8 @@ | |||
33 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialFunctionInterpretation/interpretationOf"/> | 36 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialFunctionInterpretation/interpretationOf"/> |
34 | </genClasses> | 37 | </genClasses> |
35 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialTypeInterpratation"> | 38 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialTypeInterpratation"> |
36 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialTypeInterpratation/interpretationOf"/> | ||
37 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialTypeInterpratation/elements"/> | 39 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialTypeInterpratation/elements"/> |
38 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialTypeInterpratation/supertypeInterpretation"/> | 40 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialTypeInterpratation/scopes"/> |
39 | </genClasses> | 41 | </genClasses> |
40 | <genClasses image="false" ecoreClass="PartialInterpretation.ecore#//RelationLink"/> | 42 | <genClasses image="false" ecoreClass="PartialInterpretation.ecore#//RelationLink"/> |
41 | <genClasses ecoreClass="PartialInterpretation.ecore#//UnaryElementRelationLink"> | 43 | <genClasses ecoreClass="PartialInterpretation.ecore#//UnaryElementRelationLink"> |
@@ -50,6 +52,7 @@ | |||
50 | </genClasses> | 52 | </genClasses> |
51 | <genClasses ecoreClass="PartialInterpretation.ecore#//NaryRelationLinkElement"> | 53 | <genClasses ecoreClass="PartialInterpretation.ecore#//NaryRelationLinkElement"> |
52 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//NaryRelationLinkElement/index"/> | 54 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//NaryRelationLinkElement/index"/> |
55 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//NaryRelationLinkElement/param"/> | ||
53 | </genClasses> | 56 | </genClasses> |
54 | <genClasses image="false" ecoreClass="PartialInterpretation.ecore#//PrimitiveElement"> | 57 | <genClasses image="false" ecoreClass="PartialInterpretation.ecore#//PrimitiveElement"> |
55 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//PrimitiveElement/valueSet"/> | 58 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//PrimitiveElement/valueSet"/> |
@@ -70,11 +73,16 @@ | |||
70 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//Scope/minNewElements"/> | 73 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//Scope/minNewElements"/> |
71 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//Scope/maxNewElements"/> | 74 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//Scope/maxNewElements"/> |
72 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//Scope/targetTypeInterpretation"/> | 75 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//Scope/targetTypeInterpretation"/> |
76 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PartialInterpretation.ecore#//Scope/minNewElementsHeuristic"/> | ||
73 | </genClasses> | 77 | </genClasses> |
74 | <genClasses image="false" ecoreClass="PartialInterpretation.ecore#//PartialPrimitiveInterpretation"/> | 78 | <genClasses image="false" ecoreClass="PartialInterpretation.ecore#//PartialPrimitiveInterpretation"/> |
75 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialBooleanInterpretation"/> | 79 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialBooleanInterpretation"/> |
76 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialIntegerInterpretation"/> | 80 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialIntegerInterpretation"/> |
77 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialRealInterpretation"/> | 81 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialRealInterpretation"/> |
78 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialStringInterpretation"/> | 82 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialStringInterpretation"/> |
83 | <genClasses ecoreClass="PartialInterpretation.ecore#//PartialComplexTypeInterpretation"> | ||
84 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialComplexTypeInterpretation/supertypeInterpretation"/> | ||
85 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference PartialInterpretation.ecore#//PartialComplexTypeInterpretation/interpretationOf"/> | ||
86 | </genClasses> | ||
79 | </genPackages> | 87 | </genPackages> |
80 | </genmodel:GenModel> | 88 | </genmodel:GenModel> |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretation2logic/InstanceModel2PartialInterpretation.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretation2logic/InstanceModel2PartialInterpretation.xtend index 8aaaacb5..cb5b587f 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretation2logic/InstanceModel2PartialInterpretation.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretation2logic/InstanceModel2PartialInterpretation.xtend | |||
@@ -1,5 +1,6 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic |
2 | 2 | ||
3 | import com.google.common.collect.ImmutableList | ||
3 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic | 4 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic |
4 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic_Trace | 5 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic_Trace |
5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.TracedOutput | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.TracedOutput |
@@ -12,18 +13,18 @@ import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.Par | |||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.Problem2PartialInterpretationTrace | 13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.Problem2PartialInterpretationTrace |
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation | 14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation |
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationFactory | 15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationFactory |
16 | import java.math.BigDecimal | ||
15 | import java.util.HashMap | 17 | import java.util.HashMap |
18 | import java.util.HashSet | ||
16 | import java.util.List | 19 | import java.util.List |
17 | import java.util.Map | 20 | import java.util.Map |
21 | import java.util.Set | ||
18 | import org.eclipse.emf.common.util.Enumerator | 22 | import org.eclipse.emf.common.util.Enumerator |
23 | import org.eclipse.emf.ecore.EAttribute | ||
19 | import org.eclipse.emf.ecore.EObject | 24 | import org.eclipse.emf.ecore.EObject |
20 | import org.eclipse.emf.ecore.resource.Resource | 25 | import org.eclipse.emf.ecore.resource.Resource |
21 | 26 | ||
22 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 27 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
23 | import java.util.HashSet | ||
24 | import java.util.Set | ||
25 | import java.math.BigDecimal | ||
26 | import org.eclipse.emf.ecore.EAttribute | ||
27 | 28 | ||
28 | class InstanceModel2PartialInterpretation { | 29 | class InstanceModel2PartialInterpretation { |
29 | val extension LogiclanguageFactory factory = LogiclanguageFactory.eINSTANCE | 30 | val extension LogiclanguageFactory factory = LogiclanguageFactory.eINSTANCE |
@@ -36,7 +37,19 @@ class InstanceModel2PartialInterpretation { | |||
36 | Resource resource, | 37 | Resource resource, |
37 | boolean withID) | 38 | boolean withID) |
38 | { | 39 | { |
39 | val objects = resource.allContents.toList | 40 | val objectsBuilder = ImmutableList.builder |
41 | val treeIterator = resource.allContents | ||
42 | val referencesUsed = ecore2Logic.allReferencesInScope(metamodelTranslationResult.trace).toSet | ||
43 | while (treeIterator.hasNext) { | ||
44 | val object = treeIterator.next | ||
45 | val containingReference = object.eContainmentFeature | ||
46 | if (containingReference === null || referencesUsed.contains(containingReference)) { | ||
47 | objectsBuilder.add(object) | ||
48 | } else { | ||
49 | treeIterator.prune | ||
50 | } | ||
51 | } | ||
52 | val objects = objectsBuilder.build | ||
40 | return transform(metamodelTranslationResult,objects,withID) | 53 | return transform(metamodelTranslationResult,objects,withID) |
41 | } | 54 | } |
42 | 55 | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/PartialInterpretationInitialiser.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/PartialInterpretationInitialiser.xtend index f7a1ce4f..20ff58f2 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/PartialInterpretationInitialiser.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/PartialInterpretationInitialiser.xtend | |||
@@ -2,19 +2,24 @@ package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage | |||
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.TracedOutput | 3 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.TracedOutput |
4 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.TypeScopes | 4 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.TypeScopes |
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.And | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolLiteral | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement | 7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement |
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntLiteral | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.LogiclanguageFactory | 9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.LogiclanguageFactory |
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealLiteral | ||
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | 11 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration |
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition | ||
13 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringLiteral | ||
14 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.SymbolicValue | ||
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | 15 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type |
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration | 16 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration |
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDefinition | 17 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDefinition |
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | 18 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem |
12 | import hu.bme.mit.inf.dslreasoner.logic.model.patterns.SupertypeStar | 19 | import hu.bme.mit.inf.dslreasoner.logic.model.patterns.SupertypeStar |
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partial2logicannotations.PartialModelRelation2Assertion | 20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partial2logicannotations.PartialModelRelation2Assertion |
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BooleanElement | 21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BooleanElement |
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.IntegerElement | 22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.IntegerElement |
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.NaryRelationLink | ||
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialBooleanInterpretation | 23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialBooleanInterpretation |
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | 24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation |
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialIntegerInterpretation | 25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialIntegerInterpretation |
@@ -22,10 +27,10 @@ import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.par | |||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRealInterpretation | 27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRealInterpretation |
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation | 28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation |
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialStringInterpretation | 29 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialStringInterpretation |
30 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation | ||
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationFactory | 31 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationFactory |
26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.RealElement | 32 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.RealElement |
27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.StringElement | 33 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.StringElement |
28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.UnaryElementRelationLink | ||
29 | import java.math.BigDecimal | 34 | import java.math.BigDecimal |
30 | import java.util.HashMap | 35 | import java.util.HashMap |
31 | import java.util.Map | 36 | import java.util.Map |
@@ -35,13 +40,6 @@ import org.eclipse.viatra.query.runtime.emf.EMFScope | |||
35 | import org.eclipse.xtend.lib.annotations.Data | 40 | import org.eclipse.xtend.lib.annotations.Data |
36 | 41 | ||
37 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 42 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
38 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.SymbolicValue | ||
39 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.And | ||
40 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolLiteral | ||
41 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntLiteral | ||
42 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealLiteral | ||
43 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringLiteral | ||
44 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation | ||
45 | 43 | ||
46 | @Data class Problem2PartialInterpretationTrace { | 44 | @Data class Problem2PartialInterpretationTrace { |
47 | Map<TypeDeclaration, PartialComplexTypeInterpretation> type2Interpretation | 45 | Map<TypeDeclaration, PartialComplexTypeInterpretation> type2Interpretation |
@@ -193,7 +191,7 @@ class PartialInterpretationInitialiser { | |||
193 | interpretation.minNewElements = minNewElements | 191 | interpretation.minNewElements = minNewElements |
194 | interpretation.maxNewElements = maxNewElements | 192 | interpretation.maxNewElements = maxNewElements |
195 | // elements from problem are included | 193 | // elements from problem are included |
196 | if(maxNewElements>0) { | 194 | if(maxNewElements != 0) { |
197 | val newElements = createDefinedElement => [it.name = "New Objects"] | 195 | val newElements = createDefinedElement => [it.name = "New Objects"] |
198 | interpretation.openWorldElements += newElements | 196 | interpretation.openWorldElements += newElements |
199 | } | 197 | } |
@@ -212,12 +210,8 @@ class PartialInterpretationInitialiser { | |||
212 | def private initialiseTypeScope(PartialTypeInterpratation interpretation, Integer min, Integer max) { | 210 | def private initialiseTypeScope(PartialTypeInterpratation interpretation, Integer min, Integer max) { |
213 | val res = createScope | 211 | val res = createScope |
214 | res.targetTypeInterpretation = interpretation | 212 | res.targetTypeInterpretation = interpretation |
215 | if(min !== null) { | 213 | res.minNewElements = min ?: 0 |
216 | res.minNewElements = min | 214 | res.maxNewElements = max ?: -1 |
217 | } | ||
218 | if(max !== null) { | ||
219 | res.maxNewElements = max | ||
220 | } | ||
221 | return res | 215 | return res |
222 | } | 216 | } |
223 | 217 | ||
@@ -233,7 +227,11 @@ class PartialInterpretationInitialiser { | |||
233 | 227 | ||
234 | def private Map<RelationDeclaration, PartialRelationInterpretation> initRelations(PartialInterpretation interpretation, PrimitiveValueTrace trace) { | 228 | def private Map<RelationDeclaration, PartialRelationInterpretation> initRelations(PartialInterpretation interpretation, PrimitiveValueTrace trace) { |
235 | val Map<RelationDeclaration, PartialRelationInterpretation> relation2Interpretation = new HashMap | 229 | val Map<RelationDeclaration, PartialRelationInterpretation> relation2Interpretation = new HashMap |
236 | for(relation : interpretation.problem.relations.filter(RelationDeclaration)) { | 230 | val definedRelationDeclarations = interpretation.problem.relations.filter(RelationDefinition).map[defines] |
231 | val undefinedRelationDeclarations = interpretation.problem.relations.filter(RelationDeclaration).filter[ | ||
232 | declared | !definedRelationDeclarations.exists[defined | defined === declared] | ||
233 | ] | ||
234 | for(relation : undefinedRelationDeclarations) { | ||
237 | val partialInterpretation = relation.initialisePartialRelationInterpretation | 235 | val partialInterpretation = relation.initialisePartialRelationInterpretation |
238 | interpretation.partialrelationinterpretation += partialInterpretation | 236 | interpretation.partialrelationinterpretation += partialInterpretation |
239 | relation2Interpretation.put(relation,partialInterpretation) | 237 | relation2Interpretation.put(relation,partialInterpretation) |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend index 41482b28..685a1f5a 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend | |||
@@ -4,10 +4,21 @@ import java.util.HashMap | |||
4 | import java.util.Map | 4 | import java.util.Map |
5 | import java.util.Set | 5 | import java.util.Set |
6 | import org.eclipse.xtend.lib.annotations.Data | 6 | import org.eclipse.xtend.lib.annotations.Data |
7 | import org.eclipse.xtend2.lib.StringConcatenationClient | ||
7 | 8 | ||
8 | @Data abstract class AbstractNodeDescriptor { | 9 | @Data abstract class AbstractNodeDescriptor { |
9 | long dataHash | 10 | int dataHash |
10 | 11 | ||
12 | protected def StringConcatenationClient prettyPrint() { | ||
13 | '''(«dataHash»)[«class.simpleName»]''' | ||
14 | } | ||
15 | |||
16 | override toString() { | ||
17 | ''' | ||
18 | «prettyPrint» | ||
19 | ''' | ||
20 | } | ||
21 | |||
11 | // @Pure | 22 | // @Pure |
12 | // @Override | 23 | // @Override |
13 | // override public boolean equals(Object obj) { | 24 | // override public boolean equals(Object obj) { |
@@ -24,34 +35,45 @@ import org.eclipse.xtend.lib.annotations.Data | |||
24 | // } | 35 | // } |
25 | } | 36 | } |
26 | 37 | ||
27 | @Data class LocalNodeDescriptor extends AbstractNodeDescriptor{ | 38 | @Data class LocalNodeDescriptor extends AbstractNodeDescriptor { |
28 | Set<String> types | 39 | Set<String> types |
29 | String id; | 40 | String id; |
41 | |||
30 | new(String id, Set<String> types) { | 42 | new(String id, Set<String> types) { |
31 | super(calcualteDataHash(id,types)) | 43 | super(calcualteDataHash(id, types)) |
32 | this.types = types | 44 | this.types = types |
33 | this.id = id | 45 | this.id = id |
34 | } | 46 | } |
35 | 47 | ||
36 | def private static calcualteDataHash(String id, Set<String> types) { | 48 | def private static calcualteDataHash(String id, Set<String> types) { |
37 | val int prime = 31; | 49 | val int prime = 31; |
38 | var result = 0 | 50 | var result = 0 |
39 | if(id !== null) | 51 | if (id !== null) |
40 | result = id.hashCode(); | 52 | result = id.hashCode(); |
41 | if(types !== null) { | 53 | if (types !== null) { |
42 | result = prime * result + types.hashCode | 54 | result = prime * result + types.hashCode |
43 | } | 55 | } |
44 | return result | 56 | return result |
45 | } | 57 | } |
46 | 58 | ||
47 | override hashCode() { | 59 | override hashCode() { |
48 | return this.dataHash.hashCode | 60 | return this.dataHash |
49 | } | 61 | } |
50 | 62 | ||
63 | override equals(Object other) { | ||
64 | other.class == LocalNodeDescriptor && (other as AbstractNodeDescriptor).hashCode == hashCode | ||
65 | } | ||
66 | |||
67 | override protected prettyPrint() { | ||
68 | '''(«dataHash»)[«IF id !== null»id = "«id»"«IF types === null || !types.empty», «ENDIF»«ENDIF»«IF types === null»TYPES = null«ELSE»«FOR type : types SEPARATOR ", "»«type»«ENDFOR»«ENDIF»]''' | ||
69 | } | ||
70 | |||
51 | override toString() { | 71 | override toString() { |
52 | return class.name + this.dataHash | 72 | ''' |
73 | «prettyPrint» | ||
74 | ''' | ||
53 | } | 75 | } |
54 | 76 | ||
55 | // @Pure | 77 | // @Pure |
56 | // @Override | 78 | // @Override |
57 | // override public boolean equals(Object obj) { | 79 | // override public boolean equals(Object obj) { |
@@ -66,7 +88,6 @@ import org.eclipse.xtend.lib.annotations.Data | |||
66 | // return false; | 88 | // return false; |
67 | // return true; | 89 | // return true; |
68 | // } | 90 | // } |
69 | |||
70 | // @Pure | 91 | // @Pure |
71 | // override public boolean equals(Object obj) { | 92 | // override public boolean equals(Object obj) { |
72 | // if (this === obj) | 93 | // if (this === obj) |
@@ -97,118 +118,91 @@ import org.eclipse.xtend.lib.annotations.Data | |||
97 | String type | 118 | String type |
98 | } | 119 | } |
99 | 120 | ||
100 | @Data class FurtherNodeDescriptor<NodeRep> extends AbstractNodeDescriptor{ | 121 | @Data class FurtherNodeDescriptor<NodeRep> extends AbstractNodeDescriptor { |
101 | 122 | NodeRep previousRepresentation | |
102 | NodeRep previousRepresentation | 123 | Map<IncomingRelation<NodeRep>, Integer> incomingEdges |
103 | Map<IncomingRelation<NodeRep>,Integer> incomingEdges | 124 | Map<OutgoingRelation<NodeRep>, Integer> outgoingEdges |
104 | Map<OutgoingRelation<NodeRep>,Integer> outgoingEdges | 125 | |
105 | 126 | new(NodeRep previousRepresentation, Map<IncomingRelation<NodeRep>, Integer> incomingEdges, | |
106 | new( | 127 | Map<OutgoingRelation<NodeRep>, Integer> outgoingEdges) { |
107 | NodeRep previousRepresentation, | 128 | super(calculateDataHash(previousRepresentation, incomingEdges, outgoingEdges)) |
108 | Map<IncomingRelation<NodeRep>,Integer> incomingEdges, | 129 | this.previousRepresentation = previousRepresentation |
109 | Map<OutgoingRelation<NodeRep>,Integer> outgoingEdges) | 130 | this.incomingEdges = incomingEdges |
110 | { | 131 | this.outgoingEdges = outgoingEdges |
111 | super(calculateDataHash(previousRepresentation,incomingEdges,outgoingEdges)) | ||
112 | this.previousRepresentation = previousRepresentation | ||
113 | this.incomingEdges = new HashMap(incomingEdges) | ||
114 | this.outgoingEdges = new HashMap(outgoingEdges) | ||
115 | } | ||
116 | |||
117 | static def private <NodeRep> int calculateDataHash( | ||
118 | NodeRep previousRepresentation, | ||
119 | Map<IncomingRelation<NodeRep>,Integer> incomingEdges, | ||
120 | Map<OutgoingRelation<NodeRep>,Integer> outgoingEdges) | ||
121 | { | ||
122 | val int prime = 31; | ||
123 | var int result = previousRepresentation.hashCode; | ||
124 | if(incomingEdges !== null) | ||
125 | result = prime * result + incomingEdges.hashCode(); | ||
126 | if(outgoingEdges !== null) | ||
127 | result = prime * result + outgoingEdges.hashCode(); | ||
128 | return result; | ||
129 | } | ||
130 | |||
131 | override hashCode() { | ||
132 | return this.dataHash.hashCode | ||
133 | } | 132 | } |
134 | 133 | ||
135 | override toString() { | 134 | static def private <NodeRep> int calculateDataHash(NodeRep previousRepresentation, |
136 | return class.name + dataHash | 135 | Map<IncomingRelation<NodeRep>, Integer> incomingEdges, Map<OutgoingRelation<NodeRep>, Integer> outgoingEdges) { |
137 | // return '''[«previousRepresentation»,(«FOR | 136 | val int prime = 31; |
138 | // in: incomingEdges.entrySet»(«in.key.type.name»=«in.key.from»,«in.value»)«ENDFOR»),(«FOR | 137 | var int result = previousRepresentation.hashCode; |
139 | // out: outgoingEdges.entrySet»(«out.key.type.name»=«out.key.to»,«out.value»)«ENDFOR»),«FOR | 138 | if (incomingEdges !== null) |
140 | // att: attributeValues»(«att.type.name»=«att.value»)«ENDFOR»]''' | 139 | result = prime * result + hashIncomingNeighborhood(incomingEdges) |
140 | if (outgoingEdges !== null) | ||
141 | result = prime * result + hashOutgoingNeighborhood(outgoingEdges) | ||
142 | return result; | ||
141 | } | 143 | } |
142 | |||
143 | // @Pure | ||
144 | // @Override | ||
145 | // override public boolean equals(Object obj) { | ||
146 | // if (this === obj) | ||
147 | // return true; | ||
148 | // if (obj === null) | ||
149 | // return false; | ||
150 | // if (getClass() != obj.getClass()) | ||
151 | // return false; | ||
152 | // val AbstractNodeDescriptor other = obj as AbstractNodeDescriptor; | ||
153 | // if (other.dataHash != this.dataHash) | ||
154 | // return false; | ||
155 | // return true; | ||
156 | // } | ||
157 | |||
158 | // @Pure | ||
159 | // override public boolean equals(Object obj) { | ||
160 | // if (this === obj) | ||
161 | // return true; | ||
162 | // if (obj === null) | ||
163 | // return false; | ||
164 | // if (getClass() != obj.getClass()) | ||
165 | // return false; | ||
166 | // if (!super.equals(obj)) | ||
167 | // return false; | ||
168 | // val FurtherNodeDescriptor<?> other = obj as FurtherNodeDescriptor<?>; | ||
169 | // if (this.previousRepresentation === null) { | ||
170 | // if (other.previousRepresentation != null) | ||
171 | // return false; | ||
172 | // | ||
173 | // } | ||
174 | //// } else if (!this.previousRepresentation.equals(other.previousRepresentation)) | ||
175 | //// return false; | ||
176 | // if (this.incomingEdges === null) { | ||
177 | // if (other.incomingEdges != null) | ||
178 | // return false; | ||
179 | // } else if (!this.incomingEdges.equals(other.incomingEdges)) | ||
180 | // return false; | ||
181 | // if (this.outgoingEdges === null) { | ||
182 | // if (other.outgoingEdges != null) | ||
183 | // return false; | ||
184 | // } else if (!this.outgoingEdges.equals(other.outgoingEdges)) | ||
185 | // return false; | ||
186 | // if (this.attributeValues === null) { | ||
187 | // if (other.attributeValues != null) | ||
188 | // return false; | ||
189 | // } else if (!this.attributeValues.equals(other.attributeValues)) | ||
190 | // return false; | ||
191 | // return true; | ||
192 | // } | ||
193 | } | ||
194 | 144 | ||
195 | /* | 145 | override hashCode() { |
196 | @Data | 146 | return this.dataHash |
197 | class ModelDescriptor { | 147 | } |
198 | int dataHash | 148 | |
199 | int unknownElements | 149 | override equals(Object other) { |
200 | Map<? extends AbstractNodeDescriptor,Integer> knownElements | 150 | other.class == FurtherNodeDescriptor && (other as AbstractNodeDescriptor).hashCode == hashCode |
151 | } | ||
152 | |||
153 | override prettyPrint() { | ||
154 | ''' | ||
155 | («dataHash»)[ | ||
156 | PREV = «previousRepresentation?.prettyPrint» | ||
157 | «IF incomingEdges === null» | ||
158 | IN null | ||
159 | «ELSE» | ||
160 | «FOR edge : incomingEdges.entrySet» | ||
161 | IN «edge.value» «edge.key.type» = «edge.key.from.prettyPrint» | ||
162 | «ENDFOR» | ||
163 | «ENDIF» | ||
164 | «IF outgoingEdges === null» | ||
165 | OUT null | ||
166 | «ELSE» | ||
167 | «FOR edge : outgoingEdges.entrySet» | ||
168 | OUT «edge.value» «edge.key.type» = «edge.key.to.prettyPrint» | ||
169 | «ENDFOR» | ||
170 | «ENDIF» | ||
171 | ]''' | ||
172 | } | ||
173 | |||
174 | private def StringConcatenationClient prettyPrint(NodeRep rep) { | ||
175 | if (rep instanceof AbstractNodeDescriptor) { | ||
176 | rep.prettyPrint | ||
177 | } else { | ||
178 | '''«rep»''' | ||
179 | } | ||
180 | } | ||
201 | 181 | ||
202 | public new(Map<? extends AbstractNodeDescriptor,Integer> knownElements, int unknownElements) { | 182 | private static def <NodeRep> hashIncomingNeighborhood(Map<IncomingRelation<NodeRep>, Integer> neighborhood) { |
203 | this.dataHash = calculateDataHash(knownElements,unknownElements) | 183 | val int prime = 31 |
204 | this.unknownElements = unknownElements | 184 | var int hash = 0 |
205 | this.knownElements = knownElements | 185 | for (entry : neighborhood.entrySet) { |
186 | val relation = entry.key | ||
187 | hash += (prime * relation.from.hashCode + relation.type.hashCode).bitwiseXor(entry.value.hashCode) | ||
188 | } | ||
189 | hash | ||
206 | } | 190 | } |
207 | 191 | ||
208 | def private static calculateDataHash(Map<? extends AbstractNodeDescriptor,Integer> knownElements, int unknownElements) | 192 | private static def <NodeRep> hashOutgoingNeighborhood(Map<OutgoingRelation<NodeRep>, Integer> neighborhood) { |
209 | { | 193 | val int prime = 31 |
210 | val int prime = 31; | 194 | var int hash = 0 |
211 | return knownElements.hashCode * prime + unknownElements.hashCode | 195 | for (entry : neighborhood.entrySet) { |
196 | val relation = entry.key | ||
197 | hash += (prime * relation.to.hashCode + relation.type.hashCode).bitwiseXor(entry.value.hashCode) | ||
198 | } | ||
199 | hash | ||
200 | } | ||
201 | |||
202 | override toString() { | ||
203 | ''' | ||
204 | «prettyPrint» | ||
205 | ''' | ||
212 | } | 206 | } |
213 | } | 207 | } |
214 | */ \ No newline at end of file | 208 | |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend new file mode 100644 index 00000000..c6e03f75 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend | |||
@@ -0,0 +1,22 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration | ||
5 | import java.util.Set | ||
6 | import org.eclipse.xtend.lib.annotations.Data | ||
7 | |||
8 | @Data | ||
9 | class NeighbourhoodOptions { | ||
10 | public static val FixPointRange = -1 | ||
11 | public static val GraphWidthRange = -2 | ||
12 | public static val FullParallels = Integer.MAX_VALUE | ||
13 | public static val MaxNumbers = Integer.MAX_VALUE | ||
14 | |||
15 | public static val DEFAULT = new NeighbourhoodOptions(FixPointRange, FullParallels, MaxNumbers, null, null) | ||
16 | |||
17 | val int range | ||
18 | val int parallels | ||
19 | val int maxNumber | ||
20 | val Set<TypeDeclaration> relevantTypes | ||
21 | val Set<RelationDeclaration> relevantRelations | ||
22 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2Hash.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2Hash.xtend index d474877d..5da202eb 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2Hash.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2Hash.xtend | |||
@@ -1,25 +1,33 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood |
2 | 2 | ||
3 | import java.util.Map | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement | 3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement |
4 | import java.util.Map | ||
5 | import org.eclipse.collections.api.factory.Maps | ||
5 | 6 | ||
6 | class PartialInterpretation2Hash extends PartialInterpretation2NeighbourhoodRepresentation<Integer, Integer>{ | 7 | class PartialInterpretation2Hash extends PartialInterpretation2NeighbourhoodRepresentation<Integer, Integer>{ |
7 | 8 | ||
8 | protected new() { | 9 | new() { |
9 | super(false, true) | 10 | super(false, true) |
10 | } | 11 | } |
11 | 12 | ||
12 | override protected createLocalRepresentation(Map<DefinedElement, LocalNodeDescriptor> node2Representation, Map<LocalNodeDescriptor, Integer> representation2Amount) { | 13 | override protected createLocalRepresentation(Map<DefinedElement, LocalNodeDescriptor> node2Representation, Map<LocalNodeDescriptor, Integer> representation2Amount) { |
13 | return new NeighbourhoodWithTraces( | 14 | return new NeighbourhoodWithTraces( |
14 | representation2Amount.hashCode,node2Representation.mapValues[it.hashCode], | 15 | representation2Amount.hashCode,node2Representation.hashValues, |
15 | null) | 16 | null) |
16 | } | 17 | } |
17 | 18 | ||
18 | override protected createFurtherRepresentation(Map<FurtherNodeDescriptor<Integer>, Integer> nodeDescriptors, Map<DefinedElement, FurtherNodeDescriptor<Integer>> node2Representation, NeighbourhoodWithTraces<Integer, Integer> previous, boolean deepRepresentation) { | 19 | override protected createFurtherRepresentation(Map<FurtherNodeDescriptor<Integer>, Integer> nodeDescriptors, Map<DefinedElement, FurtherNodeDescriptor<Integer>> node2Representation, NeighbourhoodWithTraces<Integer, Integer> previous, boolean deepRepresentation) { |
19 | return new NeighbourhoodWithTraces( | 20 | return new NeighbourhoodWithTraces( |
20 | nodeDescriptors.hashCode, | 21 | nodeDescriptors.hashCode, |
21 | node2Representation.mapValues[it.hashCode], | 22 | node2Representation.hashValues, |
22 | if(deepRepresentation) {previous} else {null}) | 23 | if(deepRepresentation) {previous} else {null}) |
23 | } | 24 | } |
24 | 25 | ||
26 | private def <T> hashValues(Map<DefinedElement, T> map) { | ||
27 | val hashedMap = Maps.mutable.ofInitialCapacity(map.size) | ||
28 | for (entry : map.entrySet) { | ||
29 | hashedMap.put(entry.key, entry.value.hashCode) | ||
30 | } | ||
31 | hashedMap | ||
32 | } | ||
25 | } | 33 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend index 6dc40705..93eab816 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend | |||
@@ -4,32 +4,34 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement | |||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | 4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration |
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration | 5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration |
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink | 6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink |
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
8 | import java.util.HashMap | 9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation |
9 | import java.util.HashSet | 10 | import java.util.ArrayList |
10 | import java.util.LinkedList | ||
11 | import java.util.List | 11 | import java.util.List |
12 | import java.util.Map | 12 | import java.util.Map |
13 | import java.util.Set | 13 | import java.util.Set |
14 | import org.eclipse.collections.api.factory.Maps | ||
15 | import org.eclipse.collections.impl.factory.Sets | ||
14 | 16 | ||
15 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 17 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation | ||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
18 | 18 | ||
19 | abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresentation,NodeRepresentation> { | 19 | abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresentation, NodeRepresentation> { |
20 | private val boolean deepRepresentation | 20 | val boolean deepRepresentation |
21 | private val boolean mergeSimilarNeighbourhood | 21 | val boolean mergeSimilarNeighbourhood |
22 | 22 | ||
23 | protected new(boolean deeprepresentation, boolean mergeSimilarNeighbourhood) { | 23 | protected new(boolean deeprepresentation, boolean mergeSimilarNeighbourhood) { |
24 | this.deepRepresentation = deeprepresentation | 24 | this.deepRepresentation = deeprepresentation |
25 | this.mergeSimilarNeighbourhood = mergeSimilarNeighbourhood | 25 | this.mergeSimilarNeighbourhood = mergeSimilarNeighbourhood |
26 | } | 26 | } |
27 | 27 | ||
28 | public static val FixPointRage = -1 | 28 | public static val FixPointRange = NeighbourhoodOptions.FixPointRange |
29 | public static val GraphWidthRange = -2 | 29 | public static val GraphWidthRange = NeighbourhoodOptions.GraphWidthRange |
30 | public static val FullParallels = Integer.MAX_VALUE | 30 | public static val FullParallels = NeighbourhoodOptions.FullParallels |
31 | public static val MaxNumbers = Integer.MAX_VALUE | 31 | public static val MaxNumbers = NeighbourhoodOptions.MaxNumbers |
32 | 32 | ||
33 | static val FOCUSED_ELEMENT_NAME = "<<THIS>>" | ||
34 | |||
33 | /** | 35 | /** |
34 | * Creates a neighbourhood representation with traces | 36 | * Creates a neighbourhood representation with traces |
35 | * @param model The model to be represented. | 37 | * @param model The model to be represented. |
@@ -37,10 +39,15 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta | |||
37 | * @param parallels The maximal number of parallel references to be differentiated. | 39 | * @param parallels The maximal number of parallel references to be differentiated. |
38 | * @param maxNumber The maximal number of elements in a equivalence class that chan be differentiated. | 40 | * @param maxNumber The maximal number of elements in a equivalence class that chan be differentiated. |
39 | */ | 41 | */ |
40 | def public createRepresentation(PartialInterpretation model, int range, int parallels, int maxNumber) { | 42 | def createRepresentation(PartialInterpretation model, int range, int parallels, int maxNumber) { |
41 | return createRepresentation(model,range,parallels,maxNumber,null,null) | 43 | return createRepresentation(model, range, parallels, maxNumber, null, null) |
44 | } | ||
45 | |||
46 | def createRepresentation(PartialInterpretation model, NeighbourhoodOptions options) { | ||
47 | createRepresentation(model, options.range, options.parallels, options.maxNumber, options.relevantTypes, | ||
48 | options.relevantRelations) | ||
42 | } | 49 | } |
43 | 50 | ||
44 | /** | 51 | /** |
45 | * Creates a neighbourhood representation with traces | 52 | * Creates a neighbourhood representation with traces |
46 | * @param model The model to be represented. | 53 | * @param model The model to be represented. |
@@ -48,72 +55,87 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta | |||
48 | * @param parallels The maximal number of parallel references to be differentiated. | 55 | * @param parallels The maximal number of parallel references to be differentiated. |
49 | * @param maxNumber The maximal number of elements in a equivalence class that chan be differentiated. | 56 | * @param maxNumber The maximal number of elements in a equivalence class that chan be differentiated. |
50 | */ | 57 | */ |
51 | def public createRepresentation( | 58 | def createRepresentation(PartialInterpretation model, int range, int parallels, int maxNumber, |
52 | PartialInterpretation model, | 59 | Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations) { |
53 | int range, int parallels, int maxNumber, | 60 | createRepresentationWithFocus(model, range, parallels, maxNumber, relevantTypes, relevantRelations, null) |
54 | Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations) | 61 | } |
55 | { | 62 | |
56 | val Map<DefinedElement, Set<String>> types = new HashMap | 63 | def createRepresentationWithFocus(PartialInterpretation model, NeighbourhoodOptions options, |
57 | fillTypes(model,types,relevantTypes) | 64 | DefinedElement focusedElement) { |
58 | val Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations = new HashMap; | 65 | createRepresentationWithFocus(model, options.range, options.parallels, options.maxNumber, options.relevantTypes, |
59 | val Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations = new HashMap; | 66 | options.relevantRelations, focusedElement) |
60 | fillReferences(model,IncomingRelations,OutgoingRelations,relevantRelations) | 67 | } |
61 | 68 | ||
62 | val res = doRecursiveNeighbourCalculation(model,types,IncomingRelations,OutgoingRelations,range,parallels,maxNumber); | 69 | def createRepresentationWithFocus(PartialInterpretation model, int range, int parallels, int maxNumber, |
63 | 70 | Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations, DefinedElement focusedElement) { | |
71 | val initialSize = model.elements.size | ||
72 | val Map<DefinedElement, Set<String>> types = Maps.mutable.ofInitialCapacity(initialSize) | ||
73 | fillTypes(model, types, relevantTypes) | ||
74 | val Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations = Maps.mutable.ofInitialCapacity(initialSize); | ||
75 | val Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations = Maps.mutable.ofInitialCapacity(initialSize); | ||
76 | fillReferences(model, IncomingRelations, OutgoingRelations, relevantRelations) | ||
77 | |||
78 | val res = doRecursiveNeighbourCalculation(model, types, IncomingRelations, OutgoingRelations, range, parallels, | ||
79 | maxNumber, focusedElement); | ||
80 | |||
64 | return res; | 81 | return res; |
65 | } | 82 | } |
66 | 83 | ||
67 | def private isRelevant(TypeDeclaration t, Set<TypeDeclaration> relevantTypes) { | 84 | def private isRelevant(TypeDeclaration t, Set<TypeDeclaration> relevantTypes) { |
68 | if(relevantTypes === null) { | 85 | if (relevantTypes === null) { |
69 | return true | 86 | return true |
70 | } else { | 87 | } else { |
71 | return relevantTypes.contains(t) | 88 | return relevantTypes.contains(t) |
72 | } | 89 | } |
73 | } | 90 | } |
91 | |||
74 | def private isRelevant(RelationDeclaration r, Set<RelationDeclaration> relevantRelations) { | 92 | def private isRelevant(RelationDeclaration r, Set<RelationDeclaration> relevantRelations) { |
75 | if(relevantRelations === null) { | 93 | if (relevantRelations === null) { |
76 | return true | 94 | return true |
77 | } else { | 95 | } else { |
78 | return relevantRelations.contains(r) | 96 | return relevantRelations.contains(r) |
79 | } | 97 | } |
80 | } | 98 | } |
99 | |||
81 | /** | 100 | /** |
82 | * Gets the largest | 101 | * Gets the minimal neighbourhood size such that every reachable node appears in the shape of every other at least once. |
83 | */ | 102 | */ |
84 | def private getWidth(Map<DefinedElement, Set<String>> types, | 103 | def private getWidth(Map<DefinedElement, Set<String>> types, |
85 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, | 104 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, |
86 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations) | 105 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations) { |
87 | { | 106 | val elements = types.keySet |
88 | val elements = types.keySet | 107 | var Map<DefinedElement, Set<DefinedElement>> reachable = Maps.mutable.ofInitialCapacity(elements.size) |
89 | val Map<DefinedElement,Set<DefinedElement>> reachable = new HashMap | 108 | var Map<DefinedElement, Set<DefinedElement>> newReachable = Maps.mutable.ofInitialCapacity(elements.size) |
90 | for(element : elements) { | 109 | for (element : elements) { |
91 | val set = new HashSet | 110 | val set = Sets.mutable.of |
92 | set.add(element) | 111 | set.add(element) |
93 | reachable.put(element,set) | 112 | reachable.put(element, Sets.mutable.of) |
113 | newReachable.put(element, set) | ||
94 | } | 114 | } |
95 | 115 | ||
96 | var int width = 0 | 116 | var int width = 0 |
97 | var boolean newAdded | 117 | var boolean newAdded |
98 | do { | 118 | do { |
119 | var tmp = reachable | ||
120 | reachable = newReachable | ||
121 | newReachable = tmp | ||
99 | newAdded = false | 122 | newAdded = false |
100 | for(element : elements) { | 123 | for (element : elements) { |
101 | val elementNeigbours = element.lookup(reachable) | 124 | val elementNeigbours = element.lookup(reachable) |
102 | val size = elementNeigbours.size | 125 | val newElementNeigbours = element.lookup(newReachable) |
103 | for(incoming : element.lookup(IncomingRelations)) { | 126 | newElementNeigbours.addAll(elementNeigbours) |
104 | elementNeigbours.addAll(incoming.from.lookup(reachable)) | 127 | for (incoming : element.lookup(IncomingRelations)) { |
128 | newElementNeigbours.addAll(incoming.from.lookup(reachable)) | ||
105 | } | 129 | } |
106 | for(outgoing : element.lookup(OutgoingRelations)) { | 130 | for (outgoing : element.lookup(OutgoingRelations)) { |
107 | elementNeigbours.addAll(outgoing.to.lookup(reachable)) | 131 | newElementNeigbours.addAll(outgoing.to.lookup(reachable)) |
108 | } | 132 | } |
109 | newAdded = newAdded || (elementNeigbours.size > size) | 133 | newAdded = newAdded || (newElementNeigbours.size > elementNeigbours.size) |
110 | } | 134 | } |
111 | 135 | width += 1 | |
112 | width +=1 | 136 | } while (newAdded) |
113 | } while(newAdded) | ||
114 | return width | 137 | return width |
115 | } | 138 | } |
116 | |||
117 | /** | 139 | /** |
118 | * Creates a neighbourhood representation with traces | 140 | * Creates a neighbourhood representation with traces |
119 | * @param model The model to be represented. | 141 | * @param model The model to be represented. |
@@ -122,68 +144,71 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta | |||
122 | * @param range The range of the neighbourhood. | 144 | * @param range The range of the neighbourhood. |
123 | * @param parallels The maximal number of parallel references to be differentiated. | 145 | * @param parallels The maximal number of parallel references to be differentiated. |
124 | */ | 146 | */ |
125 | def private NeighbourhoodWithTraces<ModelRepresentation,NodeRepresentation> doRecursiveNeighbourCalculation( | 147 | def private NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> doRecursiveNeighbourCalculation( |
126 | PartialInterpretation model, | 148 | PartialInterpretation model, Map<DefinedElement, Set<String>> types, |
127 | Map<DefinedElement, Set<String>> types, | ||
128 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, | 149 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, |
129 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, | 150 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, int range, int parallels, |
130 | int range, int parallels, int maxNumber) | 151 | int maxNumber, DefinedElement focusedElement) { |
131 | { | 152 | if (range == 0) { |
132 | if(range == 0){ | 153 | val r = calculateLocalNodeDescriptors(model, types, maxNumber, focusedElement) |
133 | val r = calculateLocalNodeDescriptors(model,types,maxNumber) | 154 | val res = this.createLocalRepresentation(r.value, r.key) |
134 | val res = this.createLocalRepresentation(r.value,r.key) | 155 | if (res.modelRepresentation === null) { |
135 | if(res.modelRepresentation === null) { | ||
136 | throw new IllegalArgumentException('''Model representation is null''') | 156 | throw new IllegalArgumentException('''Model representation is null''') |
137 | } else if(res.nodeRepresentations === null || res.nodeRepresentations.empty) { | 157 | } else if (res.nodeRepresentations === null || res.nodeRepresentations.empty) { |
138 | throw new IllegalArgumentException('''No node representation''') | 158 | throw new IllegalArgumentException('''No node representation''') |
139 | } else if(res.previousRepresentation !== null) { | 159 | } else if (res.previousRepresentation !== null) { |
140 | throw new IllegalArgumentException('''The previous representation of the first neighbourhood have to be null''') | 160 | throw new IllegalArgumentException('''The previous representation of the first neighbourhood have to be null''') |
141 | } else return res | 161 | } else |
142 | } else if(range > 0) { | 162 | return res |
143 | val previous = doRecursiveNeighbourCalculation(model,types,IncomingRelations,OutgoingRelations,range-1,parallels,maxNumber) | 163 | } else if (range > 0) { |
144 | val r = calculateFurtherNodeDescriptors(model,previous,IncomingRelations,OutgoingRelations,parallels,maxNumber) | 164 | val previous = doRecursiveNeighbourCalculation(model, types, IncomingRelations, OutgoingRelations, |
145 | //println('''Level «range» finished.''') | 165 | range - 1, parallels, maxNumber, focusedElement) |
146 | val res = createFurtherRepresentation(r.key,r.value,previous,deepRepresentation) | 166 | val r = calculateFurtherNodeDescriptors(model, previous, IncomingRelations, OutgoingRelations, parallels, |
147 | if(res.modelRepresentation === null) { | 167 | maxNumber) |
168 | // println('''Level «range» finished.''') | ||
169 | val res = createFurtherRepresentation(r.key, r.value, previous, deepRepresentation) | ||
170 | if (res.modelRepresentation === null) { | ||
148 | throw new IllegalArgumentException('''Model representation is null''') | 171 | throw new IllegalArgumentException('''Model representation is null''') |
149 | } else if(res.nodeRepresentations === null || res.nodeRepresentations.empty) { | 172 | } else if (res.nodeRepresentations === null || res.nodeRepresentations.empty) { |
150 | throw new IllegalArgumentException('''No node representation''') | 173 | throw new IllegalArgumentException('''No node representation''') |
151 | } else if(res.previousRepresentation === null && deepRepresentation) { | 174 | } else if (res.previousRepresentation === null && deepRepresentation) { |
152 | throw new IllegalArgumentException('''Need previous representations''') | 175 | throw new IllegalArgumentException('''Need previous representations''') |
153 | } else return res | 176 | } else |
154 | } else if (range == FixPointRage) { | 177 | return res |
155 | return refineUntilFixpoint(model,types,IncomingRelations,OutgoingRelations,parallels,maxNumber) | 178 | } else if (range == FixPointRange) { |
179 | return refineUntilFixpoint(model, types, IncomingRelations, OutgoingRelations, parallels, maxNumber, | ||
180 | focusedElement) | ||
156 | } else if (range == GraphWidthRange) { | 181 | } else if (range == GraphWidthRange) { |
157 | val width = this.getWidth(types,IncomingRelations,OutgoingRelations) | 182 | val width = this.getWidth(types, IncomingRelations, OutgoingRelations) |
158 | //println(width) | 183 | // println(width) |
159 | return doRecursiveNeighbourCalculation(model,types,IncomingRelations,OutgoingRelations,width,parallels,maxNumber) | 184 | return doRecursiveNeighbourCalculation(model, types, IncomingRelations, OutgoingRelations, width, parallels, |
185 | maxNumber, focusedElement) | ||
160 | } | 186 | } |
161 | } | 187 | } |
162 | 188 | ||
163 | def private refineUntilFixpoint( | 189 | def private refineUntilFixpoint(PartialInterpretation model, Map<DefinedElement, Set<String>> types, |
164 | PartialInterpretation model, | ||
165 | Map<DefinedElement, Set<String>> types, | ||
166 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, | 190 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, |
167 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, | 191 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, int parallels, int maxNumbers, |
168 | int parallels, int maxNumbers) | 192 | DefinedElement focusedElement) { |
169 | { | ||
170 | var lastRange = 0 | 193 | var lastRange = 0 |
171 | val last = calculateLocalNodeDescriptors(model,types,maxNumbers) | 194 | val last = calculateLocalNodeDescriptors(model, types, maxNumbers, focusedElement) |
172 | var lastRepresentation = this.createLocalRepresentation(last.value,last.key) | 195 | var lastRepresentation = this.createLocalRepresentation(last.value, last.key) |
173 | //println('''Level 0 finished.''') | 196 | // println('''Level 0 finished.''') |
174 | var boolean hasRefined | 197 | var boolean hasRefined |
175 | do { | 198 | do { |
176 | val nextRange = lastRange+1 | 199 | val nextRange = lastRange + 1 |
177 | val next = calculateFurtherNodeDescriptors(model,lastRepresentation,IncomingRelations,OutgoingRelations,parallels,maxNumbers) | 200 | val next = calculateFurtherNodeDescriptors(model, lastRepresentation, IncomingRelations, OutgoingRelations, |
178 | val nextRepresentation = createFurtherRepresentation(next.key,next.value,lastRepresentation,deepRepresentation) | 201 | parallels, maxNumbers) |
179 | 202 | val nextRepresentation = createFurtherRepresentation(next.key, next.value, lastRepresentation, | |
180 | val previousNumberOfTypes =lastRepresentation.nodeRepresentations.values.toSet.size | 203 | deepRepresentation) |
181 | val nextNumberOfTypes = nextRepresentation.nodeRepresentations.values.toSet.size | 204 | |
182 | hasRefined = nextNumberOfTypes > previousNumberOfTypes | 205 | val previousNumberOfTypes = Sets.immutable.withAll(lastRepresentation.nodeRepresentations.values).size |
183 | 206 | val nextNumberOfTypes = Sets.immutable.withAll(nextRepresentation.nodeRepresentations.values).size | |
207 | hasRefined = nextNumberOfTypes > previousNumberOfTypes | ||
208 | |||
184 | lastRange = nextRange | 209 | lastRange = nextRange |
185 | lastRepresentation = nextRepresentation | 210 | lastRepresentation = nextRepresentation |
186 | 211 | ||
187 | // if(hasRefined) { | 212 | // if(hasRefined) { |
188 | // println('''Level «nextRange» is calculated, number of types is refined: «previousNumberOfTypes» -> «nextNumberOfTypes»''') | 213 | // println('''Level «nextRange» is calculated, number of types is refined: «previousNumberOfTypes» -> «nextNumberOfTypes»''') |
189 | // } else { | 214 | // } else { |
@@ -192,211 +217,217 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta | |||
192 | } while (hasRefined) | 217 | } while (hasRefined) |
193 | return lastRepresentation | 218 | return lastRepresentation |
194 | } | 219 | } |
195 | 220 | ||
196 | def private getElements(PartialInterpretation model) { | 221 | def private getElements(PartialInterpretation model) { |
197 | return | 222 | return model.problem.elements + model.newElements + model.openWorldElements |
198 | model.problem.elements + | ||
199 | model.newElements + | ||
200 | model.openWorldElements | ||
201 | } | 223 | } |
202 | 224 | ||
203 | def private fillTypes(PartialInterpretation model, Map<DefinedElement, Set<String>> node2Type, Set<TypeDeclaration> relevantTypes) { | 225 | def private fillTypes(PartialInterpretation model, Map<DefinedElement, Set<String>> node2Type, |
204 | for(element : model.elements) { | 226 | Set<TypeDeclaration> relevantTypes) { |
205 | node2Type.put(element, new HashSet) | 227 | for (element : model.elements) { |
228 | node2Type.put(element, Sets.mutable.of) | ||
206 | } | 229 | } |
207 | 230 | ||
208 | // for(typeDefinition : model.problem.types.filter(TypeDefinition)) { | 231 | // for(typeDefinition : model.problem.types.filter(TypeDefinition)) { |
209 | // // Dont need | 232 | // // Dont need |
210 | // } | 233 | // } |
211 | for(typeInterpretation : model.partialtypeinterpratation) { | 234 | for (typeInterpretation : model.partialtypeinterpratation) { |
212 | if(typeInterpretation instanceof PartialPrimitiveInterpretation) { | 235 | if (typeInterpretation instanceof PartialPrimitiveInterpretation) { |
213 | 236 | } else if (typeInterpretation instanceof PartialComplexTypeInterpretation) { | |
214 | } else if(typeInterpretation instanceof PartialComplexTypeInterpretation) { | ||
215 | val type = typeInterpretation.interpretationOf | 237 | val type = typeInterpretation.interpretationOf |
216 | if(type.isRelevant(relevantTypes)) { | 238 | if (type.isRelevant(relevantTypes)) { |
217 | for(element : typeInterpretation.elements) { | 239 | for (element : typeInterpretation.elements) { |
218 | element.lookup(node2Type).add(type.name) | 240 | element.lookup(node2Type).add(type.name) |
219 | } | 241 | } |
220 | } | 242 | } |
221 | } | 243 | } |
222 | } | 244 | } |
223 | } | 245 | } |
224 | 246 | ||
225 | /** | 247 | /** |
226 | * Indexes the references | 248 | * Indexes the references |
227 | */ | 249 | */ |
228 | def private fillReferences(PartialInterpretation model, | 250 | def private fillReferences(PartialInterpretation model, |
229 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, | 251 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, |
230 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, | 252 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, |
231 | Set<RelationDeclaration> relevantRelations) | 253 | Set<RelationDeclaration> relevantRelations) { |
232 | { | 254 | for (object : model.elements) { |
233 | for(object : model.elements) { | 255 | IncomingRelations.put(object, new ArrayList) |
234 | IncomingRelations.put(object,new LinkedList) | 256 | OutgoingRelations.put(object, new ArrayList) |
235 | OutgoingRelations.put(object,new LinkedList) | ||
236 | } | 257 | } |
237 | for(relationInterpretation : model.partialrelationinterpretation) { | 258 | for (relationInterpretation : model.partialrelationinterpretation) { |
238 | val type = relationInterpretation.interpretationOf | 259 | val type = relationInterpretation.interpretationOf |
239 | if(type.isRelevant(relevantRelations)) { | 260 | if (type.isRelevant(relevantRelations)) { |
240 | for(link : relationInterpretation.relationlinks) { | 261 | for (link : relationInterpretation.relationlinks) { |
241 | if(link instanceof BinaryElementRelationLink) { | 262 | if (link instanceof BinaryElementRelationLink) { |
242 | OutgoingRelations.get(link.param1) += new OutgoingRelation(link.param2,type.name) | 263 | OutgoingRelations.get(link.param1) += new OutgoingRelation(link.param2, type.name) |
243 | IncomingRelations.get(link.param2) += new IncomingRelation(link.param1,type.name) | 264 | IncomingRelations.get(link.param2) += new IncomingRelation(link.param1, type.name) |
244 | } else throw new UnsupportedOperationException | 265 | } else |
266 | throw new UnsupportedOperationException | ||
245 | } | 267 | } |
246 | } | 268 | } |
247 | } | 269 | } |
248 | } | 270 | } |
249 | 271 | ||
250 | /** | 272 | /** |
251 | * Creates a local representation of the objects (aka zero range neighbourhood) | 273 | * Creates a local representation of the objects (aka zero range neighbourhood) |
252 | */ | 274 | */ |
253 | def abstract protected NeighbourhoodWithTraces<ModelRepresentation,NodeRepresentation> createLocalRepresentation( | 275 | def abstract protected NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> createLocalRepresentation( |
254 | Map<DefinedElement, LocalNodeDescriptor> node2Representation, | 276 | Map<DefinedElement, LocalNodeDescriptor> node2Representation, |
255 | Map<LocalNodeDescriptor, Integer> representation2Amount | 277 | Map<LocalNodeDescriptor, Integer> representation2Amount |
256 | ) | 278 | ) |
257 | 279 | ||
258 | /** | 280 | /** |
259 | * Creates a | 281 | * Creates a |
260 | */ | 282 | */ |
261 | def abstract protected NeighbourhoodWithTraces<ModelRepresentation,NodeRepresentation> createFurtherRepresentation( | 283 | def abstract protected NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> createFurtherRepresentation( |
262 | Map<FurtherNodeDescriptor<NodeRepresentation>, Integer> nodeDescriptors, | 284 | Map<FurtherNodeDescriptor<NodeRepresentation>, Integer> nodeDescriptors, |
263 | Map<DefinedElement, FurtherNodeDescriptor<NodeRepresentation>> node2Representation, | 285 | Map<DefinedElement, FurtherNodeDescriptor<NodeRepresentation>> node2Representation, |
264 | NeighbourhoodWithTraces<ModelRepresentation,NodeRepresentation> previous, | 286 | NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> previous, |
265 | boolean deepRepresentation | 287 | boolean deepRepresentation |
266 | ) | 288 | ) |
267 | 289 | ||
268 | def private addOne(int original, int max) { | 290 | def private addOne(Integer originalObj, int max) { |
291 | if (originalObj === null) { | ||
292 | return 1 | ||
293 | } | ||
294 | val original = originalObj.intValue | ||
269 | if(original == Integer.MAX_VALUE) return Integer.MAX_VALUE | 295 | if(original == Integer.MAX_VALUE) return Integer.MAX_VALUE |
270 | if(original +1 > max) return Integer.MAX_VALUE | 296 | if(original + 1 > max) return Integer.MAX_VALUE else return original + 1 |
271 | else return original+1 | ||
272 | } | 297 | } |
273 | 298 | ||
274 | private def calculateIncomingEdges(Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, | 299 | private def calculateIncomingEdges(Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, |
275 | DefinedElement object, Map<DefinedElement, ? extends NodeRepresentation> previousNodeRepresentations, int parallel) | 300 | DefinedElement object, Map<DefinedElement, ? extends NodeRepresentation> previousNodeRepresentations, |
276 | { | 301 | int parallel) { |
277 | val Map<IncomingRelation<NodeRepresentation>, Integer> res = new HashMap | 302 | val Map<IncomingRelation<NodeRepresentation>, Integer> res = Maps.mutable.of |
278 | for (incomingConcreteEdge : IncomingRelations.get(object)) { | 303 | for (incomingConcreteEdge : IncomingRelations.get(object)) { |
279 | val IncomingRelation<NodeRepresentation> e = new IncomingRelation( | 304 | val IncomingRelation<NodeRepresentation> e = new IncomingRelation( |
280 | previousNodeRepresentations.get(incomingConcreteEdge.from), incomingConcreteEdge.type) | 305 | previousNodeRepresentations.get(incomingConcreteEdge.from), incomingConcreteEdge.type) |
281 | if (res.containsKey(e)) { | 306 | res.compute(e, [key, value | addOne(value, parallel)]) |
282 | res.put(e, addOne(res.get(e),parallel)) | ||
283 | } else { | ||
284 | res.put(e, 1) | ||
285 | } | ||
286 | } | 307 | } |
287 | return res | 308 | return res |
288 | } | 309 | } |
289 | 310 | ||
290 | private def calcuateOutgoingEdges(Map<DefinedElement,List<OutgoingRelation<DefinedElement>>> OutgoingRelations, | 311 | private def calcuateOutgoingEdges(Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, |
291 | DefinedElement object, Map<DefinedElement, ? extends NodeRepresentation> previousNodeRepresentations, int parallel) | 312 | DefinedElement object, Map<DefinedElement, ? extends NodeRepresentation> previousNodeRepresentations, |
292 | { | 313 | int parallel) { |
293 | val Map<OutgoingRelation<NodeRepresentation>,Integer> res= new HashMap | 314 | val Map<OutgoingRelation<NodeRepresentation>, Integer> res = Maps.mutable.of |
294 | for(outgoingConcreteEdge : OutgoingRelations.get(object)) { | 315 | for (outgoingConcreteEdge : OutgoingRelations.get(object)) { |
295 | val OutgoingRelation<NodeRepresentation> e = | 316 | val OutgoingRelation<NodeRepresentation> e = new OutgoingRelation( |
296 | new OutgoingRelation( | 317 | previousNodeRepresentations.get(outgoingConcreteEdge.to), outgoingConcreteEdge.type) |
297 | previousNodeRepresentations.get(outgoingConcreteEdge.to), | 318 | res.compute(e, [key, value | addOne(value, parallel)]) |
298 | outgoingConcreteEdge.type) | ||
299 | if(res.containsKey(e)) { | ||
300 | res.put(e,addOne(res.get(e),parallel)) | ||
301 | } else { | ||
302 | res.put(e,1) | ||
303 | } | ||
304 | } | 319 | } |
305 | return res; | 320 | return res |
306 | } | 321 | } |
307 | 322 | ||
308 | /*def private <KEY,VALUE> void addOrCreate_Set(Map<KEY,Set<VALUE>> map, KEY key, VALUE value) { | 323 | /*def private <KEY,VALUE> void addOrCreate_Set(Map<KEY,Set<VALUE>> map, KEY key, VALUE value) { |
309 | var Set<VALUE> s; | 324 | * var Set<VALUE> s; |
310 | if(map.containsKey(key)) { | 325 | * if(map.containsKey(key)) { |
311 | s = map.get(key); | 326 | * s = map.get(key); |
312 | } else { | 327 | * } else { |
313 | s = new HashSet | 328 | * s = new HashSet |
314 | map.put(key,s) | 329 | * map.put(key,s) |
315 | } | 330 | * } |
316 | s.add(value) | 331 | * s.add(value) |
317 | }*/ | 332 | }*/ |
318 | 333 | private def calculateFurtherNodeDescriptors(PartialInterpretation model, | |
319 | |||
320 | private def calculateFurtherNodeDescriptors( | ||
321 | PartialInterpretation model, | ||
322 | NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> previous, | 334 | NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> previous, |
323 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, | 335 | Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, |
324 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, | 336 | Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, int parallels, int maxNumber) { |
325 | int parallels, int maxNumber) | ||
326 | { | ||
327 | val previousNodeRepresentations = previous.nodeRepresentations | 337 | val previousNodeRepresentations = previous.nodeRepresentations |
328 | val node2Representation = new HashMap<DefinedElement,FurtherNodeDescriptor<NodeRepresentation>> | 338 | val size = previousNodeRepresentations.size |
329 | val Map<FurtherNodeDescriptor<NodeRepresentation>,Integer> descriptor2Number = | 339 | val node2Representation = Maps.mutable.<DefinedElement, FurtherNodeDescriptor<NodeRepresentation>>ofInitialCapacity(size) |
330 | if(this.mergeSimilarNeighbourhood){ new HashMap } else { null } | 340 | val Map<FurtherNodeDescriptor<NodeRepresentation>, Integer> descriptor2Number = if (this. |
331 | val Map<FurtherNodeDescriptor<NodeRepresentation>,FurtherNodeDescriptor<NodeRepresentation>> uniqueDescription = | 341 | mergeSimilarNeighbourhood) { |
332 | if(this.mergeSimilarNeighbourhood){ new HashMap } else { null } | 342 | Maps.mutable.ofInitialCapacity(size) |
333 | 343 | } else { | |
334 | for(object: model.elements) { | 344 | null |
335 | val incomingEdges = this.calculateIncomingEdges(IncomingRelations, object, previousNodeRepresentations,parallels) | 345 | } |
336 | val outgoingEdges = this.calcuateOutgoingEdges(OutgoingRelations,object, previousNodeRepresentations,parallels) | 346 | val Map<FurtherNodeDescriptor<NodeRepresentation>, FurtherNodeDescriptor<NodeRepresentation>> uniqueDescription = if (this. |
337 | 347 | mergeSimilarNeighbourhood) { | |
348 | Maps.mutable.ofInitialCapacity(size) | ||
349 | } else { | ||
350 | null | ||
351 | } | ||
352 | |||
353 | for (object : model.elements) { | ||
354 | val incomingEdges = this.calculateIncomingEdges(IncomingRelations, object, previousNodeRepresentations, | ||
355 | parallels) | ||
356 | val outgoingEdges = this.calcuateOutgoingEdges(OutgoingRelations, object, previousNodeRepresentations, | ||
357 | parallels) | ||
358 | |||
338 | val previousType = previousNodeRepresentations.get(object) | 359 | val previousType = previousNodeRepresentations.get(object) |
339 | 360 | ||
340 | if(previousType === null) { | 361 | if (previousType === null) { |
341 | println("Error in state coder") | 362 | println("Error in state coder") |
342 | } | 363 | } |
343 | 364 | ||
344 | val nodeDescriptor = new FurtherNodeDescriptor( | 365 | val nodeDescriptor = new FurtherNodeDescriptor(previousType, incomingEdges, outgoingEdges) |
345 | previousType, | 366 | |
346 | incomingEdges, | 367 | if (this.mergeSimilarNeighbourhood) { |
347 | outgoingEdges) | 368 | if (descriptor2Number.containsKey(nodeDescriptor)) { |
348 | |||
349 | if(this.mergeSimilarNeighbourhood) { | ||
350 | if(descriptor2Number.containsKey(nodeDescriptor)) { | ||
351 | descriptor2Number.put( | 369 | descriptor2Number.put( |
352 | nodeDescriptor, | 370 | nodeDescriptor, |
353 | addOne(descriptor2Number.get(nodeDescriptor),maxNumber) | 371 | addOne(descriptor2Number.get(nodeDescriptor), maxNumber) |
354 | ) | 372 | ) |
355 | node2Representation.put(object,uniqueDescription.get(nodeDescriptor)) | 373 | node2Representation.put(object, uniqueDescription.get(nodeDescriptor)) |
356 | } else { | 374 | } else { |
357 | descriptor2Number.put(nodeDescriptor,if(1>maxNumber){Integer.MAX_VALUE}else{1}) | 375 | descriptor2Number.put(nodeDescriptor, if (1 > maxNumber) { |
358 | uniqueDescription.put(nodeDescriptor,nodeDescriptor) | 376 | Integer.MAX_VALUE |
359 | node2Representation.put(object,nodeDescriptor) | 377 | } else { |
378 | 1 | ||
379 | }) | ||
380 | uniqueDescription.put(nodeDescriptor, nodeDescriptor) | ||
381 | node2Representation.put(object, nodeDescriptor) | ||
360 | } | 382 | } |
361 | } else { | 383 | } else { |
362 | node2Representation.put(object,nodeDescriptor) | 384 | node2Representation.put(object, nodeDescriptor) |
363 | } | 385 | } |
364 | } | 386 | } |
365 | 387 | ||
366 | return descriptor2Number -> node2Representation | 388 | return descriptor2Number -> node2Representation |
367 | } | 389 | } |
368 | 390 | ||
369 | private def calculateLocalNodeDescriptors( | 391 | private def calculateLocalNodeDescriptors(PartialInterpretation model, Map<DefinedElement, Set<String>> types, |
370 | PartialInterpretation model, | 392 | int maxNumber, DefinedElement focusedElement) { |
371 | Map<DefinedElement, Set<String>> types, | 393 | val size = types.size |
372 | int maxNumber) | 394 | val Map<DefinedElement, LocalNodeDescriptor> node2Representation = Maps.mutable.ofInitialCapacity(size) |
373 | { | 395 | val Map<LocalNodeDescriptor, Integer> representation2Amount = if (mergeSimilarNeighbourhood) { |
374 | val Map<DefinedElement, LocalNodeDescriptor> node2Representation = new HashMap | 396 | Maps.mutable.ofInitialCapacity(size) |
375 | val Map<LocalNodeDescriptor, Integer> representation2Amount = | 397 | } else { |
376 | if(mergeSimilarNeighbourhood){ new HashMap } else { null } | 398 | null |
377 | val Map<LocalNodeDescriptor, LocalNodeDescriptor> uniqueRepresentation = | 399 | } |
378 | if(this.mergeSimilarNeighbourhood){ new HashMap } else { null } | 400 | val Map<LocalNodeDescriptor, LocalNodeDescriptor> uniqueRepresentation = if (this.mergeSimilarNeighbourhood) { |
379 | 401 | Maps.mutable.ofInitialCapacity(size) | |
380 | for(element : model.elements) { | 402 | } else { |
381 | var newDescriptor = new LocalNodeDescriptor(element.name,element.lookup(types)) | 403 | null |
382 | if(this.mergeSimilarNeighbourhood){ | 404 | } |
383 | if(uniqueRepresentation.containsKey(newDescriptor)) { | 405 | |
406 | for (element : model.elements) { | ||
407 | val name = if(element == focusedElement) FOCUSED_ELEMENT_NAME else element.name | ||
408 | var newDescriptor = new LocalNodeDescriptor(name, element.lookup(types)) | ||
409 | if (this.mergeSimilarNeighbourhood) { | ||
410 | if (uniqueRepresentation.containsKey(newDescriptor)) { | ||
384 | newDescriptor = newDescriptor.lookup(uniqueRepresentation) | 411 | newDescriptor = newDescriptor.lookup(uniqueRepresentation) |
385 | node2Representation.put(element,newDescriptor) | 412 | node2Representation.put(element, newDescriptor) |
386 | representation2Amount.put( | 413 | representation2Amount.put( |
387 | newDescriptor, | 414 | newDescriptor, |
388 | addOne(newDescriptor.lookup(representation2Amount),maxNumber) | 415 | addOne(newDescriptor.lookup(representation2Amount), maxNumber) |
389 | ) | 416 | ) |
390 | } else { | 417 | } else { |
391 | uniqueRepresentation.put(newDescriptor,newDescriptor) | 418 | uniqueRepresentation.put(newDescriptor, newDescriptor) |
392 | node2Representation.put(element,newDescriptor) | 419 | node2Representation.put(element, newDescriptor) |
393 | representation2Amount.put(newDescriptor, if(1>maxNumber){Integer.MAX_VALUE}else{1}) | 420 | representation2Amount.put(newDescriptor, if (1 > maxNumber) { |
421 | Integer.MAX_VALUE | ||
422 | } else { | ||
423 | 1 | ||
424 | }) | ||
394 | } | 425 | } |
395 | } else { | 426 | } else { |
396 | node2Representation.put(element,newDescriptor) | 427 | node2Representation.put(element, newDescriptor) |
397 | } | 428 | } |
398 | } | 429 | } |
399 | 430 | ||
400 | return representation2Amount -> node2Representation | 431 | return representation2Amount -> node2Representation |
401 | } | 432 | } |
402 | } \ No newline at end of file | 433 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend new file mode 100644 index 00000000..c10457b0 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend | |||
@@ -0,0 +1,68 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood | ||
2 | |||
3 | import com.google.common.collect.Maps | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
6 | import java.util.HashMap | ||
7 | import java.util.Map | ||
8 | import org.eclipse.xtend.lib.annotations.Data | ||
9 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
10 | |||
11 | @Data | ||
12 | class PairwiseNeighbourhoodRepresentation<BasicNodeRepresentation> { | ||
13 | val Map<?, Integer> modelRepresentation | ||
14 | val Map<DefinedElement, BasicNodeRepresentation> basicNodeRepresentations | ||
15 | val Map<DefinedElement, ? extends Map<DefinedElement, ? extends BasicNodeRepresentation>> pairwiseNodeRepresentations | ||
16 | |||
17 | def getBasicRepresentation(DefinedElement a) { | ||
18 | basicNodeRepresentations.get(a) | ||
19 | } | ||
20 | |||
21 | def getPairwiseRepresentation(DefinedElement a, DefinedElement b) { | ||
22 | pairwiseNodeRepresentations.get(a).get(b) | ||
23 | } | ||
24 | } | ||
25 | |||
26 | @FinalFieldsConstructor | ||
27 | class PartialInterpretation2PairwiseNeighbourhoodRepresentation<BasicNodeRepresentation> { | ||
28 | val PartialInterpretation2NeighbourhoodRepresentation<? extends Map<? extends BasicNodeRepresentation, Integer>, BasicNodeRepresentation> basicNeighbourhoodRepresenter | ||
29 | |||
30 | def createRepresentation(PartialInterpretation model, NeighbourhoodOptions options) { | ||
31 | val basicRepresentation = basicNeighbourhoodRepresenter.createRepresentation(model, options) | ||
32 | val basicModelRepresentation = basicRepresentation.modelRepresentation | ||
33 | val basicNodeRepresentations = basicRepresentation.nodeRepresentations | ||
34 | val pairwiseNodeRepresentations = Maps.newHashMapWithExpectedSize(basicNodeRepresentations.size) | ||
35 | val modelRepresentation = new HashMap<Object, Integer> | ||
36 | for (nodeWithBasicRepresentation : basicNodeRepresentations.entrySet) { | ||
37 | val node = nodeWithBasicRepresentation.key | ||
38 | val basicNodeRepresentation = nodeWithBasicRepresentation.value | ||
39 | val count = basicModelRepresentation.get(basicNodeRepresentation) | ||
40 | if (count == 1) { | ||
41 | pairwiseNodeRepresentations.put(node, basicNodeRepresentations) | ||
42 | modelRepresentation.put(basicNodeRepresentation, count) | ||
43 | } else { | ||
44 | val neighbourhoodRepresentation = basicNeighbourhoodRepresenter. | ||
45 | createRepresentationWithFocus(model, options, node) | ||
46 | pairwiseNodeRepresentations.put(node, neighbourhoodRepresentation.nodeRepresentations) | ||
47 | modelRepresentation.compute(neighbourhoodRepresentation.modelRepresentation) [ key, value | | ||
48 | if (value === null) { | ||
49 | if (1 > options.maxNumber) { | ||
50 | Integer.MAX_VALUE | ||
51 | } else { | ||
52 | 1 | ||
53 | } | ||
54 | } else { | ||
55 | addOne(value, options.maxNumber) | ||
56 | } | ||
57 | ] | ||
58 | } | ||
59 | } | ||
60 | new PairwiseNeighbourhoodRepresentation(modelRepresentation, basicNodeRepresentations, | ||
61 | pairwiseNodeRepresentations) | ||
62 | } | ||
63 | |||
64 | def private addOne(int original, int max) { | ||
65 | if(original == Integer.MAX_VALUE) return Integer.MAX_VALUE | ||
66 | if(original + 1 > max) return Integer.MAX_VALUE else return original + 1 | ||
67 | } | ||
68 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend new file mode 100644 index 00000000..089880b1 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend | |||
@@ -0,0 +1,137 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodOptions | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage | ||
10 | import java.util.LinkedList | ||
11 | import java.util.List | ||
12 | import org.eclipse.emf.common.notify.Notifier | ||
13 | import org.eclipse.emf.ecore.EClass | ||
14 | import org.eclipse.emf.ecore.EObject | ||
15 | import org.eclipse.emf.ecore.EStructuralFeature | ||
16 | import org.eclipse.viatra.dse.statecode.IStateCoder | ||
17 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory | ||
18 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
19 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
20 | import org.eclipse.viatra.query.runtime.base.api.FeatureListener | ||
21 | import org.eclipse.viatra.query.runtime.base.api.IndexingLevel | ||
22 | import org.eclipse.viatra.query.runtime.base.api.InstanceListener | ||
23 | import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper | ||
24 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
25 | import org.eclipse.xtend.lib.annotations.Accessors | ||
26 | |||
27 | abstract class AbstractNeighbourhoodBasedStateCoderFactory implements IStateCoderFactory { | ||
28 | val List<AbstractNeighbourhoodBasedPartialInterpretationStateCoder> statecoders = new LinkedList | ||
29 | |||
30 | val NeighbourhoodOptions options | ||
31 | |||
32 | protected new() { | ||
33 | this(NeighbourhoodOptions.DEFAULT) | ||
34 | } | ||
35 | |||
36 | protected new(NeighbourhoodOptions options) { | ||
37 | this.options = options | ||
38 | } | ||
39 | |||
40 | synchronized override createStateCoder() { | ||
41 | val res = doCreateStateCoder(options) | ||
42 | statecoders += res | ||
43 | return res | ||
44 | } | ||
45 | |||
46 | protected def AbstractNeighbourhoodBasedPartialInterpretationStateCoder doCreateStateCoder( | ||
47 | NeighbourhoodOptions options) | ||
48 | |||
49 | def getSumStatecoderRuntime() { | ||
50 | statecoders.map[statecoderRuntime].reduce[p1, p2|p1 + p2] | ||
51 | } | ||
52 | } | ||
53 | |||
54 | abstract class AbstractNeighbourhoodBasedPartialInterpretationStateCoder implements IStateCoder { | ||
55 | val NeighbourhoodOptions options | ||
56 | |||
57 | var PartialInterpretation target | ||
58 | |||
59 | protected new(NeighbourhoodOptions options) { | ||
60 | this.options = options | ||
61 | } | ||
62 | |||
63 | @Accessors(PUBLIC_GETTER) var long statecoderRuntime = 0 | ||
64 | |||
65 | synchronized private def refreshStateCodes() { | ||
66 | if (refreshNeeded) { | ||
67 | val startTime = System.nanoTime | ||
68 | doRefreshStateCodes(target, options) | ||
69 | statecoderRuntime += (System.nanoTime - startTime) | ||
70 | } | ||
71 | } | ||
72 | |||
73 | protected def boolean isRefreshNeeded() | ||
74 | |||
75 | protected def void doRefreshStateCodes(PartialInterpretation target, NeighbourhoodOptions options) | ||
76 | |||
77 | synchronized override createActivationCode(IPatternMatch match) { | ||
78 | refreshStateCodes | ||
79 | val startTime = System.nanoTime | ||
80 | val code = doCreateActivationCode(match) | ||
81 | statecoderRuntime += (System.nanoTime - startTime) | ||
82 | code | ||
83 | } | ||
84 | |||
85 | protected def Object doCreateActivationCode(IPatternMatch match) | ||
86 | |||
87 | synchronized override createStateCode() { | ||
88 | refreshStateCodes | ||
89 | doCreateStateCode | ||
90 | } | ||
91 | |||
92 | protected def Object doCreateStateCode() | ||
93 | |||
94 | override init(Notifier notifier) { | ||
95 | this.target = notifier as PartialInterpretation | ||
96 | val queryEngine = ViatraQueryEngine.on(new EMFScope(notifier)) | ||
97 | val baseIndex = queryEngine.getBaseIndex() as EMFBaseIndexWrapper | ||
98 | val navigationHelper = baseIndex.getNavigationHelper(); | ||
99 | |||
100 | val classes = PartialinterpretationPackage.eINSTANCE.EClassifiers.filter(EClass).toSet | ||
101 | val features = classes.map[it.EAllStructuralFeatures].flatten.toSet | ||
102 | navigationHelper.registerObservedTypes(classes, null, features, IndexingLevel.FULL); | ||
103 | |||
104 | navigationHelper.addFeatureListener(features, new FeatureListener() { | ||
105 | override void featureInserted(EObject host, EStructuralFeature feature, Object value) { invalidate } | ||
106 | |||
107 | override void featureDeleted(EObject host, EStructuralFeature feature, Object value) { invalidate } | ||
108 | }) | ||
109 | navigationHelper.addInstanceListener(classes, new InstanceListener() { | ||
110 | override void instanceInserted(EClass clazz, EObject instance) { invalidate } | ||
111 | |||
112 | override void instanceDeleted(EClass clazz, EObject instance) { invalidate } | ||
113 | }) | ||
114 | } | ||
115 | |||
116 | synchronized def invalidate() { | ||
117 | doInvalidate | ||
118 | } | ||
119 | |||
120 | protected def void doInvalidate() | ||
121 | |||
122 | def protected getFallbackCode(Object o) { | ||
123 | switch (o) { | ||
124 | PartialInterpretation, | ||
125 | LogicProblem: | ||
126 | null | ||
127 | PartialRelationInterpretation: | ||
128 | o.interpretationOf.name | ||
129 | PartialPrimitiveInterpretation: | ||
130 | o.class.simpleName.hashCode | ||
131 | PartialComplexTypeInterpretation: | ||
132 | o.interpretationOf.name.hashCode | ||
133 | default: | ||
134 | throw new UnsupportedOperationException('''Unsupported type: «o.class.simpleName»''') | ||
135 | } | ||
136 | } | ||
137 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend index f55a501a..c7b8ee37 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend | |||
@@ -62,13 +62,13 @@ class IdentifierBasedStateCode { | |||
62 | int numberOfNewElement | 62 | int numberOfNewElement |
63 | SortedSet<RelationStatecoder> relationStatecoders | 63 | SortedSet<RelationStatecoder> relationStatecoders |
64 | 64 | ||
65 | private static val comparator = new Comparator<RelationStatecoder>() { | 65 | static val comparator = new Comparator<RelationStatecoder>() { |
66 | override compare(RelationStatecoder o1, RelationStatecoder o2) { | 66 | override compare(RelationStatecoder o1, RelationStatecoder o2) { |
67 | o1.relationName.compareTo(o2.relationName) | 67 | o1.relationName.compareTo(o2.relationName) |
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 | ||
71 | public new(int numberOfNewElements) { | 71 | new(int numberOfNewElements) { |
72 | this.numberOfNewElement = numberOfNewElements | 72 | this.numberOfNewElement = numberOfNewElements |
73 | this.relationStatecoders = new TreeSet(comparator) | 73 | this.relationStatecoders = new TreeSet(comparator) |
74 | } | 74 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend index a86bcd1f..04c49506 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend | |||
@@ -1,223 +1,109 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder |
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor | 3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement |
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodOptions | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2Hash | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice | 6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice |
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2NeighbourhoodRepresentation | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage | ||
7 | import java.util.ArrayList | 9 | import java.util.ArrayList |
8 | import java.util.LinkedList | ||
9 | import java.util.List | ||
10 | import java.util.Map | 10 | import java.util.Map |
11 | import org.eclipse.emf.common.notify.Notifier | ||
12 | import org.eclipse.emf.ecore.EClass | ||
13 | import org.eclipse.emf.ecore.EObject | ||
14 | import org.eclipse.emf.ecore.EStructuralFeature | ||
15 | import org.eclipse.viatra.dse.statecode.IStateCoder | ||
16 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory | ||
17 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | 11 | import org.eclipse.viatra.query.runtime.api.IPatternMatch |
18 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | 12 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification |
19 | import org.eclipse.viatra.query.runtime.base.api.FeatureListener | ||
20 | import org.eclipse.viatra.query.runtime.base.api.IndexingLevel | ||
21 | import org.eclipse.viatra.query.runtime.base.api.InstanceListener | ||
22 | import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper | ||
23 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
24 | import org.eclipse.xtend.lib.annotations.Accessors | ||
25 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement | ||
26 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation | ||
28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation | ||
29 | import java.util.Set | ||
30 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration | ||
31 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | ||
32 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2NeighbourhoodRepresentation | ||
33 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
34 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation | ||
35 | 13 | ||
36 | class NeighbourhoodBasedStateCoderFactory implements IStateCoderFactory { | 14 | class NeighbourhoodBasedStateCoderFactory extends AbstractNeighbourhoodBasedStateCoderFactory { |
37 | val List<NeighbourhoodBasedPartialInterpretationStateCoder> statecoders = new LinkedList | 15 | new() { |
38 | |||
39 | val int range | ||
40 | val int parallels | ||
41 | val int maxNumber | ||
42 | val Set<TypeDeclaration> relevantTypes | ||
43 | val Set<RelationDeclaration> relevantRelations | ||
44 | |||
45 | public new() { | ||
46 | this.range = PartialInterpretation2NeighbourhoodRepresentation::GraphWidthRange | ||
47 | this.parallels = PartialInterpretation2NeighbourhoodRepresentation::FullParallels | ||
48 | this.maxNumber = PartialInterpretation2NeighbourhoodRepresentation::MaxNumbers | ||
49 | this.relevantTypes = null | ||
50 | this.relevantRelations = null | ||
51 | } | 16 | } |
52 | 17 | ||
53 | public new(int range, int parallels, int maxNumber, Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations) { | 18 | new(NeighbourhoodOptions options) { |
54 | this.range = range | 19 | super(options) |
55 | this.parallels = parallels | 20 | } |
56 | this.maxNumber = maxNumber | 21 | |
57 | this.relevantTypes = relevantTypes | 22 | override protected doCreateStateCoder(NeighbourhoodOptions options) { |
58 | this.relevantRelations = relevantRelations | 23 | new NeighbourhoodBasedPartialInterpretationStateCoder(new PartialInterpretation2ImmutableTypeLattice, options) |
59 | } | 24 | } |
60 | |||
61 | synchronized override createStateCoder() { | ||
62 | val res = new NeighbourhoodBasedPartialInterpretationStateCoder(statecoders.size, | ||
63 | range,parallels,maxNumber,relevantTypes,relevantRelations) | ||
64 | statecoders += res | ||
65 | return res | ||
66 | } | ||
67 | def getSumStatecoderRuntime() { | ||
68 | statecoders.map[statecoderRuntime].reduce[p1, p2|p1+p2] | ||
69 | } | ||
70 | } | 25 | } |
71 | 26 | ||
72 | class NeighbourhoodBasedPartialInterpretationStateCoder implements IStateCoder{ | 27 | class NeighbourhoodBasedHashStateCoderFactory extends AbstractNeighbourhoodBasedStateCoderFactory { |
73 | val int id; | 28 | new() { |
74 | val int range | 29 | } |
75 | val int parallels | 30 | |
76 | val int maxNumber | 31 | new(NeighbourhoodOptions options) { |
77 | val Set<TypeDeclaration> relevantTypes | 32 | super(options) |
78 | val Set<RelationDeclaration> relevantRelations | 33 | } |
79 | 34 | ||
80 | val calculator = | 35 | override protected doCreateStateCoder(NeighbourhoodOptions options) { |
81 | new PartialInterpretation2ImmutableTypeLattice | 36 | new NeighbourhoodBasedPartialInterpretationStateCoder(new PartialInterpretation2Hash, options) |
82 | var PartialInterpretation target | 37 | } |
83 | 38 | } | |
84 | private var Map<DefinedElement, ? extends AbstractNodeDescriptor> nodeRepresentations = null | 39 | |
85 | private var Map<? extends AbstractNodeDescriptor, Integer> modelRepresentation = null | 40 | class NeighbourhoodBasedPartialInterpretationStateCoder<ModelRep, NodeRep> extends AbstractNeighbourhoodBasedPartialInterpretationStateCoder { |
86 | 41 | val PartialInterpretation2NeighbourhoodRepresentation<ModelRep, NodeRep> calculator | |
87 | /*public new(int id) { | 42 | val Map<IQuerySpecification<?>, String> fullyQualifiedNames = newHashMap |
88 | this.id = id | 43 | var Map<DefinedElement, ? extends NodeRep> nodeRepresentations = null |
89 | this.range = PartialInterpretation2NeighbourhoodRepresentation::FixPointRage | 44 | var ModelRep modelRepresentation = null |
90 | this.parallels = PartialInterpretation2NeighbourhoodRepresentation::FullParallels | 45 | |
91 | this.maxNumber = maxNumber = PartialInterpretation2NeighbourhoodRepresentation::MaxNumbers | 46 | new(PartialInterpretation2NeighbourhoodRepresentation<ModelRep, NodeRep> calculator, NeighbourhoodOptions options) { |
92 | this.relevantTypes = relevantTypes | 47 | super(options) |
93 | this.relevantRelations = relevantRelations | 48 | this.calculator = calculator |
94 | }*/ | 49 | } |
50 | |||
51 | override protected isRefreshNeeded() { | ||
52 | nodeRepresentations === null || modelRepresentation === null | ||
53 | } | ||
54 | |||
55 | override doRefreshStateCodes(PartialInterpretation target, NeighbourhoodOptions options) { | ||
56 | val code = calculator.createRepresentation(target, options) | ||
57 | modelRepresentation = code.modelRepresentation | ||
58 | nodeRepresentations = code.nodeRepresentations | ||
59 | } | ||
95 | 60 | ||
96 | public new(int id, int range, int parallels, int maxNumber, Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations) { | 61 | private def getFullyQualifiedNameCached(IQuerySpecification<?> specification) { |
97 | this.id = id | 62 | fullyQualifiedNames.computeIfAbsent(specification, [fullyQualifiedName]) |
98 | this.range = range | ||
99 | this.parallels = parallels | ||
100 | this.maxNumber = maxNumber | ||
101 | this.relevantTypes = relevantTypes | ||
102 | this.relevantRelations = relevantRelations | ||
103 | } | 63 | } |
104 | 64 | ||
105 | @Accessors(PUBLIC_GETTER) var long statecoderRuntime = 0 | 65 | override doCreateActivationCode(IPatternMatch match) { |
106 | 66 | val size = match.specification.parameters.size | |
107 | // val range = -1 | 67 | var int hash = 0 |
108 | // val par = Integer.MAX_VALUE | 68 | val prime = 31 |
109 | //val deeprepresentation = false | 69 | |
110 | 70 | for (var int index = 0; index < size; index++) { | |
111 | ///////// | 71 | val matchArgument = match.get(index) |
112 | // Caching version | 72 | val code = getCode(matchArgument) |
113 | ///////// | 73 | val codeNumber = if (code === null) { |
114 | synchronized private def refreshStateCodes() { | 74 | 0 |
115 | if(this.nodeRepresentations === null || this.modelRepresentation === null) { | ||
116 | val startTime = System.nanoTime | ||
117 | //relevantObjects.forEach[println(it)] | ||
118 | val code = calculator.createRepresentation(target,range,parallels,maxNumber,relevantTypes,relevantRelations) | ||
119 | this.modelRepresentation = code.modelRepresentation | ||
120 | this.nodeRepresentations = code.nodeRepresentations | ||
121 | statecoderRuntime += (System.nanoTime - startTime) | ||
122 | } | ||
123 | } | ||
124 | synchronized override createActivationCode(IPatternMatch match) { | ||
125 | refreshStateCodes | ||
126 | |||
127 | val startTime = System.nanoTime | ||
128 | val size = match.specification.parameters.size | ||
129 | val res = new ArrayList(size) | ||
130 | var int index = 0 | ||
131 | var int equivalenceHash = 0 | ||
132 | val prime = 31 | ||
133 | |||
134 | while(index < size) { | ||
135 | res.add(getCode(match.get(index))) | ||
136 | index++ | ||
137 | for(var i = 0; i<index; i++) { | ||
138 | val number = if(match.get(index) === match.get(i)){1}else{0} | ||
139 | equivalenceHash = prime * equivalenceHash + number | ||
140 | } | ||
141 | } | ||
142 | |||
143 | statecoderRuntime += (System.nanoTime - startTime) | ||
144 | return match.specification.fullyQualifiedName->(res->equivalenceHash).hashCode | ||
145 | } | ||
146 | |||
147 | |||
148 | def private getCode(Object o) { | ||
149 | if(o instanceof DefinedElement) { | ||
150 | this.nodeRepresentations.get(o) | ||
151 | } else if(o instanceof PartialInterpretation || o instanceof LogicProblem) { | ||
152 | return null | ||
153 | } else if(o instanceof PartialRelationInterpretation) { | ||
154 | return o.interpretationOf.name | ||
155 | } else if(o instanceof PartialTypeInterpratation) { | ||
156 | if(o instanceof PartialPrimitiveInterpretation) { | ||
157 | o.class.simpleName.hashCode | ||
158 | } else if (o instanceof PartialComplexTypeInterpretation){ | ||
159 | return o.interpretationOf.name.hashCode | ||
160 | } else { | 75 | } else { |
161 | throw new UnsupportedOperationException('''Unsupported type: «o.class.simpleName»''') | 76 | code.hashCode |
77 | } | ||
78 | hash = prime * hash + codeNumber | ||
79 | for (var i = 0; i < index; i++) { | ||
80 | val number = if (matchArgument === match.get(i)) { | ||
81 | 1 | ||
82 | } else { | ||
83 | 0 | ||
84 | } | ||
85 | hash = prime * hash + number | ||
162 | } | 86 | } |
163 | } else { | ||
164 | throw new UnsupportedOperationException('''Unsupported type: «o.class.simpleName»''') | ||
165 | } | 87 | } |
166 | } | 88 | |
167 | 89 | match.specification.fullyQualifiedNameCached -> hash | |
168 | synchronized override createStateCode() { | 90 | } |
169 | refreshStateCodes | 91 | |
170 | return this.modelRepresentation.hashCode | 92 | def private getCode(Object o) { |
171 | } | 93 | switch (o) { |
172 | ///////// | 94 | DefinedElement: |
173 | // Caching version | 95 | nodeRepresentations.get(o) |
174 | ///////// | 96 | default: |
175 | 97 | getFallbackCode(o) | |
176 | ///////// | 98 | } |
177 | // Recalculating version | 99 | } |
178 | ///////// | 100 | |
179 | // synchronized override createActivationCode(IPatternMatch match) { | 101 | override doCreateStateCode() { |
180 | // val nodes = calculator.createRepresentation(getRelevantObjects().toList,range,par).nodeRepresentations | 102 | modelRepresentation.hashCode |
181 | // val res = match.toArray.map[objectInMatch | | 103 | } |
182 | // nodes.get(objectInMatch) | 104 | |
183 | // ] | 105 | override doInvalidate() { |
184 | // return res | 106 | nodeRepresentations = null |
185 | // } | 107 | modelRepresentation = null |
186 | // | ||
187 | // override createStateCode() { | ||
188 | // return this.calculator.createRepresentation(getRelevantObjects().toList,range,par).modelRepresentation | ||
189 | // } | ||
190 | ///////// | ||
191 | // Recalculating version | ||
192 | ///////// | ||
193 | |||
194 | override init(Notifier notifier) { | ||
195 | this.target = notifier as PartialInterpretation | ||
196 | val queryEngine = ViatraQueryEngine.on(new EMFScope(notifier)) | ||
197 | val baseIndex = queryEngine.getBaseIndex() as EMFBaseIndexWrapper | ||
198 | val navigationHelper = baseIndex.getNavigationHelper(); | ||
199 | |||
200 | val classes = PartialinterpretationPackage.eINSTANCE.EClassifiers.filter(EClass).toSet | ||
201 | val features = classes.map[it.EAllStructuralFeatures].flatten.toSet | ||
202 | navigationHelper.registerObservedTypes( | ||
203 | classes, | ||
204 | null, | ||
205 | features, | ||
206 | IndexingLevel.FULL); | ||
207 | |||
208 | |||
209 | navigationHelper.addFeatureListener(features, new FeatureListener() { | ||
210 | override public void featureInserted(EObject host, EStructuralFeature feature, Object value) { invalidate } | ||
211 | override public void featureDeleted(EObject host, EStructuralFeature feature, Object value) { invalidate } | ||
212 | }); | ||
213 | navigationHelper.addInstanceListener(classes, new InstanceListener() { | ||
214 | override public void instanceInserted(EClass clazz, EObject instance) { invalidate } | ||
215 | override public void instanceDeleted(EClass clazz, EObject instance) { invalidate } | ||
216 | }); | ||
217 | } | ||
218 | |||
219 | synchronized def public invalidate() { | ||
220 | this.nodeRepresentations = null | ||
221 | this.modelRepresentation = null | ||
222 | } | 108 | } |
223 | } | 109 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend new file mode 100644 index 00000000..84e798f2 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend | |||
@@ -0,0 +1,75 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodOptions | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PairwiseNeighbourhoodRepresentation | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2PairwiseNeighbourhoodRepresentation | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
10 | import java.util.ArrayList | ||
11 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
12 | |||
13 | class PairwiseNeighbourhoodBasedStateCoderFactory extends AbstractNeighbourhoodBasedStateCoderFactory { | ||
14 | new() { | ||
15 | } | ||
16 | |||
17 | new(NeighbourhoodOptions options) { | ||
18 | super(options) | ||
19 | } | ||
20 | |||
21 | override protected doCreateStateCoder(NeighbourhoodOptions options) { | ||
22 | new PairwiseNeighbourhoodBasedPartialInterpretationStateCoder(options) | ||
23 | } | ||
24 | } | ||
25 | |||
26 | class PairwiseNeighbourhoodBasedPartialInterpretationStateCoder extends AbstractNeighbourhoodBasedPartialInterpretationStateCoder { | ||
27 | val calculator = new PartialInterpretation2PairwiseNeighbourhoodRepresentation( | ||
28 | new PartialInterpretation2ImmutableTypeLattice) | ||
29 | var PairwiseNeighbourhoodRepresentation<? extends AbstractNodeDescriptor> representation | ||
30 | |||
31 | new(NeighbourhoodOptions options) { | ||
32 | super(options) | ||
33 | } | ||
34 | |||
35 | override protected isRefreshNeeded() { | ||
36 | representation === null | ||
37 | } | ||
38 | |||
39 | override protected doRefreshStateCodes(PartialInterpretation target, NeighbourhoodOptions options) { | ||
40 | representation = calculator.createRepresentation(target, options) | ||
41 | } | ||
42 | |||
43 | override protected doCreateActivationCode(IPatternMatch match) { | ||
44 | val size = match.specification.parameters.size | ||
45 | val res = new ArrayList(size * size) | ||
46 | for (var int i = 0; i < size; i++) { | ||
47 | val a = match.get(i) | ||
48 | for (var int j = 0; j < size; j++) { | ||
49 | val b = match.get(j) | ||
50 | res.add(getPairwiseRepresentation(a, b)) | ||
51 | } | ||
52 | } | ||
53 | match.specification.fullyQualifiedName -> res.hashCode | ||
54 | } | ||
55 | |||
56 | private def getPairwiseRepresentation(Object a, Object b) { | ||
57 | if (b instanceof DefinedElement) { | ||
58 | if (a instanceof DefinedElement) { | ||
59 | representation.getPairwiseRepresentation(a, b) | ||
60 | } else { | ||
61 | representation.getBasicRepresentation(b) | ||
62 | } | ||
63 | } else { | ||
64 | getFallbackCode(b) | ||
65 | } | ||
66 | } | ||
67 | |||
68 | override protected doCreateStateCode() { | ||
69 | representation.modelRepresentation.hashCode | ||
70 | } | ||
71 | |||
72 | override protected doInvalidate() { | ||
73 | representation = null | ||
74 | } | ||
75 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/visualisation/PartialInterpretation2Gml.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/visualisation/PartialInterpretation2Gml.xtend index 2b42a8b1..bdf402f3 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/visualisation/PartialInterpretation2Gml.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/visualisation/PartialInterpretation2Gml.xtend | |||
@@ -5,9 +5,13 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | |||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | 5 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDefinition | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDefinition |
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink | 7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink |
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BooleanElement | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.IntegerElement | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | 10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation |
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation | 12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation |
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.RealElement | ||
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.StringElement | ||
11 | import java.util.HashMap | 15 | import java.util.HashMap |
12 | import java.util.Map | 16 | import java.util.Map |
13 | import java.util.Set | 17 | import java.util.Set |
@@ -106,10 +110,38 @@ class PartialInterpretation2Gml { | |||
106 | ''' | 110 | ''' |
107 | } | 111 | } |
108 | 112 | ||
109 | def protected transormTitle(DefinedElement object) { | 113 | def protected dispatch transormTitle(DefinedElement object) { |
110 | if(object.name!= null)object.name | 114 | if(object.name !== null) object.name.replace("\"", "") |
111 | else "null" | 115 | else "null" |
112 | } | 116 | } |
117 | def protected dispatch transormTitle(BooleanElement object) { | ||
118 | if(object.valueSet) { | ||
119 | object.value.toString | ||
120 | } else { | ||
121 | "?" | ||
122 | } | ||
123 | } | ||
124 | def protected dispatch transormTitle(IntegerElement object) { | ||
125 | if(object.valueSet) { | ||
126 | object.value.toString | ||
127 | } else { | ||
128 | "?" | ||
129 | } | ||
130 | } | ||
131 | def protected dispatch transormTitle(RealElement object) { | ||
132 | if(object.valueSet) { | ||
133 | object.value.toString | ||
134 | } else { | ||
135 | "?" | ||
136 | } | ||
137 | } | ||
138 | def protected dispatch transormTitle(StringElement object) { | ||
139 | if(object.valueSet) { | ||
140 | object.value.toString | ||
141 | } else { | ||
142 | "?" | ||
143 | } | ||
144 | } | ||
113 | 145 | ||
114 | def protected transformLink( | 146 | def protected transformLink( |
115 | PartialRelationInterpretation reference, | 147 | PartialRelationInterpretation reference, |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/META-INF/MANIFEST.MF b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/META-INF/MANIFEST.MF index 7077ae34..185dac40 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/META-INF/MANIFEST.MF +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/META-INF/MANIFEST.MF | |||
@@ -3,7 +3,9 @@ Bundle-ManifestVersion: 2 | |||
3 | Bundle-Name: Reasoner | 3 | Bundle-Name: Reasoner |
4 | Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner | 4 | Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner |
5 | Bundle-Version: 1.0.0.qualifier | 5 | Bundle-Version: 1.0.0.qualifier |
6 | Export-Package: hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner | 6 | Export-Package: hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner, |
7 | hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse, | ||
8 | hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
7 | Require-Bundle: hu.bme.mit.inf.dslreasoner.ecore2logic;bundle-version="1.0.0", | 9 | Require-Bundle: hu.bme.mit.inf.dslreasoner.ecore2logic;bundle-version="1.0.0", |
8 | hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0", | 10 | hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0", |
9 | hu.bme.mit.inf.dslreasoner.viatra2logic;bundle-version="1.0.0", | 11 | hu.bme.mit.inf.dslreasoner.viatra2logic;bundle-version="1.0.0", |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodBasedGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodBasedGlobalConstraint.xtend index 28cf986d..691e0645 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodBasedGlobalConstraint.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodBasedGlobalConstraint.xtend | |||
@@ -1,11 +1,10 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner |
2 | 2 | ||
3 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint | 3 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint |
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod | 4 | |
5 | 5 | abstract class ModelGenerationMethodBasedGlobalConstraint implements IGlobalConstraint { | |
6 | abstract class ModelGenerationMethodBasedGlobalConstraint implements IGlobalConstraint { | 6 | val protected ModelGenerationMethod method |
7 | val protected ModelGenerationMethod method | 7 | new(ModelGenerationMethod method) { |
8 | new(ModelGenerationMethod method) { | 8 | this.method = method |
9 | this.method = method | 9 | } |
10 | } | 10 | } |
11 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodProvider.xtend new file mode 100644 index 00000000..25137eba --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodProvider.xtend | |||
@@ -0,0 +1,201 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner | ||
2 | |||
3 | import com.google.common.collect.ImmutableMap | ||
4 | import com.google.common.collect.ImmutableSet | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
7 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.CachingSimplePolyhedronScopePropagatorStrategy | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.CbcPolyhedronSolver | ||
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator | ||
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronExtensionOperator | ||
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronScopePropagator | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraintCalculator | ||
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator | ||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.TypeHierarchyScopePropagator | ||
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Z3PolyhedronSolver | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns | ||
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider | ||
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider | ||
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.RefinementRuleProvider | ||
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.DiversityChecker | ||
27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ViatraReasonerSolutionSaver | ||
28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ThreeValuedCostObjectiveProvider | ||
29 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace | ||
30 | import java.util.Collection | ||
31 | import java.util.List | ||
32 | import java.util.Map | ||
33 | import java.util.Set | ||
34 | import org.eclipse.viatra.dse.objectives.IObjective | ||
35 | import org.eclipse.viatra.query.runtime.api.GenericQueryGroup | ||
36 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
37 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
38 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
39 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
40 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
41 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
42 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | ||
43 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule | ||
44 | import org.eclipse.xtend.lib.annotations.Data | ||
45 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ExtendedPolyhedronScopePropagatorStrategy | ||
46 | |||
47 | @Data class ModelGenerationMethod { | ||
48 | ModelGenerationStatistics statistics | ||
49 | |||
50 | Collection<? extends BatchTransformationRule<?, ?>> objectRefinementRules | ||
51 | Collection<? extends BatchTransformationRule<?, ?>> relationRefinementRules | ||
52 | |||
53 | List<MultiplicityGoalConstraintCalculator> unfinishedMultiplicities | ||
54 | |||
55 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF | ||
56 | |||
57 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWF | ||
58 | |||
59 | Map<PConstraint, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> mustUnitPropagationPreconditions | ||
60 | Map<PConstraint, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> currentUnitPropagationPreconditions | ||
61 | |||
62 | Map<String, ModalPatternQueries> modalRelationQueries | ||
63 | |||
64 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allPatterns | ||
65 | |||
66 | Collection<IObjective> costObjectives | ||
67 | boolean optimizationProblem | ||
68 | ViatraReasonerSolutionSaver solutionSaver | ||
69 | } | ||
70 | |||
71 | class ModelGenerationMethodProvider { | ||
72 | val PatternProvider patternProvider = new PatternProvider | ||
73 | val RefinementRuleProvider refinementRuleProvider = new RefinementRuleProvider | ||
74 | val GoalConstraintProvider goalConstraintProvider = new GoalConstraintProvider | ||
75 | val relationConstraintCalculator = new RelationConstraintCalculator | ||
76 | |||
77 | def ModelGenerationMethod createModelGenerationMethod( | ||
78 | LogicProblem logicProblem, | ||
79 | PartialInterpretation emptySolution, | ||
80 | ReasonerWorkspace workspace, | ||
81 | ViatraReasonerConfiguration config | ||
82 | ) { | ||
83 | val statistics = new ModelGenerationStatistics | ||
84 | val debugLevel = config.documentationLevel | ||
85 | val writeFiles = (debugLevel === DocumentationLevel.NORMAL || debugLevel === DocumentationLevel.FULL) | ||
86 | |||
87 | val Set<PQuery> existingQueries = logicProblem.relations.map[annotations].flatten.filter(TransfomedViatraQuery). | ||
88 | map[it.patternPQuery as PQuery].toSet | ||
89 | |||
90 | val relationConstraints = relationConstraintCalculator.calculateRelationConstraints(logicProblem) | ||
91 | val queries = patternProvider.generateQueries(logicProblem, emptySolution, statistics, existingQueries, | ||
92 | workspace, config.typeInferenceMethod, config.scopePropagatorStrategy, relationConstraints, config.hints, | ||
93 | config.unitPropagationPatternGenerators, writeFiles) | ||
94 | |||
95 | val unfinishedMultiplicities = goalConstraintProvider.getUnfinishedMultiplicityQueries(logicProblem, queries, | ||
96 | config.calculateObjectCreationCosts) | ||
97 | val unfinishedWF = queries.getUnfinishedWFQueries.values | ||
98 | val modalRelationQueriesBuilder = ImmutableMap.builder | ||
99 | for (entry : queries.modalRelationQueries.entrySet) { | ||
100 | val annotation = entry.key.annotations.filter(TransfomedViatraQuery).head | ||
101 | if (annotation !== null) { | ||
102 | modalRelationQueriesBuilder.put(annotation.patternFullyQualifiedName, entry.value) | ||
103 | } | ||
104 | } | ||
105 | val modalRelationQueries = modalRelationQueriesBuilder.build | ||
106 | val invalidWF = queries.getInvalidWFQueries.values | ||
107 | val mustUnitPropagationPreconditions = queries.getMustUnitPropagationPreconditionPatterns | ||
108 | val currentUnitPropagationPreconditions = queries.getCurrentUnitPropagationPreconditionPatterns | ||
109 | val queriesToPrepare = ImmutableSet.builder.addAll(queries.refineObjectQueries.values).addAll( | ||
110 | queries.refineTypeQueries.values).addAll(queries.refineRelationQueries.values).addAll( | ||
111 | queries.mustRelationPropagationQueries.values).addAll(queries.multiplicityConstraintQueries.values.flatMap [ | ||
112 | allQueries | ||
113 | ]).addAll(queries.unfinishedWFQueries.values).addAll(queries.invalidWFQueries.values).addAll( | ||
114 | queries.mustUnitPropagationPreconditionPatterns.values).addAll( | ||
115 | queries.currentUnitPropagationPreconditionPatterns.values).add(queries.hasElementInContainmentQuery).build | ||
116 | val queryEngine = ViatraQueryEngine.on(new EMFScope(emptySolution)) | ||
117 | GenericQueryGroup.of(queriesToPrepare).prepare(queryEngine) | ||
118 | |||
119 | val objectiveProvider = new ThreeValuedCostObjectiveProvider(queryEngine, emptySolution, modalRelationQueries) | ||
120 | val transformedObjectives = objectiveProvider.getCostObjectives(config.costObjectives) | ||
121 | |||
122 | val solutionSaver = new ViatraReasonerSolutionSaver(transformedObjectives.leveledExtremalObjectives, | ||
123 | config.solutionScope.numberOfRequiredSolutions, DiversityChecker.of(config.diversityRequirement)) | ||
124 | |||
125 | val allHints = ImmutableSet.builder | ||
126 | allHints.addAll(config.hints) | ||
127 | for (hint : transformedObjectives.hints) { | ||
128 | hint.boundsProvider = solutionSaver | ||
129 | allHints.add(hint) | ||
130 | } | ||
131 | |||
132 | val scopePropagator = createScopePropagator(config.scopePropagatorStrategy, emptySolution, allHints.build, | ||
133 | transformedObjectives.extensionOperators, queries, statistics) | ||
134 | scopePropagator.propagateAllScopeConstraints | ||
135 | val unitRulePropagator = refinementRuleProvider.createUnitPrulePropagator(logicProblem, emptySolution, queries, | ||
136 | scopePropagator, statistics) | ||
137 | val objectRefinementRules = refinementRuleProvider.createObjectRefinementRules(logicProblem, emptySolution, | ||
138 | queries, unitRulePropagator, config.nameNewElements, statistics) | ||
139 | val relationRefinementRules = refinementRuleProvider.createRelationRefinementRules(queries, unitRulePropagator, | ||
140 | statistics) | ||
141 | |||
142 | return new ModelGenerationMethod( | ||
143 | statistics, | ||
144 | objectRefinementRules.values, | ||
145 | relationRefinementRules.values, | ||
146 | unfinishedMultiplicities, | ||
147 | unfinishedWF, | ||
148 | invalidWF, | ||
149 | mustUnitPropagationPreconditions, | ||
150 | currentUnitPropagationPreconditions, | ||
151 | modalRelationQueries, | ||
152 | queries.allQueries, | ||
153 | transformedObjectives.objectives, | ||
154 | transformedObjectives.optimizationProblem, | ||
155 | solutionSaver | ||
156 | ) | ||
157 | } | ||
158 | |||
159 | private def createScopePropagator(ScopePropagatorStrategy scopePropagatorStrategy, | ||
160 | PartialInterpretation emptySolution, Collection<LinearTypeConstraintHint> hints, | ||
161 | Collection<PolyhedronExtensionOperator> extensionOperators, GeneratedPatterns queries, | ||
162 | ModelGenerationStatistics statistics) { | ||
163 | if (!hints.empty && !(scopePropagatorStrategy instanceof ScopePropagatorStrategy.Polyhedral)) { | ||
164 | throw new IllegalArgumentException("Only the Polyhedral scope propagator strategy can use hints.") | ||
165 | } | ||
166 | switch (scopePropagatorStrategy) { | ||
167 | case ScopePropagatorStrategy.None, | ||
168 | case ScopePropagatorStrategy.Basic: | ||
169 | new ScopePropagator(emptySolution, statistics) | ||
170 | case ScopePropagatorStrategy.BasicTypeHierarchy: | ||
171 | new TypeHierarchyScopePropagator(emptySolution, statistics) | ||
172 | ScopePropagatorStrategy.Polyhedral: { | ||
173 | val types = queries.refineObjectQueries.keySet.map[newType].toSet | ||
174 | val allPatternsByName = queries.allQueries.toMap[fullyQualifiedName] | ||
175 | val solver = switch (scopePropagatorStrategy.solver) { | ||
176 | case Z3Integer: | ||
177 | new Z3PolyhedronSolver(false, scopePropagatorStrategy.timeoutSeconds) | ||
178 | case Z3Real: | ||
179 | new Z3PolyhedronSolver(true, scopePropagatorStrategy.timeoutSeconds) | ||
180 | case Cbc: | ||
181 | new CbcPolyhedronSolver(false, scopePropagatorStrategy.timeoutSeconds, true) | ||
182 | case Clp: | ||
183 | new CbcPolyhedronSolver(true, scopePropagatorStrategy.timeoutSeconds, true) | ||
184 | default: | ||
185 | throw new IllegalArgumentException("Unknown polyhedron solver: " + | ||
186 | scopePropagatorStrategy.solver) | ||
187 | } | ||
188 | val strategy = if (extensionOperators.empty) { | ||
189 | new CachingSimplePolyhedronScopePropagatorStrategy(solver, statistics) | ||
190 | } else { | ||
191 | new ExtendedPolyhedronScopePropagatorStrategy(solver, extensionOperators, statistics) | ||
192 | } | ||
193 | new PolyhedronScopePropagator(emptySolution, statistics, types, queries.multiplicityConstraintQueries, | ||
194 | queries.hasElementInContainmentQuery, allPatternsByName, hints, strategy, | ||
195 | scopePropagatorStrategy.requiresUpperBoundIndexing, scopePropagatorStrategy.updateHeuristic) | ||
196 | } | ||
197 | default: | ||
198 | throw new IllegalArgumentException("Unknown scope propagator strategy: " + scopePropagatorStrategy) | ||
199 | } | ||
200 | } | ||
201 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend index 4331420d..4d2fd741 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend | |||
@@ -10,20 +10,28 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | |||
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage | 10 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage |
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicresultFactory | 11 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicresultFactory |
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult | 12 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult |
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethodProvider | ||
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator | 13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator |
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.PartialInterpretationInitialiser | 15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.PartialInterpretationInitialiser |
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage | 17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage |
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.AbstractNeighbourhoodBasedStateCoderFactory | ||
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.IdentifierBasedStateCoderFactory | 19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.IdentifierBasedStateCoderFactory |
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedStateCoderFactory | 20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedHashStateCoderFactory |
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.PairwiseNeighbourhoodBasedStateCoderFactory | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.BasicScopeGlobalConstraint | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.HillClimbingOnRealisticMetricStrategyForModelGeneration | 23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.HillClimbingOnRealisticMetricStrategyForModelGeneration |
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.InconsistentScopeGlobalConstraint | ||
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.LoggerSolutionFoundHandler | ||
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ModelGenerationCompositeObjective | 26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ModelGenerationCompositeObjective |
27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.NumericSolver | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PartialModelAsLogicInterpretation | 28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PartialModelAsLogicInterpretation |
29 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PunishSizeObjective | ||
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ScopeObjective | 30 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ScopeObjective |
31 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.SurelyViolatedObjectiveGlobalConstraint | ||
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.UnfinishedMultiplicityObjective | 32 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.UnfinishedMultiplicityObjective |
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.UnfinishedWFObjective | ||
26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.WF2ObjectiveConverter | 33 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.WF2ObjectiveConverter |
34 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind | ||
27 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace | 35 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace |
28 | import java.util.List | 36 | import java.util.List |
29 | import java.util.Map | 37 | import java.util.Map |
@@ -34,193 +42,320 @@ import org.eclipse.viatra.dse.api.DesignSpaceExplorer.DseLoggingLevel | |||
34 | import org.eclipse.viatra.dse.solutionstore.SolutionStore | 42 | import org.eclipse.viatra.dse.solutionstore.SolutionStore |
35 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory | 43 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory |
36 | 44 | ||
37 | class ViatraReasoner extends LogicReasoner{ | 45 | class ViatraReasoner extends LogicReasoner { |
38 | val PartialInterpretationInitialiser initialiser = new PartialInterpretationInitialiser() | 46 | val PartialInterpretationInitialiser initialiser = new PartialInterpretationInitialiser() |
39 | val ModelGenerationMethodProvider modelGenerationMethodProvider = new ModelGenerationMethodProvider | 47 | val ModelGenerationMethodProvider modelGenerationMethodProvider = new ModelGenerationMethodProvider |
40 | val extension LogicresultFactory factory = LogicresultFactory.eINSTANCE | 48 | val extension LogicresultFactory factory = LogicresultFactory.eINSTANCE |
41 | val WF2ObjectiveConverter wf2ObjectiveConverter = new WF2ObjectiveConverter | 49 | val WF2ObjectiveConverter wf2ObjectiveConverter = new WF2ObjectiveConverter |
42 | 50 | ||
43 | 51 | override solve(LogicProblem problem, LogicSolverConfiguration configuration, | |
44 | override solve(LogicProblem problem, LogicSolverConfiguration configuration, ReasonerWorkspace workspace) throws LogicReasonerException { | 52 | ReasonerWorkspace workspace) throws LogicReasonerException { |
45 | val viatraConfig = configuration.asConfig | 53 | val viatraConfig = configuration.asConfig |
46 | 54 | ||
47 | if(viatraConfig.debugCongiguration.logging) { | 55 | if (viatraConfig.documentationLevel == DocumentationLevel.FULL) { |
48 | DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.VERBOSE_FULL) | 56 | DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.VERBOSE_FULL) |
49 | } else { | 57 | } else { |
50 | DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.WARN) | 58 | DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.WARN) |
51 | } | 59 | } |
52 | 60 | ||
53 | val DesignSpaceExplorer dse = new DesignSpaceExplorer(); | 61 | val DesignSpaceExplorer dse = new DesignSpaceExplorer(); |
54 | 62 | ||
55 | dse.addMetaModelPackage(LogiclanguagePackage.eINSTANCE) | 63 | dse.addMetaModelPackage(LogiclanguagePackage.eINSTANCE) |
56 | dse.addMetaModelPackage(LogicproblemPackage.eINSTANCE) | 64 | dse.addMetaModelPackage(LogicproblemPackage.eINSTANCE) |
57 | dse.addMetaModelPackage(PartialinterpretationPackage.eINSTANCE) | 65 | dse.addMetaModelPackage(PartialinterpretationPackage.eINSTANCE) |
58 | 66 | ||
59 | val transformationStartTime = System.nanoTime | 67 | val transformationStartTime = System.nanoTime |
60 | 68 | val emptySolution = initialiser.initialisePartialInterpretation(problem, viatraConfig.typeScopes).output | |
61 | 69 | if ((viatraConfig.documentationLevel == DocumentationLevel::FULL || | |
62 | 70 | viatraConfig.documentationLevel == DocumentationLevel::NORMAL) && workspace !== null) { | |
63 | val emptySolution = initialiser.initialisePartialInterpretation(problem,viatraConfig.typeScopes).output | 71 | workspace.writeModel(emptySolution, "init.partialmodel") |
64 | 72 | } | |
65 | if((viatraConfig.documentationLevel == DocumentationLevel::FULL || viatraConfig.documentationLevel == DocumentationLevel::NORMAL) && workspace !== null) { | 73 | |
66 | workspace.writeModel(emptySolution,"init.partialmodel") | ||
67 | } | ||
68 | emptySolution.problemConainer = problem | 74 | emptySolution.problemConainer = problem |
69 | val emptySolutionCopy = EcoreUtil.copy(emptySolution) | 75 | val emptySolutionCopy = EcoreUtil.copy(emptySolution) |
76 | |||
70 | val ScopePropagator scopePropagator = new ScopePropagator(emptySolution) | 77 | val ScopePropagator scopePropagator = new ScopePropagator(emptySolution) |
71 | scopePropagator.propagateAllScopeConstraints | 78 | scopePropagator.propagateAllScopeConstraints |
72 | 79 | ||
80 | var BasicScopeGlobalConstraint basicScopeGlobalConstraint = null | ||
81 | if (viatraConfig.scopePropagatorStrategy == ScopePropagatorStrategy.None) { | ||
82 | basicScopeGlobalConstraint = new BasicScopeGlobalConstraint(emptySolution) | ||
83 | emptySolution.scopes.clear | ||
84 | } | ||
85 | |||
73 | val method = modelGenerationMethodProvider.createModelGenerationMethod( | 86 | val method = modelGenerationMethodProvider.createModelGenerationMethod( |
74 | problem, | 87 | problem, |
75 | emptySolution, | 88 | emptySolution, |
76 | workspace, | 89 | workspace, |
77 | viatraConfig.nameNewElements, | 90 | viatraConfig |
78 | viatraConfig.typeInferenceMethod, | ||
79 | scopePropagator, | ||
80 | viatraConfig.documentationLevel | ||
81 | ) | 91 | ) |
82 | 92 | ||
83 | dse.addObjective(new ModelGenerationCompositeObjective( | 93 | val compositeObjective = new ModelGenerationCompositeObjective( |
84 | new ScopeObjective, | 94 | basicScopeGlobalConstraint ?: new ScopeObjective, |
85 | method.unfinishedMultiplicities.map[new UnfinishedMultiplicityObjective(it)], | 95 | method.unfinishedMultiplicities.map[new UnfinishedMultiplicityObjective(it)], |
86 | new UnfinishedWFObjective(method.unfinishedWF), | 96 | wf2ObjectiveConverter.createCompletenessObjective(method.unfinishedWF), |
87 | viatraConfig.isWFOptional | 97 | viatraConfig |
88 | )) | 98 | ) |
99 | dse.addObjective(compositeObjective) | ||
100 | if (viatraConfig.punishSize != PunishSizeStrategy.NONE) { | ||
101 | val punishSizeStrategy = switch (viatraConfig.punishSize) { | ||
102 | case SMALLER_IS_BETTER: ObjectiveKind.LOWER_IS_BETTER | ||
103 | case LARGER_IS_BETTER: ObjectiveKind.HIGHER_IS_BETTER | ||
104 | default: throw new IllegalArgumentException("Unknown PunishSizeStrategy: " + viatraConfig.punishSize) | ||
105 | } | ||
106 | val punishObjective = new PunishSizeObjective(punishSizeStrategy, compositeObjective.level + 1) | ||
107 | dse.addObjective(punishObjective) | ||
108 | } | ||
89 | 109 | ||
90 | dse.addGlobalConstraint(wf2ObjectiveConverter.createInvalidationObjective(method.invalidWF)) | 110 | for (costObjective : method.costObjectives) { |
91 | for(additionalConstraint : viatraConfig.searchSpaceConstraints.additionalGlobalConstraints) { | 111 | dse.addObjective(costObjective) |
112 | } | ||
113 | val numberOfRequiredSolutions = configuration.solutionScope.numberOfRequiredSolutions | ||
114 | val solutionStore = if (method.optimizationProblem) { | ||
115 | new SolutionStore() | ||
116 | } else { | ||
117 | new SolutionStore(numberOfRequiredSolutions) | ||
118 | } | ||
119 | solutionStore.registerSolutionFoundHandler(new LoggerSolutionFoundHandler(viatraConfig)) | ||
120 | val numericSolver = new NumericSolver(method, viatraConfig.runIntermediateNumericalConsistencyChecks, false) | ||
121 | val solutionSaver = method.solutionSaver | ||
122 | solutionSaver.numericSolver = numericSolver | ||
123 | val solutionCopier = solutionSaver.solutionCopier | ||
124 | val diversityChecker = solutionSaver.diversityChecker | ||
125 | solutionStore.withSolutionSaver(solutionSaver) | ||
126 | dse.solutionStore = solutionStore | ||
127 | |||
128 | dse.addGlobalConstraint(wf2ObjectiveConverter.createInvalidationGlobalConstraint(method.invalidWF)) | ||
129 | dse.addGlobalConstraint(new SurelyViolatedObjectiveGlobalConstraint(solutionSaver)) | ||
130 | dse.addGlobalConstraint(new InconsistentScopeGlobalConstraint) | ||
131 | if (basicScopeGlobalConstraint !== null) { | ||
132 | dse.addGlobalConstraint(basicScopeGlobalConstraint) | ||
133 | } | ||
134 | for (additionalConstraint : viatraConfig.searchSpaceConstraints.additionalGlobalConstraints) { | ||
92 | dse.addGlobalConstraint(additionalConstraint.apply(method)) | 135 | dse.addGlobalConstraint(additionalConstraint.apply(method)) |
93 | } | 136 | } |
94 | 137 | ||
95 | dse.setInitialModel(emptySolution,false) | 138 | dse.setInitialModel(emptySolution, false) |
96 | 139 | ||
97 | val IStateCoderFactory statecoder = if(viatraConfig.stateCoderStrategy == StateCoderStrategy.Neighbourhood) { | 140 | val IStateCoderFactory statecoder = switch (viatraConfig.stateCoderStrategy) { |
98 | new NeighbourhoodBasedStateCoderFactory | 141 | case Neighbourhood: |
99 | } else { | 142 | new NeighbourhoodBasedHashStateCoderFactory |
100 | new IdentifierBasedStateCoderFactory | 143 | case PairwiseNeighbourhood: |
144 | new PairwiseNeighbourhoodBasedStateCoderFactory | ||
145 | default: | ||
146 | new IdentifierBasedStateCoderFactory | ||
101 | } | 147 | } |
102 | dse.stateCoderFactory = statecoder | 148 | dse.stateCoderFactory = statecoder |
103 | 149 | ||
104 | dse.maxNumberOfThreads = 1 | 150 | dse.maxNumberOfThreads = 1 |
105 | 151 | ||
106 | val solutionStore = new SolutionStore(configuration.solutionScope.numberOfRequiredSolution) | 152 | for (rule : method.relationRefinementRules) { |
107 | dse.solutionStore = solutionStore | ||
108 | |||
109 | for(rule : method.relationRefinementRules) { | ||
110 | dse.addTransformationRule(rule) | 153 | dse.addTransformationRule(rule) |
111 | } | 154 | } |
112 | for(rule : method.objectRefinementRules) { | 155 | for (rule : method.objectRefinementRules) { |
113 | dse.addTransformationRule(rule) | 156 | dse.addTransformationRule(rule) |
114 | } | 157 | } |
115 | 158 | ||
116 | val strategy = new HillClimbingOnRealisticMetricStrategyForModelGeneration(workspace,viatraConfig,method) | 159 | val strategy = new HillClimbingOnRealisticMetricStrategyForModelGeneration(workspace,viatraConfig,method) |
117 | viatraConfig.progressMonitor.workedForwardTransformation | 160 | viatraConfig.progressMonitor.workedForwardTransformation |
118 | 161 | val transformationFinished = System.nanoTime | |
119 | val transformationTime = System.nanoTime - transformationStartTime | 162 | val transformationTime = transformationFinished - transformationStartTime |
120 | val solverStartTime = System.nanoTime | 163 | val solverStartTime = System.nanoTime |
121 | 164 | ||
122 | var boolean stoppedByTimeout | 165 | var boolean stoppedByTimeout |
123 | var boolean stoppedByException | 166 | try { |
124 | try{ | 167 | stoppedByTimeout = dse.startExplorationWithTimeout(strategy, configuration.runtimeLimit * 1000); |
125 | stoppedByTimeout = dse.startExplorationWithTimeout(strategy,configuration.runtimeLimit*1000); | ||
126 | stoppedByException = false | ||
127 | } catch (NullPointerException npe) { | 168 | } catch (NullPointerException npe) { |
128 | stoppedByTimeout = false | 169 | stoppedByTimeout = false |
129 | stoppedByException = true | ||
130 | } | 170 | } |
131 | val solverTime = System.nanoTime - solverStartTime | 171 | val solverTime = System.nanoTime - solverStartTime |
132 | viatraConfig.progressMonitor.workedSearchFinished | 172 | viatraConfig.progressMonitor.workedSearchFinished |
133 | 173 | ||
134 | //find trajectory to each solution | 174 | // additionalMatches = strategy.solutionStoreWithCopy.additionalMatches |
135 | if(viatraConfig.documentationLevel == DocumentationLevel.NONE){ | ||
136 | PartialInterpretationMetric.initPaths(); | ||
137 | //PartialInterpretationMetric.outputTrajectories(emptySolutionCopy, dse.solutions.toList()); | ||
138 | } | ||
139 | |||
140 | //additionalMatches = strategy.solutionStoreWithCopy.additionalMatches | ||
141 | val statistics = createStatistics => [ | 175 | val statistics = createStatistics => [ |
142 | //it.solverTime = viatraConfig.runtimeLimit | 176 | // it.solverTime = viatraConfig.runtimeLimit |
143 | it.solverTime = (solverTime/1000000) as int | 177 | it.solverTime = (solverTime / 1000000) as int |
144 | it.transformationTime = (transformationTime/1000000) as int | 178 | it.transformationTime = (transformationTime / 1000000) as int |
145 | for(x : 0..<strategy.solutionStoreWithCopy.allRuntimes.size) { | 179 | for (pair : solutionCopier.getAllCopierRuntimes(true).indexed) { |
146 | it.entries += createIntStatisticEntry => [ | 180 | it.entries += createIntStatisticEntry => [ |
147 | it.name = '''_Solution«x»FoundAt''' | 181 | it.name = '''Solution«pair.key»FoundAt''' |
148 | it.value = (strategy.solutionStoreWithCopy.allRuntimes.get(x)/1000000) as int | 182 | it.value = (pair.value / 1000000) as int |
149 | ] | 183 | ] |
150 | } | 184 | } |
185 | for (x : 0 ..< strategy.times.size) { | ||
186 | it.entries += createStringStatisticEntry => [ | ||
187 | it.name = '''Solution«x+1»DetailedStatistics''' | ||
188 | it.value = strategy.times.get(x) | ||
189 | ] | ||
190 | } | ||
191 | it.entries += createIntStatisticEntry => [ | ||
192 | it.name = "ExplorationInitializationTime" | ||
193 | it.value = ((strategy.explorationStarted - transformationFinished) / 1000000) as int | ||
194 | ] | ||
195 | it.entries += createIntStatisticEntry => [ | ||
196 | it.name = "TransformationExecutionTime" | ||
197 | it.value = (method.statistics.transformationExecutionTime / 1000000) as int | ||
198 | ] | ||
199 | it.entries += createIntStatisticEntry => [ | ||
200 | it.name = "ScopePropagationTime" | ||
201 | it.value = (method.statistics.scopePropagationTime / 1000000) as int | ||
202 | ] | ||
203 | it.entries += createIntStatisticEntry => [ | ||
204 | it.name = "MustRelationPropagationTime" | ||
205 | it.value = (method.statistics.mustRelationPropagationTime / 1000000) as int | ||
206 | ] | ||
207 | it.entries += createIntStatisticEntry => [ | ||
208 | it.name = "TypeAnalysisTime" | ||
209 | it.value = (method.statistics.preliminaryTypeAnalisisTime / 1000000) as int | ||
210 | ] | ||
211 | it.entries += createIntStatisticEntry => [ | ||
212 | it.name = "StateCoderTime" | ||
213 | it.value = (statecoder.runtime / 1000000) as int | ||
214 | ] | ||
215 | it.entries += createIntStatisticEntry => [ | ||
216 | it.name = "StateCoderFailCount" | ||
217 | it.value = strategy.numberOfStatecoderFail | ||
218 | ] | ||
151 | it.entries += createIntStatisticEntry => [ | 219 | it.entries += createIntStatisticEntry => [ |
152 | it.name = "TransformationExecutionTime" it.value = (method.statistics.transformationExecutionTime/1000000) as int | 220 | it.name = "SolutionCopyTime" |
221 | it.value = (solutionCopier.getTotalCopierRuntime / 1000000) as int | ||
153 | ] | 222 | ] |
154 | it.entries += createIntStatisticEntry => [ | 223 | it.entries += createIntStatisticEntry => [ |
155 | it.name = "TypeAnalysisTime" it.value = (method.statistics.PreliminaryTypeAnalisisTime/1000000) as int | 224 | it.name = "States" |
225 | it.value = dse.numberOfStates as int | ||
226 | ] | ||
227 | it.entries += createIntStatisticEntry => [ | ||
228 | it.name = "ForwardTime" | ||
229 | it.value = (strategy.forwardTime / 1000000) as int | ||
230 | ] | ||
231 | it.entries += createIntStatisticEntry => [ | ||
232 | it.name = "BacktrackingTime" | ||
233 | it.value = (strategy.backtrackingTime / 1000000) as int | ||
234 | ] | ||
235 | it.entries += createIntStatisticEntry => [ | ||
236 | it.name = "GlobalConstraintEvaluationTime" | ||
237 | it.value = (strategy.globalConstraintEvaluationTime / 1000000) as int | ||
238 | ] | ||
239 | it.entries += createIntStatisticEntry => [ | ||
240 | it.name = "FitnessCalculationTime" | ||
241 | it.value = (strategy.fitnessCalculationTime / 1000000) as int | ||
242 | ] | ||
243 | it.entries += createIntStatisticEntry => [ | ||
244 | it.name = "SolutionCopyTime" | ||
245 | it.value = (solutionSaver.totalCopierRuntime / 1000000) as int | ||
246 | ] | ||
247 | it.entries += createIntStatisticEntry => [ | ||
248 | it.name = "ActivationSelectionTime" | ||
249 | it.value = (strategy.activationSelector.runtime / 1000000) as int | ||
250 | ] | ||
251 | it.entries += createIntStatisticEntry => [ | ||
252 | it.name = "Decisions" | ||
253 | it.value = method.statistics.decisionsTried | ||
156 | ] | 254 | ] |
157 | it.entries += createIntStatisticEntry =>[ | 255 | it.entries += createIntStatisticEntry =>[ |
158 | it.name = "MetricCalculationTime" it.value = (method.statistics.metricCalculationTime/1000000) as int | 256 | it.name = "MetricCalculationTime" it.value = (method.statistics.metricCalculationTime/1000000) as int |
159 | ] | 257 | ] |
160 | it.entries += createIntStatisticEntry => [ | 258 | it.entries += createIntStatisticEntry => [ |
161 | it.name = "StateCoderTime" it.value = (statecoder.runtime/1000000) as int | 259 | it.name = "Transformations" |
260 | it.value = method.statistics.transformationInvocations | ||
162 | ] | 261 | ] |
163 | it.entries += createIntStatisticEntry => [ | 262 | it.entries += createIntStatisticEntry => [ |
164 | it.name = "StateCoderFailCount" it.value = strategy.numberOfStatecoderFail | 263 | it.name = "ScopePropagations" |
264 | it.value = method.statistics.scopePropagatorInvocations | ||
165 | ] | 265 | ] |
166 | it.entries += createIntStatisticEntry => [ | 266 | it.entries += createIntStatisticEntry => [ |
167 | it.name = "SolutionCopyTime" it.value = (strategy.solutionStoreWithCopy.sumRuntime/1000000) as int | 267 | it.name = "ScopePropagationsSolverCalls" |
268 | it.value = method.statistics.scopePropagatorSolverInvocations | ||
168 | ] | 269 | ] |
169 | if(strategy.solutionStoreWithDiversityDescriptor.isActive) { | 270 | // it.entries += createIntStatisticEntry => [ |
271 | // it.name = "NumericalSolverSumTime" | ||
272 | // it.value = (strategy.numericSolver.runtime / 1000000) as int | ||
273 | // ] | ||
274 | // it.entries += createIntStatisticEntry => [ | ||
275 | // it.name = "NumericalSolverProblemFormingTime" | ||
276 | // it.value = (strategy.numericSolver.solverFormingProblem / 1000000) as int | ||
277 | // ] | ||
278 | // it.entries += createIntStatisticEntry => [ | ||
279 | // it.name = "NumericalSolverSolvingTime" | ||
280 | // it.value = (strategy.numericSolver.solverSolvingProblem / 1000000) as int | ||
281 | // ] | ||
282 | // it.entries += createIntStatisticEntry => [ | ||
283 | // it.name = "NumericalSolverInterpretingSolution" | ||
284 | // it.value = (strategy.numericSolver.solverSolution / 1000000) as int | ||
285 | // ] | ||
286 | // it.entries += createIntStatisticEntry => [ | ||
287 | // it.name = "NumericalSolverCachingTime" | ||
288 | // it.value = (strategy.numericSolver.cachingTime / 1000000) as int | ||
289 | // ] | ||
290 | // it.entries += createIntStatisticEntry => [ | ||
291 | // it.name = "NumericalSolverCallNumber" | ||
292 | // it.value = strategy.numericSolver.numberOfSolverCalls | ||
293 | // ] | ||
294 | // it.entries += createIntStatisticEntry => [ | ||
295 | // it.name = "NumericalSolverCachedAnswerNumber" | ||
296 | // it.value = strategy.numericSolver.numberOfCachedSolverCalls | ||
297 | // ] | ||
298 | if (diversityChecker.active) { | ||
170 | it.entries += createIntStatisticEntry => [ | 299 | it.entries += createIntStatisticEntry => [ |
171 | it.name = "SolutionDiversityCheckTime" it.value = (strategy.solutionStoreWithDiversityDescriptor.sumRuntime/1000000) as int | 300 | it.name = "SolutionDiversityCheckTime" |
301 | it.value = (diversityChecker.totalRuntime / 1000000) as int | ||
172 | ] | 302 | ] |
173 | it.entries += createRealStatisticEntry => [ | 303 | it.entries += createRealStatisticEntry => [ |
174 | it.name = "SolutionDiversitySuccessRate" it.value = strategy.solutionStoreWithDiversityDescriptor.successRate | 304 | it.name = "SolutionDiversitySuccessRate" |
305 | it.value = diversityChecker.successRate | ||
175 | ] | 306 | ] |
176 | } | 307 | } |
177 | ] | 308 | ] |
178 | 309 | ||
179 | viatraConfig.progressMonitor.workedBackwardTransformationFinished | 310 | viatraConfig.progressMonitor.workedBackwardTransformationFinished |
180 | 311 | ||
181 | if(stoppedByTimeout) { | 312 | if (stoppedByTimeout) { |
182 | return createInsuficientResourcesResult=>[ | 313 | return createInsuficientResourcesResult => [ |
183 | it.problem = problem | 314 | it.problem = problem |
184 | it.resourceName="time" | 315 | it.resourceName = "time" |
185 | it.representation += strategy.solutionStoreWithCopy.solutions | 316 | it.representation += solutionCopier.getPartialInterpretations(true) |
186 | it.statistics = statistics | 317 | it.statistics = statistics |
187 | ] | 318 | ] |
188 | } else { | 319 | } else { |
189 | if(solutionStore.solutions.empty) { | 320 | if (solutionStore.solutions.empty) { |
190 | return createInconsistencyResult => [ | 321 | return createInconsistencyResult => [ |
191 | it.problem = problem | 322 | it.problem = problem |
192 | it.representation += strategy.solutionStoreWithCopy.solutions | 323 | it.representation += solutionCopier.getPartialInterpretations(true) |
193 | it.statistics = statistics | 324 | it.statistics = statistics |
194 | ] | 325 | ] |
195 | } else { | 326 | } else { |
196 | return createModelResult => [ | 327 | return createModelResult => [ |
197 | it.problem = problem | 328 | it.problem = problem |
198 | it.trace = strategy.solutionStoreWithCopy.copyTraces | 329 | it.trace = solutionCopier.getTraces(true) |
199 | it.representation += strategy.solutionStoreWithCopy.solutions | 330 | it.representation += solutionCopier.getPartialInterpretations(true) |
200 | it.statistics = statistics | 331 | it.statistics = statistics |
201 | ] | 332 | ] |
202 | } | 333 | } |
203 | } | 334 | } |
204 | } | 335 | } |
205 | 336 | ||
206 | private def dispatch long runtime(NeighbourhoodBasedStateCoderFactory sc) { | 337 | private def dispatch long runtime(AbstractNeighbourhoodBasedStateCoderFactory sc) { |
207 | sc.sumStatecoderRuntime | 338 | sc.sumStatecoderRuntime |
208 | } | 339 | } |
209 | 340 | ||
210 | private def dispatch long runtime(IdentifierBasedStateCoderFactory sc) { | 341 | private def dispatch long runtime(IdentifierBasedStateCoderFactory sc) { |
211 | sc.sumStatecoderRuntime | 342 | sc.sumStatecoderRuntime |
212 | } | 343 | } |
213 | 344 | ||
214 | override getInterpretations(ModelResult modelResult) { | 345 | override getInterpretations(ModelResult modelResult) { |
215 | val indexes = 0..<modelResult.representation.size | 346 | val indexes = 0 ..< modelResult.representation.size |
216 | val traces = modelResult.trace as List<Map<EObject, EObject>>; | 347 | val traces = modelResult.trace as List<Map<EObject, EObject>>; |
217 | val res = indexes.map[i | new PartialModelAsLogicInterpretation(modelResult.representation.get(i) as PartialInterpretation,traces.get(i))].toList | 348 | val res = indexes.map [ i | |
349 | new PartialModelAsLogicInterpretation(modelResult.representation.get(i) as PartialInterpretation, | ||
350 | traces.get(i)) | ||
351 | ].toList | ||
218 | return res | 352 | return res |
219 | } | 353 | } |
220 | 354 | ||
221 | private def ViatraReasonerConfiguration asConfig(LogicSolverConfiguration configuration) { | 355 | private def ViatraReasonerConfiguration asConfig(LogicSolverConfiguration configuration) { |
222 | if(configuration instanceof ViatraReasonerConfiguration) { | 356 | if (configuration instanceof ViatraReasonerConfiguration) { |
223 | return configuration | 357 | return configuration |
224 | } else throw new IllegalArgumentException('''Wrong configuration. Expected: «ViatraReasonerConfiguration.name», but got: «configuration.class.name»"''') | 358 | } else |
359 | throw new IllegalArgumentException('''Wrong configuration. Expected: «ViatraReasonerConfiguration.name», but got: «configuration.class.name»"''') | ||
225 | } | 360 | } |
226 | } | 361 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend index 10734859..628844de 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend | |||
@@ -5,21 +5,37 @@ import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasoner | |||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicSolverConfiguration | 5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicSolverConfiguration |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration |
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration | 7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration |
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod | 8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod |
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorConstraints | ||
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorSolver | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.UnitPropagationPatternGenerator | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser | 14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser |
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.CostObjectiveHint | ||
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind | ||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold | ||
11 | import java.util.LinkedList | 18 | import java.util.LinkedList |
12 | import java.util.List | 19 | import java.util.List |
13 | import java.util.Set | 20 | import java.util.Set |
14 | import org.eclipse.xtext.xbase.lib.Functions.Function1 | 21 | import org.eclipse.xtext.xbase.lib.Functions.Function1 |
15 | 22 | ||
16 | public enum StateCoderStrategy { | 23 | enum StateCoderStrategy { |
17 | Neighbourhood, NeighbourhoodWithEquivalence, IDBased, DefinedByDiversity | 24 | Neighbourhood, |
25 | PairwiseNeighbourhood, | ||
26 | NeighbourhoodWithEquivalence, | ||
27 | IDBased, | ||
28 | DefinedByDiversity | ||
18 | } | 29 | } |
19 | 30 | ||
20 | class ViatraReasonerConfiguration extends LogicSolverConfiguration{ | 31 | enum PunishSizeStrategy { |
21 | //public var Iterable<PQuery> existingQueries | 32 | NONE, |
22 | 33 | SMALLER_IS_BETTER, | |
34 | LARGER_IS_BETTER | ||
35 | } | ||
36 | |||
37 | class ViatraReasonerConfiguration extends LogicSolverConfiguration { | ||
38 | // public var Iterable<PQuery> existingQueries | ||
23 | public var nameNewElements = false | 39 | public var nameNewElements = false |
24 | public var StateCoderStrategy stateCoderStrategy = StateCoderStrategy.Neighbourhood | 40 | public var StateCoderStrategy stateCoderStrategy = StateCoderStrategy.Neighbourhood |
25 | public var TypeInferenceMethod typeInferenceMethod = TypeInferenceMethod.PreliminaryAnalysis | 41 | public var TypeInferenceMethod typeInferenceMethod = TypeInferenceMethod.PreliminaryAnalysis |
@@ -27,7 +43,7 @@ class ViatraReasonerConfiguration extends LogicSolverConfiguration{ | |||
27 | * Once per 1/randomBacktrackChance the search selects a random state. | 43 | * Once per 1/randomBacktrackChance the search selects a random state. |
28 | */ | 44 | */ |
29 | public var int randomBacktrackChance = 20; | 45 | public var int randomBacktrackChance = 20; |
30 | 46 | ||
31 | /** | 47 | /** |
32 | * Describes the required diversity between the solutions. | 48 | * Describes the required diversity between the solutions. |
33 | * Null means that the solutions have to have different state codes only. | 49 | * Null means that the solutions have to have different state codes only. |
@@ -41,22 +57,40 @@ class ViatraReasonerConfiguration extends LogicSolverConfiguration{ | |||
41 | /** | 57 | /** |
42 | * Configuration for debugging support. | 58 | * Configuration for debugging support. |
43 | */ | 59 | */ |
44 | public var DebugConfiguration debugCongiguration = new DebugConfiguration | 60 | public var DebugConfiguration debugConfiguration = new DebugConfiguration |
45 | /** | 61 | /** |
46 | * Configuration for cutting search space. | 62 | * Configuration for cutting search space. |
47 | */ | 63 | */ |
48 | public var SearchSpaceConstraint searchSpaceConstraints = new SearchSpaceConstraint | 64 | public var SearchSpaceConstraint searchSpaceConstraints = new SearchSpaceConstraint |
49 | 65 | ||
50 | public var RealisticGuidance realisticGuidance = RealisticGuidance.Composite; | 66 | public var runIntermediateNumericalConsistencyChecks = true |
67 | |||
68 | public var punishSize = PunishSizeStrategy.NONE | ||
69 | public var scopeWeight = 1 | ||
70 | public var conaintmentWeight = 2 | ||
71 | public var nonContainmentWeight = 1 | ||
72 | public var unfinishedWFWeight = 1 | ||
73 | public var calculateObjectCreationCosts = false | ||
74 | |||
75 | public var RealisticGuidance realisticGuidance = RealisticGuidance.Composite; | ||
51 | 76 | ||
52 | public var isWFOptional = false; | 77 | public var isWFOptional = false; |
53 | 78 | ||
54 | public var allowMustViolations = false; | 79 | public var allowMustViolations = false; |
55 | 80 | ||
56 | public var String domain = ''; | 81 | public var String domain = ''; |
82 | public var ScopePropagatorStrategy scopePropagatorStrategy = new ScopePropagatorStrategy.Polyhedral( | ||
83 | PolyhedralScopePropagatorConstraints.Relational, PolyhedralScopePropagatorSolver.Clp) | ||
84 | // public var ScopePropagatorStrategy scopePropagatorStrategy = ScopePropagatorStrategy.BasicTypeHierarchy | ||
85 | |||
86 | public var List<LinearTypeConstraintHint> hints = newArrayList | ||
87 | |||
88 | public var List<CostObjectiveConfiguration> costObjectives = newArrayList | ||
89 | |||
90 | public var List<UnitPropagationPatternGenerator> unitPropagationPatternGenerators = newArrayList | ||
57 | } | 91 | } |
58 | 92 | ||
59 | public class DiversityDescriptor { | 93 | class DiversityDescriptor { |
60 | public var ensureDiversity = false | 94 | public var ensureDiversity = false |
61 | public static val FixPointRange = -1 | 95 | public static val FixPointRange = -1 |
62 | public var int range = FixPointRange | 96 | public var int range = FixPointRange |
@@ -66,6 +100,23 @@ public class DiversityDescriptor { | |||
66 | public var Set<RelationDeclaration> relevantRelations = null | 100 | public var Set<RelationDeclaration> relevantRelations = null |
67 | } | 101 | } |
68 | 102 | ||
103 | class DebugConfiguration { | ||
104 | public var PartialInterpretationVisualiser partialInterpretatioVisualiser = null | ||
105 | public var partalInterpretationVisualisationFrequency = 1 | ||
106 | } | ||
107 | |||
108 | class InternalConsistencyCheckerConfiguration { | ||
109 | public var LogicReasoner internalIncosnsitencyDetector = null | ||
110 | public var LogicSolverConfiguration internalInconsistencDetectorConfiguration = null | ||
111 | public var incternalConsistencyCheckingFrequency = 1 | ||
112 | } | ||
113 | |||
114 | class SearchSpaceConstraint { | ||
115 | public static val UNLIMITED_MAXDEPTH = Integer.MAX_VALUE | ||
116 | public var int maxDepth = UNLIMITED_MAXDEPTH | ||
117 | public var List<Function1<ModelGenerationMethod, ModelGenerationMethodBasedGlobalConstraint>> additionalGlobalConstraints = new LinkedList | ||
118 | } | ||
119 | |||
69 | public enum RealisticGuidance{ | 120 | public enum RealisticGuidance{ |
70 | MPC, | 121 | MPC, |
71 | NodeActivity, | 122 | NodeActivity, |
@@ -75,21 +126,16 @@ public enum RealisticGuidance{ | |||
75 | Composite_Without_Violations, | 126 | Composite_Without_Violations, |
76 | Violations | 127 | Violations |
77 | } | 128 | } |
78 | 129 | class CostObjectiveConfiguration { | |
79 | public class DebugConfiguration { | 130 | public var List<CostObjectiveElementConfiguration> elements = newArrayList |
80 | public var logging = false | 131 | public var ObjectiveKind kind |
81 | public var PartialInterpretationVisualiser partialInterpretatioVisualiser = null; | 132 | public var ObjectiveThreshold threshold |
82 | public var partalInterpretationVisualisationFrequency = 1 | 133 | public var boolean findExtremum |
134 | public var CostObjectiveHint hint | ||
83 | } | 135 | } |
84 | 136 | ||
85 | public class InternalConsistencyCheckerConfiguration { | 137 | class CostObjectiveElementConfiguration { |
86 | public var LogicReasoner internalIncosnsitencyDetector = null | 138 | public var String patternQualifiedName |
87 | public var LogicSolverConfiguration internalInconsistencDetectorConfiguration = null | 139 | public var int weight |
88 | public var incternalConsistencyCheckingFrequency = 1 | ||
89 | } | 140 | } |
90 | 141 | ||
91 | public class SearchSpaceConstraint { | ||
92 | public static val UNLIMITED_MAXDEPTH = Integer.MAX_VALUE | ||
93 | public var int maxDepth = UNLIMITED_MAXDEPTH | ||
94 | public var List<Function1<ModelGenerationMethod, ModelGenerationMethodBasedGlobalConstraint>> additionalGlobalConstraints = new LinkedList | ||
95 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ActivationSelector.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ActivationSelector.xtend new file mode 100644 index 00000000..65f9814c --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ActivationSelector.xtend | |||
@@ -0,0 +1,24 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import java.util.ArrayList | ||
4 | import java.util.Collection | ||
5 | import java.util.Random | ||
6 | |||
7 | abstract class ActivationSelector { | ||
8 | long runtime = 0 | ||
9 | protected val Random r | ||
10 | new(Random r) { | ||
11 | this.r = r | ||
12 | } | ||
13 | |||
14 | def randomizeActivationIDs(Collection<Object> activationIDs) { | ||
15 | val startTime = System.nanoTime | ||
16 | val res = internalRandomizationOfActivationIDs(activationIDs) | ||
17 | runtime+= System.nanoTime-startTime | ||
18 | return res | ||
19 | } | ||
20 | def protected ArrayList<Object> internalRandomizationOfActivationIDs(Collection<Object> activationIDs); | ||
21 | def getRuntime(){ | ||
22 | return runtime | ||
23 | } | ||
24 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BalancedActivationSelector.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BalancedActivationSelector.xtend new file mode 100644 index 00000000..2df9957b --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BalancedActivationSelector.xtend | |||
@@ -0,0 +1,51 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import java.util.Collection | ||
4 | import java.util.HashMap | ||
5 | import java.util.Map | ||
6 | import java.util.List | ||
7 | import java.util.Random | ||
8 | import java.util.ArrayList | ||
9 | import java.util.LinkedList | ||
10 | import java.util.Collections | ||
11 | |||
12 | class BalancedActivationSelector extends ActivationSelector{ | ||
13 | val Random r = new Random | ||
14 | |||
15 | new(Random r) { | ||
16 | super(r) | ||
17 | } | ||
18 | |||
19 | override protected internalRandomizationOfActivationIDs(Collection<Object> activationIDs) { | ||
20 | val Map<String,List<Object>> urns = new HashMap | ||
21 | val res = new ArrayList(activationIDs.size) | ||
22 | for(activationID : activationIDs) { | ||
23 | val pair = activationID as Pair<String,? extends Object> | ||
24 | val name = pair.key | ||
25 | val selectedUrn = urns.get(name) | ||
26 | if(selectedUrn!==null) { | ||
27 | selectedUrn.add(activationID) | ||
28 | } else { | ||
29 | val collection = new LinkedList | ||
30 | collection.add(activationID) | ||
31 | urns.put(name,collection) | ||
32 | } | ||
33 | } | ||
34 | |||
35 | for(list:urns.values) { | ||
36 | Collections.shuffle(list,r) | ||
37 | } | ||
38 | |||
39 | while(!urns.empty) { | ||
40 | val randomEntry = urns.entrySet.get(r.nextInt(urns.size)) | ||
41 | val list = randomEntry.value | ||
42 | val removedLast = list.remove(list.size-1) | ||
43 | res.add(removedLast) | ||
44 | if(list.empty) { | ||
45 | urns.remove(randomEntry.key) | ||
46 | } | ||
47 | } | ||
48 | return res | ||
49 | } | ||
50 | |||
51 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BasicScopeGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BasicScopeGlobalConstraint.xtend new file mode 100644 index 00000000..67f447ed --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BasicScopeGlobalConstraint.xtend | |||
@@ -0,0 +1,103 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation | ||
6 | import java.util.Comparator | ||
7 | import java.util.List | ||
8 | import org.eclipse.viatra.dse.base.ThreadContext | ||
9 | import org.eclipse.viatra.dse.objectives.Comparators | ||
10 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint | ||
11 | import org.eclipse.viatra.dse.objectives.IObjective | ||
12 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
13 | |||
14 | class BasicScopeGlobalConstraint implements IGlobalConstraint, IObjective { | ||
15 | val PartialInterpretation p | ||
16 | val List<ScopeAssertion> assertions | ||
17 | |||
18 | new(PartialInterpretation p) { | ||
19 | this.p = p | ||
20 | assertions = ImmutableList.copyOf(p.scopes.map [ | ||
21 | val currentSize = targetTypeInterpretation.elements.size | ||
22 | val minElements = minNewElements + currentSize | ||
23 | val maxElements = if (maxNewElements < 0) { | ||
24 | -1 | ||
25 | } else { | ||
26 | maxNewElements + currentSize | ||
27 | } | ||
28 | new ScopeAssertion(minElements, maxElements, targetTypeInterpretation) | ||
29 | ]) | ||
30 | } | ||
31 | |||
32 | override init(ThreadContext context) { | ||
33 | if (context.model != p) { | ||
34 | throw new IllegalArgumentException( | ||
35 | "Partial model must be passed to the constructor of BasicScopeGlobalConstraint") | ||
36 | } | ||
37 | } | ||
38 | |||
39 | override checkGlobalConstraint(ThreadContext context) { | ||
40 | assertions.forall[upperBoundSatisfied] | ||
41 | } | ||
42 | |||
43 | override getFitness(ThreadContext context) { | ||
44 | var double fitness = p.minNewElements | ||
45 | for (assertion : assertions) { | ||
46 | if (!assertion.lowerBoundSatisfied) { | ||
47 | fitness += 1 | ||
48 | } | ||
49 | } | ||
50 | fitness | ||
51 | } | ||
52 | |||
53 | override satisifiesHardObjective(Double fitness) { | ||
54 | fitness <= 0.01 | ||
55 | } | ||
56 | |||
57 | override BasicScopeGlobalConstraint createNew() { | ||
58 | this | ||
59 | } | ||
60 | |||
61 | override getName() { | ||
62 | class.name | ||
63 | } | ||
64 | |||
65 | override getComparator() { | ||
66 | Comparators.LOWER_IS_BETTER | ||
67 | } | ||
68 | |||
69 | override getLevel() { | ||
70 | 2 | ||
71 | } | ||
72 | |||
73 | override isHardObjective() { | ||
74 | true | ||
75 | } | ||
76 | |||
77 | override setComparator(Comparator<Double> comparator) { | ||
78 | throw new UnsupportedOperationException | ||
79 | } | ||
80 | |||
81 | override setLevel(int level) { | ||
82 | throw new UnsupportedOperationException | ||
83 | } | ||
84 | |||
85 | @FinalFieldsConstructor | ||
86 | private static class ScopeAssertion { | ||
87 | val int lowerBound | ||
88 | val int upperBound | ||
89 | val PartialTypeInterpratation typeDefinitions | ||
90 | |||
91 | private def getCount() { | ||
92 | typeDefinitions.elements.size | ||
93 | } | ||
94 | |||
95 | private def isLowerBoundSatisfied() { | ||
96 | count >= lowerBound | ||
97 | } | ||
98 | |||
99 | private def isUpperBoundSatisfied() { | ||
100 | upperBound < 0 || count <= upperBound | ||
101 | } | ||
102 | } | ||
103 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java index d9a1e54c..2940d12d 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java | |||
@@ -9,9 +9,7 @@ | |||
9 | *******************************************************************************/ | 9 | *******************************************************************************/ |
10 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse; | 10 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse; |
11 | 11 | ||
12 | import java.util.ArrayList; | ||
13 | import java.util.Arrays; | 12 | import java.util.Arrays; |
14 | import java.util.Collection; | ||
15 | import java.util.Collections; | 13 | import java.util.Collections; |
16 | import java.util.Comparator; | 14 | import java.util.Comparator; |
17 | import java.util.Iterator; | 15 | import java.util.Iterator; |
@@ -22,17 +20,16 @@ import java.util.Random; | |||
22 | 20 | ||
23 | import org.apache.log4j.Level; | 21 | import org.apache.log4j.Level; |
24 | import org.apache.log4j.Logger; | 22 | import org.apache.log4j.Logger; |
23 | import org.eclipse.emf.ecore.EObject; | ||
25 | import org.eclipse.emf.ecore.util.EcoreUtil; | 24 | import org.eclipse.emf.ecore.util.EcoreUtil; |
25 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
26 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | 26 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; |
27 | import org.eclipse.viatra.dse.base.ThreadContext; | 27 | import org.eclipse.viatra.dse.base.ThreadContext; |
28 | import org.eclipse.viatra.dse.objectives.Fitness; | 28 | import org.eclipse.viatra.dse.objectives.Fitness; |
29 | import org.eclipse.viatra.dse.objectives.IObjective; | 29 | import org.eclipse.viatra.dse.objectives.IObjective; |
30 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | 30 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; |
31 | import org.eclipse.viatra.dse.solutionstore.ISolutionFoundHandler; | ||
31 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | 32 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; |
32 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
33 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
34 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
35 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
36 | 33 | ||
37 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel; | 34 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel; |
38 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasoner; | 35 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasoner; |
@@ -40,11 +37,11 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem; | |||
40 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.InconsistencyResult; | 37 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.InconsistencyResult; |
41 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicResult; | 38 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicResult; |
42 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult; | 39 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult; |
43 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod; | ||
44 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.PartialInterpretation2Logic; | 40 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.PartialInterpretation2Logic; |
45 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation; | 41 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation; |
46 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualisation; | 42 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualisation; |
47 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser; | 43 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser; |
44 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ModelGenerationMethod; | ||
48 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration; | 45 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration; |
49 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace; | 46 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace; |
50 | 47 | ||
@@ -77,54 +74,72 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
77 | // Running | 74 | // Running |
78 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; | 75 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; |
79 | private SolutionStore solutionStore; | 76 | private SolutionStore solutionStore; |
80 | private SolutionStoreWithCopy solutionStoreWithCopy; | ||
81 | private SolutionStoreWithDiversityDescriptor solutionStoreWithDiversityDescriptor; | ||
82 | private volatile boolean isInterrupted = false; | 77 | private volatile boolean isInterrupted = false; |
83 | private ModelResult modelResultByInternalSolver = null; | 78 | private ModelResult modelResultByInternalSolver = null; |
84 | private Random random = new Random(); | 79 | private Random random = new Random(); |
85 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> matchers; | 80 | // private Collection<ViatraQueryMatcher<? extends IPatternMatch>> matchers; |
86 | 81 | public ActivationSelector activationSelector = new EvenActivationSelector(random); | |
82 | public ViatraReasonerSolutionSaver solutionSaver; | ||
83 | public NumericSolver numericSolver; | ||
87 | // Statistics | 84 | // Statistics |
88 | private int numberOfStatecoderFail = 0; | 85 | private int numberOfStatecoderFail = 0; |
89 | private int numberOfPrintedModel = 0; | 86 | private int numberOfPrintedModel = 0; |
90 | private int numberOfSolverCalls = 0; | 87 | private int numberOfSolverCalls = 0; |
88 | public long globalConstraintEvaluationTime = 0; | ||
89 | public long fitnessCalculationTime = 0; | ||
90 | |||
91 | public long explorationStarted = 0; | ||
91 | 92 | ||
92 | public BestFirstStrategyForModelGeneration( | 93 | public BestFirstStrategyForModelGeneration( |
93 | ReasonerWorkspace workspace, | 94 | ReasonerWorkspace workspace, |
94 | ViatraReasonerConfiguration configuration, | 95 | ViatraReasonerConfiguration configuration, |
95 | ModelGenerationMethod method) | 96 | ModelGenerationMethod method, |
96 | { | 97 | ViatraReasonerSolutionSaver solutionSaver, |
98 | NumericSolver numericSolver) { | ||
97 | this.workspace = workspace; | 99 | this.workspace = workspace; |
98 | this.configuration = configuration; | 100 | this.configuration = configuration; |
99 | this.method = method; | 101 | this.method = method; |
102 | this.solutionSaver = solutionSaver; | ||
103 | this.numericSolver = numericSolver; | ||
104 | // logger.setLevel(Level.DEBUG); | ||
100 | } | 105 | } |
101 | 106 | ||
102 | public SolutionStoreWithCopy getSolutionStoreWithCopy() { | ||
103 | return solutionStoreWithCopy; | ||
104 | } | ||
105 | public SolutionStoreWithDiversityDescriptor getSolutionStoreWithDiversityDescriptor() { | ||
106 | return solutionStoreWithDiversityDescriptor; | ||
107 | } | ||
108 | public int getNumberOfStatecoderFail() { | 107 | public int getNumberOfStatecoderFail() { |
109 | return numberOfStatecoderFail; | 108 | return numberOfStatecoderFail; |
110 | } | 109 | } |
110 | public long getForwardTime() { | ||
111 | return context.getDesignSpaceManager().getForwardTime(); | ||
112 | } | ||
113 | public long getBacktrackingTime() { | ||
114 | return context.getDesignSpaceManager().getBacktrackingTime(); | ||
115 | } | ||
111 | 116 | ||
112 | @Override | 117 | @Override |
113 | public void initStrategy(ThreadContext context) { | 118 | public void initStrategy(ThreadContext context) { |
114 | this.context = context; | 119 | this.context = context; |
115 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | 120 | this.solutionStore = context.getGlobalContext().getSolutionStore(); |
116 | ViatraQueryEngine engine = context.getQueryEngine(); | 121 | solutionStore.registerSolutionFoundHandler(new ISolutionFoundHandler() { |
117 | // // TODO: visualisation | 122 | |
118 | matchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | 123 | @Override |
119 | for(IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> p : this.method.getAllPatterns()) { | 124 | public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { |
120 | //System.out.println(p.getSimpleName()); | 125 | // Ignore. |
121 | ViatraQueryMatcher<? extends IPatternMatch> matcher = p.getMatcher(engine); | 126 | } |
122 | matchers.add(matcher); | 127 | |
123 | } | 128 | @Override |
129 | public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
130 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolutions); | ||
131 | saveTimes(); | ||
132 | logger.debug("Found a solution."); | ||
133 | } | ||
134 | }); | ||
135 | numericSolver.init(context); | ||
124 | 136 | ||
125 | this.solutionStoreWithCopy = new SolutionStoreWithCopy(); | 137 | // ViatraQueryEngine engine = context.getQueryEngine(); |
126 | this.solutionStoreWithDiversityDescriptor = new SolutionStoreWithDiversityDescriptor(configuration.diversityRequirement); | 138 | // matchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); |
127 | 139 | // for(IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> p : this.method.getAllPatterns()) { | |
140 | // ViatraQueryMatcher<? extends IPatternMatch> matcher = p.getMatcher(engine); | ||
141 | // } | ||
142 | // | ||
128 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 143 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
129 | this.comparator = new Comparator<TrajectoryWithFitness>() { | 144 | this.comparator = new Comparator<TrajectoryWithFitness>() { |
130 | @Override | 145 | @Override |
@@ -138,23 +153,26 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
138 | 153 | ||
139 | @Override | 154 | @Override |
140 | public void explore() { | 155 | public void explore() { |
141 | if (!context.checkGlobalConstraints()) { | 156 | this.explorationStarted=System.nanoTime(); |
157 | if (!checkGlobalConstraints()) { | ||
142 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | 158 | logger.info("Global contraint is not satisifed in the first state. Terminate."); |
143 | return; | 159 | return; |
160 | } else if(!numericSolver.maySatisfiable()) { | ||
161 | logger.info("Numeric contraints are not satisifed in the first state. Terminate."); | ||
162 | return; | ||
144 | } | 163 | } |
145 | if (configuration.searchSpaceConstraints.maxDepth == 0) { | 164 | if (configuration.searchSpaceConstraints.maxDepth == 0) { |
146 | logger.info("Maximal depth is reached in the initial solution. Terminate."); | 165 | logger.info("Maximal depth is reached in the initial solution. Terminate."); |
147 | return; | 166 | return; |
148 | } | 167 | } |
149 | 168 | ||
150 | final Fitness firstFittness = context.calculateFitness(); | 169 | final Fitness firstFitness = calculateFitness(); |
151 | checkForSolution(firstFittness); | 170 | checkForSolution(firstFitness); |
152 | 171 | ||
153 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 172 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
154 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); | 173 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); |
155 | TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness); | 174 | TrajectoryWithFitness currentTrajectoryWithFitness = new TrajectoryWithFitness(firstTrajectory, firstFitness); |
156 | trajectoiresToExplore.add(currentTrajectoryWithFittness); | 175 | trajectoiresToExplore.add(currentTrajectoryWithFitness); |
157 | |||
158 | //if(configuration) | 176 | //if(configuration) |
159 | visualiseCurrentState(); | 177 | visualiseCurrentState(); |
160 | // for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { | 178 | // for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { |
@@ -168,22 +186,22 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
168 | 186 | ||
169 | mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) { | 187 | mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) { |
170 | 188 | ||
171 | if (currentTrajectoryWithFittness == null) { | 189 | if (currentTrajectoryWithFitness == null) { |
172 | if (trajectoiresToExplore.isEmpty()) { | 190 | if (trajectoiresToExplore.isEmpty()) { |
173 | logger.debug("State space is fully traversed."); | 191 | logger.debug("State space is fully traversed."); |
174 | return; | 192 | return; |
175 | } else { | 193 | } else { |
176 | currentTrajectoryWithFittness = selectState(); | 194 | currentTrajectoryWithFitness = selectState(); |
177 | if (logger.isDebugEnabled()) { | 195 | if (logger.isDebugEnabled()) { |
178 | logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray())); | 196 | logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray())); |
179 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness); | 197 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFitness); |
180 | } | 198 | } |
181 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory); | 199 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFitness.trajectory); |
182 | } | 200 | } |
183 | } | 201 | } |
184 | 202 | ||
185 | // visualiseCurrentState(); | 203 | // visualiseCurrentState(); |
186 | // boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); | 204 | // boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithfitness); |
187 | // if(consistencyCheckResult == true) { | 205 | // if(consistencyCheckResult == true) { |
188 | // continue mainLoop; | 206 | // continue mainLoop; |
189 | // } | 207 | // } |
@@ -193,32 +211,30 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
193 | 211 | ||
194 | while (!isInterrupted && !configuration.progressMonitor.isCancelled() && iterator.hasNext()) { | 212 | while (!isInterrupted && !configuration.progressMonitor.isCancelled() && iterator.hasNext()) { |
195 | final Object nextActivation = iterator.next(); | 213 | final Object nextActivation = iterator.next(); |
196 | // if (!iterator.hasNext()) { | ||
197 | // logger.debug("Last untraversed activation of the state."); | ||
198 | // trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
199 | // } | ||
200 | logger.debug("Executing new activation: " + nextActivation); | 214 | logger.debug("Executing new activation: " + nextActivation); |
201 | context.executeAcitvationId(nextActivation); | 215 | context.executeAcitvationId(nextActivation); |
216 | method.getStatistics().incrementDecisionCount(); | ||
202 | 217 | ||
203 | visualiseCurrentState(); | 218 | visualiseCurrentState(); |
204 | // for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { | 219 | // for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { |
205 | // System.out.println(matcher.getPatternName()); | 220 | // int c = matcher.countMatches(); |
206 | // System.out.println("---------"); | 221 | // if(c>=1) { |
207 | // for(IPatternMatch m : matcher.getAllMatches()) { | 222 | // System.out.println(c+ " " +matcher.getPatternName()); |
208 | // System.out.println(m); | 223 | // } |
209 | // } | ||
210 | // System.out.println("---------"); | ||
211 | // } | 224 | // } |
212 | 225 | ||
213 | boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); | 226 | boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFitness); |
214 | if(consistencyCheckResult == true) { continue mainLoop; } | 227 | if(consistencyCheckResult == true) { continue mainLoop; } |
215 | 228 | ||
216 | if (context.isCurrentStateAlreadyTraversed()) { | 229 | if (context.isCurrentStateAlreadyTraversed()) { |
217 | logger.info("The new state is already visited."); | 230 | logger.info("The new state is already visited."); |
218 | context.backtrack(); | 231 | context.backtrack(); |
219 | } else if (!context.checkGlobalConstraints()) { | 232 | } else if (!checkGlobalConstraints()) { |
220 | logger.debug("Global contraint is not satisifed."); | 233 | logger.debug("Global contraint is not satisifed."); |
221 | context.backtrack(); | 234 | context.backtrack(); |
235 | } else if (!numericSolver.maySatisfiable()) { | ||
236 | logger.debug("Numeric constraints are not satisifed."); | ||
237 | context.backtrack(); | ||
222 | } else { | 238 | } else { |
223 | final Fitness nextFitness = context.calculateFitness(); | 239 | final Fitness nextFitness = context.calculateFitness(); |
224 | checkForSolution(nextFitness); | 240 | checkForSolution(nextFitness); |
@@ -228,59 +244,89 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
228 | continue; | 244 | continue; |
229 | } | 245 | } |
230 | 246 | ||
231 | TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness( | 247 | TrajectoryWithFitness nextTrajectoryWithfitness = new TrajectoryWithFitness( |
232 | context.getTrajectory().toArray(), nextFitness); | 248 | context.getTrajectory().toArray(), nextFitness); |
233 | trajectoiresToExplore.add(nextTrajectoryWithFittness); | 249 | trajectoiresToExplore.add(nextTrajectoryWithfitness); |
234 | 250 | ||
235 | int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFittness.fitness, | 251 | int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFitness.fitness, |
236 | nextTrajectoryWithFittness.fitness); | 252 | nextTrajectoryWithfitness.fitness); |
237 | if (compare < 0) { | 253 | if (compare < 0) { |
238 | logger.debug("Better fitness, moving on: " + nextFitness); | 254 | logger.debug("Better fitness, moving on: " + nextFitness); |
239 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | 255 | currentTrajectoryWithFitness = nextTrajectoryWithfitness; |
240 | continue mainLoop; | 256 | continue mainLoop; |
241 | } else if (compare == 0) { | 257 | } else if (compare == 0) { |
242 | logger.debug("Equally good fitness, moving on: " + nextFitness); | 258 | logger.debug("Equally good fitness, moving on: " + nextFitness); |
243 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | 259 | currentTrajectoryWithFitness = nextTrajectoryWithfitness; |
244 | continue mainLoop; | 260 | continue mainLoop; |
245 | } else { | 261 | } else { |
246 | logger.debug("Worse fitness."); | 262 | logger.debug("Worse fitness."); |
247 | currentTrajectoryWithFittness = null; | 263 | currentTrajectoryWithFitness = null; |
248 | continue mainLoop; | 264 | continue mainLoop; |
249 | } | 265 | } |
250 | } | 266 | } |
251 | } | 267 | } |
252 | 268 | ||
253 | logger.debug("State is fully traversed."); | 269 | logger.debug("State is fully traversed."); |
254 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | 270 | trajectoiresToExplore.remove(currentTrajectoryWithFitness); |
255 | currentTrajectoryWithFittness = null; | 271 | currentTrajectoryWithFitness = null; |
256 | 272 | ||
257 | } | 273 | } |
258 | logger.info("Interrupted."); | 274 | logger.info("Interrupted."); |
259 | } | 275 | } |
260 | 276 | ||
277 | private boolean checkGlobalConstraints() { | ||
278 | long start = System.nanoTime(); | ||
279 | boolean result = context.checkGlobalConstraints(); | ||
280 | globalConstraintEvaluationTime += System.nanoTime() - start; | ||
281 | return result; | ||
282 | } | ||
283 | |||
284 | private Fitness calculateFitness() { | ||
285 | long start = System.nanoTime(); | ||
286 | Fitness fitness = context.calculateFitness(); | ||
287 | fitnessCalculationTime += System.nanoTime() - start; | ||
288 | return fitness; | ||
289 | } | ||
290 | |||
261 | private List<Object> selectActivation() { | 291 | private List<Object> selectActivation() { |
262 | List<Object> activationIds; | 292 | List<Object> activationIds; |
263 | try { | 293 | try { |
264 | activationIds = new ArrayList<Object>(context.getUntraversedActivationIds()); | 294 | activationIds = this.activationSelector.randomizeActivationIDs(context.getUntraversedActivationIds()); |
265 | Collections.shuffle(activationIds); | ||
266 | } catch (NullPointerException e) { | 295 | } catch (NullPointerException e) { |
296 | // logger.warn("Unexpected state code: " + context.getDesignSpaceManager().getCurrentState()); | ||
267 | numberOfStatecoderFail++; | 297 | numberOfStatecoderFail++; |
268 | activationIds = Collections.emptyList(); | 298 | activationIds = Collections.emptyList(); |
269 | } | 299 | } |
270 | return activationIds; | 300 | return activationIds; |
271 | } | 301 | } |
272 | 302 | ||
273 | private void checkForSolution(final Fitness fittness) { | 303 | private void checkForSolution(final Fitness fitness) { |
274 | if (fittness.isSatisifiesHardObjectives()) { | 304 | solutionStore.newSolution(context); |
275 | if (solutionStoreWithDiversityDescriptor.isDifferent(context)) { | 305 | } |
276 | solutionStoreWithCopy.newSolution(context); | 306 | |
277 | solutionStoreWithDiversityDescriptor.newSolution(context); | 307 | public List<String> times = new LinkedList<String>(); |
278 | solutionStore.newSolution(context); | 308 | private void saveTimes() { |
279 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolution); | 309 | long forwardTime = context.getDesignSpaceManager().getForwardTime()/1000000; |
280 | 310 | long backtrackingTime = context.getDesignSpaceManager().getBacktrackingTime()/1000000; | |
281 | logger.debug("Found a solution."); | 311 | long activationSelection = this.activationSelector.getRuntime()/1000000; |
282 | } | 312 | long solutionCopierTime = this.solutionSaver.getTotalCopierRuntime()/1000000; |
283 | } | 313 | long numericalSolverSumTime = this.numericSolver.getRuntime()/1000000; |
314 | long numericalSolverProblemForming = this.numericSolver.getSolverSolvingProblem()/1000000; | ||
315 | long numericalSolverSolving = this.numericSolver.getSolverSolvingProblem()/1000000; | ||
316 | long numericalSolverInterpreting = this.numericSolver.getSolverSolution()/1000000; | ||
317 | this.times.add( | ||
318 | "(TransformationExecutionTime"+method.getStatistics().transformationExecutionTime/1000000+ | ||
319 | "|ForwardTime:"+forwardTime+ | ||
320 | "|Backtrackingtime:"+backtrackingTime+ | ||
321 | "|GlobalConstraintEvaluationTime:"+(globalConstraintEvaluationTime/1000000)+ | ||
322 | "|FitnessCalculationTime:"+(fitnessCalculationTime/1000000)+ | ||
323 | "|ActivationSelectionTime:"+activationSelection+ | ||
324 | "|SolutionCopyTime:"+solutionCopierTime+ | ||
325 | "|NumericalSolverSumTime:"+numericalSolverSumTime+ | ||
326 | "|NumericalSolverProblemFormingTime:"+numericalSolverProblemForming+ | ||
327 | "|NumericalSolverSolvingTime:"+numericalSolverSolving+ | ||
328 | "|NumericalSolverInterpretingSolution:"+numericalSolverInterpreting+")"); | ||
329 | |||
284 | } | 330 | } |
285 | 331 | ||
286 | @Override | 332 | @Override |
@@ -309,7 +355,7 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
309 | } else { | 355 | } else { |
310 | return trajectoiresToExplore.element(); | 356 | return trajectoiresToExplore.element(); |
311 | } | 357 | } |
312 | } | 358 | } |
313 | 359 | ||
314 | // private void logCurrentStateMetric() { | 360 | // private void logCurrentStateMetric() { |
315 | // if(this.configuration.documentationLevel != DocumentationLevel.NONE || workspace == null) { | 361 | // if(this.configuration.documentationLevel != DocumentationLevel.NONE || workspace == null) { |
@@ -322,13 +368,16 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
322 | 368 | ||
323 | 369 | ||
324 | public void visualiseCurrentState() { | 370 | public void visualiseCurrentState() { |
325 | PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugCongiguration.partialInterpretatioVisualiser; | 371 | PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugConfiguration.partialInterpretatioVisualiser; |
326 | if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) { | 372 | if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) { |
327 | PartialInterpretation p = (PartialInterpretation) (context.getModel()); | 373 | PartialInterpretation p = (PartialInterpretation) (context.getModel()); |
328 | int id = ++numberOfPrintedModel; | 374 | int id = ++numberOfPrintedModel; |
329 | if (id % configuration.debugCongiguration.partalInterpretationVisualisationFrequency == 0) { | 375 | if (id % configuration.debugConfiguration.partalInterpretationVisualisationFrequency == 0) { |
330 | PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); | 376 | PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); |
331 | visualisation.writeToFile(workspace, String.format("state%09d.png", id)); | 377 | logger.debug("Visualizing state: " + id + " (" + context.getDesignSpaceManager().getCurrentState() + ")"); |
378 | String name = String.format("state%09d", id); | ||
379 | visualisation.writeToFile(workspace, name + ".png"); | ||
380 | workspace.writeModel((EObject) context.getModel(), name + ".xmi"); | ||
332 | } | 381 | } |
333 | } | 382 | } |
334 | } | 383 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend new file mode 100644 index 00000000..fb1b2066 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend | |||
@@ -0,0 +1,184 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import com.google.common.collect.HashMultiset | ||
4 | import com.google.common.collect.ImmutableSet | ||
5 | import com.google.common.collect.Multiset | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodWithTraces | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.DiversityDescriptor | ||
11 | import java.util.Collection | ||
12 | import java.util.HashSet | ||
13 | import java.util.Map | ||
14 | import java.util.Set | ||
15 | import org.eclipse.viatra.dse.base.ThreadContext | ||
16 | import org.eclipse.xtend.lib.annotations.Accessors | ||
17 | |||
18 | interface DiversityChecker { | ||
19 | public static val NO_DIVERSITY_CHECKER = new DiversityChecker { | ||
20 | override isActive() { | ||
21 | false | ||
22 | } | ||
23 | |||
24 | override getTotalRuntime() { | ||
25 | 0 | ||
26 | } | ||
27 | |||
28 | override getSuccessRate() { | ||
29 | 1.0 | ||
30 | } | ||
31 | |||
32 | override newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
33 | true | ||
34 | } | ||
35 | } | ||
36 | |||
37 | def boolean isActive() | ||
38 | |||
39 | def long getTotalRuntime() | ||
40 | |||
41 | def double getSuccessRate() | ||
42 | |||
43 | def boolean newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) | ||
44 | |||
45 | static def of(DiversityDescriptor descriptor) { | ||
46 | if (descriptor.ensureDiversity) { | ||
47 | new NodewiseDiversityChecker(descriptor) | ||
48 | } else { | ||
49 | NO_DIVERSITY_CHECKER | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | abstract class AbstractDiversityChecker implements DiversityChecker { | ||
55 | val DiversityDescriptor descriptor | ||
56 | val PartialInterpretation2ImmutableTypeLattice solutionCoder = new PartialInterpretation2ImmutableTypeLattice | ||
57 | |||
58 | @Accessors(PUBLIC_GETTER) var long totalRuntime = 0 | ||
59 | var int allCheckCount = 0 | ||
60 | var int successfulCheckCount = 0 | ||
61 | |||
62 | protected new(DiversityDescriptor descriptor) { | ||
63 | if (!descriptor.ensureDiversity) { | ||
64 | throw new IllegalArgumentException( | ||
65 | "Diversity description should enforce diversity or NO_DIVERSITY_CHECKER should be used instead.") | ||
66 | } | ||
67 | this.descriptor = descriptor | ||
68 | } | ||
69 | |||
70 | override isActive() { | ||
71 | true | ||
72 | } | ||
73 | |||
74 | override getTotalRuntime() { | ||
75 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | ||
76 | } | ||
77 | |||
78 | override getSuccessRate() { | ||
79 | (allCheckCount as double) / (successfulCheckCount as double) | ||
80 | } | ||
81 | |||
82 | override newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
83 | val start = System.nanoTime | ||
84 | val model = threadContext.model as PartialInterpretation | ||
85 | val representation = solutionCoder.createRepresentation(model, descriptor.range, descriptor.parallels, | ||
86 | descriptor.maxNumber, descriptor.relevantTypes, descriptor.relevantRelations) | ||
87 | val isDifferent = internalNewSolution(representation, solutionId, dominatedSolutionIds) | ||
88 | totalRuntime += System.nanoTime - start | ||
89 | allCheckCount++ | ||
90 | if (isDifferent) { | ||
91 | successfulCheckCount++ | ||
92 | } | ||
93 | isDifferent | ||
94 | } | ||
95 | |||
96 | protected abstract def boolean internalNewSolution( | ||
97 | NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation, | ||
98 | Object solutionId, Collection<Object> dominatedSolutionIds) | ||
99 | } | ||
100 | |||
101 | class NodewiseDiversityChecker extends AbstractDiversityChecker { | ||
102 | var Multiset<Integer> nodeCodes = HashMultiset.create | ||
103 | val Map<Object, Set<Integer>> tracedNodeCodes = newHashMap | ||
104 | |||
105 | new(DiversityDescriptor descriptor) { | ||
106 | super(descriptor) | ||
107 | } | ||
108 | |||
109 | override protected internalNewSolution( | ||
110 | NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation, | ||
111 | Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
112 | val nodeCodesInSolution = ImmutableSet.copyOf(representation.modelRepresentation.keySet.map[hashCode]) | ||
113 | val remainingNodeCodes = if (dominatedSolutionIds.empty) { | ||
114 | nodeCodes | ||
115 | } else { | ||
116 | getRemainingNodeCodes(dominatedSolutionIds) | ||
117 | } | ||
118 | val hasNewCode = nodeCodesInSolution.exists[!remainingNodeCodes.contains(it)] | ||
119 | if (hasNewCode) { | ||
120 | nodeCodes = remainingNodeCodes | ||
121 | nodeCodes.addAll(nodeCodesInSolution) | ||
122 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
123 | tracedNodeCodes.remove(dominatedSolutionId) | ||
124 | } | ||
125 | tracedNodeCodes.put(solutionId, nodeCodesInSolution) | ||
126 | } | ||
127 | hasNewCode | ||
128 | } | ||
129 | |||
130 | private def getRemainingNodeCodes(Collection<Object> dominatedSolutionIds) { | ||
131 | // TODO Optimize multiset operations. | ||
132 | val copyOfNodeCodes = HashMultiset.create(nodeCodes) | ||
133 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
134 | val dominatedModelCode = tracedNodeCodes.get(dominatedSolutionId) | ||
135 | if (dominatedModelCode === null) { | ||
136 | throw new IllegalArgumentException("Unknown dominated solution: " + dominatedSolutionId) | ||
137 | } | ||
138 | copyOfNodeCodes.removeAll(dominatedModelCode) | ||
139 | } | ||
140 | copyOfNodeCodes | ||
141 | } | ||
142 | } | ||
143 | |||
144 | class GraphwiseDiversityChecker extends AbstractDiversityChecker { | ||
145 | var Set<Integer> modelCodes = newHashSet | ||
146 | val Map<Object, Integer> tracedModelCodes = newHashMap | ||
147 | |||
148 | new(DiversityDescriptor descriptor) { | ||
149 | super(descriptor) | ||
150 | } | ||
151 | |||
152 | override protected internalNewSolution( | ||
153 | NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation, | ||
154 | Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
155 | val modelCodeOfSolution = representation.modelRepresentation.hashCode | ||
156 | val remainingModelCodes = if (dominatedSolutionIds.empty) { | ||
157 | modelCodes | ||
158 | } else { | ||
159 | getRemainingModelCodes(dominatedSolutionIds) | ||
160 | } | ||
161 | val isNewCode = !remainingModelCodes.contains(modelCodeOfSolution) | ||
162 | if (isNewCode) { | ||
163 | modelCodes = remainingModelCodes | ||
164 | modelCodes += modelCodeOfSolution | ||
165 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
166 | tracedModelCodes.remove(dominatedSolutionId) | ||
167 | } | ||
168 | tracedModelCodes.put(solutionId, modelCodeOfSolution) | ||
169 | } | ||
170 | isNewCode | ||
171 | } | ||
172 | |||
173 | private def getRemainingModelCodes(Collection<Object> dominatedSolutionIds) { | ||
174 | val copyOfModelCodes = new HashSet(modelCodes) | ||
175 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
176 | val dominatedModelCode = tracedModelCodes.get(dominatedSolutionId) | ||
177 | if (dominatedModelCode === null) { | ||
178 | throw new IllegalArgumentException("Unknown dominated solution: " + dominatedSolutionId) | ||
179 | } | ||
180 | copyOfModelCodes -= dominatedModelCode | ||
181 | } | ||
182 | copyOfModelCodes | ||
183 | } | ||
184 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend new file mode 100644 index 00000000..3c2e3319 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend | |||
@@ -0,0 +1,66 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.IThreeValuedObjective | ||
4 | import org.eclipse.viatra.dse.base.ThreadContext | ||
5 | import org.eclipse.viatra.dse.objectives.Comparators | ||
6 | import org.eclipse.viatra.dse.objectives.Fitness | ||
7 | import org.eclipse.viatra.dse.objectives.IObjective | ||
8 | |||
9 | final class DseUtils { | ||
10 | private new() { | ||
11 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly.") | ||
12 | } | ||
13 | |||
14 | static def calculateFitness(ThreadContext it, (IObjective)=>Double getFitness) { | ||
15 | val result = new Fitness | ||
16 | var boolean satisifiesHardObjectives = true | ||
17 | for (objective : objectives) { | ||
18 | val fitness = getFitness.apply(objective) | ||
19 | result.put(objective.name, fitness) | ||
20 | if (objective.isHardObjective() && !objective.satisifiesHardObjective(fitness)) { | ||
21 | satisifiesHardObjectives = false | ||
22 | } | ||
23 | } | ||
24 | result.satisifiesHardObjectives = satisifiesHardObjectives | ||
25 | result | ||
26 | } | ||
27 | |||
28 | static def caclulateBestPossibleFitness(ThreadContext threadContext) { | ||
29 | threadContext.calculateFitness [ objective | | ||
30 | if (objective instanceof IThreeValuedObjective) { | ||
31 | objective.getBestPossibleFitness(threadContext) | ||
32 | } else { | ||
33 | switch (objective.comparator) { | ||
34 | case Comparators.LOWER_IS_BETTER: | ||
35 | Double.NEGATIVE_INFINITY | ||
36 | case Comparators.HIGHER_IS_BETTER: | ||
37 | Double.POSITIVE_INFINITY | ||
38 | case Comparators.DIFFERENCE_TO_ZERO_IS_BETTER: | ||
39 | 0.0 | ||
40 | default: | ||
41 | throw new IllegalArgumentException("Unknown comparator for non-three-valued objective: " + | ||
42 | objective.name) | ||
43 | } | ||
44 | } | ||
45 | ] | ||
46 | } | ||
47 | |||
48 | static def caclulateWorstPossibleFitness(ThreadContext threadContext) { | ||
49 | threadContext.calculateFitness [ objective | | ||
50 | if (objective instanceof IThreeValuedObjective) { | ||
51 | objective.getWorstPossibleFitness(threadContext) | ||
52 | } else { | ||
53 | switch (objective.comparator) { | ||
54 | case Comparators.LOWER_IS_BETTER, | ||
55 | case Comparators.DIFFERENCE_TO_ZERO_IS_BETTER: | ||
56 | Double.POSITIVE_INFINITY | ||
57 | case Comparators.HIGHER_IS_BETTER: | ||
58 | Double.NEGATIVE_INFINITY | ||
59 | default: | ||
60 | throw new IllegalArgumentException("Unknown comparator for non-three-valued objective: " + | ||
61 | objective.name) | ||
62 | } | ||
63 | } | ||
64 | ] | ||
65 | } | ||
66 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/EvenActivationSelector.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/EvenActivationSelector.xtend new file mode 100644 index 00000000..82a5f32d --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/EvenActivationSelector.xtend | |||
@@ -0,0 +1,20 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import java.util.Random | ||
4 | import java.util.Collection | ||
5 | import java.util.Collections | ||
6 | import java.util.ArrayList | ||
7 | |||
8 | class EvenActivationSelector extends ActivationSelector { | ||
9 | |||
10 | new(Random r) { | ||
11 | super(r) | ||
12 | } | ||
13 | |||
14 | override protected internalRandomizationOfActivationIDs(Collection<Object> activationIDs) { | ||
15 | val toShuffle = new ArrayList<Object>(activationIDs); | ||
16 | Collections.shuffle(toShuffle); | ||
17 | return toShuffle | ||
18 | } | ||
19 | |||
20 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/HillClimbingOnRealisticMetricStrategyForModelGeneration.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/HillClimbingOnRealisticMetricStrategyForModelGeneration.java index eb7df089..d9f84b36 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/HillClimbingOnRealisticMetricStrategyForModelGeneration.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/HillClimbingOnRealisticMetricStrategyForModelGeneration.java | |||
@@ -16,6 +16,7 @@ import java.util.Random; | |||
16 | import java.util.Set; | 16 | import java.util.Set; |
17 | 17 | ||
18 | import org.apache.log4j.Logger; | 18 | import org.apache.log4j.Logger; |
19 | import org.eclipse.emf.ecore.EObject; | ||
19 | import org.eclipse.emf.ecore.util.EcoreUtil; | 20 | import org.eclipse.emf.ecore.util.EcoreUtil; |
20 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | 21 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; |
21 | import org.eclipse.viatra.dse.base.ThreadContext; | 22 | import org.eclipse.viatra.dse.base.ThreadContext; |
@@ -35,480 +36,540 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem; | |||
35 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.InconsistencyResult; | 36 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.InconsistencyResult; |
36 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicResult; | 37 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicResult; |
37 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult; | 38 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult; |
38 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod; | ||
39 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.PartialInterpretation2Logic; | 39 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.PartialInterpretation2Logic; |
40 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation; | 40 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation; |
41 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedPartialInterpretationStateCoder; | ||
41 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualisation; | 42 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualisation; |
42 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser; | 43 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser; |
44 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ModelGenerationMethod; | ||
43 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.RealisticGuidance; | 45 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.RealisticGuidance; |
44 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration; | 46 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration; |
45 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace; | 47 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace; |
46 | 48 | ||
47 | public class HillClimbingOnRealisticMetricStrategyForModelGeneration implements IStrategy { | 49 | public class HillClimbingOnRealisticMetricStrategyForModelGeneration implements IStrategy { |
48 | // Services and Configuration | 50 | // Services and Configuration |
49 | private ThreadContext context; | 51 | private ThreadContext context; |
50 | private ReasonerWorkspace workspace; | 52 | private ReasonerWorkspace workspace; |
51 | private ViatraReasonerConfiguration configuration; | 53 | private ViatraReasonerConfiguration configuration; |
52 | private ModelGenerationMethod method; | 54 | private ModelGenerationMethod method; |
53 | private PartialInterpretation2Logic partialInterpretation2Logic = new PartialInterpretation2Logic(); | 55 | private PartialInterpretation2Logic partialInterpretation2Logic = new PartialInterpretation2Logic(); |
54 | private Comparator<TrajectoryWithFitness> comparator; | 56 | private Comparator<TrajectoryWithFitness> comparator; |
55 | private Logger logger = Logger.getLogger(IStrategy.class); | 57 | private Logger logger = Logger.getLogger(IStrategy.class); |
58 | public NumericSolver numericSolver = null; | ||
59 | |||
60 | // Running | ||
61 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; | ||
62 | private SolutionStore solutionStore; | ||
63 | private SolutionStoreWithCopy solutionStoreWithCopy; | ||
64 | private SolutionStoreWithDiversityDescriptor solutionStoreWithDiversityDescriptor; | ||
65 | private volatile boolean isInterrupted = false; | ||
66 | private ModelResult modelResultByInternalSolver = null; | ||
67 | private Random random = new Random(); | ||
68 | |||
69 | // matchers for detecting the number of violations | ||
70 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> mustMatchers; | ||
71 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> mayMatchers; | ||
72 | |||
73 | // Encode the used activations of a particular state | ||
74 | private Map<Object, List<Object>> stateAndActivations; | ||
75 | private boolean allowMustViolation; | ||
76 | private Domain domain; | ||
77 | int targetSize; | ||
78 | public ActivationSelector activationSelector = new EvenActivationSelector(random); | ||
79 | // Statistics | ||
80 | private int numberOfStatecoderFail = 0; | ||
81 | private int numberOfPrintedModel = 0; | ||
82 | private int numberOfSolverCalls = 0; | ||
83 | private PartialInterpretationMetricDistance metricDistance; | ||
84 | private double currentStateValue = Double.MAX_VALUE; | ||
85 | private double currentNodeTypeDistance = 1; | ||
86 | private int numNodesToGenerate = 0; | ||
87 | public long explorationStarted = 0; | ||
88 | public long globalConstraintEvaluationTime = 0; | ||
89 | public long fitnessCalculationTime = 0; | ||
90 | |||
91 | public HillClimbingOnRealisticMetricStrategyForModelGeneration( | ||
92 | ReasonerWorkspace workspace, | ||
93 | ViatraReasonerConfiguration configuration, | ||
94 | ModelGenerationMethod method) | ||
95 | { | ||
96 | this.workspace = workspace; | ||
97 | this.configuration = configuration; | ||
98 | this.method = method; | ||
99 | } | ||
100 | |||
101 | public SolutionStoreWithCopy getSolutionStoreWithCopy() { | ||
102 | return solutionStoreWithCopy; | ||
103 | } | ||
104 | public SolutionStoreWithDiversityDescriptor getSolutionStoreWithDiversityDescriptor() { | ||
105 | return solutionStoreWithDiversityDescriptor; | ||
106 | } | ||
107 | public int getNumberOfStatecoderFail() { | ||
108 | return numberOfStatecoderFail; | ||
109 | } | ||
110 | |||
111 | public long getForwardTime() { | ||
112 | return context.getDesignSpaceManager().getForwardTime(); | ||
113 | } | ||
114 | public long getBacktrackingTime() { | ||
115 | return context.getDesignSpaceManager().getBacktrackingTime(); | ||
116 | } | ||
117 | |||
118 | @Override | ||
119 | public void initStrategy(ThreadContext context) { | ||
120 | this.context = context; | ||
121 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | ||
122 | domain = Domain.valueOf(configuration.domain); | ||
123 | |||
124 | ViatraQueryEngine engine = context.getQueryEngine(); | ||
125 | // // TODO: visualisation | ||
126 | mustMatchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
127 | mayMatchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
56 | 128 | ||
57 | // Running | 129 | // manully restict the number of super types of one class |
58 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; | 130 | this.method.getInvalidWF().forEach(a ->{ |
59 | private SolutionStore solutionStore; | 131 | ViatraQueryMatcher<? extends IPatternMatch> matcher = a.getMatcher(engine); |
60 | private SolutionStoreWithCopy solutionStoreWithCopy; | 132 | mustMatchers.add(matcher); |
61 | private SolutionStoreWithDiversityDescriptor solutionStoreWithDiversityDescriptor; | 133 | }); |
62 | private volatile boolean isInterrupted = false; | ||
63 | private ModelResult modelResultByInternalSolver = null; | ||
64 | private Random random = new Random(); | ||
65 | 134 | ||
66 | // matchers for detecting the number of violations | 135 | this.method.getUnfinishedWF().forEach(a ->{ |
67 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> mustMatchers; | 136 | ViatraQueryMatcher<? extends IPatternMatch> matcher = a.getMatcher(engine); |
68 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> mayMatchers; | 137 | mayMatchers.add(matcher); |
138 | }); | ||
69 | 139 | ||
70 | // Encode the used activations of a particular state | ||
71 | private Map<Object, List<Object>> stateAndActivations; | ||
72 | private boolean allowMustViolation; | ||
73 | private Domain domain; | ||
74 | int targetSize; | ||
75 | |||
76 | // Statistics | ||
77 | private int numberOfStatecoderFail = 0; | ||
78 | private int numberOfPrintedModel = 0; | ||
79 | private int numberOfSolverCalls = 0; | ||
80 | private PartialInterpretationMetricDistance metricDistance; | ||
81 | private double currentStateValue = Double.MAX_VALUE; | ||
82 | private double currentNodeTypeDistance = 1; | ||
83 | private int numNodesToGenerate = 0; | ||
84 | 140 | ||
85 | public HillClimbingOnRealisticMetricStrategyForModelGeneration( | 141 | //set up comparator |
86 | ReasonerWorkspace workspace, | 142 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
87 | ViatraReasonerConfiguration configuration, | 143 | this.comparator = new Comparator<TrajectoryWithFitness>() { |
88 | ModelGenerationMethod method) | 144 | @Override |
89 | { | 145 | public int compare(TrajectoryWithFitness o1, TrajectoryWithFitness o2) { |
90 | this.workspace = workspace; | 146 | return objectiveComparatorHelper.compare(o2.fitness, o1.fitness); |
91 | this.configuration = configuration; | 147 | } |
92 | this.method = method; | 148 | }; |
93 | } | ||
94 | 149 | ||
95 | public SolutionStoreWithCopy getSolutionStoreWithCopy() { | 150 | this.solutionStoreWithCopy = new SolutionStoreWithCopy(); |
96 | return solutionStoreWithCopy; | 151 | this.solutionStoreWithDiversityDescriptor = new SolutionStoreWithDiversityDescriptor(configuration.diversityRequirement); |
97 | } | 152 | |
98 | public SolutionStoreWithDiversityDescriptor getSolutionStoreWithDiversityDescriptor() { | 153 | trajectoiresToExplore = new PriorityQueue<TrajectoryWithFitness>(11, comparator); |
99 | return solutionStoreWithDiversityDescriptor; | 154 | stateAndActivations = new HashMap<Object, List<Object>>(); |
155 | metricDistance = new PartialInterpretationMetricDistance(domain); | ||
156 | |||
157 | //set whether allows must violations during the realistic generation | ||
158 | allowMustViolation = configuration.allowMustViolations; | ||
159 | targetSize = configuration.typeScopes.maxNewElements + 2; | ||
160 | //this.numericSolver = new NumericSolver(method, this.configuration.runIntermediateNumericalConsistencyChecks, false); | ||
161 | } | ||
162 | |||
163 | @Override | ||
164 | public void explore() { | ||
165 | this.explorationStarted=System.nanoTime(); | ||
166 | if (!checkGlobalConstraints()) { | ||
167 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | ||
168 | return; | ||
100 | } | 169 | } |
101 | public int getNumberOfStatecoderFail() { | 170 | if (configuration.searchSpaceConstraints.maxDepth == 0) { |
102 | return numberOfStatecoderFail; | 171 | logger.info("Maximal depth is reached in the initial solution. Terminate."); |
172 | return; | ||
103 | } | 173 | } |
104 | |||
105 | @Override | ||
106 | public void initStrategy(ThreadContext context) { | ||
107 | this.context = context; | ||
108 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | ||
109 | domain = Domain.valueOf(configuration.domain); | ||
110 | |||
111 | ViatraQueryEngine engine = context.getQueryEngine(); | ||
112 | // // TODO: visualisation | ||
113 | mustMatchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
114 | mayMatchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
115 | |||
116 | // manully restict the number of super types of one class | ||
117 | this.method.getInvalidWF().forEach(a ->{ | ||
118 | ViatraQueryMatcher<? extends IPatternMatch> matcher = a.getMatcher(engine); | ||
119 | mustMatchers.add(matcher); | ||
120 | }); | ||
121 | |||
122 | this.method.getUnfinishedWF().forEach(a ->{ | ||
123 | ViatraQueryMatcher<? extends IPatternMatch> matcher = a.getMatcher(engine); | ||
124 | mayMatchers.add(matcher); | ||
125 | }); | ||
126 | 174 | ||
127 | 175 | final Fitness firstFittness = context.calculateFitness(); | |
128 | //set up comparator | 176 | |
129 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 177 | //final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
130 | this.comparator = new Comparator<TrajectoryWithFitness>() { | 178 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); |
131 | @Override | 179 | TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness); |
132 | public int compare(TrajectoryWithFitness o1, TrajectoryWithFitness o2) { | 180 | trajectoiresToExplore.add(currentTrajectoryWithFittness); |
133 | return objectiveComparatorHelper.compare(o2.fitness, o1.fitness); | 181 | Object lastState = null; |
182 | |||
183 | //if(configuration) | ||
184 | visualiseCurrentState(); | ||
185 | // the two is the True and False node generated at the beginning of the generation | ||
186 | int count = 0; | ||
187 | mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) { | ||
188 | |||
189 | if (currentTrajectoryWithFittness == null) { | ||
190 | if (trajectoiresToExplore.isEmpty()) { | ||
191 | logger.debug("State space is fully traversed."); | ||
192 | return; | ||
193 | } else { | ||
194 | currentTrajectoryWithFittness = selectState(); | ||
195 | if (logger.isDebugEnabled()) { | ||
196 | logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray())); | ||
197 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness); | ||
198 | } | ||
199 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory); | ||
200 | |||
201 | // reset the regression for this trajectory | ||
202 | metricDistance.getLinearModel().resetRegression(context.getCurrentStateId()); | ||
134 | } | 203 | } |
135 | }; | 204 | } |
136 | 205 | ||
137 | this.solutionStoreWithCopy = new SolutionStoreWithCopy(); | 206 | List<Object> activationIds = selectActivation(); |
138 | this.solutionStoreWithDiversityDescriptor = new SolutionStoreWithDiversityDescriptor(configuration.diversityRequirement); | 207 | PartialInterpretation model = (PartialInterpretation) context.getModel(); |
208 | System.out.println(model.getNewElements().size()); | ||
209 | System.out.println("# violations: " + getNumberOfViolations(mayMatchers)); | ||
139 | 210 | ||
140 | trajectoiresToExplore = new PriorityQueue<TrajectoryWithFitness>(11, comparator); | 211 | Map<Object, Double> valueMap = new HashMap<Object,Double>(); |
141 | stateAndActivations = new HashMap<Object, List<Object>>(); | ||
142 | metricDistance = new PartialInterpretationMetricDistance(domain); | ||
143 | 212 | ||
144 | //set whether allows must violations during the realistic generation | 213 | //init epsilon and draw |
145 | allowMustViolation = configuration.allowMustViolations; | 214 | MetricDistanceGroup heuristics = metricDistance.calculateMetricDistanceKS(model); |
146 | targetSize = configuration.typeScopes.maxNewElements + 2; | ||
147 | } | ||
148 | 215 | ||
149 | @Override | 216 | if(!stateAndActivations.containsKey(context.getCurrentStateId())) { |
150 | public void explore() { | 217 | stateAndActivations.put(context.getCurrentStateId(), new ArrayList<Object>()); |
151 | if (!context.checkGlobalConstraints()) { | ||
152 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | ||
153 | return; | ||
154 | } | ||
155 | if (configuration.searchSpaceConstraints.maxDepth == 0) { | ||
156 | logger.info("Maximal depth is reached in the initial solution. Terminate."); | ||
157 | return; | ||
158 | } | 218 | } |
159 | 219 | ||
160 | final Fitness firstFittness = context.calculateFitness(); | 220 | // calculate values for epsilon greedy |
161 | 221 | double epsilon = 1.0/count; | |
162 | //final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 222 | double draw = Math.random(); |
163 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); | 223 | count++; |
164 | TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness); | 224 | this.currentNodeTypeDistance = heuristics.getNodeTypeDistance(); |
165 | trajectoiresToExplore.add(currentTrajectoryWithFittness); | 225 | numNodesToGenerate = model.getMaxNewElements(); |
166 | Object lastState = null; | 226 | System.out.println("NA distance: " + heuristics.getNADistance()); |
167 | 227 | System.out.println("MPC distance: " + heuristics.getMPCDistance()); | |
168 | //if(configuration) | 228 | System.out.println("Out degree distance:" + heuristics.getOutDegreeDistance()); |
169 | visualiseCurrentState(); | 229 | System.out.println("NodeType :" + currentNodeTypeDistance); |
170 | // the two is the True and False node generated at the beginning of the generation | ||
171 | int count = 0; | ||
172 | mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) { | ||
173 | 230 | ||
174 | if (currentTrajectoryWithFittness == null) { | ||
175 | if (trajectoiresToExplore.isEmpty()) { | ||
176 | logger.debug("State space is fully traversed."); | ||
177 | return; | ||
178 | } else { | ||
179 | currentTrajectoryWithFittness = selectState(); | ||
180 | if (logger.isDebugEnabled()) { | ||
181 | logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray())); | ||
182 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness); | ||
183 | } | ||
184 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory); | ||
185 | |||
186 | // reset the regression for this trajectory | ||
187 | metricDistance.getLinearModel().resetRegression(context.getCurrentStateId()); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | List<Object> activationIds = selectActivation(); | ||
192 | PartialInterpretation model = (PartialInterpretation) context.getModel(); | ||
193 | // System.out.println(model.getNewElements().size()); | ||
194 | // System.out.println("# violations: " + getNumberOfViolations(mayMatchers)); | ||
195 | |||
196 | Map<Object, Double> valueMap = new HashMap<Object,Double>(); | ||
197 | |||
198 | //init epsilon and draw | ||
199 | MetricDistanceGroup heuristics = metricDistance.calculateMetricDistanceKS(model); | ||
200 | 231 | ||
201 | if(!stateAndActivations.containsKey(context.getCurrentStateId())) { | 232 | //TODO: the number of activations to be checked should be configurasble |
202 | stateAndActivations.put(context.getCurrentStateId(), new ArrayList<Object>()); | 233 | if(activationIds.size() > 50) { |
203 | } | 234 | activationIds = activationIds.subList(0, 50); |
235 | } | ||
236 | |||
237 | valueMap = sortWithWeight(activationIds); | ||
238 | lastState = context.getCurrentStateId(); | ||
239 | while (!isInterrupted && !configuration.progressMonitor.isCancelled() && activationIds.size() > 0) { | ||
240 | final Object nextActivation = drawWithEpsilonProbabilty(activationIds, valueMap, epsilon, draw); | ||
241 | |||
242 | stateAndActivations.get(context.getCurrentStateId()).add(nextActivation); | ||
243 | logger.debug("Executing new activation: " + nextActivation); | ||
244 | context.executeAcitvationId(nextActivation); | ||
245 | visualiseCurrentState(); | ||
246 | boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); | ||
247 | if(consistencyCheckResult == true) { continue mainLoop; } | ||
204 | 248 | ||
205 | // calculate values for epsilon greedy | 249 | // if (context.isCurrentStateAlreadyTraversed()) { |
206 | double epsilon = 1.0/count; | 250 | // logger.info("The new state is already visited."); |
207 | double draw = Math.random(); | 251 | // context.backtrack(); |
208 | count++; | 252 | // } else if (!checkGlobalConstraints()) { |
209 | this.currentNodeTypeDistance = heuristics.getNodeTypeDistance(); | 253 | // logger.debug("Global contraint is not satisifed."); |
210 | numNodesToGenerate = model.getMaxNewElements(); | 254 | // context.backtrack(); |
211 | // System.out.println("NA distance: " + heuristics.getNADistance()); | 255 | // } |
212 | // System.out.println("MPC distance: " + heuristics.getMPCDistance()); | ||
213 | // System.out.println("Out degree distance:" + heuristics.getOutDegreeDistance()); | ||
214 | // System.out.println("NodeType :" + currentNodeTypeDistance); | ||
215 | |||
216 | |||
217 | //TODO: the number of activations to be checked should be configurasble | ||
218 | if(activationIds.size() > 50) { | ||
219 | activationIds = activationIds.subList(0, 50); | ||
220 | } | ||
221 | 256 | ||
222 | valueMap = sortWithWeight(activationIds); | 257 | int currentSize = model.getNewElements().size(); |
223 | lastState = context.getCurrentStateId(); | 258 | int targetDiff = targetSize - currentSize; |
224 | while (!isInterrupted && !configuration.progressMonitor.isCancelled() && activationIds.size() > 0) { | 259 | boolean shouldFinish = currentSize >= targetSize; |
225 | final Object nextActivation = drawWithEpsilonProbabilty(activationIds, valueMap, epsilon, draw); | 260 | |
226 | 261 | // does not allow must violations | |
227 | stateAndActivations.get(context.getCurrentStateId()).add(nextActivation); | 262 | if((getNumberOfViolations(mustMatchers) > 0|| getNumberOfViolations(mayMatchers) > targetDiff) && !allowMustViolation && !shouldFinish) { |
228 | logger.debug("Executing new activation: " + nextActivation); | 263 | context.backtrack(); |
229 | context.executeAcitvationId(nextActivation); | 264 | }else { |
230 | visualiseCurrentState(); | 265 | final Fitness nextFitness = context.calculateFitness(); |
231 | boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); | ||
232 | if(consistencyCheckResult == true) { continue mainLoop; } | ||
233 | |||
234 | int currentSize = model.getNewElements().size(); | ||
235 | int targetDiff = targetSize - currentSize; | ||
236 | boolean shouldFinish = currentSize >= targetSize; | ||
237 | 266 | ||
238 | // does not allow must violations | 267 | // the only hard objectives are configured in the config file |
239 | if((getNumberOfViolations(mustMatchers) > 0|| getNumberOfViolations(mayMatchers) > targetDiff) && !allowMustViolation && !shouldFinish) { | 268 | checkForSolution(nextFitness); |
269 | |||
270 | if (context.getDepth() > configuration.searchSpaceConstraints.maxDepth) { | ||
271 | logger.debug("Reached max depth."); | ||
240 | context.backtrack(); | 272 | context.backtrack(); |
241 | }else { | 273 | continue; |
242 | final Fitness nextFitness = context.calculateFitness(); | ||
243 | |||
244 | // the only hard objectives are configured in the config file | ||
245 | checkForSolution(nextFitness); | ||
246 | |||
247 | if (context.getDepth() > configuration.searchSpaceConstraints.maxDepth) { | ||
248 | logger.debug("Reached max depth."); | ||
249 | context.backtrack(); | ||
250 | continue; | ||
251 | } | ||
252 | |||
253 | //Record value for current trajectory | ||
254 | TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness( | ||
255 | context.getTrajectory().toArray(), nextFitness); | ||
256 | int nodeSize = ((PartialInterpretation) context.getModel()).getNewElements().size(); | ||
257 | int violation = getNumberOfViolations(mayMatchers); | ||
258 | double currentValue = calculateCurrentStateValue(nodeSize, violation); | ||
259 | metricDistance.getLinearModel().feedData(context.getCurrentStateId(), metricDistance.calculateFeature(nodeSize, violation), currentValue, lastState); | ||
260 | trajectoiresToExplore.add(nextTrajectoryWithFittness); | ||
261 | currentStateValue = currentValue; | ||
262 | //Currently, just go to the next state without considering the value of trajectory | ||
263 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | ||
264 | continue mainLoop; | ||
265 | |||
266 | } | 274 | } |
275 | |||
276 | //Record value for current trajectory | ||
277 | TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness( | ||
278 | context.getTrajectory().toArray(), nextFitness); | ||
279 | int nodeSize = ((PartialInterpretation) context.getModel()).getNewElements().size(); | ||
280 | int violation = getNumberOfViolations(mayMatchers); | ||
281 | double currentValue = calculateCurrentStateValue(nodeSize, violation); | ||
282 | metricDistance.getLinearModel().feedData(context.getCurrentStateId(), metricDistance.calculateFeature(nodeSize, violation), currentValue, lastState); | ||
283 | trajectoiresToExplore.add(nextTrajectoryWithFittness); | ||
284 | currentStateValue = currentValue; | ||
285 | //Currently, just go to the next state without considering the value of trajectory | ||
286 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | ||
287 | continue mainLoop; | ||
288 | |||
267 | } | 289 | } |
268 | logger.debug("State is fully traversed."); | ||
269 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
270 | currentTrajectoryWithFittness = null; | ||
271 | context.backtrack(); | ||
272 | } | 290 | } |
273 | logger.info("Interrupted."); | 291 | logger.debug("State is fully traversed."); |
292 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
293 | currentTrajectoryWithFittness = null; | ||
294 | context.backtrack(); | ||
274 | } | 295 | } |
296 | logger.info("Interrupted."); | ||
297 | } | ||
275 | 298 | ||
276 | /** | 299 | private boolean checkGlobalConstraints() { |
277 | * | 300 | long start = System.nanoTime(); |
278 | * @param activationIds | 301 | boolean result = context.checkGlobalConstraints(); |
279 | * @return: activation to value map | 302 | globalConstraintEvaluationTime += System.nanoTime() - start; |
280 | */ | 303 | return result; |
281 | private Map<Object, Double> sortWithWeight(List<Object> activationIds){ | 304 | } |
282 | Map<Object, Double> valueMap = new HashMap<Object, Double>(); | 305 | |
283 | Object currentId = context.getCurrentStateId(); | 306 | private Fitness calculateFitness() { |
284 | // check for next states | 307 | long start = System.nanoTime(); |
285 | for(Object id : activationIds) { | 308 | Fitness fitness = context.calculateFitness(); |
286 | context.executeAcitvationId(id); | 309 | fitnessCalculationTime += System.nanoTime() - start; |
287 | int violation = getNumberOfViolations(mayMatchers); | 310 | return fitness; |
311 | } | ||
312 | |||
313 | /** | ||
314 | * | ||
315 | * @param activationIds | ||
316 | * @return: activation to value map | ||
317 | */ | ||
318 | private Map<Object, Double> sortWithWeight(List<Object> activationIds){ | ||
319 | Map<Object, Double> valueMap = new HashMap<Object, Double>(); | ||
320 | Object currentId = context.getCurrentStateId(); | ||
321 | // check for next states | ||
322 | for(Object id : activationIds) { | ||
323 | context.executeAcitvationId(id); | ||
324 | int violation = getNumberOfViolations(mayMatchers); | ||
288 | 325 | ||
289 | if(!allowMustViolation && getNumberOfViolations(mustMatchers) > 0) { | 326 | if(!allowMustViolation && getNumberOfViolations(mustMatchers) > 0) { |
290 | valueMap.put(id, Double.MAX_VALUE); | 327 | valueMap.put(id, Double.MAX_VALUE); |
291 | stateAndActivations.get(currentId).add(id); | 328 | stateAndActivations.get(currentId).add(id); |
292 | }else { | 329 | }else { |
293 | valueMap.put(id, calculateFutureStateValue(violation)); | 330 | valueMap.put(id, calculateFutureStateValue(violation)); |
294 | } | ||
295 | |||
296 | |||
297 | |||
298 | context.backtrack(); | ||
299 | } | 331 | } |
332 | |||
333 | |||
300 | 334 | ||
301 | //remove all the elements having large distance | 335 | context.backtrack(); |
302 | Collections.sort(activationIds, Comparator.comparing(li -> valueMap.get(li))); | ||
303 | return valueMap; | ||
304 | } | 336 | } |
305 | 337 | ||
306 | private double calculateFutureStateValue(int violation) { | 338 | //remove all the elements having large distance |
307 | long start = System.nanoTime(); | 339 | Collections.sort(activationIds, Comparator.comparing(li -> valueMap.get(li))); |
308 | int nodeSize = ((PartialInterpretation) context.getModel()).getNewElements().size(); | 340 | return valueMap; |
309 | double currentValue = calculateCurrentStateValue(nodeSize,violation); | 341 | } |
310 | double[] toPredict = metricDistance.calculateFeature(100, violation); | 342 | |
311 | if(Math.abs(currentValue - currentStateValue) < 0.001) { | 343 | private double calculateFutureStateValue(int violation) { |
312 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); | 344 | long start = System.nanoTime(); |
313 | return Double.MAX_VALUE; | 345 | int nodeSize = ((PartialInterpretation) context.getModel()).getNewElements().size(); |
314 | } | 346 | double currentValue = calculateCurrentStateValue(nodeSize,violation); |
315 | try { | 347 | double[] toPredict = metricDistance.calculateFeature(100, violation); |
316 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); | 348 | if(Math.abs(currentValue - currentStateValue) < 0.001) { |
317 | return metricDistance.getLinearModel().getPredictionForNextDataSample(metricDistance.calculateFeature(nodeSize, violation), currentValue, toPredict); | 349 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); |
318 | }catch(IllegalArgumentException e) { | 350 | return Double.MAX_VALUE; |
319 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); | 351 | } |
320 | return currentValue; | 352 | try { |
321 | } | 353 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); |
322 | 354 | return metricDistance.getLinearModel().getPredictionForNextDataSample(metricDistance.calculateFeature(nodeSize, violation), currentValue, toPredict); | |
355 | }catch(IllegalArgumentException e) { | ||
356 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); | ||
357 | return currentValue; | ||
323 | } | 358 | } |
324 | private double calculateCurrentStateValue(int factor, int violation) { | ||
325 | PartialInterpretation model = (PartialInterpretation) context.getModel(); | ||
326 | MetricDistanceGroup g = metricDistance.calculateMetricDistanceKS(model); | ||
327 | if(configuration.realisticGuidance == RealisticGuidance.MPC) { | ||
328 | return g.getMPCDistance(); | ||
329 | }else if(configuration.realisticGuidance == RealisticGuidance.NodeActivity) { | ||
330 | return g.getNADistance(); | ||
331 | }else if(configuration.realisticGuidance == RealisticGuidance.OutDegree) { | ||
332 | return g.getOutDegreeDistance(); | ||
333 | }else if(configuration.realisticGuidance == RealisticGuidance.NodeType) { | ||
334 | return g.getNodeTypeDistance(); | ||
335 | }else if(configuration.realisticGuidance == RealisticGuidance.Composite) { | ||
336 | double consistenceWeights = 5 * factor / (configuration.typeScopes.maxNewElements + 2) * (1- 1.0/(1+violation)); | ||
337 | if(domain == Domain.Yakindumm) { | ||
338 | double unfinishFactor = 50 * (1 - (double)factor / targetSize); | ||
339 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
340 | double normalFactor = 5; | ||
341 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { | ||
342 | nodeTypeFactor = 0; | ||
343 | normalFactor = 100; | ||
344 | unfinishFactor = 0; | ||
345 | } | ||
346 | |||
347 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
348 | }else if (domain == Domain.Ecore) { | ||
349 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | ||
350 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
351 | double normalFactor = 5; | ||
352 | if(currentNodeTypeDistance <= 0.12 || numNodesToGenerate == 1) { | ||
353 | nodeTypeFactor = 0; | ||
354 | normalFactor = 100; | ||
355 | unfinishFactor *= 0.5; | ||
356 | } | ||
357 | |||
358 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
359 | }else { | ||
360 | double unfinishFactor = context.calculateFitness().get("CompositeUnfinishednessObjective"); | ||
361 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
362 | double normalFactor = 5; | ||
363 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { | ||
364 | nodeTypeFactor = 0; | ||
365 | normalFactor = 100; | ||
366 | //unfinishFactor *= 0.5; | ||
367 | } | ||
368 | |||
369 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + 2*g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
370 | } | ||
371 | 359 | ||
372 | }else if(configuration.realisticGuidance == RealisticGuidance.Composite_Without_Violations) { | 360 | } |
373 | if(domain == Domain.Yakindumm) { | 361 | private double calculateCurrentStateValue(int factor, int violation) { |
374 | double unfinishFactor = 50 * (1 - (double)factor / targetSize); | 362 | PartialInterpretation model = (PartialInterpretation) context.getModel(); |
375 | double nodeTypeFactor = g.getNodeTypeDistance(); | 363 | MetricDistanceGroup g = metricDistance.calculateMetricDistanceKS(model); |
376 | double normalFactor = 5; | 364 | if(configuration.realisticGuidance == RealisticGuidance.MPC) { |
377 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { | 365 | return g.getMPCDistance(); |
378 | nodeTypeFactor = 0; | 366 | }else if(configuration.realisticGuidance == RealisticGuidance.NodeActivity) { |
379 | normalFactor = 100; | 367 | return g.getNADistance(); |
380 | unfinishFactor = 0; | 368 | }else if(configuration.realisticGuidance == RealisticGuidance.OutDegree) { |
381 | } | 369 | return g.getOutDegreeDistance(); |
382 | 370 | }else if(configuration.realisticGuidance == RealisticGuidance.NodeType) { | |
383 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; | 371 | return g.getNodeTypeDistance(); |
384 | }else if (domain == Domain.Github) { | 372 | }else if(configuration.realisticGuidance == RealisticGuidance.Composite) { |
385 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | 373 | double consistenceWeights = 5 * factor / (configuration.typeScopes.maxNewElements + 2) * (1- 1.0/(1+violation)); |
386 | double nodeTypeFactor = g.getNodeTypeDistance(); | 374 | if(domain == Domain.Yakindumm) { |
387 | double normalFactor = 5; | 375 | double unfinishFactor = 50 * (1 - (double)factor / targetSize); |
388 | if(currentNodeTypeDistance <= 0.12 || numNodesToGenerate == 1) { | 376 | double nodeTypeFactor = g.getNodeTypeDistance(); |
389 | nodeTypeFactor = 0; | 377 | double normalFactor = 5; |
390 | normalFactor = 100; | 378 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { |
391 | unfinishFactor *= 0.5; | 379 | nodeTypeFactor = 0; |
392 | } | 380 | normalFactor = 100; |
393 | 381 | unfinishFactor = 0; | |
394 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; | ||
395 | } else { | ||
396 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | ||
397 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
398 | double normalFactor = 5; | ||
399 | if(currentNodeTypeDistance <= 0.20 || numNodesToGenerate == 1) { | ||
400 | nodeTypeFactor = 0; | ||
401 | normalFactor = 100; | ||
402 | unfinishFactor *= 0.5; | ||
403 | } | ||
404 | |||
405 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; | ||
406 | } | 382 | } |
383 | |||
384 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
385 | }else if (domain == Domain.Ecore) { | ||
386 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | ||
387 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
388 | double normalFactor = 5; | ||
389 | if(currentNodeTypeDistance <= 0.12 || numNodesToGenerate == 1) { | ||
390 | nodeTypeFactor = 0; | ||
391 | normalFactor = 100; | ||
392 | unfinishFactor *= 0.5; | ||
393 | } | ||
394 | |||
395 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
407 | }else { | 396 | }else { |
408 | return violation; | 397 | double unfinishFactor = context.calculateFitness().get("CompositeUnfinishednessObjective"); |
409 | } | 398 | double nodeTypeFactor = g.getNodeTypeDistance(); |
410 | } | 399 | double normalFactor = 5; |
411 | 400 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { | |
412 | private int getNumberOfViolations(Collection<ViatraQueryMatcher<? extends IPatternMatch>> matchers) { | 401 | nodeTypeFactor = 0; |
413 | int violations = matchers.stream().mapToInt(m -> m.countMatches()).sum(); | 402 | normalFactor = 100; |
414 | 403 | //unfinishFactor *= 0.5; | |
415 | return violations; | 404 | } |
416 | } | 405 | |
417 | 406 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + 2*g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | |
418 | // Modified epsilon greedy choose for action based on value function | ||
419 | // with probability epsilon, choose the state with probability based on the weight | ||
420 | // with probability 1 - epsilon, choose the best state | ||
421 | // epsilon should decay w.r.t. time | ||
422 | private Object drawWithEpsilonProbabilty(List<Object> activationIds, Map<Object, Double> valueMap, double epsilon, double currentDraw) { | ||
423 | if(activationIds.size() <= 0) { | ||
424 | return null; | ||
425 | } | 407 | } |
426 | 408 | ||
427 | // if epsilon is smaller than current draw, return greedy choice | 409 | }else if(configuration.realisticGuidance == RealisticGuidance.Composite_Without_Violations) { |
428 | if(epsilon < currentDraw) { | 410 | if(domain == Domain.Yakindumm) { |
429 | return activationIds.remove(0); | 411 | double unfinishFactor = 50 * (1 - (double)factor / targetSize); |
430 | }else { | 412 | double nodeTypeFactor = g.getNodeTypeDistance(); |
431 | //else return draw with probability of the weights | 413 | double normalFactor = 5; |
432 | //find the sum of all 1-weights: the smaller the better | 414 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { |
433 | double sum = valueMap.values().stream().mapToDouble(d->1).sum(); | 415 | nodeTypeFactor = 0; |
434 | double rand = Math.random() * sum; | 416 | normalFactor = 100; |
435 | double iterator = 0.0; | 417 | unfinishFactor = 0; |
436 | Object idToReturn = null; | 418 | } |
437 | 419 | ||
438 | // draw an item with probability | 420 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; |
439 | for(Object o : valueMap.keySet()) { | 421 | }else if (domain == Domain.Github) { |
440 | iterator += (1); | 422 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); |
441 | if(rand < iterator) { | 423 | double nodeTypeFactor = g.getNodeTypeDistance(); |
442 | idToReturn = o; | 424 | double normalFactor = 5; |
443 | break; | 425 | if(currentNodeTypeDistance <= 0.12 || numNodesToGenerate == 1) { |
444 | } | 426 | nodeTypeFactor = 0; |
427 | normalFactor = 100; | ||
428 | unfinishFactor *= 0.5; | ||
429 | } | ||
430 | |||
431 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; | ||
432 | } else { | ||
433 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | ||
434 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
435 | double normalFactor = 5; | ||
436 | if(currentNodeTypeDistance <= 0.20 || numNodesToGenerate == 1) { | ||
437 | nodeTypeFactor = 0; | ||
438 | normalFactor = 100; | ||
439 | unfinishFactor *= 0.5; | ||
445 | } | 440 | } |
446 | 441 | ||
447 | //delete the item from the list | 442 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; |
448 | activationIds.remove(idToReturn); | ||
449 | valueMap.remove(idToReturn); | ||
450 | return idToReturn; | ||
451 | } | 443 | } |
444 | }else { | ||
445 | return violation; | ||
452 | } | 446 | } |
447 | } | ||
448 | |||
449 | private int getNumberOfViolations(Collection<ViatraQueryMatcher<? extends IPatternMatch>> matchers) { | ||
450 | int violations = matchers.stream().mapToInt(m -> m.countMatches()).sum(); | ||
453 | 451 | ||
454 | private List<Object> selectActivation() { | 452 | return violations; |
455 | List<Object> activationIds; | 453 | } |
456 | try { | 454 | |
457 | activationIds = new ArrayList<Object>(context.getCurrentActivationIds()); | 455 | // Modified epsilon greedy choose for action based on value function |
458 | if(stateAndActivations.containsKey(context.getCurrentStateId())) { | 456 | // with probability epsilon, choose the state with probability based on the weight |
459 | activationIds.removeAll(stateAndActivations.get(context.getCurrentStateId())); | 457 | // with probability 1 - epsilon, choose the best state |
458 | // epsilon should decay w.r.t. time | ||
459 | private Object drawWithEpsilonProbabilty(List<Object> activationIds, Map<Object, Double> valueMap, double epsilon, double currentDraw) { | ||
460 | if(activationIds.size() <= 0) { | ||
461 | return null; | ||
462 | } | ||
463 | |||
464 | // if epsilon is smaller than current draw, return greedy choice | ||
465 | if(epsilon < currentDraw) { | ||
466 | return activationIds.remove(0); | ||
467 | }else { | ||
468 | //else return draw with probability of the weights | ||
469 | //find the sum of all 1-weights: the smaller the better | ||
470 | double sum = valueMap.values().stream().mapToDouble(d->1).sum(); | ||
471 | double rand = Math.random() * sum; | ||
472 | double iterator = 0.0; | ||
473 | Object idToReturn = null; | ||
474 | |||
475 | // draw an item with probability | ||
476 | for(Object o : valueMap.keySet()) { | ||
477 | iterator += (1); | ||
478 | if(rand < iterator) { | ||
479 | idToReturn = o; | ||
480 | break; | ||
460 | } | 481 | } |
461 | Collections.shuffle(activationIds); | ||
462 | } catch (NullPointerException e) { | ||
463 | numberOfStatecoderFail++; | ||
464 | activationIds = Collections.emptyList(); | ||
465 | } | 482 | } |
466 | return activationIds; | 483 | |
484 | //delete the item from the list | ||
485 | activationIds.remove(idToReturn); | ||
486 | valueMap.remove(idToReturn); | ||
487 | return idToReturn; | ||
467 | } | 488 | } |
489 | } | ||
490 | |||
491 | private List<Object> selectActivation() { | ||
492 | List<Object> activationIds; | ||
493 | try { | ||
494 | activationIds = this.activationSelector.randomizeActivationIDs(context.getUntraversedActivationIds()); | ||
495 | } catch (NullPointerException e) { | ||
496 | numberOfStatecoderFail++; | ||
497 | activationIds = Collections.emptyList(); | ||
498 | } | ||
499 | return activationIds; | ||
500 | } | ||
468 | 501 | ||
469 | private void checkForSolution(final Fitness fittness) { | 502 | private void checkForSolution(final Fitness fittness) { |
470 | if (fittness.isSatisifiesHardObjectives()) { | 503 | if (fittness.isSatisifiesHardObjectives()) { |
471 | logger.debug("Solution Found!!"); | 504 | logger.debug("Solution Found!!"); |
472 | logger.debug("# violations: " + (getNumberOfViolations(mustMatchers))); | 505 | logger.debug("# violations: " + (getNumberOfViolations(mustMatchers))); |
473 | if (solutionStoreWithDiversityDescriptor.isDifferent(context)) { | 506 | if (solutionStoreWithDiversityDescriptor.isDifferent(context)) { |
474 | solutionStoreWithCopy.newSolution(context); | 507 | solutionStoreWithCopy.newSolution(context); |
475 | solutionStoreWithDiversityDescriptor.newSolution(context); | 508 | solutionStoreWithDiversityDescriptor.newSolution(context); |
476 | solutionStore.newSolution(context); | 509 | solutionStore.newSolution(context); |
477 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolution); | 510 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolutions); |
478 | 511 | ||
479 | logger.debug("Found a solution."); | 512 | logger.debug("Found a solution."); |
480 | } | ||
481 | } | 513 | } |
482 | } | 514 | } |
515 | } | ||
516 | |||
517 | public List<String> times = new LinkedList<String>(); | ||
518 | private void saveTimes() { | ||
519 | long forwardTime = context.getDesignSpaceManager().getForwardTime()/1000000; | ||
520 | long backtrackingTime = context.getDesignSpaceManager().getBacktrackingTime()/1000000; | ||
521 | long statecoderTime = ((NeighbourhoodBasedPartialInterpretationStateCoder)this.context.getStateCoder()).getStatecoderRuntime()/1000000; | ||
522 | long solutionCopy = solutionStoreWithCopy.getSumRuntime()/1000000; | ||
523 | long activationSelection = this.activationSelector.getRuntime()/1000000; | ||
524 | // long numericalSolverSumTime = this.numericSolver.getRuntime()/1000000; | ||
525 | // long numericalSolverProblemForming = this.numericSolver.getSolverSolvingProblem()/1000000; | ||
526 | // long numericalSolverSolving = this.numericSolver.getSolverSolvingProblem()/1000000; | ||
527 | // long numericalSolverInterpreting = this.numericSolver.getSolverSolution()/1000000; | ||
528 | long metricCalculationTime = this.method.getStatistics().metricCalculationTime / 1000000; | ||
529 | this.times.add( | ||
530 | "(TransformationExecutionTime"+method.getStatistics().transformationExecutionTime/1000000+ | ||
531 | "|ForwardTime:"+forwardTime+ | ||
532 | "|Backtrackingtime:"+backtrackingTime+ | ||
533 | "|StateCoderTime:"+statecoderTime+ | ||
534 | "|SolutionCopyTime:"+solutionCopy+ | ||
535 | "|ActivationSelectionTime:"+activationSelection+ | ||
536 | //"|NumericalSolverSumTime:"+numericalSolverSumTime+ | ||
537 | //"|NumericalSolverProblemFormingTime:"+numericalSolverProblemForming+ | ||
538 | //"|NumericalSolverSolvingTime:"+numericalSolverSolving+ | ||
539 | //"|NumericalSolverInterpretingSolution:"+numericalSolverInterpreting+ | ||
540 | "|MetricCalculationTime:"+metricCalculationTime + ")" | ||
541 | ); | ||
542 | |||
543 | } | ||
483 | 544 | ||
484 | @Override | 545 | @Override |
485 | public void interruptStrategy() { | 546 | public void interruptStrategy() { |
486 | isInterrupted = true; | 547 | isInterrupted = true; |
487 | } | 548 | } |
488 | 549 | ||
489 | 550 | ||
490 | private TrajectoryWithFitness selectState() { | 551 | private TrajectoryWithFitness selectState() { |
491 | int randomNumber = random.nextInt(configuration.randomBacktrackChance); | 552 | int randomNumber = random.nextInt(configuration.randomBacktrackChance); |
492 | if (randomNumber == 0) { | 553 | if (randomNumber == 0) { |
493 | int elements = trajectoiresToExplore.size(); | 554 | int elements = trajectoiresToExplore.size(); |
494 | int randomElementIndex = random.nextInt(elements); | 555 | int randomElementIndex = random.nextInt(elements); |
495 | logger.debug("Randomly backtract to the " + randomElementIndex + " best solution..."); | 556 | logger.debug("Randomly backtract to the " + randomElementIndex + " best solution..."); |
496 | Iterator<TrajectoryWithFitness> iterator = trajectoiresToExplore.iterator(); | 557 | Iterator<TrajectoryWithFitness> iterator = trajectoiresToExplore.iterator(); |
497 | while (randomElementIndex != 0) { | 558 | while (randomElementIndex != 0) { |
498 | iterator.next(); | 559 | iterator.next(); |
499 | randomElementIndex--; | 560 | randomElementIndex--; |
500 | } | 561 | } |
501 | TrajectoryWithFitness res = iterator.next(); | 562 | TrajectoryWithFitness res = iterator.next(); |
502 | if (res == null) { | 563 | if (res == null) { |
503 | return trajectoiresToExplore.element(); | ||
504 | } else { | ||
505 | return res; | ||
506 | } | ||
507 | } else { | ||
508 | return trajectoiresToExplore.element(); | 564 | return trajectoiresToExplore.element(); |
565 | } else { | ||
566 | return res; | ||
509 | } | 567 | } |
510 | } | 568 | } else { |
511 | 569 | return trajectoiresToExplore.element(); | |
570 | } | ||
571 | } | ||
572 | |||
512 | // private void logCurrentStateMetric() { | 573 | // private void logCurrentStateMetric() { |
513 | // if(this.configuration.documentationLevel != DocumentationLevel.NONE || workspace == null) { | 574 | // if(this.configuration.documentationLevel != DocumentationLevel.NONE || workspace == null) { |
514 | // return; | 575 | // return; |
@@ -518,77 +579,80 @@ public class HillClimbingOnRealisticMetricStrategyForModelGeneration implements | |||
518 | // PartialInterpretationMetric.calculateMetric(interpretation, "debug/metric/" + context.getModel().hashCode(), context.getCurrentStateId().toString()); | 579 | // PartialInterpretationMetric.calculateMetric(interpretation, "debug/metric/" + context.getModel().hashCode(), context.getCurrentStateId().toString()); |
519 | // } | 580 | // } |
520 | 581 | ||
521 | public void visualiseCurrentState() { | 582 | public void visualiseCurrentState() { |
522 | PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugCongiguration.partialInterpretatioVisualiser; | 583 | PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugConfiguration.partialInterpretatioVisualiser; |
523 | if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) { | 584 | if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) { |
524 | PartialInterpretation p = (PartialInterpretation) (context.getModel()); | 585 | PartialInterpretation p = (PartialInterpretation) (context.getModel()); |
525 | int id = ++numberOfPrintedModel; | 586 | int id = ++numberOfPrintedModel; |
526 | if (id % configuration.debugCongiguration.partalInterpretationVisualisationFrequency == 0) { | 587 | if (id % configuration.debugConfiguration.partalInterpretationVisualisationFrequency == 0) { |
527 | PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); | 588 | PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); |
528 | visualisation.writeToFile(workspace, String.format("state%09d.png", id)); | 589 | logger.debug("Visualizing state: " + id + " (" + context.getDesignSpaceManager().getCurrentState() + ")"); |
529 | } | 590 | String name = String.format("state%09d", id); |
591 | visualisation.writeToFile(workspace, name + ".png"); | ||
592 | workspace.writeModel((EObject) context.getModel(), name + ".xmi"); | ||
530 | } | 593 | } |
531 | } | 594 | } |
595 | } | ||
532 | 596 | ||
533 | protected boolean checkConsistency(TrajectoryWithFitness t) { | 597 | protected boolean checkConsistency(TrajectoryWithFitness t) { |
534 | LogicReasoner internalIncosnsitencyDetector = configuration.internalConsistencyCheckerConfiguration.internalIncosnsitencyDetector; | 598 | LogicReasoner internalIncosnsitencyDetector = configuration.internalConsistencyCheckerConfiguration.internalIncosnsitencyDetector; |
535 | if (internalIncosnsitencyDetector!= null) { | 599 | if (internalIncosnsitencyDetector!= null) { |
536 | int id = ++numberOfSolverCalls; | 600 | int id = ++numberOfSolverCalls; |
537 | if (id % configuration.internalConsistencyCheckerConfiguration.incternalConsistencyCheckingFrequency == 0) { | 601 | if (id % configuration.internalConsistencyCheckerConfiguration.incternalConsistencyCheckingFrequency == 0) { |
538 | try { | 602 | try { |
539 | PartialInterpretation interpretation = (PartialInterpretation) (context.getModel()); | 603 | PartialInterpretation interpretation = (PartialInterpretation) (context.getModel()); |
540 | PartialInterpretation copied = EcoreUtil.copy(interpretation); | 604 | PartialInterpretation copied = EcoreUtil.copy(interpretation); |
541 | this.partialInterpretation2Logic.transformPartialIntepretation2Logic(copied.getProblem(), copied); | 605 | this.partialInterpretation2Logic.transformPartialIntepretation2Logic(copied.getProblem(), copied); |
542 | LogicProblem newProblem = copied.getProblem(); | 606 | LogicProblem newProblem = copied.getProblem(); |
543 | 607 | ||
544 | this.configuration.typeScopes.maxNewElements = interpretation.getMaxNewElements(); | 608 | this.configuration.typeScopes.maxNewElements = interpretation.getMaxNewElements(); |
545 | this.configuration.typeScopes.minNewElements = interpretation.getMinNewElements(); | 609 | this.configuration.typeScopes.minNewElements = interpretation.getMinNewElements(); |
546 | LogicResult result = internalIncosnsitencyDetector.solve(newProblem, configuration, workspace); | 610 | LogicResult result = internalIncosnsitencyDetector.solve(newProblem, configuration, workspace); |
547 | if (result instanceof InconsistencyResult) { | 611 | if (result instanceof InconsistencyResult) { |
548 | logger.debug("Solver found an Inconsistency!"); | 612 | logger.debug("Solver found an Inconsistency!"); |
549 | removeSubtreeFromQueue(t); | 613 | removeSubtreeFromQueue(t); |
550 | return true; | 614 | return true; |
551 | } else if (result instanceof ModelResult) { | 615 | } else if (result instanceof ModelResult) { |
552 | logger.debug("Solver found a model!"); | 616 | logger.debug("Solver found a model!"); |
553 | solutionStore.newSolution(context); | 617 | solutionStore.newSolution(context); |
554 | 618 | ||
555 | this.modelResultByInternalSolver = (ModelResult) result; | 619 | this.modelResultByInternalSolver = (ModelResult) result; |
556 | return true; | 620 | return true; |
557 | } else { | 621 | } else { |
558 | logger.debug("Failed consistency check."); | 622 | logger.debug("Failed consistency check."); |
559 | return false; | ||
560 | } | ||
561 | } catch (Exception e) { | ||
562 | logger.debug("Problem with internal consistency checking: "+e.getMessage()); | ||
563 | e.printStackTrace(); | ||
564 | return false; | 623 | return false; |
565 | } | 624 | } |
625 | } catch (Exception e) { | ||
626 | logger.debug("Problem with internal consistency checking: "+e.getMessage()); | ||
627 | e.printStackTrace(); | ||
628 | return false; | ||
566 | } | 629 | } |
567 | |||
568 | } | 630 | } |
569 | return false; | ||
570 | } | ||
571 | 631 | ||
572 | protected void removeSubtreeFromQueue(TrajectoryWithFitness t) { | ||
573 | PriorityQueue<TrajectoryWithFitness> previous = this.trajectoiresToExplore; | ||
574 | this.trajectoiresToExplore = new PriorityQueue<>(this.comparator); | ||
575 | for (TrajectoryWithFitness trajectoryWithFitness : previous) { | ||
576 | if (!containsAsSubstring(trajectoryWithFitness.trajectory, t.trajectory)) { | ||
577 | this.trajectoiresToExplore.add(trajectoryWithFitness); | ||
578 | } else { | ||
579 | logger.debug("State has been excluded due to inherent inconsistency"); | ||
580 | } | ||
581 | } | ||
582 | } | 632 | } |
633 | return false; | ||
634 | } | ||
583 | 635 | ||
584 | private boolean containsAsSubstring(Object[] full, Object[] substring) { | 636 | protected void removeSubtreeFromQueue(TrajectoryWithFitness t) { |
585 | if (substring.length > full.length) { | 637 | PriorityQueue<TrajectoryWithFitness> previous = this.trajectoiresToExplore; |
586 | return false; | 638 | this.trajectoiresToExplore = new PriorityQueue<>(this.comparator); |
587 | } else if (substring.length == full.length) { | 639 | for (TrajectoryWithFitness trajectoryWithFitness : previous) { |
588 | return Arrays.equals(full, substring); | 640 | if (!containsAsSubstring(trajectoryWithFitness.trajectory, t.trajectory)) { |
641 | this.trajectoiresToExplore.add(trajectoryWithFitness); | ||
589 | } else { | 642 | } else { |
590 | Object[] part = Arrays.copyOfRange(full, 0, substring.length); | 643 | logger.debug("State has been excluded due to inherent inconsistency"); |
591 | return Arrays.equals(part, substring); | ||
592 | } | 644 | } |
593 | } | 645 | } |
646 | } | ||
647 | |||
648 | private boolean containsAsSubstring(Object[] full, Object[] substring) { | ||
649 | if (substring.length > full.length) { | ||
650 | return false; | ||
651 | } else if (substring.length == full.length) { | ||
652 | return Arrays.equals(full, substring); | ||
653 | } else { | ||
654 | Object[] part = Arrays.copyOfRange(full, 0, substring.length); | ||
655 | return Arrays.equals(part, substring); | ||
656 | } | ||
657 | } | ||
594 | } | 658 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend new file mode 100644 index 00000000..2e039ca2 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend | |||
@@ -0,0 +1,25 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint | ||
4 | import org.eclipse.viatra.dse.base.ThreadContext | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
6 | |||
7 | class InconsistentScopeGlobalConstraint implements IGlobalConstraint { | ||
8 | |||
9 | override init(ThreadContext context) { | ||
10 | // Nothing to initialize. | ||
11 | } | ||
12 | |||
13 | override createNew() { | ||
14 | this | ||
15 | } | ||
16 | |||
17 | override getName() { | ||
18 | class.name | ||
19 | } | ||
20 | |||
21 | override checkGlobalConstraint(ThreadContext context) { | ||
22 | val partialModel = context.model as PartialInterpretation | ||
23 | partialModel.minNewElements <= partialModel.maxNewElements || partialModel.maxNewElements < 0 | ||
24 | } | ||
25 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend new file mode 100644 index 00000000..39ef5f9a --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend | |||
@@ -0,0 +1,24 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration | ||
4 | import org.apache.log4j.Logger | ||
5 | import org.eclipse.viatra.dse.api.SolutionTrajectory | ||
6 | import org.eclipse.viatra.dse.base.ThreadContext | ||
7 | import org.eclipse.viatra.dse.solutionstore.ISolutionFoundHandler | ||
8 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
9 | |||
10 | @FinalFieldsConstructor | ||
11 | class LoggerSolutionFoundHandler implements ISolutionFoundHandler { | ||
12 | val ViatraReasonerConfiguration configuration | ||
13 | |||
14 | val logger = Logger.getLogger(SolutionCopier) | ||
15 | |||
16 | override solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
17 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolutions) | ||
18 | logger.debug("Found a solution.") | ||
19 | } | ||
20 | |||
21 | override solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { | ||
22 | // We are not interested in invalid solutions, ignore. | ||
23 | } | ||
24 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend index 9fc6853c..27208cf4 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend | |||
@@ -1,99 +1,123 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import com.google.common.collect.ImmutableList | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.IThreeValuedObjective | ||
3 | import java.util.Comparator | 7 | import java.util.Comparator |
4 | import java.util.List | 8 | import java.util.List |
5 | import org.eclipse.viatra.dse.base.ThreadContext | 9 | import org.eclipse.viatra.dse.base.ThreadContext |
6 | import org.eclipse.viatra.dse.objectives.Comparators | 10 | import org.eclipse.viatra.dse.objectives.Comparators |
7 | import org.eclipse.viatra.dse.objectives.IObjective | 11 | import org.eclipse.viatra.dse.objectives.IObjective |
8 | import org.eclipse.viatra.dse.objectives.impl.BaseObjective | 12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PrimitiveElement |
9 | 13 | ||
10 | //class ViatraReasonerNumbers { | 14 | class ModelGenerationCompositeObjective implements IThreeValuedObjective { |
11 | // public static val scopePriority = 2 | 15 | val IObjective scopeObjective |
12 | // public static val unfinishedMultiplicityPriority = 2 | ||
13 | // public static val unifinshedWFPriority = 2 | ||
14 | // //public static val complexityPriority = 4 | ||
15 | // | ||
16 | // public static val scopeWeigth = 1.0 | ||
17 | // public static val unfinishedMultiplicityWeigth = 1.5 | ||
18 | // public static val unfinishedWFWeigth = 1.5 | ||
19 | // //public static val complexityWeigth = 0.1 | ||
20 | // | ||
21 | // public static val useCompositeObjective = true | ||
22 | // public static val compositePriority = 2 | ||
23 | //} | ||
24 | |||
25 | class ModelGenerationCompositeObjective implements IObjective{ | ||
26 | val ScopeObjective scopeObjective | ||
27 | val List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives | 16 | val List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives |
28 | val UnfinishedWFObjective unfinishedWFObjective | 17 | val UnfinishedWFObjective unfinishedWFObjective |
29 | var boolean isWFOptional = false; | 18 | var PartialInterpretation model = null |
19 | val int scopeWeight | ||
20 | val int conaintmentWeight | ||
21 | val int nonContainmentWeight | ||
22 | val int unfinishedWFWeight | ||
30 | 23 | ||
31 | public new( | 24 | new( |
32 | ScopeObjective scopeObjective, | 25 | IObjective scopeObjective, |
26 | List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives, | ||
27 | UnfinishedWFObjective unfinishedWFObjective, | ||
28 | ViatraReasonerConfiguration configuration) | ||
29 | { | ||
30 | this( | ||
31 | scopeObjective, unfinishedMultiplicityObjectives, unfinishedWFObjective, | ||
32 | configuration.scopeWeight, configuration.conaintmentWeight, configuration.nonContainmentWeight, | ||
33 | configuration.unfinishedWFWeight | ||
34 | ) | ||
35 | } | ||
36 | |||
37 | new( | ||
38 | IObjective scopeObjective, | ||
33 | List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives, | 39 | List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives, |
34 | UnfinishedWFObjective unfinishedWFObjective, | 40 | UnfinishedWFObjective unfinishedWFObjective, |
35 | boolean isWFOptional) | 41 | int scopeWeight, int conaintmentWeight, int nonContainmentWeight, int unfinishedWFWeight) |
36 | { | 42 | { |
37 | this.scopeObjective = scopeObjective | 43 | this.scopeObjective = scopeObjective |
38 | this.unfinishedMultiplicityObjectives = unfinishedMultiplicityObjectives | 44 | this.unfinishedMultiplicityObjectives = unfinishedMultiplicityObjectives |
39 | this.unfinishedWFObjective = unfinishedWFObjective | 45 | this.unfinishedWFObjective = unfinishedWFObjective |
40 | this.isWFOptional = isWFOptional; | 46 | |
41 | } | 47 | this.scopeWeight = scopeWeight |
42 | 48 | this.conaintmentWeight = conaintmentWeight | |
43 | def getIsWFOptional(){ | 49 | this.nonContainmentWeight = nonContainmentWeight |
44 | return this.isWFOptional; | 50 | this.unfinishedWFWeight = unfinishedWFWeight |
45 | } | 51 | } |
46 | 52 | ||
47 | override init(ThreadContext context) { | 53 | override init(ThreadContext context) { |
54 | model = context.model as PartialInterpretation | ||
48 | this.scopeObjective.init(context) | 55 | this.scopeObjective.init(context) |
49 | this.unfinishedMultiplicityObjectives.forEach[it.init(context)] | 56 | this.unfinishedMultiplicityObjectives.forEach[it.init(context)] |
50 | this.unfinishedWFObjective.init(context) | 57 | this.unfinishedWFObjective.init(context) |
51 | } | 58 | } |
52 | 59 | ||
53 | override createNew() { | 60 | override createNew() { |
54 | return new ModelGenerationCompositeObjective( | 61 | return new ModelGenerationCompositeObjective( |
55 | this.scopeObjective, this.unfinishedMultiplicityObjectives, this.unfinishedWFObjective, this.isWFOptional) | 62 | scopeObjective.createNew, |
63 | ImmutableList.copyOf(unfinishedMultiplicityObjectives.map[createNew as UnfinishedMultiplicityObjective]), | ||
64 | unfinishedWFObjective.createNew as UnfinishedWFObjective, | ||
65 | scopeWeight, conaintmentWeight, nonContainmentWeight, unfinishedWFWeight | ||
66 | ) | ||
56 | } | 67 | } |
57 | 68 | ||
58 | override getComparator() { Comparators.LOWER_IS_BETTER } | 69 | override getComparator() { Comparators.LOWER_IS_BETTER } |
70 | |||
59 | override getFitness(ThreadContext context) { | 71 | override getFitness(ThreadContext context) { |
60 | var sum = 0.0 | 72 | |
61 | val scopeFitnes = scopeObjective.getFitness(context) | 73 | val scopeFitnes = scopeObjective.getFitness(context) |
62 | //val unfinishedMultiplicitiesFitneses = unfinishedMultiplicityObjectives.map[x|x.getFitness(context)] | 74 | val unfinishedWFsFitness = unfinishedWFObjective.getFitness(context) |
63 | 75 | ||
64 | sum+=scopeFitnes | 76 | var containmentMultiplicity = 0.0 |
65 | var multiplicity = 0.0 | 77 | var nonContainmentMultiplicity = 0.0 |
66 | for(multiplicityObjective : unfinishedMultiplicityObjectives) { | 78 | for(multiplicityObjective : unfinishedMultiplicityObjectives) { |
67 | multiplicity+=multiplicityObjective.getFitness(context)//*0.5 | 79 | val multiplicity = multiplicityObjective.getFitness(context) |
80 | // println(multiplicityObjective.name + "=" + multiplicity) | ||
81 | if(multiplicityObjective.containment) { | ||
82 | containmentMultiplicity+=multiplicity | ||
83 | } else { | ||
84 | nonContainmentMultiplicity+=multiplicity | ||
85 | } | ||
86 | |||
68 | } | 87 | } |
69 | sum+=multiplicity | ||
70 | 88 | ||
71 | // the WF can be optional when generating realistic models | 89 | var sum = 0.0 |
72 | if(!isWFOptional){ | 90 | sum += scopeFitnes*scopeWeight |
73 | val unfinishedWFsFitness = unfinishedWFObjective.getFitness(context) | 91 | sum += containmentMultiplicity*conaintmentWeight |
74 | sum += unfinishedWFsFitness//*0.5 | 92 | sum += nonContainmentMultiplicity*nonContainmentWeight |
75 | } | 93 | sum += unfinishedWFsFitness*unfinishedWFWeight |
76 | 94 | ||
77 | //println('''Sum=«sum»|Scope=«scopeFitnes»|Multiplicity=«multiplicity»|WFs=«unfinishedWFsFitness»''') | 95 | // println('''scope=«scopeFitnes», containment=«containmentMultiplicity», nonContainment=«nonContainmentMultiplicity», wf=«unfinishedWFsFitness», sum=«sum»''') |
78 | 96 | ||
79 | return sum | 97 | return sum |
80 | } | 98 | } |
81 | 99 | ||
82 | override getLevel() { 2 } | 100 | override getWorstPossibleFitness(ThreadContext threadContext) { |
83 | override getName() { "CompositeUnfinishednessObjective"} | 101 | Double.POSITIVE_INFINITY |
84 | def getObjective(){ | ||
85 | return this.unfinishedMultiplicityObjectives; | ||
86 | } | 102 | } |
87 | 103 | ||
104 | override getBestPossibleFitness(ThreadContext threadContext) { | ||
105 | 0.0 | ||
106 | } | ||
107 | |||
108 | override getLevel() { 2 } | ||
109 | |||
110 | override getName() { "CompositeUnfinishednessObjective" } | ||
111 | |||
88 | override isHardObjective() { true } | 112 | override isHardObjective() { true } |
89 | override satisifiesHardObjective(Double fitness) { fitness <= 0.001 } | 113 | |
90 | 114 | override satisifiesHardObjective(Double fitness) { fitness < 0.01 } | |
91 | 115 | ||
92 | override setComparator(Comparator<Double> comparator) { | 116 | override setComparator(Comparator<Double> comparator) { |
93 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 117 | throw new UnsupportedOperationException("Model generation objective comparator cannot be set.") |
94 | } | 118 | } |
119 | |||
95 | override setLevel(int level) { | 120 | override setLevel(int level) { |
96 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 121 | throw new UnsupportedOperationException("Model generation objective level cannot be set.") |
97 | } | 122 | } |
98 | 123 | } | |
99 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/NumericSolver.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/NumericSolver.xtend new file mode 100644 index 00000000..70e8e9c2 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/NumericSolver.xtend | |||
@@ -0,0 +1,192 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatra2logic.NumericTranslator | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BooleanElement | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.IntegerElement | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PrimitiveElement | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.RealElement | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.StringElement | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ModelGenerationMethod | ||
11 | import java.math.BigDecimal | ||
12 | import java.util.HashMap | ||
13 | import java.util.LinkedHashMap | ||
14 | import java.util.LinkedHashSet | ||
15 | import java.util.List | ||
16 | import java.util.Map | ||
17 | import org.eclipse.emf.ecore.EObject | ||
18 | import org.eclipse.viatra.dse.base.ThreadContext | ||
19 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
20 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
21 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
22 | |||
23 | class NumericSolver { | ||
24 | val ModelGenerationMethod method | ||
25 | var ThreadContext threadContext | ||
26 | val constraint2MustUnitPropagationPrecondition = new HashMap<PConstraint,ViatraQueryMatcher<? extends IPatternMatch>> | ||
27 | val constraint2CurrentUnitPropagationPrecondition = new HashMap<PConstraint,ViatraQueryMatcher<? extends IPatternMatch>> | ||
28 | NumericTranslator t = new NumericTranslator | ||
29 | |||
30 | val boolean intermediateConsistencyCheck | ||
31 | val boolean caching; | ||
32 | Map<LinkedHashMap<PConstraint, Iterable<List<Integer>>>,Boolean> satisfiabilityCache = new HashMap | ||
33 | |||
34 | var long runtime = 0 | ||
35 | var long cachingTime = 0 | ||
36 | var int numberOfSolverCalls = 0 | ||
37 | var int numberOfCachedSolverCalls = 0 | ||
38 | |||
39 | new(ModelGenerationMethod method, boolean intermediateConsistencyCheck, boolean caching) { | ||
40 | this.method = method | ||
41 | this.intermediateConsistencyCheck = intermediateConsistencyCheck | ||
42 | this.caching = caching | ||
43 | } | ||
44 | |||
45 | def init(ThreadContext context) { | ||
46 | // This makes the NumericSolver single-threaded, | ||
47 | // but that's not a problem, because we only use the solver on a single thread anyways. | ||
48 | this.threadContext = context | ||
49 | val engine = threadContext.queryEngine | ||
50 | for(entry : method.mustUnitPropagationPreconditions.entrySet) { | ||
51 | val constraint = entry.key | ||
52 | val querySpec = entry.value | ||
53 | val matcher = querySpec.getMatcher(engine); | ||
54 | constraint2MustUnitPropagationPrecondition.put(constraint,matcher) | ||
55 | } | ||
56 | for(entry : method.currentUnitPropagationPreconditions.entrySet) { | ||
57 | val constraint = entry.key | ||
58 | val querySpec = entry.value | ||
59 | val matcher = querySpec.getMatcher(engine); | ||
60 | constraint2CurrentUnitPropagationPrecondition.put(constraint,matcher) | ||
61 | } | ||
62 | } | ||
63 | |||
64 | def getRuntime(){runtime} | ||
65 | def getCachingTime(){cachingTime} | ||
66 | def getNumberOfSolverCalls(){numberOfSolverCalls} | ||
67 | def getNumberOfCachedSolverCalls(){numberOfCachedSolverCalls} | ||
68 | def getSolverFormingProblem(){this.t.formingProblemTime} | ||
69 | def getSolverSolvingProblem(){this.t.solvingProblemTime} | ||
70 | def getSolverSolution(){this.t.formingSolutionTime} | ||
71 | |||
72 | def boolean maySatisfiable() { | ||
73 | if(intermediateConsistencyCheck) { | ||
74 | return isSatisfiable(this.constraint2MustUnitPropagationPrecondition) | ||
75 | } else { | ||
76 | return true | ||
77 | } | ||
78 | } | ||
79 | def boolean currentSatisfiable() { | ||
80 | isSatisfiable(this.constraint2CurrentUnitPropagationPrecondition) | ||
81 | } | ||
82 | |||
83 | private def boolean isSatisfiable(Map<PConstraint,ViatraQueryMatcher<? extends IPatternMatch>> matches) { | ||
84 | val start = System.nanoTime | ||
85 | var boolean finalResult | ||
86 | if(matches.empty){ | ||
87 | finalResult=true | ||
88 | } else { | ||
89 | val propagatedConstraints = new HashMap | ||
90 | for(entry : matches.entrySet) { | ||
91 | val constraint = entry.key | ||
92 | //println(constraint) | ||
93 | val allMatches = entry.value.allMatches.map[it.toArray] | ||
94 | //println(allMatches.toList) | ||
95 | propagatedConstraints.put(constraint,allMatches) | ||
96 | } | ||
97 | if(propagatedConstraints.values.forall[empty]) { | ||
98 | finalResult=true | ||
99 | } else { | ||
100 | if(caching) { | ||
101 | val code = getCode(propagatedConstraints) | ||
102 | val cachedResult = satisfiabilityCache.get(code) | ||
103 | if(cachedResult === null) { | ||
104 | // println('''new problem, call solver''') | ||
105 | // for(entry : code.entrySet) { | ||
106 | // println('''«entry.key» -> «entry.value»''') | ||
107 | // } | ||
108 | //println(code.hashCode) | ||
109 | this.numberOfSolverCalls++ | ||
110 | val res = t.delegateIsSatisfiable(propagatedConstraints) | ||
111 | satisfiabilityCache.put(code,res) | ||
112 | finalResult=res | ||
113 | } else { | ||
114 | //println('''similar problem, answer from cache''') | ||
115 | finalResult=cachedResult | ||
116 | this.numberOfCachedSolverCalls++ | ||
117 | } | ||
118 | } else { | ||
119 | finalResult= t.delegateIsSatisfiable(propagatedConstraints) | ||
120 | this.numberOfSolverCalls++ | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | this.runtime+=System.nanoTime-start | ||
125 | return finalResult | ||
126 | } | ||
127 | |||
128 | def getCode(HashMap<PConstraint, Iterable<Object[]>> propagatedConstraints) { | ||
129 | val start = System.nanoTime | ||
130 | val involvedObjects = new LinkedHashSet(propagatedConstraints.values.flatten.map[toList].flatten.toList).toList | ||
131 | val res = new LinkedHashMap(propagatedConstraints.mapValues[matches | matches.map[objects | objects.map[object | involvedObjects.indexOf(object)].toList]]) | ||
132 | this.cachingTime += System.nanoTime-start | ||
133 | return res | ||
134 | } | ||
135 | |||
136 | def fillSolutionCopy(Map<EObject, EObject> trace) { | ||
137 | val model = threadContext.getModel as PartialInterpretation | ||
138 | val dataObjects = model.newElements.filter(PrimitiveElement).filter[!model.openWorldElements.contains(it)].toList | ||
139 | if(constraint2CurrentUnitPropagationPrecondition.empty) { | ||
140 | fillWithDefaultValues(dataObjects,trace) | ||
141 | } else { | ||
142 | val propagatedConstraints = new HashMap | ||
143 | for(entry : constraint2CurrentUnitPropagationPrecondition.entrySet) { | ||
144 | val constraint = entry.key | ||
145 | val allMatches = entry.value.allMatches.map[it.toArray] | ||
146 | propagatedConstraints.put(constraint,allMatches) | ||
147 | } | ||
148 | |||
149 | if(propagatedConstraints.values.forall[empty]) { | ||
150 | fillWithDefaultValues(dataObjects,trace) | ||
151 | } else { | ||
152 | val solution = t.delegateGetSolution(dataObjects,propagatedConstraints) | ||
153 | fillWithSolutions(dataObjects,solution,trace) | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | def protected fillWithDefaultValues(List<PrimitiveElement> elements, Map<EObject, EObject> trace) { | ||
159 | for(element : elements) { | ||
160 | if(element.valueSet==false) { | ||
161 | val value = getDefaultValue(element) | ||
162 | val target = trace.get(element) as PrimitiveElement | ||
163 | target.fillWithValue(value) | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | |||
168 | def protected dispatch getDefaultValue(BooleanElement e) {false} | ||
169 | def protected dispatch getDefaultValue(IntegerElement e) {0} | ||
170 | def protected dispatch getDefaultValue(RealElement e) {0.0} | ||
171 | def protected dispatch getDefaultValue(StringElement e) {""} | ||
172 | |||
173 | def protected fillWithSolutions(List<PrimitiveElement> elements, Map<PrimitiveElement, Number> solution, Map<EObject, EObject> trace) { | ||
174 | for(element : elements) { | ||
175 | if(element.valueSet==false) { | ||
176 | if(solution.containsKey(element)) { | ||
177 | val value = solution.get(element) | ||
178 | val target = trace.get(element) as PrimitiveElement | ||
179 | target.fillWithValue(value) | ||
180 | } else { | ||
181 | val target = trace.get(element) as PrimitiveElement | ||
182 | target.fillWithValue(target.defaultValue) | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | |||
188 | def protected dispatch fillWithValue(BooleanElement e, Object value) {e.valueSet=true e.value=value as Boolean} | ||
189 | def protected dispatch fillWithValue(IntegerElement e, Object value) {e.valueSet=true e.value=value as Integer} | ||
190 | def protected dispatch fillWithValue(RealElement e, Object value) {e.valueSet=true e.value=BigDecimal.valueOf(value as Double) } | ||
191 | def protected dispatch fillWithValue(StringElement e, Object value) {e.valueSet=true e.value=value as String} | ||
192 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PartialModelAsLogicInterpretation.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PartialModelAsLogicInterpretation.xtend index f61c7333..b48d0831 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PartialModelAsLogicInterpretation.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PartialModelAsLogicInterpretation.xtend | |||
@@ -22,12 +22,13 @@ import java.util.List | |||
22 | import java.util.Map | 22 | import java.util.Map |
23 | import java.util.TreeSet | 23 | import java.util.TreeSet |
24 | import org.eclipse.emf.ecore.EObject | 24 | import org.eclipse.emf.ecore.EObject |
25 | import org.eclipse.xtend.lib.annotations.Accessors | ||
25 | import org.eclipse.xtext.xbase.lib.Functions.Function1 | 26 | import org.eclipse.xtext.xbase.lib.Functions.Function1 |
26 | 27 | ||
27 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 28 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
28 | 29 | ||
29 | class PartialModelAsLogicInterpretation implements LogicModelInterpretation{ | 30 | class PartialModelAsLogicInterpretation implements LogicModelInterpretation{ |
30 | val PartialInterpretation partialInterpretation | 31 | @Accessors val PartialInterpretation partialInterpretation |
31 | val Map<EObject, EObject> trace; | 32 | val Map<EObject, EObject> trace; |
32 | val Map<TypeDeclaration,PartialComplexTypeInterpretation> type2Interpretation | 33 | val Map<TypeDeclaration,PartialComplexTypeInterpretation> type2Interpretation |
33 | val Map<RelationDeclaration,PartialRelationInterpretation> relation2Interpretation | 34 | val Map<RelationDeclaration,PartialRelationInterpretation> relation2Interpretation |
@@ -153,14 +154,70 @@ class PartialModelAsLogicInterpretation implements LogicModelInterpretation{ | |||
153 | } | 154 | } |
154 | 155 | ||
155 | override getAllIntegersInStructure() { | 156 | override getAllIntegersInStructure() { |
156 | new TreeSet(this.integerForwardTrace.keySet) | 157 | new TreeSet(allIntegersWithInterpretation.values) |
158 | } | ||
159 | |||
160 | override getAllIntegersWithInterpretation() { | ||
161 | val builder = new HashMap | ||
162 | for (entry : integerForwardTrace.entrySet) { | ||
163 | builder.put(entry.value, entry.key) | ||
164 | } | ||
165 | for (element : partialInterpretation.newElements) { | ||
166 | if (element instanceof IntegerElement) { | ||
167 | builder.put(element, element.value) | ||
168 | } | ||
169 | } | ||
170 | builder | ||
157 | } | 171 | } |
158 | 172 | ||
159 | override getAllRealsInStructure() { | 173 | override getAllRealsInStructure() { |
160 | new TreeSet(this.realForwardTrace.keySet) | 174 | new TreeSet(allRealsWithInterpretation.values) |
175 | } | ||
176 | |||
177 | override getAllRealsWithInterpretation() { | ||
178 | val builder = new HashMap | ||
179 | for (entry : realForwardTrace.entrySet) { | ||
180 | builder.put(entry.value, entry.key) | ||
181 | } | ||
182 | for (element : partialInterpretation.newElements) { | ||
183 | if (element instanceof RealElement) { | ||
184 | builder.put(element, element.value) | ||
185 | } | ||
186 | } | ||
187 | builder | ||
161 | } | 188 | } |
162 | 189 | ||
163 | override getAllStringsInStructure() { | 190 | override getAllStringsInStructure() { |
164 | new TreeSet(this.stringForwardTrace.keySet) | 191 | new TreeSet(allStringsWithInterpretation.values) |
192 | } | ||
193 | |||
194 | override getAllStringsWithInterpretation() { | ||
195 | val builder = new HashMap | ||
196 | for (entry : stringForwardTrace.entrySet) { | ||
197 | builder.put(entry.value, entry.key) | ||
198 | } | ||
199 | for (element : partialInterpretation.newElements) { | ||
200 | if (element instanceof StringElement) { | ||
201 | builder.put(element, element.value) | ||
202 | } | ||
203 | } | ||
204 | builder | ||
205 | } | ||
206 | |||
207 | override getAllBooleansInStructure() { | ||
208 | new TreeSet(allBooleansWithInterpretation.values) | ||
209 | } | ||
210 | |||
211 | override getAllBooleansWithInterpretation() { | ||
212 | val builder = new HashMap | ||
213 | for (entry : booleanForwardTrace.entrySet) { | ||
214 | builder.put(entry.value, entry.key) | ||
215 | } | ||
216 | for (element : partialInterpretation.newElements) { | ||
217 | if (element instanceof BooleanElement) { | ||
218 | builder.put(element, element.value) | ||
219 | } | ||
220 | } | ||
221 | builder | ||
165 | } | 222 | } |
166 | } \ No newline at end of file | 223 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PunishSizeObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PunishSizeObjective.xtend new file mode 100644 index 00000000..bad8e4d1 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PunishSizeObjective.xtend | |||
@@ -0,0 +1,52 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PrimitiveElement | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.AbstractThreeValuedObjective | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold | ||
8 | import org.eclipse.viatra.dse.base.ThreadContext | ||
9 | |||
10 | class PunishSizeObjective extends AbstractThreeValuedObjective { | ||
11 | static val NAME = typeof(PunishSizeObjective).name | ||
12 | |||
13 | new(ObjectiveKind kind, int level) { | ||
14 | super(NAME, kind, ObjectiveThreshold.NO_THRESHOLD, level) | ||
15 | } | ||
16 | |||
17 | override createNew() { | ||
18 | new PunishSizeObjective(kind, level) | ||
19 | } | ||
20 | |||
21 | override init(ThreadContext context) { | ||
22 | // Nothing to initialize. | ||
23 | } | ||
24 | |||
25 | override getRawFitness(ThreadContext threadContext) { | ||
26 | val model = threadContext.model | ||
27 | if (model instanceof PartialInterpretation) { | ||
28 | val size = model.newObjectCount | ||
29 | // println('''size=«size»''') | ||
30 | size as double | ||
31 | } else { | ||
32 | throw new IllegalArgumentException("notifier must be a PartialInterpretation") | ||
33 | } | ||
34 | } | ||
35 | |||
36 | override getLowestPossibleFitness(ThreadContext threadContext) { | ||
37 | getRawFitness(threadContext) | ||
38 | } | ||
39 | |||
40 | override getHighestPossibleFitness(ThreadContext threadContext) { | ||
41 | val model = threadContext.model | ||
42 | if (model instanceof PartialInterpretation) { | ||
43 | (model.newObjectCount + model.maxNewElements) as double | ||
44 | } else { | ||
45 | throw new IllegalArgumentException("notifier must be a PartialInterpretation") | ||
46 | } | ||
47 | } | ||
48 | |||
49 | private def getNewObjectCount(PartialInterpretation interpretation) { | ||
50 | interpretation.newElements.reject[it instanceof PrimitiveElement].size | ||
51 | } | ||
52 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ScopeObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ScopeObjective.xtend index 69efe0d7..b61bd20b 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ScopeObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ScopeObjective.xtend | |||
@@ -23,9 +23,9 @@ class ScopeObjective implements IObjective{ | |||
23 | 23 | ||
24 | override getFitness(ThreadContext context) { | 24 | override getFitness(ThreadContext context) { |
25 | val interpretation = context.model as PartialInterpretation | 25 | val interpretation = context.model as PartialInterpretation |
26 | var res = interpretation.minNewElements.doubleValue | 26 | var res = interpretation.minNewElementsHeuristic.doubleValue |
27 | for(scope : interpretation.scopes) { | 27 | for(scope : interpretation.scopes) { |
28 | res += scope.minNewElements*2 | 28 | res += scope.minNewElementsHeuristic * 2 |
29 | } | 29 | } |
30 | return res | 30 | return res |
31 | } | 31 | } |
@@ -41,4 +41,4 @@ class ScopeObjective implements IObjective{ | |||
41 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 41 | throw new UnsupportedOperationException("TODO: auto-generated method stub") |
42 | } | 42 | } |
43 | override getLevel() { 2 } | 43 | override getLevel() { 2 } |
44 | } \ No newline at end of file | 44 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend new file mode 100644 index 00000000..888eda18 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend | |||
@@ -0,0 +1,82 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import java.util.LinkedHashMap | ||
6 | import java.util.List | ||
7 | import java.util.Map | ||
8 | import org.eclipse.emf.ecore.EObject | ||
9 | import org.eclipse.emf.ecore.util.EcoreUtil | ||
10 | import org.eclipse.viatra.dse.base.ThreadContext | ||
11 | import org.eclipse.xtend.lib.annotations.Accessors | ||
12 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
13 | |||
14 | @FinalFieldsConstructor | ||
15 | class CopiedSolution { | ||
16 | @Accessors val PartialInterpretation partialInterpretations | ||
17 | @Accessors val Map<EObject, EObject> trace | ||
18 | @Accessors val long copierRuntime | ||
19 | @Accessors var boolean current = true | ||
20 | } | ||
21 | |||
22 | /** | ||
23 | * Based on {@link SolutionStore.BestSolutionSaver}. | ||
24 | * | ||
25 | * Will also automatically fill any missing numerical values in the saved solutions | ||
26 | * using the supplied {@link NumericSolver}. | ||
27 | */ | ||
28 | class SolutionCopier { | ||
29 | val copiedSolutions = new LinkedHashMap<Object, CopiedSolution> | ||
30 | |||
31 | @Accessors NumericSolver numericSolver | ||
32 | long startTime = System.nanoTime | ||
33 | @Accessors(PUBLIC_GETTER) long totalCopierRuntime = 0 | ||
34 | |||
35 | def void copySolution(ThreadContext context, Object solutionId) { | ||
36 | val existingCopy = copiedSolutions.get(solutionId) | ||
37 | if (existingCopy === null) { | ||
38 | val copyStart = System.nanoTime | ||
39 | val solution = context.model as PartialInterpretation | ||
40 | val copier = new EcoreUtil.Copier | ||
41 | val copiedPartialInterpretation = copier.copy(solution) as PartialInterpretation | ||
42 | copier.copyReferences | ||
43 | totalCopierRuntime += System.nanoTime - copyStart | ||
44 | val copierRuntime = System.nanoTime - startTime | ||
45 | val copiedSolution = new CopiedSolution(copiedPartialInterpretation, copier, copierRuntime) | ||
46 | //numericSolver?.fillSolutionCopy(copiedSolution.trace) | ||
47 | copiedSolutions.put(solutionId, copiedSolution) | ||
48 | } else { | ||
49 | existingCopy.current = true | ||
50 | } | ||
51 | } | ||
52 | |||
53 | def void markAsObsolete(Object solutionId) { | ||
54 | val copiedSolution = copiedSolutions.get(solutionId) | ||
55 | if (copiedSolution === null) { | ||
56 | throw new IllegalStateException("No solution to mark as obsolete for state code: " + solutionId) | ||
57 | } | ||
58 | copiedSolution.current = false | ||
59 | } | ||
60 | |||
61 | def List<PartialInterpretation> getPartialInterpretations(boolean currentOnly) { | ||
62 | getListOfCopiedSolutions(currentOnly).map[partialInterpretations] | ||
63 | } | ||
64 | |||
65 | def List<Map<EObject, EObject>> getTraces(boolean currentOnly) { | ||
66 | getListOfCopiedSolutions(currentOnly).map[trace] | ||
67 | } | ||
68 | |||
69 | def List<Long> getAllCopierRuntimes(boolean currentOnly) { | ||
70 | getListOfCopiedSolutions(currentOnly).map[copierRuntime] | ||
71 | } | ||
72 | |||
73 | def List<CopiedSolution> getListOfCopiedSolutions(boolean currentOnly) { | ||
74 | val values = copiedSolutions.values | ||
75 | val filteredSolutions = if (currentOnly) { | ||
76 | values.filter[current] | ||
77 | } else { | ||
78 | values | ||
79 | } | ||
80 | ImmutableList.copyOf(filteredSolutions) | ||
81 | } | ||
82 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend index a8b7301e..4bd2c349 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend | |||
@@ -1,14 +1,12 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import java.util.List | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
5 | import java.util.LinkedList | 4 | import java.util.LinkedList |
6 | import org.eclipse.emf.ecore.EObject | 5 | import java.util.List |
7 | import java.util.Map | 6 | import java.util.Map |
7 | import org.eclipse.emf.ecore.EObject | ||
8 | import org.eclipse.emf.ecore.util.EcoreUtil | 8 | import org.eclipse.emf.ecore.util.EcoreUtil |
9 | import org.eclipse.viatra.dse.base.ThreadContext | 9 | import org.eclipse.viatra.dse.base.ThreadContext |
10 | import java.util.TreeMap | ||
11 | import java.util.SortedMap | ||
12 | 10 | ||
13 | class SolutionStoreWithCopy { | 11 | class SolutionStoreWithCopy { |
14 | 12 | ||
@@ -25,7 +23,7 @@ class SolutionStoreWithCopy { | |||
25 | newSolution(context) | 23 | newSolution(context) |
26 | }*/ | 24 | }*/ |
27 | 25 | ||
28 | def newSolution(ThreadContext context) { | 26 | def Map<EObject,EObject> newSolution(ThreadContext context) { |
29 | //print(System.nanoTime-initTime + ";") | 27 | //print(System.nanoTime-initTime + ";") |
30 | val copyStart = System.nanoTime | 28 | val copyStart = System.nanoTime |
31 | val solution = context.model as PartialInterpretation | 29 | val solution = context.model as PartialInterpretation |
@@ -36,6 +34,7 @@ class SolutionStoreWithCopy { | |||
36 | copyTraces.add(copier) | 34 | copyTraces.add(copier) |
37 | runtime += System.nanoTime - copyStart | 35 | runtime += System.nanoTime - copyStart |
38 | solutionTimes.add(System.nanoTime-sartTime) | 36 | solutionTimes.add(System.nanoTime-sartTime) |
37 | return copier | ||
39 | } | 38 | } |
40 | def getSumRuntime() { | 39 | def getSumRuntime() { |
41 | return runtime | 40 | return runtime |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend deleted file mode 100644 index 1e7f18a8..00000000 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.DiversityDescriptor | ||
6 | import java.util.LinkedList | ||
7 | import java.util.List | ||
8 | import org.eclipse.viatra.dse.base.ThreadContext | ||
9 | import java.util.HashSet | ||
10 | import java.util.Set | ||
11 | |||
12 | enum DiversityGranularity { | ||
13 | Nodewise, Graphwise | ||
14 | } | ||
15 | |||
16 | class SolutionStoreWithDiversityDescriptor { | ||
17 | val DiversityDescriptor descriptor | ||
18 | DiversityGranularity granularity | ||
19 | val PartialInterpretation2ImmutableTypeLattice solutionCoder = new PartialInterpretation2ImmutableTypeLattice | ||
20 | val Set<Integer> solutionCodeList = new HashSet | ||
21 | |||
22 | var long runtime | ||
23 | var int allCheck | ||
24 | var int successfulCheck | ||
25 | |||
26 | new(DiversityDescriptor descriptor) { | ||
27 | if(descriptor.ensureDiversity) { | ||
28 | this.descriptor = descriptor | ||
29 | this.granularity = DiversityGranularity::Nodewise | ||
30 | } else { | ||
31 | this.descriptor = null | ||
32 | this.granularity = DiversityGranularity::Nodewise | ||
33 | } | ||
34 | } | ||
35 | |||
36 | def public isActive() { | ||
37 | descriptor!==null | ||
38 | } | ||
39 | |||
40 | def getSumRuntime() { | ||
41 | return runtime | ||
42 | } | ||
43 | def getSuccessRate() { | ||
44 | return successfulCheck as double / allCheck | ||
45 | } | ||
46 | |||
47 | def isDifferent(ThreadContext context) { | ||
48 | if(active) { | ||
49 | val start = System.nanoTime | ||
50 | val model = context.model as PartialInterpretation | ||
51 | var boolean isDifferent | ||
52 | if(this.granularity == DiversityGranularity::Graphwise) { | ||
53 | val code = solutionCoder.createRepresentation(model, | ||
54 | descriptor.range, | ||
55 | descriptor.parallels, | ||
56 | descriptor.maxNumber, | ||
57 | descriptor.relevantTypes, | ||
58 | descriptor.relevantRelations).modelRepresentation.hashCode | ||
59 | |||
60 | isDifferent = !solutionCodeList.contains(code) | ||
61 | } else if(this.granularity == DiversityGranularity::Nodewise){ | ||
62 | val codes = solutionCoder.createRepresentation(model, | ||
63 | descriptor.range, | ||
64 | descriptor.parallels, | ||
65 | descriptor.maxNumber, | ||
66 | descriptor.relevantTypes, | ||
67 | descriptor.relevantRelations).modelRepresentation.keySet.map[hashCode].toList | ||
68 | val differentCodes = codes.filter[!solutionCodeList.contains(it)] | ||
69 | //println(differentCodes.size) | ||
70 | |||
71 | isDifferent = differentCodes.size>=1 | ||
72 | } else { | ||
73 | throw new UnsupportedOperationException('''Unsupported diversity type: «this.granularity»''') | ||
74 | } | ||
75 | |||
76 | runtime += System.nanoTime - start | ||
77 | allCheck++ | ||
78 | if(isDifferent) { successfulCheck++ } | ||
79 | return isDifferent | ||
80 | } else { | ||
81 | allCheck++ | ||
82 | successfulCheck++ | ||
83 | return true | ||
84 | } | ||
85 | } | ||
86 | |||
87 | def canBeDifferent(ThreadContext context) { | ||
88 | return true | ||
89 | } | ||
90 | |||
91 | def newSolution(ThreadContext context) { | ||
92 | if(active) { | ||
93 | val start = System.nanoTime | ||
94 | val model = context.model as PartialInterpretation | ||
95 | if(this.granularity == DiversityGranularity::Graphwise) { | ||
96 | val code = solutionCoder.createRepresentation(model, | ||
97 | descriptor.range, | ||
98 | descriptor.parallels, | ||
99 | descriptor.maxNumber, | ||
100 | descriptor.relevantTypes, | ||
101 | descriptor.relevantRelations).modelRepresentation.hashCode | ||
102 | |||
103 | solutionCodeList += code.hashCode | ||
104 | } else if(this.granularity == DiversityGranularity::Nodewise){ | ||
105 | val codes = solutionCoder.createRepresentation(model, | ||
106 | descriptor.range, | ||
107 | descriptor.parallels, | ||
108 | descriptor.maxNumber, | ||
109 | descriptor.relevantTypes, | ||
110 | descriptor.relevantRelations).modelRepresentation.keySet.map[hashCode].toList | ||
111 | |||
112 | solutionCodeList += codes.map[it.hashCode] | ||
113 | } else { | ||
114 | throw new UnsupportedOperationException('''Unsupported diversity type: «this.granularity»''') | ||
115 | } | ||
116 | |||
117 | runtime += System.nanoTime - start | ||
118 | } | ||
119 | } | ||
120 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend new file mode 100644 index 00000000..8ed3e912 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend | |||
@@ -0,0 +1,27 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import org.eclipse.viatra.dse.base.ThreadContext | ||
4 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint | ||
5 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
6 | |||
7 | @FinalFieldsConstructor | ||
8 | class SurelyViolatedObjectiveGlobalConstraint implements IGlobalConstraint { | ||
9 | val ViatraReasonerSolutionSaver solutionSaver | ||
10 | |||
11 | override init(ThreadContext context) { | ||
12 | // Nothing to initialize. | ||
13 | } | ||
14 | |||
15 | override createNew() { | ||
16 | this | ||
17 | } | ||
18 | |||
19 | override getName() { | ||
20 | class.name | ||
21 | } | ||
22 | |||
23 | override checkGlobalConstraint(ThreadContext context) { | ||
24 | val bestFitness = DseUtils.caclulateBestPossibleFitness(context) | ||
25 | bestFitness.satisifiesHardObjectives && solutionSaver.fitnessMayBeSaved(bestFitness) | ||
26 | } | ||
27 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend index aad9a448..e1582d3b 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend | |||
@@ -1,15 +1,15 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.MultiplicityGoalConstraintCalculator | 3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator |
4 | import java.util.Comparator | 4 | import java.util.Comparator |
5 | import org.eclipse.viatra.dse.base.ThreadContext | 5 | import org.eclipse.viatra.dse.base.ThreadContext |
6 | import org.eclipse.viatra.dse.objectives.IObjective | ||
7 | import org.eclipse.viatra.dse.objectives.Comparators | 6 | import org.eclipse.viatra.dse.objectives.Comparators |
7 | import org.eclipse.viatra.dse.objectives.IObjective | ||
8 | 8 | ||
9 | class UnfinishedMultiplicityObjective implements IObjective { | 9 | class UnfinishedMultiplicityObjective implements IObjective { |
10 | val MultiplicityGoalConstraintCalculator unfinishedMultiplicity; | 10 | val MultiplicityGoalConstraintCalculator unfinishedMultiplicity |
11 | 11 | ||
12 | public new(MultiplicityGoalConstraintCalculator unfinishedMultiplicity) { | 12 | new(MultiplicityGoalConstraintCalculator unfinishedMultiplicity) { |
13 | this.unfinishedMultiplicity = unfinishedMultiplicity | 13 | this.unfinishedMultiplicity = unfinishedMultiplicity |
14 | } | 14 | } |
15 | 15 | ||
@@ -29,9 +29,13 @@ class UnfinishedMultiplicityObjective implements IObjective { | |||
29 | override satisifiesHardObjective(Double fitness) { return fitness <=0.01 } | 29 | override satisifiesHardObjective(Double fitness) { return fitness <=0.01 } |
30 | 30 | ||
31 | override setComparator(Comparator<Double> comparator) { | 31 | override setComparator(Comparator<Double> comparator) { |
32 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 32 | throw new UnsupportedOperationException |
33 | } | 33 | } |
34 | override setLevel(int level) { | 34 | override setLevel(int level) { |
35 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 35 | throw new UnsupportedOperationException |
36 | } | ||
37 | |||
38 | def isContainment() { | ||
39 | return this.unfinishedMultiplicity.containment | ||
36 | } | 40 | } |
37 | } \ No newline at end of file | 41 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend index e0111cf6..1b61ffa5 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend | |||
@@ -1,56 +1,64 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import org.eclipse.viatra.dse.objectives.IObjective | 3 | import java.util.ArrayList |
4 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
5 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
6 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
7 | import java.util.Collection | 4 | import java.util.Collection |
8 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | 5 | import java.util.Comparator |
9 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
10 | import org.eclipse.viatra.dse.base.ThreadContext | ||
11 | import java.util.List | 6 | import java.util.List |
7 | import org.eclipse.viatra.dse.base.ThreadContext | ||
12 | import org.eclipse.viatra.dse.objectives.Comparators | 8 | import org.eclipse.viatra.dse.objectives.Comparators |
13 | import java.util.ArrayList | 9 | import org.eclipse.viatra.dse.objectives.IObjective |
14 | import java.util.Comparator | 10 | import org.eclipse.viatra.query.runtime.api.IPatternMatch |
11 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
12 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
15 | 13 | ||
16 | class UnfinishedWFObjective implements IObjective { | 14 | class UnfinishedWFObjective implements IObjective { |
17 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs | 15 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs |
18 | val List<ViatraQueryMatcher<?>> matchers | 16 | val List<ViatraQueryMatcher<?>> matchers |
19 | 17 | ||
20 | public new(Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs) { | 18 | new( |
19 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs) { | ||
21 | this.unfinishedWFs = unfinishedWFs | 20 | this.unfinishedWFs = unfinishedWFs |
22 | matchers = new ArrayList(unfinishedWFs.size) | 21 | matchers = new ArrayList(unfinishedWFs.size) |
23 | } | 22 | } |
23 | |||
24 | override getName() '''unfinishedWFs''' | 24 | override getName() '''unfinishedWFs''' |
25 | |||
25 | override createNew() { | 26 | override createNew() { |
26 | return new UnfinishedWFObjective(unfinishedWFs) | 27 | return new UnfinishedWFObjective(unfinishedWFs) |
27 | } | 28 | } |
29 | |||
28 | override init(ThreadContext context) { | 30 | override init(ThreadContext context) { |
29 | val engine = context.queryEngine//ViatraQueryEngine.on(new EMFScope(context.model)) | 31 | val engine = context.queryEngine // ViatraQueryEngine.on(new EMFScope(context.model)) |
30 | for(unfinishedWF : unfinishedWFs) { | 32 | for (unfinishedWF : unfinishedWFs) { |
31 | matchers += unfinishedWF.getMatcher(engine) | 33 | matchers += unfinishedWF.getMatcher(engine) |
32 | } | 34 | } |
33 | } | 35 | } |
34 | 36 | ||
35 | override getComparator() { Comparators.LOWER_IS_BETTER } | 37 | override getComparator() { Comparators.LOWER_IS_BETTER } |
38 | |||
36 | override getFitness(ThreadContext context) { | 39 | override getFitness(ThreadContext context) { |
37 | var sumOfMatches = 0 | 40 | var sumOfMatches = 0 |
38 | for(matcher : matchers) { | 41 | for (matcher : matchers) { |
39 | val number = matcher.countMatches | 42 | val number = matcher.countMatches |
40 | //println('''«matcher.patternName» = «number»''') | 43 | // if (number > 0) { |
41 | sumOfMatches+=number | 44 | // println('''«matcher.patternName» = «number»''') |
45 | // } | ||
46 | sumOfMatches += number | ||
42 | } | 47 | } |
43 | return sumOfMatches.doubleValue | 48 | return sumOfMatches.doubleValue |
44 | } | 49 | } |
45 | 50 | ||
46 | override getLevel() { 2 } | 51 | override getLevel() { 2 } |
52 | |||
47 | override isHardObjective() { true } | 53 | override isHardObjective() { true } |
48 | override satisifiesHardObjective(Double fitness) { return fitness <=0.01 } | 54 | |
49 | 55 | override satisifiesHardObjective(Double fitness) { return fitness <= 0.01 } | |
56 | |||
50 | override setComparator(Comparator<Double> comparator) { | 57 | override setComparator(Comparator<Double> comparator) { |
51 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 58 | throw new UnsupportedOperationException() |
52 | } | 59 | } |
60 | |||
53 | override setLevel(int level) { | 61 | override setLevel(int level) { |
54 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 62 | throw new UnsupportedOperationException() |
55 | } | 63 | } |
56 | } \ No newline at end of file | 64 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend new file mode 100644 index 00000000..e00f76ff --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend | |||
@@ -0,0 +1,250 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Bounds | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.DirectionalThresholdObjective | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.IObjectiveBoundsProvider | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold | ||
7 | import java.util.HashMap | ||
8 | import java.util.Map | ||
9 | import org.eclipse.viatra.dse.api.DSEException | ||
10 | import org.eclipse.viatra.dse.api.Solution | ||
11 | import org.eclipse.viatra.dse.api.SolutionTrajectory | ||
12 | import org.eclipse.viatra.dse.base.ThreadContext | ||
13 | import org.eclipse.viatra.dse.objectives.Fitness | ||
14 | import org.eclipse.viatra.dse.objectives.IObjective | ||
15 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper | ||
16 | import org.eclipse.viatra.dse.solutionstore.SolutionStore.ISolutionSaver | ||
17 | import org.eclipse.xtend.lib.annotations.Accessors | ||
18 | |||
19 | /** | ||
20 | * Based on {@link SolutionStore.BestSolutionSaver}. | ||
21 | * | ||
22 | * Will also automatically fill any missing numerical values in the saved solutions | ||
23 | * using the supplied {@link NumericSolver}. | ||
24 | */ | ||
25 | class ViatraReasonerSolutionSaver implements ISolutionSaver, IObjectiveBoundsProvider { | ||
26 | static val TOLERANCE = 1e-10 | ||
27 | |||
28 | @Accessors val SolutionCopier solutionCopier | ||
29 | @Accessors val DiversityChecker diversityChecker | ||
30 | val IObjective[][] leveledExtremalObjectives | ||
31 | val boolean hasExtremalObjectives | ||
32 | val int numberOfRequiredSolutions | ||
33 | val ObjectiveComparatorHelper comparatorHelper | ||
34 | val Map<SolutionTrajectory, Fitness> trajectories = new HashMap | ||
35 | |||
36 | @Accessors var NumericSolver numericSolver | ||
37 | @Accessors var Map<Object, Solution> solutionsCollection | ||
38 | |||
39 | new(IObjective[][] leveledExtremalObjectives, int numberOfRequiredSolutions, DiversityChecker diversityChecker) { | ||
40 | this.diversityChecker = diversityChecker | ||
41 | comparatorHelper = new ObjectiveComparatorHelper(leveledExtremalObjectives) | ||
42 | this.leveledExtremalObjectives = leveledExtremalObjectives | ||
43 | hasExtremalObjectives = leveledExtremalObjectives.exists[!empty] | ||
44 | this.numberOfRequiredSolutions = numberOfRequiredSolutions | ||
45 | this.solutionCopier = new SolutionCopier | ||
46 | } | ||
47 | |||
48 | def setNumericSolver(NumericSolver numericSolver) { | ||
49 | this.numericSolver = numericSolver | ||
50 | solutionCopier.numericSolver = numericSolver | ||
51 | } | ||
52 | |||
53 | override saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
54 | if (hasExtremalObjectives) { | ||
55 | saveBestSolutionOnly(context, id, solutionTrajectory) | ||
56 | } else { | ||
57 | saveAnyDiverseSolution(context, id, solutionTrajectory) | ||
58 | } | ||
59 | } | ||
60 | |||
61 | private def saveBestSolutionOnly(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
62 | val fitness = context.lastFitness | ||
63 | if (!shouldSaveSolution(fitness, context)) { | ||
64 | return false | ||
65 | } | ||
66 | println("Found: " + fitness) | ||
67 | val dominatedTrajectories = newArrayList | ||
68 | for (entry : trajectories.entrySet) { | ||
69 | val isLastFitnessBetter = comparatorHelper.compare(fitness, entry.value) | ||
70 | if (isLastFitnessBetter < 0) { | ||
71 | // Found a trajectory that dominates the current one, no need to save | ||
72 | return false | ||
73 | } | ||
74 | if (isLastFitnessBetter > 0) { | ||
75 | dominatedTrajectories += entry.key | ||
76 | } | ||
77 | } | ||
78 | if (dominatedTrajectories.size == 0 && !needsMoreSolutionsWithSameFitness) { | ||
79 | return false | ||
80 | } | ||
81 | if (!diversityChecker.newSolution(context, id, dominatedTrajectories.map[solution.stateCode])) { | ||
82 | return false | ||
83 | } | ||
84 | // We must save the new trajectory before removing dominated trajectories | ||
85 | // to avoid removing the current solution when it is reachable only via dominated trajectories. | ||
86 | val solutionSaved = basicSaveSolution(context, id, solutionTrajectory, fitness) | ||
87 | for (dominatedTrajectory : dominatedTrajectories) { | ||
88 | trajectories -= dominatedTrajectory | ||
89 | val dominatedSolution = dominatedTrajectory.solution | ||
90 | if (!dominatedSolution.trajectories.remove(dominatedTrajectory)) { | ||
91 | throw new DSEException( | ||
92 | "Dominated solution is not reachable from dominated trajectory. This should never happen!") | ||
93 | } | ||
94 | if (dominatedSolution.trajectories.empty) { | ||
95 | val dominatedSolutionId = dominatedSolution.stateCode | ||
96 | solutionCopier.markAsObsolete(dominatedSolutionId) | ||
97 | solutionsCollection -= dominatedSolutionId | ||
98 | } | ||
99 | } | ||
100 | solutionSaved | ||
101 | } | ||
102 | |||
103 | private def saveAnyDiverseSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
104 | val fitness = context.lastFitness | ||
105 | if (!shouldSaveSolution(fitness, context)) { | ||
106 | return false | ||
107 | } | ||
108 | if (!diversityChecker.newSolution(context, id, emptyList)) { | ||
109 | return false | ||
110 | } | ||
111 | basicSaveSolution(context, id, solutionTrajectory, fitness) | ||
112 | } | ||
113 | |||
114 | private def shouldSaveSolution(Fitness fitness, ThreadContext context) { | ||
115 | fitness.satisifiesHardObjectives && (numericSolver === null || numericSolver.currentSatisfiable) | ||
116 | } | ||
117 | |||
118 | private def basicSaveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory, | ||
119 | Fitness fitness) { | ||
120 | var boolean solutionSaved = false | ||
121 | var dseSolution = solutionsCollection.get(id) | ||
122 | if (dseSolution === null) { | ||
123 | solutionCopier.copySolution(context, id) | ||
124 | dseSolution = new Solution(id, solutionTrajectory) | ||
125 | solutionsCollection.put(id, dseSolution) | ||
126 | solutionSaved = true | ||
127 | } else { | ||
128 | solutionSaved = dseSolution.trajectories.add(solutionTrajectory) | ||
129 | } | ||
130 | if (solutionSaved) { | ||
131 | solutionTrajectory.solution = dseSolution | ||
132 | trajectories.put(solutionTrajectory, fitness) | ||
133 | } | ||
134 | solutionSaved | ||
135 | } | ||
136 | |||
137 | def fitnessMayBeSaved(Fitness fitness) { | ||
138 | if (!hasExtremalObjectives) { | ||
139 | return true | ||
140 | } | ||
141 | var boolean mayDominate | ||
142 | for (existingFitness : trajectories.values) { | ||
143 | val isNewFitnessBetter = comparatorHelper.compare(fitness, existingFitness) | ||
144 | if (isNewFitnessBetter < 0) { | ||
145 | return false | ||
146 | } | ||
147 | if (isNewFitnessBetter > 0) { | ||
148 | mayDominate = true | ||
149 | } | ||
150 | } | ||
151 | mayDominate || needsMoreSolutionsWithSameFitness | ||
152 | } | ||
153 | |||
154 | private def boolean needsMoreSolutionsWithSameFitness() { | ||
155 | if (solutionsCollection === null) { | ||
156 | // The solutions collection will only be initialized upon saving the first solution. | ||
157 | return true | ||
158 | } | ||
159 | solutionsCollection.size < numberOfRequiredSolutions | ||
160 | } | ||
161 | |||
162 | def getTotalCopierRuntime() { | ||
163 | solutionCopier.totalCopierRuntime | ||
164 | } | ||
165 | |||
166 | override computeRequiredBounds(IObjective objective, Bounds bounds) { | ||
167 | if (!hasExtremalObjectives) { | ||
168 | return | ||
169 | } | ||
170 | if (objective instanceof DirectionalThresholdObjective) { | ||
171 | switch (threshold : objective.threshold) { | ||
172 | case ObjectiveThreshold.NO_THRESHOLD: { | ||
173 | // No threshold to set. | ||
174 | } | ||
175 | ObjectiveThreshold.Exclusive: { | ||
176 | switch (kind : objective.kind) { | ||
177 | case HIGHER_IS_BETTER: | ||
178 | bounds.tightenLowerBound(Math.floor(threshold.threshold + 1) as int) | ||
179 | case LOWER_IS_BETTER: | ||
180 | bounds.tightenUpperBound(Math.ceil(threshold.threshold - 1) as int) | ||
181 | default: | ||
182 | throw new IllegalArgumentException("Unknown objective kind" + kind) | ||
183 | } | ||
184 | if (threshold.clampToThreshold) { | ||
185 | return | ||
186 | } | ||
187 | } | ||
188 | ObjectiveThreshold.Inclusive: { | ||
189 | switch (kind : objective.kind) { | ||
190 | case HIGHER_IS_BETTER: | ||
191 | bounds.tightenLowerBound(Math.ceil(threshold.threshold) as int) | ||
192 | case LOWER_IS_BETTER: | ||
193 | bounds.tightenUpperBound(Math.floor(threshold.threshold) as int) | ||
194 | default: | ||
195 | throw new IllegalArgumentException("Unknown objective kind" + kind) | ||
196 | } | ||
197 | if (threshold.clampToThreshold) { | ||
198 | return | ||
199 | } | ||
200 | } | ||
201 | default: | ||
202 | throw new IllegalArgumentException("Unknown threshold: " + threshold) | ||
203 | } | ||
204 | for (level : leveledExtremalObjectives) { | ||
205 | switch (level.size) { | ||
206 | case 0: { | ||
207 | // Nothing to do, wait for the next level. | ||
208 | } | ||
209 | case 1: { | ||
210 | val primaryObjective = level.get(0) | ||
211 | if (primaryObjective != objective) { | ||
212 | // There are no worst-case bounds for secondary objectives. | ||
213 | return | ||
214 | } | ||
215 | } | ||
216 | default: | ||
217 | // There are no worst-case bounds for Pareto front calculation. | ||
218 | return | ||
219 | } | ||
220 | } | ||
221 | val fitnessIterator = trajectories.values.iterator | ||
222 | if (!fitnessIterator.hasNext) { | ||
223 | return | ||
224 | } | ||
225 | val fitness = fitnessIterator.next.get(objective.name) | ||
226 | while (fitnessIterator.hasNext) { | ||
227 | val otherFitness = fitnessIterator.next.get(objective.name) | ||
228 | if (Math.abs(fitness - otherFitness) > TOLERANCE) { | ||
229 | throw new IllegalStateException("Inconsistent fitness: " + objective.name) | ||
230 | } | ||
231 | } | ||
232 | switch (kind : objective.kind) { | ||
233 | case HIGHER_IS_BETTER: | ||
234 | if (needsMoreSolutionsWithSameFitness) { | ||
235 | bounds.tightenLowerBound(Math.floor(fitness) as int) | ||
236 | } else { | ||
237 | bounds.tightenLowerBound(Math.floor(fitness + 1) as int) | ||
238 | } | ||
239 | case LOWER_IS_BETTER: | ||
240 | if (needsMoreSolutionsWithSameFitness) { | ||
241 | bounds.tightenUpperBound(Math.ceil(fitness) as int) | ||
242 | } else { | ||
243 | bounds.tightenUpperBound(Math.ceil(fitness - 1) as int) | ||
244 | } | ||
245 | default: | ||
246 | throw new IllegalArgumentException("Unknown objective kind" + kind) | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend index 5a528a9e..6d772f32 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend | |||
@@ -1,5 +1,6 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import com.google.common.collect.ImmutableList | ||
3 | import java.util.ArrayList | 4 | import java.util.ArrayList |
4 | import java.util.Collection | 5 | import java.util.Collection |
5 | import org.eclipse.viatra.dse.objectives.Comparators | 6 | import org.eclipse.viatra.dse.objectives.Comparators |
@@ -12,25 +13,33 @@ import org.eclipse.viatra.query.runtime.api.IQuerySpecification | |||
12 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | 13 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher |
13 | 14 | ||
14 | class WF2ObjectiveConverter { | 15 | class WF2ObjectiveConverter { |
15 | 16 | static val INVALIDATED_WFS_NAME = "invalidatedWFs" | |
17 | |||
16 | def createCompletenessObjective( | 18 | def createCompletenessObjective( |
17 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF) | 19 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF) { |
18 | { | 20 | new UnfinishedWFObjective(unfinishedWF) |
19 | val res = new ConstraintsObjective('''unfinishedWFs''', | 21 | } |
20 | unfinishedWF.map[ | 22 | |
21 | new QueryConstraint(it.fullyQualifiedName,it,2.0) | 23 | def createInvalidationObjective( |
22 | ].toList | 24 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidatedByWF) { |
25 | createConstraintObjective(INVALIDATED_WFS_NAME, invalidatedByWF) | ||
26 | } | ||
27 | |||
28 | def IGlobalConstraint createInvalidationGlobalConstraint( | ||
29 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidatedByWF) { | ||
30 | new ModelQueriesGlobalConstraint(INVALIDATED_WFS_NAME, new ArrayList(invalidatedByWF)) | ||
31 | } | ||
32 | |||
33 | private def createConstraintObjective(String name, | ||
34 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> queries) { | ||
35 | val res = new ConstraintsObjective( | ||
36 | name, | ||
37 | ImmutableList.copyOf(queries.map [ | ||
38 | new QueryConstraint(it.fullyQualifiedName, it, 1.0) | ||
39 | ]) | ||
23 | ) | 40 | ) |
24 | res.withComparator(Comparators.LOWER_IS_BETTER) | 41 | res.withComparator(Comparators.LOWER_IS_BETTER) |
25 | res.level = 2 | 42 | res.level = 2 |
26 | return res | 43 | res |
27 | } | ||
28 | |||
29 | def IGlobalConstraint createInvalidationObjective( | ||
30 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidatedByWF) | ||
31 | { | ||
32 | return new ModelQueriesGlobalConstraint('''invalidatedWFs''', | ||
33 | new ArrayList(invalidatedByWF) | ||
34 | ) | ||
35 | } | 44 | } |
36 | } \ No newline at end of file | 45 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend new file mode 100644 index 00000000..cd911ab5 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend | |||
@@ -0,0 +1,35 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import org.eclipse.viatra.dse.base.ThreadContext | ||
4 | |||
5 | abstract class AbstractThreeValuedObjective extends DirectionalThresholdObjective implements IThreeValuedObjective { | ||
6 | protected new(String name, ObjectiveKind kind, ObjectiveThreshold threshold, int level) { | ||
7 | super(name, kind, threshold, level) | ||
8 | } | ||
9 | |||
10 | abstract def double getLowestPossibleFitness(ThreadContext threadContext) | ||
11 | |||
12 | abstract def double getHighestPossibleFitness(ThreadContext threadContext) | ||
13 | |||
14 | override getWorstPossibleFitness(ThreadContext threadContext) { | ||
15 | switch (kind) { | ||
16 | case LOWER_IS_BETTER: | ||
17 | getHighestPossibleFitness(threadContext) | ||
18 | case HIGHER_IS_BETTER: | ||
19 | getLowestPossibleFitness(threadContext) | ||
20 | default: | ||
21 | throw new IllegalStateException("Unknown three valued objective kind: " + kind) | ||
22 | } | ||
23 | } | ||
24 | |||
25 | override getBestPossibleFitness(ThreadContext threadContext) { | ||
26 | switch (kind) { | ||
27 | case LOWER_IS_BETTER: | ||
28 | getLowestPossibleFitness(threadContext) | ||
29 | case HIGHER_IS_BETTER: | ||
30 | getHighestPossibleFitness(threadContext) | ||
31 | default: | ||
32 | throw new IllegalStateException("Unknown three valued objective kind: " + kind) | ||
33 | } | ||
34 | } | ||
35 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend new file mode 100644 index 00000000..0aa442f5 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend | |||
@@ -0,0 +1,62 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import java.util.Collection | ||
5 | import org.eclipse.viatra.dse.base.ThreadContext | ||
6 | |||
7 | class CompositeDirectionalThresholdObjective extends DirectionalThresholdObjective { | ||
8 | val Collection<DirectionalThresholdObjective> objectives | ||
9 | |||
10 | new(String name, Collection<DirectionalThresholdObjective> objectives) { | ||
11 | this(name, objectives, getKind(objectives), getThreshold(objectives), getLevel(objectives)) | ||
12 | } | ||
13 | |||
14 | new(String name, DirectionalThresholdObjective... objectives) { | ||
15 | this(name, objectives as Collection<DirectionalThresholdObjective>) | ||
16 | } | ||
17 | |||
18 | protected new(String name, Iterable<DirectionalThresholdObjective> objectives, ObjectiveKind kind, | ||
19 | ObjectiveThreshold threshold, int level) { | ||
20 | super(name, kind, threshold, level) | ||
21 | this.objectives = ImmutableList.copyOf(objectives) | ||
22 | } | ||
23 | |||
24 | override createNew() { | ||
25 | new CompositeDirectionalThresholdObjective(name, objectives.map[createNew as DirectionalThresholdObjective], | ||
26 | kind, threshold, level) | ||
27 | } | ||
28 | |||
29 | override init(ThreadContext context) { | ||
30 | for (objective : objectives) { | ||
31 | objective.init(context) | ||
32 | } | ||
33 | } | ||
34 | |||
35 | override protected getRawFitness(ThreadContext context) { | ||
36 | var double fitness = 0 | ||
37 | for (objective : objectives) { | ||
38 | fitness += objective.getFitness(context) | ||
39 | } | ||
40 | fitness | ||
41 | } | ||
42 | |||
43 | private static def getKind(Collection<DirectionalThresholdObjective> objectives) { | ||
44 | val kinds = objectives.map[kind].toSet | ||
45 | if (kinds.size != 1) { | ||
46 | throw new IllegalArgumentException("Passed objectives must have the same kind") | ||
47 | } | ||
48 | kinds.head | ||
49 | } | ||
50 | |||
51 | private static def getThreshold(Collection<DirectionalThresholdObjective> objectives) { | ||
52 | objectives.map[threshold].reduce[a, b|a.merge(b)] | ||
53 | } | ||
54 | |||
55 | private static def int getLevel(Collection<DirectionalThresholdObjective> objectives) { | ||
56 | val levels = objectives.map[level].toSet | ||
57 | if (levels.size != 1) { | ||
58 | throw new IllegalArgumentException("Passed objectives must have the same level") | ||
59 | } | ||
60 | levels.head | ||
61 | } | ||
62 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostElementMatchers.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostElementMatchers.xtend new file mode 100644 index 00000000..885b14e8 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostElementMatchers.xtend | |||
@@ -0,0 +1,137 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage | ||
6 | import java.util.List | ||
7 | import org.eclipse.emf.ecore.EObject | ||
8 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
9 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
10 | import org.eclipse.xtend.lib.annotations.Data | ||
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
13 | |||
14 | @FunctionalInterface | ||
15 | interface ParameterScopeBound { | ||
16 | def double getUpperBound() | ||
17 | } | ||
18 | |||
19 | @Data | ||
20 | class CostElementMatch { | ||
21 | val IPatternMatch match | ||
22 | val boolean must | ||
23 | |||
24 | def isMulti() { | ||
25 | CostElementMatchers.isMultiMatch(match) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | @Data | ||
30 | class CostElementMatchers { | ||
31 | val ViatraQueryMatcher<? extends IPatternMatch> currentMatcher | ||
32 | val ViatraQueryMatcher<? extends IPatternMatch> mayMatcher | ||
33 | val ViatraQueryMatcher<? extends IPatternMatch> mustMatcher | ||
34 | val List<ParameterScopeBound> parameterScopeBounds | ||
35 | val int weight | ||
36 | |||
37 | def getCurrentNumberOfMatches() { | ||
38 | currentMatcher.countMatches | ||
39 | } | ||
40 | |||
41 | def getMinimumNumberOfMatches() { | ||
42 | mustMatcher.countMatches | ||
43 | } | ||
44 | |||
45 | def getMaximumNumberOfMatches() { | ||
46 | var double sum = 0 | ||
47 | val iterator = mayMatcher.streamAllMatches.iterator | ||
48 | while (iterator.hasNext) { | ||
49 | val match = iterator.next | ||
50 | var double product = 1 | ||
51 | val numberOfParameters = parameterScopeBounds.size | ||
52 | for (var int i = 0; i < numberOfParameters; i++) { | ||
53 | if (isMulti(match.get(i + 2))) { | ||
54 | val scopeBound = parameterScopeBounds.get(i) | ||
55 | product *= scopeBound.upperBound | ||
56 | } | ||
57 | |||
58 | } | ||
59 | sum += product | ||
60 | } | ||
61 | sum | ||
62 | } | ||
63 | |||
64 | def getMatches() { | ||
65 | ImmutableList.copyOf(mayMatcher.streamAllMatches.iterator.map [ match | | ||
66 | new CostElementMatch(match, mustMatcher.isMatch(match)) | ||
67 | ]) | ||
68 | } | ||
69 | |||
70 | def projectMayMatch(IPatternMatch match, int... indices) { | ||
71 | mayMatcher.projectMatch(match, indices) | ||
72 | } | ||
73 | |||
74 | private static def <T extends IPatternMatch> projectMatch(ViatraQueryMatcher<T> matcher, IPatternMatch match, int... indices) { | ||
75 | checkMatch(match) | ||
76 | val n = matcher.specification.parameters.length - 2 | ||
77 | if (indices.length != n) { | ||
78 | throw new IllegalArgumentException("Invalid number of projection indices") | ||
79 | } | ||
80 | val newMatch = matcher.newEmptyMatch | ||
81 | newMatch.set(0, match.get(0)) | ||
82 | newMatch.set(1, match.get(1)) | ||
83 | for (var int i = 0; i < n; i++) { | ||
84 | newMatch.set(i + 2, match.get(indices.get(i))) | ||
85 | } | ||
86 | if (!matcher.hasMatch(newMatch)) { | ||
87 | throw new IllegalArgumentException("Projected match does not exist") | ||
88 | } | ||
89 | return newMatch | ||
90 | } | ||
91 | |||
92 | private static def <T extends IPatternMatch> isMatch(ViatraQueryMatcher<T> matcher, IPatternMatch match) { | ||
93 | val n = matcher.specification.parameters.length | ||
94 | if (n != match.specification.parameters.length) { | ||
95 | throw new IllegalArgumentException("Invalid number of match arguments") | ||
96 | } | ||
97 | val newMatch = matcher.newEmptyMatch | ||
98 | for (var int i = 0; i < n; i++) { | ||
99 | newMatch.set(i, match.get(i)) | ||
100 | } | ||
101 | return matcher.hasMatch(newMatch) | ||
102 | } | ||
103 | |||
104 | static def isMulti(Object o) { | ||
105 | if (o instanceof EObject) { | ||
106 | switch (feature : o.eContainmentFeature) { | ||
107 | case LogicproblemPackage.eINSTANCE.logicProblem_Elements, | ||
108 | case PartialinterpretationPackage.eINSTANCE.partialInterpretation_NewElements: | ||
109 | false | ||
110 | case PartialinterpretationPackage.eINSTANCE.partialInterpretation_OpenWorldElements: | ||
111 | true | ||
112 | default: | ||
113 | throw new IllegalStateException("Unknown containment feature for element: " + feature) | ||
114 | } | ||
115 | } else { | ||
116 | false | ||
117 | } | ||
118 | } | ||
119 | |||
120 | static def isMultiMatch(IPatternMatch match) { | ||
121 | checkMatch(match) | ||
122 | val n = match.specification.parameters.length | ||
123 | for (var int i = 2; i < n; i++) { | ||
124 | if (isMulti(match.get(i))) { | ||
125 | return true | ||
126 | } | ||
127 | } | ||
128 | false | ||
129 | } | ||
130 | |||
131 | private static def checkMatch(IPatternMatch match) { | ||
132 | val n = match.specification.parameters.length | ||
133 | if (n < 2 || !(match.get(0) instanceof LogicProblem) || !(match.get(1) instanceof PartialInterpretation)) { | ||
134 | throw new IllegalArgumentException("Match is not from the partial interpretation") | ||
135 | } | ||
136 | } | ||
137 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostObjectiveHint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostObjectiveHint.xtend new file mode 100644 index 00000000..2434073d --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostObjectiveHint.xtend | |||
@@ -0,0 +1,68 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.BoundSaturationListener | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ExtendedLinearExpressionBuilder | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeExpressionBuilderFactory | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronExtensionOperator | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternGenerator | ||
9 | import java.util.Map | ||
10 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | ||
11 | import org.eclipse.xtend.lib.annotations.Accessors | ||
12 | |||
13 | abstract class CostObjectiveHint implements LinearTypeConstraintHint, BoundSaturationListener { | ||
14 | @Accessors ThreeValuedCostObjective objective | ||
15 | @Accessors IObjectiveBoundsProvider boundsProvider | ||
16 | |||
17 | Integer bestUpper = null | ||
18 | |||
19 | override getAdditionalPatterns(PatternGenerator patternGenerator, Map<String, PQuery> fqnToPQuery) { | ||
20 | '''''' | ||
21 | } | ||
22 | |||
23 | override createConstraintUpdater(LinearTypeExpressionBuilderFactory builderFactory) { | ||
24 | null | ||
25 | } | ||
26 | |||
27 | def isExact() { | ||
28 | false | ||
29 | } | ||
30 | |||
31 | def PolyhedronExtensionOperator createPolyhedronExtensionOperator( | ||
32 | Map<String, CostElementMatchers> costElementMatchers) { | ||
33 | null | ||
34 | } | ||
35 | |||
36 | def setObjective(ThreeValuedCostObjective objective) { | ||
37 | if (this.objective !== null) { | ||
38 | throw new IllegalStateException("Objective was already set") | ||
39 | } | ||
40 | this.objective = objective | ||
41 | } | ||
42 | |||
43 | def setBoundsProvider(IObjectiveBoundsProvider boundsProvider) { | ||
44 | if (this.boundsProvider !== null) { | ||
45 | throw new IllegalStateException("Objective bounds provider was already set") | ||
46 | } | ||
47 | this.boundsProvider = boundsProvider | ||
48 | } | ||
49 | |||
50 | protected def buildWithBounds(ExtendedLinearExpressionBuilder builder) { | ||
51 | val bounds = builder.build(this) | ||
52 | if (objective !== null && boundsProvider !== null) { | ||
53 | boundsProvider.computeRequiredBounds(objective, bounds) | ||
54 | } | ||
55 | if (exact && bestUpper !== null) { | ||
56 | bounds.tightenLowerBound(bestUpper) | ||
57 | } | ||
58 | bounds | ||
59 | } | ||
60 | |||
61 | override boundsSaturated(Integer lower, Integer upper) { | ||
62 | if (upper !== null && (bestUpper === null || bestUpper < upper)) { | ||
63 | bestUpper = upper | ||
64 | } | ||
65 | objective?.boundsSaturated(lower, upper) | ||
66 | } | ||
67 | |||
68 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend new file mode 100644 index 00000000..376e3d1a --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend | |||
@@ -0,0 +1,164 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import java.util.Comparator | ||
4 | import org.eclipse.viatra.dse.base.ThreadContext | ||
5 | import org.eclipse.viatra.dse.objectives.IObjective | ||
6 | import org.eclipse.xtend.lib.annotations.Accessors | ||
7 | import org.eclipse.xtend.lib.annotations.Data | ||
8 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
9 | |||
10 | abstract class ObjectiveThreshold { | ||
11 | public static val NO_THRESHOLD = new ObjectiveThreshold { | ||
12 | override isHard() { | ||
13 | false | ||
14 | } | ||
15 | |||
16 | override satisfiesThreshold(double cost, Comparator<Double> comparator) { | ||
17 | true | ||
18 | } | ||
19 | |||
20 | override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) { | ||
21 | cost | ||
22 | } | ||
23 | |||
24 | override ObjectiveThreshold merge(ObjectiveThreshold other) { | ||
25 | if (other == NO_THRESHOLD) { | ||
26 | NO_THRESHOLD | ||
27 | } else { | ||
28 | throw new IllegalArgumentException("Merged thresholds must have the same type") | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | |||
33 | private new() { | ||
34 | } | ||
35 | |||
36 | def boolean isHard() { | ||
37 | true | ||
38 | } | ||
39 | |||
40 | def boolean satisfiesThreshold(double cost, ObjectiveKind kind) { | ||
41 | satisfiesThreshold(cost, kind.comparator) | ||
42 | } | ||
43 | |||
44 | def boolean satisfiesThreshold(double cost, Comparator<Double> comparator) | ||
45 | |||
46 | def double postProcessCost(double cost, ObjectiveKind kind) { | ||
47 | if (satisfiesThreshold(cost, kind)) { | ||
48 | postProcessSatisfactoryCost(cost, kind) | ||
49 | } else { | ||
50 | cost | ||
51 | } | ||
52 | } | ||
53 | |||
54 | protected def double postProcessSatisfactoryCost(double cost, ObjectiveKind kind) | ||
55 | |||
56 | def ObjectiveThreshold merge(ObjectiveThreshold other) | ||
57 | |||
58 | @Data | ||
59 | static class Exclusive extends ObjectiveThreshold { | ||
60 | static val EPSILON = 0.1 | ||
61 | |||
62 | val double threshold | ||
63 | val boolean clampToThreshold | ||
64 | |||
65 | @FinalFieldsConstructor | ||
66 | new() { | ||
67 | } | ||
68 | |||
69 | new(double threshold) { | ||
70 | this(threshold, true) | ||
71 | } | ||
72 | |||
73 | override satisfiesThreshold(double cost, Comparator<Double> comparator) { | ||
74 | comparator.compare(threshold, cost) < 0 | ||
75 | } | ||
76 | |||
77 | override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) { | ||
78 | if (clampToThreshold) { | ||
79 | threshold + Math.signum(kind.satisfiedValue) * EPSILON | ||
80 | } else { | ||
81 | cost | ||
82 | } | ||
83 | } | ||
84 | |||
85 | override ObjectiveThreshold merge(ObjectiveThreshold other) { | ||
86 | if (other instanceof Exclusive) { | ||
87 | new Exclusive(threshold + other.threshold) | ||
88 | } else { | ||
89 | throw new IllegalArgumentException("Merged thresholds must have the same type") | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
94 | @Data | ||
95 | static class Inclusive extends ObjectiveThreshold { | ||
96 | val double threshold | ||
97 | val boolean clampToThreshold | ||
98 | |||
99 | @FinalFieldsConstructor | ||
100 | new() { | ||
101 | } | ||
102 | |||
103 | new(double threshold) { | ||
104 | this(threshold, true) | ||
105 | } | ||
106 | |||
107 | override satisfiesThreshold(double cost, Comparator<Double> comparator) { | ||
108 | comparator.compare(threshold, cost) <= 0 | ||
109 | } | ||
110 | |||
111 | override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) { | ||
112 | if (clampToThreshold) { | ||
113 | threshold | ||
114 | } else { | ||
115 | cost | ||
116 | } | ||
117 | } | ||
118 | |||
119 | override ObjectiveThreshold merge(ObjectiveThreshold other) { | ||
120 | if (other instanceof Inclusive) { | ||
121 | new Inclusive(threshold + other.threshold) | ||
122 | } else { | ||
123 | throw new IllegalArgumentException("Merged thresholds must have the same type") | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | abstract class DirectionalThresholdObjective implements IObjective { | ||
130 | @Accessors val String name | ||
131 | @Accessors ObjectiveKind kind | ||
132 | @Accessors ObjectiveThreshold threshold | ||
133 | @Accessors int level | ||
134 | |||
135 | protected new(String name, ObjectiveKind kind, ObjectiveThreshold threshold, int level) { | ||
136 | this.name = name | ||
137 | this.kind = kind | ||
138 | this.threshold = threshold | ||
139 | this.level = level | ||
140 | } | ||
141 | |||
142 | override isHardObjective() { | ||
143 | threshold.hard | ||
144 | } | ||
145 | |||
146 | override satisifiesHardObjective(Double fitness) { | ||
147 | threshold.satisfiesThreshold(fitness, comparator) | ||
148 | } | ||
149 | |||
150 | override getComparator() { | ||
151 | kind.comparator | ||
152 | } | ||
153 | |||
154 | override setComparator(Comparator<Double> comparator) { | ||
155 | kind = ObjectiveKind.fromComparator(comparator) | ||
156 | } | ||
157 | |||
158 | override getFitness(ThreadContext context) { | ||
159 | val fitness = getRawFitness(context) | ||
160 | threshold.postProcessCost(fitness, kind) | ||
161 | } | ||
162 | |||
163 | protected def double getRawFitness(ThreadContext context) | ||
164 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IObjectiveBoundsProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IObjectiveBoundsProvider.xtend new file mode 100644 index 00000000..3c4d36a5 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IObjectiveBoundsProvider.xtend | |||
@@ -0,0 +1,8 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Bounds | ||
4 | import org.eclipse.viatra.dse.objectives.IObjective | ||
5 | |||
6 | interface IObjectiveBoundsProvider { | ||
7 | def void computeRequiredBounds(IObjective objective, Bounds bounds) | ||
8 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend new file mode 100644 index 00000000..4a870a3e --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend | |||
@@ -0,0 +1,10 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import org.eclipse.viatra.dse.base.ThreadContext | ||
4 | import org.eclipse.viatra.dse.objectives.IObjective | ||
5 | |||
6 | interface IThreeValuedObjective extends IObjective { | ||
7 | def Double getWorstPossibleFitness(ThreadContext threadContext) | ||
8 | |||
9 | def Double getBestPossibleFitness(ThreadContext threadContext) | ||
10 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend new file mode 100644 index 00000000..a0c6a2c1 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend | |||
@@ -0,0 +1,52 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import java.util.Collection | ||
5 | import org.eclipse.viatra.dse.base.ThreadContext | ||
6 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
7 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
8 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
9 | import org.eclipse.xtend.lib.annotations.Data | ||
10 | |||
11 | @Data | ||
12 | class MatchCostElement { | ||
13 | val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification | ||
14 | val double weight | ||
15 | } | ||
16 | |||
17 | class MatchCostObjective extends DirectionalThresholdObjective { | ||
18 | val Collection<MatchCostElement> costElements | ||
19 | Collection<CostElementMatcher> matchers | ||
20 | |||
21 | new(String name, Collection<MatchCostElement> costElements, ObjectiveKind kind, ObjectiveThreshold threshold, | ||
22 | int level) { | ||
23 | super(name, kind, threshold, level) | ||
24 | this.costElements = costElements | ||
25 | } | ||
26 | |||
27 | override createNew() { | ||
28 | new MatchCostObjective(name, costElements, kind, threshold, level) | ||
29 | } | ||
30 | |||
31 | override init(ThreadContext context) { | ||
32 | val queryEngine = context.queryEngine | ||
33 | matchers = ImmutableList.copyOf(costElements.map [ | ||
34 | val matcher = querySpecification.getMatcher(queryEngine) | ||
35 | new CostElementMatcher(matcher, weight) | ||
36 | ]) | ||
37 | } | ||
38 | |||
39 | override protected getRawFitness(ThreadContext context) { | ||
40 | var double cost = 0 | ||
41 | for (it : matchers) { | ||
42 | cost += weight * matcher.countMatches | ||
43 | } | ||
44 | cost | ||
45 | } | ||
46 | |||
47 | @Data | ||
48 | private static class CostElementMatcher { | ||
49 | val ViatraQueryMatcher<? extends IPatternMatch> matcher | ||
50 | val double weight | ||
51 | } | ||
52 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java new file mode 100644 index 00000000..cbbaaafd --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java | |||
@@ -0,0 +1,60 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization; | ||
2 | |||
3 | import java.util.Comparator; | ||
4 | |||
5 | import org.eclipse.viatra.dse.objectives.Comparators; | ||
6 | |||
7 | public enum ObjectiveKind { | ||
8 | LOWER_IS_BETTER { | ||
9 | |||
10 | @Override | ||
11 | public Comparator<Double> getComparator() { | ||
12 | return Comparators.LOWER_IS_BETTER; | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public double getInvalidValue() { | ||
17 | return Double.POSITIVE_INFINITY; | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public double getSatisfiedValue() { | ||
22 | return Double.NEGATIVE_INFINITY; | ||
23 | } | ||
24 | |||
25 | }, | ||
26 | HIGHER_IS_BETTER { | ||
27 | |||
28 | @Override | ||
29 | public Comparator<Double> getComparator() { | ||
30 | return Comparators.HIGHER_IS_BETTER; | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public double getInvalidValue() { | ||
35 | return Double.NEGATIVE_INFINITY; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public double getSatisfiedValue() { | ||
40 | return Double.POSITIVE_INFINITY; | ||
41 | } | ||
42 | |||
43 | }; | ||
44 | |||
45 | public abstract Comparator<Double> getComparator(); | ||
46 | |||
47 | public abstract double getInvalidValue(); | ||
48 | |||
49 | public abstract double getSatisfiedValue(); | ||
50 | |||
51 | public static ObjectiveKind fromComparator(Comparator<Double> comparator) { | ||
52 | if (Comparators.LOWER_IS_BETTER.equals(comparator)) { | ||
53 | return ObjectiveKind.LOWER_IS_BETTER; | ||
54 | } else if (Comparators.HIGHER_IS_BETTER.equals(comparator)) { | ||
55 | return ObjectiveKind.HIGHER_IS_BETTER; | ||
56 | } else { | ||
57 | throw new IllegalStateException("Only LOWER_IS_BETTER and HIGHER_IS_BETTER comparators are supported."); | ||
58 | } | ||
59 | } | ||
60 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend new file mode 100644 index 00000000..d355f5be --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend | |||
@@ -0,0 +1,48 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import org.eclipse.viatra.dse.base.ThreadContext | ||
4 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
5 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
6 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
7 | |||
8 | class QueryBasedObjective extends DirectionalThresholdObjective { | ||
9 | val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification | ||
10 | ViatraQueryMatcher<? extends IPatternMatch> matcher | ||
11 | |||
12 | new(IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification, | ||
13 | ObjectiveKind kind, ObjectiveThreshold threshold, int level) { | ||
14 | super(querySpecification.simpleName + " objective", kind, threshold, level) | ||
15 | if (querySpecification.parameters.size != 1) { | ||
16 | throw new IllegalArgumentException("Objective query must have a single parameter") | ||
17 | } | ||
18 | this.querySpecification = querySpecification | ||
19 | } | ||
20 | |||
21 | override createNew() { | ||
22 | new QueryBasedObjective(querySpecification, kind, threshold, level) | ||
23 | } | ||
24 | |||
25 | override init(ThreadContext context) { | ||
26 | matcher = querySpecification.getMatcher(context.queryEngine) | ||
27 | } | ||
28 | |||
29 | override protected getRawFitness(ThreadContext context) { | ||
30 | val iterator = matcher.allMatches.iterator | ||
31 | if (!iterator.hasNext) { | ||
32 | return invalidValue | ||
33 | } | ||
34 | val value = iterator.next.get(0) | ||
35 | if (iterator.hasNext) { | ||
36 | throw new IllegalStateException("Multiple matches for objective query") | ||
37 | } | ||
38 | if (value instanceof Number) { | ||
39 | value.doubleValue | ||
40 | } else { | ||
41 | throw new IllegalStateException("Objective value is not an instance of Number") | ||
42 | } | ||
43 | } | ||
44 | |||
45 | private def getInvalidValue() { | ||
46 | kind.invalidValue | ||
47 | } | ||
48 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend new file mode 100644 index 00000000..9b1a7e9f --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend | |||
@@ -0,0 +1,80 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.BoundSaturationListener | ||
4 | import java.util.Map | ||
5 | import org.eclipse.viatra.dse.base.ThreadContext | ||
6 | import org.eclipse.xtend.lib.annotations.Accessors | ||
7 | |||
8 | class ThreeValuedCostObjective extends AbstractThreeValuedObjective implements BoundSaturationListener { | ||
9 | @Accessors val Map<String, CostElementMatchers> matchers | ||
10 | double lowerBoundHint = Double.NEGATIVE_INFINITY | ||
11 | double upperBoundHint = Double.POSITIVE_INFINITY | ||
12 | |||
13 | new(String name, Map<String, CostElementMatchers> matchers, ObjectiveKind kind, ObjectiveThreshold threshold, | ||
14 | int level) { | ||
15 | super(name, kind, threshold, level) | ||
16 | this.matchers = matchers | ||
17 | } | ||
18 | |||
19 | override createNew() { | ||
20 | // new ThreeValuedCostObjective(name, matchers, kind, threshold, level) | ||
21 | throw new UnsupportedOperationException("ThreeValuedCostObjective can only be used from a single thread") | ||
22 | } | ||
23 | |||
24 | override init(ThreadContext context) { | ||
25 | } | ||
26 | |||
27 | override getRawFitness(ThreadContext context) { | ||
28 | var double cost = 0 | ||
29 | for (matcher : matchers.values) { | ||
30 | cost += matcher.weight * matcher.currentNumberOfMatches | ||
31 | } | ||
32 | cost | ||
33 | } | ||
34 | |||
35 | override getLowestPossibleFitness(ThreadContext threadContext) { | ||
36 | var double cost = 0 | ||
37 | for (matcher : matchers.values) { | ||
38 | if (matcher.weight >= 0) { | ||
39 | cost += matcher.weight * matcher.minimumNumberOfMatches | ||
40 | } else { | ||
41 | cost += matcher.weight * matcher.maximumNumberOfMatches | ||
42 | } | ||
43 | } | ||
44 | val boundWithHint = Math.max(lowerBoundHint, cost) | ||
45 | if (boundWithHint > upperBoundHint) { | ||
46 | throw new IllegalStateException("Inconsistent cost bounds") | ||
47 | } | ||
48 | boundWithHint | ||
49 | } | ||
50 | |||
51 | override getHighestPossibleFitness(ThreadContext threadContext) { | ||
52 | var double cost = 0 | ||
53 | for (matcher : matchers.values) { | ||
54 | if (matcher.weight <= 0) { | ||
55 | cost += matcher.weight * matcher.minimumNumberOfMatches | ||
56 | } else { | ||
57 | cost += matcher.weight * matcher.maximumNumberOfMatches | ||
58 | } | ||
59 | } | ||
60 | val boundWithHint = Math.min(upperBoundHint, cost) | ||
61 | if (boundWithHint < lowerBoundHint) { | ||
62 | throw new IllegalStateException("Inconsistent cost bounds") | ||
63 | } | ||
64 | boundWithHint | ||
65 | } | ||
66 | |||
67 | override boundsSaturated(Integer lower, Integer upper) { | ||
68 | lowerBoundHint = if (lower === null) { | ||
69 | Double.NEGATIVE_INFINITY | ||
70 | } else { | ||
71 | lower | ||
72 | } | ||
73 | upperBoundHint = if (upper === null) { | ||
74 | Double.POSITIVE_INFINITY | ||
75 | } else { | ||
76 | upper | ||
77 | } | ||
78 | println('''Bounds saturated: «lower»..«upper»''') | ||
79 | } | ||
80 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjectiveProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjectiveProvider.xtend new file mode 100644 index 00000000..c2750acd --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjectiveProvider.xtend | |||
@@ -0,0 +1,205 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import com.google.common.collect.ImmutableMap | ||
5 | import com.google.common.collect.Lists | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference | ||
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | ||
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference | ||
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference | ||
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference | ||
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration | ||
13 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeReference | ||
14 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronExtensionOperator | ||
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries | ||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialBooleanInterpretation | ||
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialIntegerInterpretation | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRealInterpretation | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialStringInterpretation | ||
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope | ||
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.CostObjectiveConfiguration | ||
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.CostObjectiveElementConfiguration | ||
26 | import java.util.Collection | ||
27 | import java.util.Map | ||
28 | import org.eclipse.viatra.dse.objectives.IObjective | ||
29 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
30 | import org.eclipse.xtend.lib.annotations.Data | ||
31 | |||
32 | @Data | ||
33 | class ThreeValuedCostObjectiveProviderResult { | ||
34 | val Collection<IObjective> objectives | ||
35 | val Collection<CostObjectiveHint> hints | ||
36 | val Collection<PolyhedronExtensionOperator> extensionOperators | ||
37 | val IObjective[][] leveledExtremalObjectives | ||
38 | val boolean optimizationProblem | ||
39 | } | ||
40 | |||
41 | class ThreeValuedCostObjectiveProvider { | ||
42 | static val COST_OBJECTIVE_LEVEL = 3 | ||
43 | |||
44 | val ViatraQueryEngine queryEngine | ||
45 | val Map<String, ModalPatternQueries> modalRelationQueries | ||
46 | val Map<String, Relation> qualifiedNameToRelationMap | ||
47 | val ParameterScopeBound defaultBounds | ||
48 | val ParameterScopeBound booleanBounds | ||
49 | val ParameterScopeBound integerBounds | ||
50 | val ParameterScopeBound realBounds | ||
51 | val ParameterScopeBound stringBounds | ||
52 | val Map<TypeDeclaration, ParameterScopeBound> typeDeclarationToBoundsMap | ||
53 | |||
54 | new(ViatraQueryEngine queryEngine, PartialInterpretation interpretation, | ||
55 | Map<String, ModalPatternQueries> modalRelationQueries) { | ||
56 | this.queryEngine = queryEngine | ||
57 | this.modalRelationQueries = modalRelationQueries | ||
58 | qualifiedNameToRelationMap = ImmutableMap.copyOf( | ||
59 | interpretation.problem.annotations.filter(TransfomedViatraQuery). | ||
60 | toMap([patternFullyQualifiedName], [target])) | ||
61 | defaultBounds = new PartialInterpretationBasedParameterScopeBound(interpretation) | ||
62 | var ParameterScopeBound booleanBounds = null | ||
63 | var ParameterScopeBound integerBounds = null | ||
64 | var ParameterScopeBound realBounds = null | ||
65 | var ParameterScopeBound stringBounds = null | ||
66 | val typeDeclarationToBoundsMapBuilder = ImmutableMap.builder | ||
67 | for (scope : interpretation.scopes) { | ||
68 | val bounds = new ScopeBasedParameterScopeBound(scope) | ||
69 | switch (typeInterpretation : scope.targetTypeInterpretation) { | ||
70 | PartialBooleanInterpretation: | ||
71 | if (booleanBounds === null) { | ||
72 | booleanBounds = bounds | ||
73 | } else { | ||
74 | throw new IllegalStateException("Duplicate partial boolean interpretation") | ||
75 | } | ||
76 | PartialIntegerInterpretation: | ||
77 | if (integerBounds === null) { | ||
78 | integerBounds = bounds | ||
79 | } else { | ||
80 | throw new IllegalStateException("Duplicate partial integer interpretation") | ||
81 | } | ||
82 | PartialRealInterpretation: | ||
83 | if (realBounds === null) { | ||
84 | realBounds = bounds | ||
85 | } else { | ||
86 | throw new IllegalStateException("Duplicate partial real interpretation") | ||
87 | } | ||
88 | PartialStringInterpretation: | ||
89 | if (stringBounds === null) { | ||
90 | stringBounds = bounds | ||
91 | } else { | ||
92 | throw new IllegalStateException("Duplicate partial string interpretation") | ||
93 | } | ||
94 | PartialComplexTypeInterpretation: | ||
95 | typeDeclarationToBoundsMapBuilder.put(typeInterpretation.interpretationOf, bounds) | ||
96 | } | ||
97 | } | ||
98 | this.booleanBounds = booleanBounds ?: defaultBounds | ||
99 | this.integerBounds = integerBounds ?: defaultBounds | ||
100 | this.realBounds = realBounds ?: defaultBounds | ||
101 | this.stringBounds = stringBounds ?: defaultBounds | ||
102 | typeDeclarationToBoundsMap = typeDeclarationToBoundsMapBuilder.build | ||
103 | } | ||
104 | |||
105 | def getCostObjectives(Collection<CostObjectiveConfiguration> costObjectives) { | ||
106 | val objectives = ImmutableList.<IObjective>builder | ||
107 | val hints = ImmutableList.<CostObjectiveHint>builder | ||
108 | val extensionOperators = ImmutableList.<PolyhedronExtensionOperator>builder | ||
109 | val extremalObjectives = Lists.newArrayListWithExpectedSize(costObjectives.size) | ||
110 | for (entry : costObjectives.indexed) { | ||
111 | val objectiveName = '''costObjective«entry.key»''' | ||
112 | val objectiveConfig = entry.value | ||
113 | val costObjective = transformCostObjective(objectiveConfig, objectiveName) | ||
114 | objectives.add(costObjective) | ||
115 | if (objectiveConfig.findExtremum) { | ||
116 | extremalObjectives += costObjective | ||
117 | } | ||
118 | val hint = objectiveConfig.hint | ||
119 | if (hint !== null) { | ||
120 | hints.add(hint) | ||
121 | hint.objective = costObjective | ||
122 | val extensionOperator = hint.createPolyhedronExtensionOperator(costObjective.matchers) | ||
123 | if (extensionOperator !== null) { | ||
124 | extensionOperators.add(extensionOperator) | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | new ThreeValuedCostObjectiveProviderResult( | ||
129 | objectives.build, | ||
130 | hints.build, | ||
131 | extensionOperators.build, | ||
132 | newArrayList(extremalObjectives), | ||
133 | !extremalObjectives.empty | ||
134 | ) | ||
135 | } | ||
136 | |||
137 | private def transformCostObjective(CostObjectiveConfiguration configuration, String name) { | ||
138 | val costElements = ImmutableMap.copyOf(configuration.elements.toMap([patternQualifiedName], [ | ||
139 | transformCostElement | ||
140 | ])) | ||
141 | new ThreeValuedCostObjective(name, costElements, configuration.kind, configuration.threshold, | ||
142 | COST_OBJECTIVE_LEVEL) | ||
143 | } | ||
144 | |||
145 | private def transformCostElement(CostObjectiveElementConfiguration elementConfig) { | ||
146 | val relationName = elementConfig.patternQualifiedName | ||
147 | val modalQueries = modalRelationQueries.get(relationName) | ||
148 | if (modalQueries === null) { | ||
149 | throw new IllegalArgumentException("Unknown relation queries: " + relationName) | ||
150 | } | ||
151 | val relation = qualifiedNameToRelationMap.get(relationName) | ||
152 | if (relation === null) { | ||
153 | throw new IllegalArgumentException("Unknown transformed relation: " + relationName) | ||
154 | } | ||
155 | val parameterBounds = ImmutableList.copyOf(relation.parameters.map[parameterBound]) | ||
156 | new CostElementMatchers( | ||
157 | queryEngine.getMatcher(modalQueries.currentQuery), | ||
158 | queryEngine.getMatcher(modalQueries.mayQuery), | ||
159 | queryEngine.getMatcher(modalQueries.mustQuery), | ||
160 | parameterBounds, | ||
161 | elementConfig.weight | ||
162 | ) | ||
163 | } | ||
164 | |||
165 | private def getParameterBound(TypeReference typeReference) { | ||
166 | switch (typeReference) { | ||
167 | BoolTypeReference: booleanBounds | ||
168 | IntTypeReference: integerBounds | ||
169 | RealTypeReference: realBounds | ||
170 | StringTypeReference: stringBounds | ||
171 | ComplexTypeReference: typeDeclarationToBoundsMap.getOrDefault(typeReference.referred, defaultBounds) | ||
172 | } | ||
173 | } | ||
174 | |||
175 | private static abstract class AbstractParameterScopeBound implements ParameterScopeBound { | ||
176 | override getUpperBound() { | ||
177 | val rawValue = rawUpperBound | ||
178 | if (rawValue < 0) { | ||
179 | Double.POSITIVE_INFINITY | ||
180 | } else { | ||
181 | rawValue | ||
182 | } | ||
183 | } | ||
184 | |||
185 | protected def int getRawUpperBound() | ||
186 | } | ||
187 | |||
188 | @Data | ||
189 | private static class ScopeBasedParameterScopeBound extends AbstractParameterScopeBound { | ||
190 | val Scope scope | ||
191 | |||
192 | override protected getRawUpperBound() { | ||
193 | scope.maxNewElements | ||
194 | } | ||
195 | } | ||
196 | |||
197 | @Data | ||
198 | private static class PartialInterpretationBasedParameterScopeBound extends AbstractParameterScopeBound { | ||
199 | val PartialInterpretation interpretation | ||
200 | |||
201 | override protected getRawUpperBound() { | ||
202 | interpretation.maxNewElements | ||
203 | } | ||
204 | } | ||
205 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/META-INF/MANIFEST.MF b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/META-INF/MANIFEST.MF index 2abc6d50..754ff55d 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/META-INF/MANIFEST.MF +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/META-INF/MANIFEST.MF | |||
@@ -27,8 +27,7 @@ Require-Bundle: com.google.guava, | |||
27 | org.apache.batik.util.gui;bundle-version="[1.6.0,1.6.1]", | 27 | org.apache.batik.util.gui;bundle-version="[1.6.0,1.6.1]", |
28 | org.apache.xerces;bundle-version="2.9.0", | 28 | org.apache.xerces;bundle-version="2.9.0", |
29 | org.w3c.dom.svg;bundle-version="1.1.0", | 29 | org.w3c.dom.svg;bundle-version="1.1.0", |
30 | org.w3c.css.sac;bundle-version="1.3.1", | 30 | org.w3c.css.sac;bundle-version="1.3.1" |
31 | org.eclipse.m2e.maven.runtime.slf4j.simple;bundle-version="1.10.0" | ||
32 | Import-Package: com.eclipsesource.v8;version="4.6.0", | 31 | Import-Package: com.eclipsesource.v8;version="4.6.0", |
33 | com.eclipsesource.v8.debug;version="4.6.0", | 32 | com.eclipsesource.v8.debug;version="4.6.0", |
34 | com.eclipsesource.v8.utils;version="4.6.0", | 33 | com.eclipsesource.v8.utils;version="4.6.0", |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/GraphvizV8WithMemory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/GraphvizV8WithMemory.xtend new file mode 100644 index 00000000..542289d4 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/GraphvizV8WithMemory.xtend | |||
@@ -0,0 +1,16 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.visualisation.pi2graphviz | ||
2 | |||
3 | import guru.nidi.graphviz.engine.GraphvizV8Engine | ||
4 | |||
5 | class GraphvizV8WithMemory extends GraphvizV8Engine { | ||
6 | val int memory; | ||
7 | new(int memory) { | ||
8 | this.memory = memory | ||
9 | //this. | ||
10 | } | ||
11 | |||
12 | override protected jsInitEnv() { | ||
13 | println super.jsInitEnv() | ||
14 | super.jsInitEnv() | ||
15 | } | ||
16 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/PartialInterpretation2Graphviz.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/PartialInterpretation2Graphviz.xtend index 78326207..cd0b3e00 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/PartialInterpretation2Graphviz.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/PartialInterpretation2Graphviz.xtend | |||
@@ -30,6 +30,7 @@ import org.eclipse.xtext.xbase.lib.Functions.Function1 | |||
30 | import static guru.nidi.graphviz.model.Factory.* | 30 | import static guru.nidi.graphviz.model.Factory.* |
31 | 31 | ||
32 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 32 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
33 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PrimitiveElement | ||
33 | 34 | ||
34 | class GraphvizVisualiser implements PartialInterpretationVisualiser { | 35 | class GraphvizVisualiser implements PartialInterpretationVisualiser { |
35 | 36 | ||
@@ -106,10 +107,10 @@ class GraphvizVisualiser implements PartialInterpretationVisualiser { | |||
106 | // elements2Node.put(newElement,image) | 107 | // elements2Node.put(newElement,image) |
107 | // } | 108 | // } |
108 | 109 | ||
109 | partialInterpretation.newElements.filter(BooleanElement).drawDataTypes([it.value.toString],elements2Node,elements2ID) | 110 | //partialInterpretation.newElements.filter(BooleanElement).drawDataTypes([it.value.toString],elements2Node,elements2ID) |
110 | partialInterpretation.newElements.filter(IntegerElement).drawDataTypes([it.value.toString],elements2Node,elements2ID) | 111 | //partialInterpretation.newElements.filter(IntegerElement).drawDataTypes([it.value.toString],elements2Node,elements2ID) |
111 | partialInterpretation.newElements.filter(StringElement).drawDataTypes(['''"«it.value.toString»"'''],elements2Node,elements2ID) | 112 | //partialInterpretation.newElements.filter(StringElement).drawDataTypes(['''"«it.value.toString»"'''],elements2Node,elements2ID) |
112 | partialInterpretation.newElements.filter(RealElement).drawDataTypes([it.value.toString],elements2Node,elements2ID) | 113 | //partialInterpretation.newElements.filter(RealElement).drawDataTypes([it.value.toString],elements2Node,elements2ID) |
113 | 114 | ||
114 | // Drawing the edges | 115 | // Drawing the edges |
115 | val edges = new HashMap | 116 | val edges = new HashMap |
@@ -135,35 +136,51 @@ class GraphvizVisualiser implements PartialInterpretationVisualiser { | |||
135 | return new GraphvizVisualisation(graph) | 136 | return new GraphvizVisualisation(graph) |
136 | } | 137 | } |
137 | 138 | ||
138 | def protected <T extends DefinedElement> void drawDataTypes(Iterable<T> collection, Function1<T,String> namer, HashMap<DefinedElement, Node> elements2Node, HashMap<DefinedElement, String> elements2ID) { | 139 | // def protected <T extends DefinedElement> void drawDataTypes(Iterable<T> collection, Function1<T,String> namer, HashMap<DefinedElement, Node> elements2Node, HashMap<DefinedElement, String> elements2ID) { |
139 | for(booleanElementIndex: 0..<collection.size) { | 140 | // for(booleanElementIndex: 0..<collection.size) { |
140 | val newElement = collection.get(booleanElementIndex) | 141 | // val newElement = collection.get(booleanElementIndex) |
141 | val id = namer.apply(newElement) | 142 | // val name = namer.apply(newElement) |
142 | val image = drawElement(newElement,id,false,emptySet,emptySet) | 143 | // val image = drawElement(newElement,name,newElement.lookup(elements2ID),false,emptySet,emptySet) |
143 | elements2ID.put(newElement,id) | 144 | // elements2Node.put(newElement,image) |
144 | elements2Node.put(newElement,image) | 145 | // } |
145 | } | 146 | // } |
146 | } | ||
147 | 147 | ||
148 | def protected drawElement(DefinedElement element, String ID, boolean old, Set<Type> mustTypes, Set<Type> mayTypes) { | 148 | def protected drawElement(DefinedElement element, String ID, boolean old, Set<Type> mustTypes, Set<Type> mayTypes) { |
149 | var tableStyle = ''' CELLSPACING="0" BORDER="2" CELLBORDER="0" CELLPADDING="1" STYLE="ROUNDED"''' | 149 | var tableStyle = ''' CELLSPACING="0" BORDER="2" CELLBORDER="0" CELLPADDING="1" STYLE="ROUNDED"''' |
150 | if(typeColoringStyle==TypeColoringStyle::AVERAGE) { | 150 | if(typeColoringStyle==TypeColoringStyle::AVERAGE) { |
151 | tableStyle += ''' BGCOLOR="#«typePredicateColor(mustTypes).toBackgroundColorString»"''' | 151 | tableStyle += ''' BGCOLOR="#«typePredicateColor(mustTypes).toBackgroundColorString»"''' |
152 | } | 152 | } |
153 | val mainLabel = if(element.name !== null) { | 153 | val mainLabel = if(element instanceof PrimitiveElement) { |
154 | if(element.isValueSet) { | ||
155 | if(element instanceof BooleanElement) { element.value.toString } | ||
156 | else if(element instanceof IntegerElement) { element.value.toString } | ||
157 | else if(element instanceof RealElement) { element.value.toString } | ||
158 | else if(element instanceof StringElement) { "\""+element.value.toString+"\"" } | ||
159 | } else { | ||
160 | "?" | ||
161 | } | ||
162 | }else if(element.name !== null) { | ||
154 | val parts = element.name.split("\\s+") | 163 | val parts = element.name.split("\\s+") |
155 | textWithSubSup(parts.getOrNull(0),parts.getOrNull(1),parts.getOrNull(2),null) | 164 | textWithSubSup(parts.getOrNull(0),parts.getOrNull(1),parts.getOrNull(2),null) |
156 | } else { | 165 | } else { |
157 | val parts = ID.split("\\s+") | 166 | val parts = ID.split("\\s+") |
158 | textWithSubSup(parts.get(0),parts.get(1),parts.getOrNull(2),null) | 167 | textWithSubSup(parts.getOrNull(0),parts.getOrNull(1),parts.getOrNull(2),null) |
159 | } | 168 | } |
160 | val label = Label.html( | 169 | val hasNoCompexType = (mustTypes.empty) && (mayTypes.empty) |
170 | |||
171 | val label = if(hasNoCompexType) { | ||
172 | Label.html( | ||
173 | '''<TABLE«tableStyle»>'''+ | ||
174 | '''<TR><TD COLSPAN="2"> «mainLabel» </TD></TR>'''+ | ||
175 | '''</TABLE>''') | ||
176 | } else { | ||
177 | Label.html( | ||
161 | '''<TABLE«tableStyle»>'''+ | 178 | '''<TABLE«tableStyle»>'''+ |
162 | '''<TR><TD COLSPAN="2" BORDER="2" SIDES="B">«mainLabel»</TD></TR>'''+ | 179 | '''<TR><TD COLSPAN="2" BORDER="2" SIDES="B">«mainLabel»</TD></TR>'''+ |
163 | '''«FOR mustTypeName : mustTypes.map[it.name].sort»«typePredicateDescription(mustTypeName,true)»«ENDFOR»'''+ | 180 | '''«FOR mustTypeName : mustTypes.map[it.name].sort»«typePredicateDescription(mustTypeName,true)»«ENDFOR»'''+ |
164 | '''«FOR mayTypeName : mayTypes.map[it.name].sort»«typePredicateDescription(mayTypeName,false)»«ENDFOR»'''+ | 181 | '''«FOR mayTypeName : mayTypes.map[it.name].sort»«typePredicateDescription(mayTypeName,false)»«ENDFOR»'''+ |
165 | '''</TABLE>''') | 182 | '''</TABLE>''') |
166 | 183 | } | |
167 | val node = node(ID).with(label).with( | 184 | val node = node(ID).with(label).with( |
168 | Shape.NONE | 185 | Shape.NONE |
169 | //, | 186 | //, |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/VisualisationQueque.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/VisualisationQueque.xtend index b067ba7d..6f003f80 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/VisualisationQueque.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.visualisation/src/hu/bme/mit/inf/dslreasoner/visualisation/pi2graphviz/VisualisationQueque.xtend | |||
@@ -3,15 +3,15 @@ package hu.bme.mit.inf.dslreasoner.visualisation.pi2graphviz | |||
3 | import guru.nidi.graphviz.engine.Format | 3 | import guru.nidi.graphviz.engine.Format |
4 | import guru.nidi.graphviz.engine.Graphviz | 4 | import guru.nidi.graphviz.engine.Graphviz |
5 | import guru.nidi.graphviz.engine.GraphvizEngine | 5 | import guru.nidi.graphviz.engine.GraphvizEngine |
6 | import guru.nidi.graphviz.engine.GraphvizV8Engine | ||
7 | import guru.nidi.graphviz.model.Graph | 6 | import guru.nidi.graphviz.model.Graph |
8 | import java.io.File | 7 | import java.io.File |
9 | import java.io.IOException | 8 | import java.io.IOException |
10 | import java.util.concurrent.BlockingQueue | 9 | import java.util.concurrent.BlockingQueue |
11 | import java.util.concurrent.CompletableFuture | 10 | import java.util.concurrent.CompletableFuture |
12 | import java.util.concurrent.LinkedBlockingQueue | 11 | import java.util.concurrent.LinkedBlockingQueue |
13 | import org.eclipse.xtend.lib.annotations.Data | ||
14 | import java.util.function.Consumer | 12 | import java.util.function.Consumer |
13 | import org.eclipse.xtend.lib.annotations.Data | ||
14 | import guru.nidi.graphviz.engine.GraphvizV8Engine | ||
15 | 15 | ||
16 | class VisualisationQueque { | 16 | class VisualisationQueque { |
17 | val BlockingQueue<VisualisationQueueEntry> taskQueue = new LinkedBlockingQueue | 17 | val BlockingQueue<VisualisationQueueEntry> taskQueue = new LinkedBlockingQueue |
@@ -45,7 +45,7 @@ class VisualisationQueque { | |||
45 | } else { | 45 | } else { |
46 | runnerThread = new Thread(new Runnable() { | 46 | runnerThread = new Thread(new Runnable() { |
47 | override run() { | 47 | override run() { |
48 | val engine = new GraphvizV8Engine() | 48 | val engine = new GraphvizV8Engine |
49 | val nullConsumer = new Consumer<GraphvizEngine>() { | 49 | val nullConsumer = new Consumer<GraphvizEngine>() { |
50 | override accept(GraphvizEngine t) {} | 50 | override accept(GraphvizEngine t) {} |
51 | } | 51 | } |
@@ -69,7 +69,7 @@ class VisualisationQueque { | |||
69 | private def execute(GraphvizEngine engine, Graph document, File targetFile, Format format) { | 69 | private def execute(GraphvizEngine engine, Graph document, File targetFile, Format format) { |
70 | Graphviz.useEngine(engine); | 70 | Graphviz.useEngine(engine); |
71 | try { | 71 | try { |
72 | Graphviz.fromGraph(document).render(format).toFile(targetFile) | 72 | Graphviz.fromGraph(document).totalMemory(536870912).render(format).toFile(targetFile) |
73 | return null | 73 | return null |
74 | } catch(IOException e){ | 74 | } catch(IOException e){ |
75 | return e.message | 75 | return e.message |
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.classpath b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.classpath new file mode 100644 index 00000000..ed0eb24c --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.classpath | |||
@@ -0,0 +1,7 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <classpath> | ||
3 | <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> | ||
4 | <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> | ||
5 | <classpathentry kind="src" path="src/"/> | ||
6 | <classpathentry kind="output" path="bin"/> | ||
7 | </classpath> | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.project b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.project new file mode 100644 index 00000000..aa414f43 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.project | |||
@@ -0,0 +1,28 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <projectDescription> | ||
3 | <name>org.eclipse.viatra.dse</name> | ||
4 | <comment></comment> | ||
5 | <projects> | ||
6 | </projects> | ||
7 | <buildSpec> | ||
8 | <buildCommand> | ||
9 | <name>org.eclipse.jdt.core.javabuilder</name> | ||
10 | <arguments> | ||
11 | </arguments> | ||
12 | </buildCommand> | ||
13 | <buildCommand> | ||
14 | <name>org.eclipse.pde.ManifestBuilder</name> | ||
15 | <arguments> | ||
16 | </arguments> | ||
17 | </buildCommand> | ||
18 | <buildCommand> | ||
19 | <name>org.eclipse.pde.SchemaBuilder</name> | ||
20 | <arguments> | ||
21 | </arguments> | ||
22 | </buildCommand> | ||
23 | </buildSpec> | ||
24 | <natures> | ||
25 | <nature>org.eclipse.pde.PluginNature</nature> | ||
26 | <nature>org.eclipse.jdt.core.javanature</nature> | ||
27 | </natures> | ||
28 | </projectDescription> | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.settings/org.eclipse.jdt.core.prefs b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..9f6ece88 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/.settings/org.eclipse.jdt.core.prefs | |||
@@ -0,0 +1,8 @@ | |||
1 | eclipse.preferences.version=1 | ||
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled | ||
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 | ||
4 | org.eclipse.jdt.core.compiler.compliance=1.8 | ||
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error | ||
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error | ||
7 | org.eclipse.jdt.core.compiler.release=disabled | ||
8 | org.eclipse.jdt.core.compiler.source=1.8 | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/MANIFEST.MF b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/MANIFEST.MF new file mode 100644 index 00000000..fabef844 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/MANIFEST.MF | |||
@@ -0,0 +1,387 @@ | |||
1 | Manifest-Version: 1.0 | ||
2 | Automatic-Module-Name: org.eclipse.viatra.dse | ||
3 | Bundle-SymbolicName: org.eclipse.viatra.dse;singleton:=true | ||
4 | Require-Bundle: org.eclipse.viatra.query.runtime;bundle-version="[2.4. | ||
5 | 0,2.5.0)";visibility:=reexport,org.eclipse.viatra.transformation.evm; | ||
6 | bundle-version="[2.4.0,2.5.0)";visibility:=reexport,org.eclipse.emf.e | ||
7 | core,org.eclipse.emf.ecore.xmi;bundle-version="2.7.0",org.eclipse.emf | ||
8 | .edit,org.eclipse.viatra.transformation.runtime.emf;bundle-version="[ | ||
9 | 2.4.0,2.5.0)";visibility:=reexport | ||
10 | Bundle-ManifestVersion: 2 | ||
11 | Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | ||
12 | Bundle-ActivationPolicy: lazy | ||
13 | Eclipse-SourceReferences: scm:git:git://git.eclipse.org/gitroot/viatra | ||
14 | /org.eclipse.viatra.git;path="dse/plugins/org.eclipse.viatra.dse";com | ||
15 | mitId=2a7314b6b21df594743fa017d18ae62da85c73fa | ||
16 | Bundle-Vendor: Eclipse VIATRA Project | ||
17 | Import-Package: com.google.common.base;version="27.1.0",com.google.com | ||
18 | mon.collect;version="27.1.0",com.google.common.util.concurrent;versio | ||
19 | n="27.1.0",org.apache.log4j;version="1.2.15" | ||
20 | Export-Package: org.eclipse.viatra.dse.api,org.eclipse.viatra.dse.api. | ||
21 | strategy.impl,org.eclipse.viatra.dse.api.strategy.interfaces,org.ecli | ||
22 | pse.viatra.dse.base,org.eclipse.viatra.dse.designspace.api,org.eclips | ||
23 | e.viatra.dse.multithreading,org.eclipse.viatra.dse.objectives,org.ecl | ||
24 | ipse.viatra.dse.objectives.impl,org.eclipse.viatra.dse.solutionstore, | ||
25 | org.eclipse.viatra.dse.statecode,org.eclipse.viatra.dse.statecoding,o | ||
26 | rg.eclipse.viatra.dse.statecoding.simple,org.eclipse.viatra.dse.util, | ||
27 | org.eclipse.viatra.dse.visualizer | ||
28 | SCM-Revision: 2a7314b6b21df594743fa017d18ae62da85c73fa | ||
29 | Bundle-Name: VIATRA-DSE framework Base (Incubation) | ||
30 | Bundle-Version: 0.24.0.202005060951 | ||
31 | Build-Jdk-Spec: 1.8 | ||
32 | Created-By: Maven Archiver 3.5.0 | ||
33 | |||
34 | Name: org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObje | ||
35 | ctive.class | ||
36 | SHA-256-Digest: nEIutogP27RZKAUo9eH/DshkhyOF8voUnj4BC/pkhYU= | ||
37 | |||
38 | Name: org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder$1.cla | ||
39 | ss | ||
40 | SHA-256-Digest: t7KG11FngBrFGTPHJuEaP5BvpPqRYMDq8qKuQyccRWQ= | ||
41 | |||
42 | Name: org/eclipse/viatra/dse/base/ThreadContext.class | ||
43 | SHA-256-Digest: 0Z+RpFCBKvn1+SVJSLpRbEpoMATPujvvfqGsBr99mBI= | ||
44 | |||
45 | Name: org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstra | ||
46 | int.class | ||
47 | SHA-256-Digest: 3qw4e1RY7TqpTKHRngBjCRWfJmMmu+DiUnKHO0yXVA4= | ||
48 | |||
49 | Name: org/eclipse/viatra/dse/objectives/IObjective.class | ||
50 | SHA-256-Digest: io0MQDhFysUXcHYcPUZENsy/xLn98SE65b2RbJ7QttM= | ||
51 | |||
52 | Name: org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.class | ||
53 | SHA-256-Digest: yOvisOPQT9D/tuLV5fLonIoDpqi8bSRbPVjtLtv4UKo= | ||
54 | |||
55 | Name: org/eclipse/viatra/dse/base/ExplorerThread.class | ||
56 | SHA-256-Digest: N4tY8yMnFoKGoMyS0RdRtqpGIh6ucbvvAxnf/YPr/xk= | ||
57 | |||
58 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$BestSolutionS | ||
59 | aver.class | ||
60 | SHA-256-Digest: yZkg5ntRMOsrKEgo7kkAaK5J8h11Ng8tzH4QXsLRhsM= | ||
61 | |||
62 | Name: org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy$Sh | ||
63 | aredData.class | ||
64 | SHA-256-Digest: 2jBwT4lfAUh7LDDmpi3JuzyjcWhVeb+53PPB5ZKlGx4= | ||
65 | |||
66 | Name: org/eclipse/viatra/dse/base/DseIdPoolHelper$IGetRuleExecutions.c | ||
67 | lass | ||
68 | SHA-256-Digest: s7Pr9OPNF5baYmoZlOTWl6keA+b1TVxV8zxBXMGewrM= | ||
69 | |||
70 | Name: org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.cl | ||
71 | ass | ||
72 | SHA-256-Digest: 0R8ENAT9UA3BCsveA38VjvR4k+Um3i1fFlQB85inLZY= | ||
73 | |||
74 | Name: org/eclipse/viatra/dse/api/DesignSpaceExplorer.class | ||
75 | SHA-256-Digest: JCDN006fVS56ROn6cV7Ssdl4CN+xtbdiWjVfDkkgRDM= | ||
76 | |||
77 | Name: org/eclipse/viatra/dse/util/EMFHelper$ENamedElementComparator.cl | ||
78 | ass | ||
79 | SHA-256-Digest: J8o5TEdYpuU/6q1qTw3lUIHaE4pEH/EpDUvuTNWusVA= | ||
80 | |||
81 | Name: org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap$EObj | ||
82 | ectComparator.class | ||
83 | SHA-256-Digest: iwLJSS2Ip9WvN2lC8gfg+ys5Cp+P7ZSpGP6QF5lKYKQ= | ||
84 | |||
85 | Name: org/eclipse/viatra/dse/api/DesignSpaceExplorer$DseLoggingLevel.c | ||
86 | lass | ||
87 | SHA-256-Digest: z3h4wzaSMGzPvV4KL6ilStnLdT/mVCNNp7C/AwfQhqk= | ||
88 | |||
89 | Name: org/eclipse/viatra/dse/multithreading/DSEThreadPool.class | ||
90 | SHA-256-Digest: XoKcmDnafPfiyQ0LemN0ni31T+aY+lXp/Q8p157kj/g= | ||
91 | |||
92 | Name: org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.clas | ||
93 | s | ||
94 | SHA-256-Digest: SGlKz9PbynZwkmaJ1rpE0kVUOHl7vl7GOscNFoNEHLg= | ||
95 | |||
96 | Name: org/eclipse/viatra/dse/base/GlobalContext.class | ||
97 | SHA-256-Digest: dLn/Iu9JVDaaKK21VeFAMDXGaJWROEJCWJjULwMzNik= | ||
98 | |||
99 | Name: org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.cla | ||
100 | ss | ||
101 | SHA-256-Digest: L0yK9bhku/F8MX/NyKoBuydeMbMgZir8N0BRcFzHnKs= | ||
102 | |||
103 | Name: org/eclipse/viatra/dse/statecode/IStateCoderFactory.class | ||
104 | SHA-256-Digest: 1GsfU5aBQs1ieo3dblcXFZ07oq9QzWr1NZLppgSdCOM= | ||
105 | |||
106 | Name: org/eclipse/viatra/dse/base/DesignSpaceManager$1.class | ||
107 | SHA-256-Digest: /suIApW5KeZ7OifoR8SRPc3gU+2B8/ZnWInhdpAOTd8= | ||
108 | |||
109 | Name: org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.cla | ||
110 | ss | ||
111 | SHA-256-Digest: vML6AN6aCbn/cKeccmvzRAai47jZJk0CpYhwFQdhwvI= | ||
112 | |||
113 | Name: org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider | ||
114 | .class | ||
115 | SHA-256-Digest: QFWpXui2nID6PKhTHs/1e0gj9u8NiniES6/G0C/oSzM= | ||
116 | |||
117 | Name: org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy$Bf | ||
118 | sSharedObject.class | ||
119 | SHA-256-Digest: wVno1chuJ8pYpfv5cpB0fjsGbO2s+2OWcaVQgoQb5+k= | ||
120 | |||
121 | Name: org/eclipse/viatra/dse/objectives/TrajectoryFitness.class | ||
122 | SHA-256-Digest: DIEgS7SFg5pWuxvFhRn3f7hBt8+qk1+40w9WpOkoyrc= | ||
123 | |||
124 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$1.class | ||
125 | SHA-256-Digest: V5AAqo4/81KOegdl1Wl8jIBrH57y4TdYrj+wOzV2vdM= | ||
126 | |||
127 | Name: org/eclipse/viatra/dse/api/Solution.class | ||
128 | SHA-256-Digest: U71jRd/R8tarIiHM+dETwXiwwPcmXO5m82bDUp/Mduo= | ||
129 | |||
130 | Name: org/eclipse/viatra/dse/util/EMFHelper$EmfHelperException.class | ||
131 | SHA-256-Digest: +OCT0+wqq9XGCze/qDE8hh3zprFMBAnkR7H1J7k/Htk= | ||
132 | |||
133 | Name: org/eclipse/viatra/dse/base/DseEvmRuleBase.class | ||
134 | SHA-256-Digest: iRILqfjFCMPd020YX8dMyRaNlUGfEUTd4N3gnqQRtDo= | ||
135 | |||
136 | Name: org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjecti | ||
137 | ve.class | ||
138 | SHA-256-Digest: wXSfFPucpZyh72nGKuKn83N63Orl75XUM9SkzKfFBi4= | ||
139 | |||
140 | Name: org/eclipse/viatra/dse/api/DSETransformationRule.class | ||
141 | SHA-256-Digest: 01Ngrz/qbLR6j/4z9NxvtD2jHQAHMl698POXw8BSpPY= | ||
142 | |||
143 | Name: org/eclipse/viatra/dse/objectives/impl/ModelQueryType.class | ||
144 | SHA-256-Digest: SS0yM7NbAU0U4KoA4Tzy4gXKZ2IZaszyaqbtSN4GE74= | ||
145 | |||
146 | Name: org/eclipse/viatra/dse/base/DseConflictResolver.class | ||
147 | SHA-256-Digest: kLquKehufJSc2fJoUgztO62ucr1UUqfLQpyiFrY8BJc= | ||
148 | |||
149 | Name: org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.class | ||
150 | SHA-256-Digest: 7tog5/ud60nPTYwPT6HHpHBDeutpFl2KLKXt8GnM3U8= | ||
151 | |||
152 | Name: org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.class | ||
153 | SHA-256-Digest: cbpeCy8w558CbnhljT2TKalNqWBpKlIsMppr6hWDRpw= | ||
154 | |||
155 | Name: org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.class | ||
156 | SHA-256-Digest: mXYUokn/RePXJXnfL7O3AZjvwqFkwiLZ0IipQGgdp0A= | ||
157 | |||
158 | Name: org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.cla | ||
159 | ss | ||
160 | SHA-256-Digest: ef+0X9EnYYjpPiRNmjXrElCCaPekh+Wh6yimRTpp15E= | ||
161 | |||
162 | Name: org/eclipse/viatra/dse/objectives/impl/CompositeObjective.class | ||
163 | SHA-256-Digest: SJiO5Oina3I760xBUDGc4qYp1WrcSG6Yh0+8hQKf69U= | ||
164 | |||
165 | Name: org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.clas | ||
166 | s | ||
167 | SHA-256-Digest: +uKjMIfQvBlKY9djJoP5Wd/EBKMkbrdk7shGdZ0rS2M= | ||
168 | |||
169 | Name: org/eclipse/viatra/dse/api/Objectives.class | ||
170 | SHA-256-Digest: pNQDcSeUV3oOM7aCgscjJwdyysQrMSZCyLhrSWLMUrI= | ||
171 | |||
172 | Name: org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.c | ||
173 | lass | ||
174 | SHA-256-Digest: nf/uvPeNaC8Nu9SPhk+sgvSheB/kh+GqsXXHbm7qer0= | ||
175 | |||
176 | Name: org/eclipse/viatra/dse/api/DSEException.class | ||
177 | SHA-256-Digest: MCUPB2tBDK01enENQDJ+qONxtl+WQyZaJf87iU+NFyU= | ||
178 | |||
179 | Name: org/eclipse/viatra/dse/base/SingletonSetConflictResolver.class | ||
180 | SHA-256-Digest: bd4gh7UG91EkNSE0JrpAKbHDxv6HYhL7YEq7PZZkRjo= | ||
181 | |||
182 | Name: org/eclipse/viatra/dse/statecoding/IObjectsProvider.class | ||
183 | SHA-256-Digest: SIcYuklHbTwYjV+gvS1B77Z0CR/2bannTSL77/qm/Gs= | ||
184 | |||
185 | Name: org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFact | ||
186 | ory.class | ||
187 | SHA-256-Digest: F12xo+nr94L4B1m1w2xmtA7t1TzGin5pFSEqkBmYxC0= | ||
188 | |||
189 | Name: org/eclipse/viatra/dse/api/SolutionTrajectory.class | ||
190 | SHA-256-Digest: uFjxXsF4khsOwgCsmRPMZbSayZ4qTDtwPGxDBH2lG74= | ||
191 | |||
192 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$SimpleSolutio | ||
193 | nSaver.class | ||
194 | SHA-256-Digest: 12aDZULU6fhdXx8a/BvCQwXW7RZfEmIPFueU7GOpBB0= | ||
195 | |||
196 | Name: org/eclipse/viatra/dse/util/Hasher.class | ||
197 | SHA-256-Digest: 0nFBMPZ6/YudYlnE/l8XiECkWIHBRvkdyi9WUCIaN4c= | ||
198 | |||
199 | Name: org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.class | ||
200 | SHA-256-Digest: Ig8utojCZoNY8V37gbZVVJFOX8NZiu2tPsnAIkS1BaU= | ||
201 | |||
202 | Name: org/eclipse/viatra/dse/objectives/IGlobalConstraint.class | ||
203 | SHA-256-Digest: UvJwqLRVvv444GgELIu/tUGs4eV8cf/Anqh6horECP8= | ||
204 | |||
205 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore.class | ||
206 | SHA-256-Digest: V9OJ/9GqLq9cBToiBzapjyCs3mDuk4PkeduT5YpiTwE= | ||
207 | |||
208 | Name: org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.class | ||
209 | SHA-256-Digest: Ra8i2f1YiRldwF06QotRoHkhKJLyGMYJnS6Lco1ldTM= | ||
210 | |||
211 | Name: org/eclipse/viatra/dse/objectives/impl/BaseObjective.class | ||
212 | SHA-256-Digest: DH8BIQo1OvBt5oEtS4sqsjtGOhlD1Nwz2yv7gdW3/hA= | ||
213 | |||
214 | Name: org/eclipse/viatra/dse/api/DesignSpaceExplorer$1.class | ||
215 | SHA-256-Digest: 1AccsshxVCMI2GPkioO7lQtS9JwPx17YrPTSjTZfqBQ= | ||
216 | |||
217 | Name: org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.clas | ||
218 | s | ||
219 | SHA-256-Digest: +eesnPuyvrf4xQOslHAFlNIyd4K9scCn8f6qprCxKzs= | ||
220 | |||
221 | Name: org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.c | ||
222 | lass | ||
223 | SHA-256-Digest: /+Dkno94lswrX5YEr60iH8szAKDL9hfAe2ZZ/amSe20= | ||
224 | |||
225 | Name: org/eclipse/viatra/dse/base/IDseStrategyContext.class | ||
226 | SHA-256-Digest: ACDjZwH6zo71KF8hXuAvC7NWmGPDv9lJ06U/iAptwEw= | ||
227 | |||
228 | Name: org/eclipse/viatra/dse/statecode/IStateCoder.class | ||
229 | SHA-256-Digest: L+foclr4t9XV4ltc7aDor4Ngf135J+UvTpTxCcegz9M= | ||
230 | |||
231 | Name: org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardOb | ||
232 | jective.class | ||
233 | SHA-256-Digest: KB8QybGLqya7vrKCMnwRdCOaJ/URoTIeR1NVYDNiOB4= | ||
234 | |||
235 | Name: org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardO | ||
236 | bjective.class | ||
237 | SHA-256-Digest: TzG4kskc7rM96sfpJc6YsSNF7PyE48NJLkUpkkwqsiI= | ||
238 | |||
239 | Name: org/eclipse/viatra/dse/base/DesignSpaceManager.class | ||
240 | SHA-256-Digest: WlF2FWYiBFQNAW2PsPpPorz64wQBWssTC/73maFotD8= | ||
241 | |||
242 | Name: org/eclipse/viatra/dse/visualizer/IExploreEventHandler.class | ||
243 | SHA-256-Digest: ZJwhUYNU+L1B88hsbfdIejJVUwhnvBjJSDHugw+RFh0= | ||
244 | |||
245 | Name: META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.pro | ||
246 | perties | ||
247 | SHA-256-Digest: 0JWWPFaIUkYh4BehmajscXzAloPgjeIs0iZSPFC/g1g= | ||
248 | |||
249 | Name: org/eclipse/viatra/dse/statecoding/StatecodingDependency.class | ||
250 | SHA-256-Digest: AeHJlVqUAUsjBlYumYq/e/WEBNbtlvCk00SG9rHPO88= | ||
251 | |||
252 | Name: org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.class | ||
253 | SHA-256-Digest: K5feGvnijYpwPJCOvR4m7ChtC7wX7LhLaau5/SBnFek= | ||
254 | |||
255 | Name: org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.class | ||
256 | SHA-256-Digest: gF2AAXk6xxQIDqdn56Aeifqmj71pBicLO7VJJoB64bY= | ||
257 | |||
258 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$ANumberOfEnou | ||
259 | ghSolutions.class | ||
260 | SHA-256-Digest: qAOxgehQKfKkDSF2W2Gk/cXkDIBsQuN4yJ8Q3eRCnps= | ||
261 | |||
262 | Name: META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.xml | ||
263 | SHA-256-Digest: /LSOqjjd6+fmn3MHbXK9bGr7k+1GKE3kgzaDoJkgCQQ= | ||
264 | |||
265 | Name: org/eclipse/viatra/dse/base/DseIdPoolHelper$IdProvider.class | ||
266 | SHA-256-Digest: VRQcpABZNkp3Lgivy9PUraJf04riM1MOZvY64suvo3M= | ||
267 | |||
268 | Name: org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder$2.cla | ||
269 | ss | ||
270 | SHA-256-Digest: NqiG7/1poRDLI2BbRvr2hfHZqH73hfFxBic+4YKHcCM= | ||
271 | |||
272 | Name: org/eclipse/viatra/dse/base/ThreadContext$GetRuleExecutionsImpl. | ||
273 | class | ||
274 | SHA-256-Digest: HGFHcAmOg3O3se9FT4oE4pWZ8EFdyRkkHkBVJZi+hmM= | ||
275 | |||
276 | Name: org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.class | ||
277 | SHA-256-Digest: qJyc4dMUiLGVoJPrMWQtCI2o2HW5p6Ki5J8Ra6wb/gE= | ||
278 | |||
279 | Name: org/eclipse/viatra/dse/designspace/api/IDesignSpace.class | ||
280 | SHA-256-Digest: IS5IjYyUCvaHWBvUsPFeGFv65W+YTG7u+iRXp/eDIuM= | ||
281 | |||
282 | Name: org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.cl | ||
283 | ass | ||
284 | SHA-256-Digest: UfrnKlXVqN8LWbUPSoA5PDiJOT7cnCA46kIXicC5mg0= | ||
285 | |||
286 | Name: org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy$Traje | ||
287 | ctoryWithFitness.class | ||
288 | SHA-256-Digest: n3K90JLwOOVAXsrkROhn0ZNogaAKVdcUpXBj8RUMI3c= | ||
289 | |||
290 | Name: org/eclipse/viatra/dse/util/EMFHelper$MetaModelElements.class | ||
291 | SHA-256-Digest: FjS8V9JksWMjbV9a1dn04gWFH3fctq9HdWSfbMsV5Ck= | ||
292 | |||
293 | Name: org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactor | ||
294 | y.class | ||
295 | SHA-256-Digest: jcBdVzrTpamZrT0pQZHyJJnooB+DKF6ADVS4RRhZGl4= | ||
296 | |||
297 | Name: org/eclipse/viatra/dse/objectives/Fitness.class | ||
298 | SHA-256-Digest: CJPJnXYS0WMnW4JVW2YO5/vvwKhRkRE7qROa87Ailpg= | ||
299 | |||
300 | Name: org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.cl | ||
301 | ass | ||
302 | SHA-256-Digest: 4odjR0x9jzt7Ed/hw6Q+ydZUrQQggqL8y216Lq60azM= | ||
303 | |||
304 | Name: org/eclipse/viatra/dse/api/Strategies.class | ||
305 | SHA-256-Digest: tURHC++pafgodWMnk4CperJDpZ9m4Do6xHAV37bHUoc= | ||
306 | |||
307 | Name: org/eclipse/viatra/dse/statecoding/StatecodingNode.class | ||
308 | SHA-256-Digest: 2xM/ShgCBqpV9tgQZPBxzTSPgbT7lcp7auQE14dEEqc= | ||
309 | |||
310 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$ISolutionSave | ||
311 | r.class | ||
312 | SHA-256-Digest: nuYmJKeNKfM0a9sAbRpA6Knzqu51hlK011aoAQpTH3Q= | ||
313 | |||
314 | Name: org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.cl | ||
315 | ass | ||
316 | SHA-256-Digest: 9ZxUtKP6+hvWqY9l0b+opdginEK1BoksdLqZ+DYViqI= | ||
317 | |||
318 | Name: org/eclipse/viatra/dse/util/EMFHelper.class | ||
319 | SHA-256-Digest: hpOu0HMuLuiLYUbg0rhdfVG4/ZrlVftoKLmTsRAHW/E= | ||
320 | |||
321 | Name: org/eclipse/viatra/dse/base/DesignSpaceManager$2.class | ||
322 | SHA-256-Digest: x8i8lLzE/UkaQJya1kGbTlJnB/JFNy5607FLESkMQXA= | ||
323 | |||
324 | Name: org/eclipse/viatra/dse/base/ActivationCodesConflictSet.class | ||
325 | SHA-256-Digest: 0G/W2cxiS4R9GEpBWovAIEA4brmQ2sTjqi1F7vgS0/c= | ||
326 | |||
327 | Name: org/eclipse/viatra/dse/api/SolutionTrajectory$1.class | ||
328 | SHA-256-Digest: 7epxs7VJgi7Jmo2pKb22m2OLhOOIu3OHTJrWC8HjEzQ= | ||
329 | |||
330 | Name: org/eclipse/viatra/dse/solutionstore/SolutionStore$IEnoughSoluti | ||
331 | ons.class | ||
332 | SHA-256-Digest: /5Ux9DFOI3UHcG8om2rGzX2k0Yj1lIoeG/tR82P3zpQ= | ||
333 | |||
334 | Name: org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective$Quer | ||
335 | yConstraint.class | ||
336 | SHA-256-Digest: 79pmTnUZbgOHEdGzyj5PIb2eGrd554q3c17LNdbTQxM= | ||
337 | |||
338 | Name: org/eclipse/viatra/dse/objectives/Comparators.class | ||
339 | SHA-256-Digest: V5MzedIHj3KBEBbR4UNAhqmbqB3sHuk183zxMlKhGD4= | ||
340 | |||
341 | Name: org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.class | ||
342 | SHA-256-Digest: VlWdfwyWo39xhvgIF9PedWC+Yv1Q0hYaDBSF7Z+ClSA= | ||
343 | |||
344 | Name: org/eclipse/viatra/dse/base/GlobalContext$ExplorationProcessStat | ||
345 | e.class | ||
346 | SHA-256-Digest: rNnsUlZX7z1yPBoNSfWvoXwKhSAjGUhpBo9CZVJwadw= | ||
347 | |||
348 | Name: org/eclipse/viatra/dse/base/DseIdPoolHelper.class | ||
349 | SHA-256-Digest: 8wUkapQg0xNS3Vy/Mtv18N9dEB9ev/QiH1tYPzFtBN8= | ||
350 | |||
351 | Name: about.html | ||
352 | SHA-256-Digest: Qx53vUKBh4ByLG9I8uUS7GH8BTecG5s70WKYlnHc04k= | ||
353 | |||
354 | Name: org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.class | ||
355 | SHA-256-Digest: bjBZdHvq37DxouRprrTxR0l8CWUCY+aw5JtccbEeAJg= | ||
356 | |||
357 | Name: org/eclipse/viatra/dse/designspace/api/DesignSpace.class | ||
358 | SHA-256-Digest: D51XZw1Z2bCk+PxzX7i8WpE64L9s64FoedEMxM0fSYA= | ||
359 | |||
360 | Name: org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.clas | ||
361 | s | ||
362 | SHA-256-Digest: VYf9HcY2IbUo2d1K+c2rKIFkxNIRFeEi9zr9s1Inc7o= | ||
363 | |||
364 | Name: org/eclipse/viatra/dse/statecoding/StatecodingNodeType.class | ||
365 | SHA-256-Digest: VUsDepoiER2/0o3aIE8uX08eOdXzvKBkfXPpPaow5yU= | ||
366 | |||
367 | Name: org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory. | ||
368 | class | ||
369 | SHA-256-Digest: K51RjSOSyMrj86BO/zgmo4kO83HgxKvrEGeOTo5WoVs= | ||
370 | |||
371 | Name: org/eclipse/viatra/dse/base/ActivationCodesConflictSet$Activatio | ||
372 | nCodesMultiBiMap.class | ||
373 | SHA-256-Digest: DEtZHFLUnrSZG5x15o2lTasPd5+ufqWCCQXg+YXGxQA= | ||
374 | |||
375 | Name: org/eclipse/viatra/dse/statecoding/TheStateCoder.class | ||
376 | SHA-256-Digest: 7iWoLYIXKNGjRgpIHZDuW3i8wBpV5OqO978Fg9WxEK8= | ||
377 | |||
378 | Name: org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.class | ||
379 | SHA-256-Digest: HYJ6Z75XEjy3UGBB00bv/GfxdOey+9MpGM5aJuFm5fM= | ||
380 | |||
381 | Name: org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHand | ||
382 | ler.class | ||
383 | SHA-256-Digest: CmINEWESAe5ynUDWoc8YQQdsmBx1bRLNabbzmoxxsUg= | ||
384 | |||
385 | Name: org/eclipse/viatra/dse/base/DseConflictSet.class | ||
386 | SHA-256-Digest: boreOAKc8L3ZEts53PUwZiZ4l+8Em3aLeXDQBJZihbY= | ||
387 | |||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.properties b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.properties new file mode 100644 index 00000000..33746c20 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.properties | |||
@@ -0,0 +1,3 @@ | |||
1 | artifactId=org.eclipse.viatra.dse | ||
2 | groupId=org.eclipse.viatra | ||
3 | version=0.24.0-SNAPSHOT | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.xml b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.xml new file mode 100644 index 00000000..4d50659f --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/META-INF/maven/org.eclipse.viatra/org.eclipse.viatra.dse/pom.xml | |||
@@ -0,0 +1,14 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <project | ||
3 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | ||
4 | xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | ||
5 | <modelVersion>4.0.0</modelVersion> | ||
6 | <parent> | ||
7 | <artifactId>org.eclipse.viatra.parent.dse</artifactId> | ||
8 | <groupId>org.eclipse.viatra</groupId> | ||
9 | <version>0.24.0-SNAPSHOT</version> | ||
10 | <relativePath>../../../releng/org.eclipse.viatra.parent.dse/pom.xml</relativePath> | ||
11 | </parent> | ||
12 | <artifactId>org.eclipse.viatra.dse</artifactId> | ||
13 | <packaging>eclipse-plugin</packaging> | ||
14 | </project> \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/about.html b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/about.html new file mode 100644 index 00000000..4c69fcc0 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/about.html | |||
@@ -0,0 +1,21 @@ | |||
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> | ||
2 | <html> | ||
3 | <head> | ||
4 | <title>About</title> | ||
5 | <meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1"> | ||
6 | </head> | ||
7 | <body lang="EN-US"> | ||
8 | <h2>About This Content</h2> | ||
9 | |||
10 | <p>March 18, 2019</p> | ||
11 | <h3>License</h3> | ||
12 | |||
13 | <p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the | ||
14 | Eclipse Public License Version 2.0 ("EPL"). A copy of the EPL is available at <a href="http://www.eclipse.org/org/documents/epl-v20.php">http://www.eclipse.org/legal/epl-v20.html</a>. | ||
15 | For purposes of the EPL, "Program" will mean the Content.</p> | ||
16 | |||
17 | <p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party ("Redistributor") and different terms and conditions may | ||
18 | apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise | ||
19 | indicated below, the terms and conditions of the EPL still apply to any source code in the Content and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p> | ||
20 | </body> | ||
21 | </html> \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/build.properties b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/build.properties new file mode 100644 index 00000000..08373bf1 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/build.properties | |||
@@ -0,0 +1,4 @@ | |||
1 | source.. = src/ | ||
2 | bin.includes = META-INF/,\ | ||
3 | .,\ | ||
4 | about.html | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java new file mode 100644 index 00000000..f0da19ed --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSEException.java | |||
@@ -0,0 +1,47 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api; | ||
10 | |||
11 | /** | ||
12 | * Represents a general runtime exception that happened during the execution of the design space exploration process. | ||
13 | * Problems that cause this exception are not recoverable within the scope of the design space exploration process. | ||
14 | */ | ||
15 | public class DSEException extends RuntimeException { | ||
16 | |||
17 | private static final long serialVersionUID = -8312212010574763824L; | ||
18 | |||
19 | /** | ||
20 | * @see RuntimeException#RuntimeException() | ||
21 | */ | ||
22 | public DSEException() { | ||
23 | super(); | ||
24 | } | ||
25 | |||
26 | /** | ||
27 | * @see RuntimeException#RuntimeException(String) | ||
28 | */ | ||
29 | public DSEException(String message) { | ||
30 | super(message); | ||
31 | } | ||
32 | |||
33 | /** | ||
34 | * @see RuntimeException#RuntimeException(String, Throwable) | ||
35 | */ | ||
36 | public DSEException(String message, Throwable cause) { | ||
37 | super(message, cause); | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * @see RuntimeException#RuntimeException(Throwable) | ||
42 | */ | ||
43 | public DSEException(Throwable cause) { | ||
44 | super(cause); | ||
45 | } | ||
46 | |||
47 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java new file mode 100644 index 00000000..8c3511ae --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DSETransformationRule.java | |||
@@ -0,0 +1,51 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api; | ||
10 | |||
11 | import java.util.Objects; | ||
12 | import java.util.function.Consumer; | ||
13 | |||
14 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
15 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
16 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
17 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
18 | |||
19 | /** | ||
20 | * An instance of this class is a specification of a graph transformation rule on a given metamodel. Such a rule | ||
21 | * consists of a left hand side (LHS), which is specified by an {@link IQuerySpecification} and a right hand side (RHS), | ||
22 | * which is specified by an {@link Consumer}. | ||
23 | * | ||
24 | * @author Andras Szabolcs Nagy | ||
25 | * | ||
26 | * @param <Match> | ||
27 | * A VIATRA Query pattern match - left hand side of the rule | ||
28 | * @param <Matcher> | ||
29 | * A VIATRA Query pattern matcher - left hand side of the rule | ||
30 | * @deprecated | ||
31 | */ | ||
32 | @Deprecated | ||
33 | public class DSETransformationRule<Match extends IPatternMatch, Matcher extends ViatraQueryMatcher<Match>> extends | ||
34 | BatchTransformationRule<Match, Matcher> { | ||
35 | |||
36 | public DSETransformationRule(String name, IQuerySpecification<Matcher> querySpec, | ||
37 | Consumer<Match> action) { | ||
38 | super(name, querySpec, BatchTransformationRule.STATELESS_RULE_LIFECYCLE, action); | ||
39 | |||
40 | Objects.requireNonNull(name); | ||
41 | Objects.requireNonNull(querySpec); | ||
42 | Objects.requireNonNull(action); | ||
43 | |||
44 | } | ||
45 | |||
46 | public DSETransformationRule(IQuerySpecification<Matcher> querySpec, | ||
47 | Consumer<Match> action) { | ||
48 | this(querySpec.getFullyQualifiedName(), querySpec, action); | ||
49 | } | ||
50 | |||
51 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java new file mode 100644 index 00000000..9cd6e68a --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/DesignSpaceExplorer.java | |||
@@ -0,0 +1,622 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Set; | ||
14 | import java.util.Timer; | ||
15 | import java.util.TimerTask; | ||
16 | import java.util.concurrent.atomic.AtomicBoolean; | ||
17 | |||
18 | import org.apache.log4j.BasicConfigurator; | ||
19 | import org.apache.log4j.Level; | ||
20 | import org.apache.log4j.Logger; | ||
21 | import org.eclipse.emf.common.notify.Notifier; | ||
22 | import org.eclipse.emf.ecore.EObject; | ||
23 | import org.eclipse.emf.ecore.EPackage; | ||
24 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
25 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
26 | import org.eclipse.viatra.dse.base.GlobalContext; | ||
27 | import org.eclipse.viatra.dse.designspace.api.DesignSpace; | ||
28 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
29 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
30 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
31 | import org.eclipse.viatra.dse.solutionstore.ISolutionNameProvider; | ||
32 | import org.eclipse.viatra.dse.solutionstore.IdBasedSolutionNameProvider; | ||
33 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
34 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
35 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
36 | import org.eclipse.viatra.dse.statecoding.simple.SimpleStateCoderFactory; | ||
37 | import org.eclipse.viatra.dse.visualizer.IDesignSpaceVisualizer; | ||
38 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
39 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
40 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
41 | |||
42 | /** | ||
43 | * <p> | ||
44 | * The {@link DesignSpaceExplorer} is the main API of the <b>Design Space Exploration</b> engine. | ||
45 | * </p> | ||
46 | * | ||
47 | * <p> | ||
48 | * To parameterize the algorithm one must use the following methods after instantiating: | ||
49 | * <ul> | ||
50 | * <li>{@link #setInitialModel(EObject)} or it's overloads to set the starting model.</li> | ||
51 | * <li>{@link #addTransformationRule(BatchTransformationRule)} to define the transformations.</li> <li | ||
52 | * {@link #addObjective(IObjective)} to define the objective functions. Use the {@link Objectives} helper class for | ||
53 | * instantiating built-in, configurable objectives.</li> | ||
54 | * <li>{@link #startExploration(IStrategy)} or it's overloads to start an exploration with the given exploration | ||
55 | * strategy. Use the {@link Strategies} helper class for instantiating built-in, configurable exploration strategies. | ||
56 | * </li> | ||
57 | * </ul> | ||
58 | * </p> | ||
59 | * | ||
60 | * <p> | ||
61 | * <b>Designs Space Exploration</b> is the process of finding a sequence (or sequences) of predefined transformation | ||
62 | * rules ("transitions") that, if applied in order on the starting model, results in a new model state that fulfills the | ||
63 | * hard (or goal) constraints and is near optimal with respect to the objectives. | ||
64 | * </p> | ||
65 | * | ||
66 | * <p> | ||
67 | * An extension to this paradigm is the introduction of global constraints, which guarantees, that no sequence will be | ||
68 | * returned, which if executed, results in an intermediate model state that violates the specified global constraints, | ||
69 | * including the final state. You can add constraints by invoking {@link #addGlobalConstraint(IGlobalConstraint)}. | ||
70 | * </p> | ||
71 | * | ||
72 | * @author Andras Szabolcs Nagy & Miklos Foldenyi | ||
73 | * | ||
74 | */ | ||
75 | public class DesignSpaceExplorer { | ||
76 | |||
77 | private Notifier model; | ||
78 | |||
79 | private GlobalContext globalContext = new GlobalContext(); | ||
80 | |||
81 | private final Logger logger = Logger.getLogger(this.getClass()); | ||
82 | |||
83 | private Set<EPackage> metaModelPackages = new HashSet<EPackage>(); | ||
84 | |||
85 | private static final String MODEL_NOT_YET_GIVEN = "The starting model is not given yet. Please call the setInitialModel method first."; | ||
86 | |||
87 | private boolean deepCopyModel; | ||
88 | |||
89 | /** | ||
90 | * <p> | ||
91 | * Creates a {@link DesignSpaceExplorer} object that is able to execute a design space exploration process. | ||
92 | * </p> | ||
93 | * | ||
94 | * <p> | ||
95 | * By default the state coder used is the generic (not meta-model specific) {@link GraphHash}. You can provide your | ||
96 | * custom state coder by implementing the {@link IStateCoderFactory} and {@link IStateCoder} interfaces, and passing | ||
97 | * the former to the {@link #setStateCoderFactory(IStateCoderFactory)} method. | ||
98 | * | ||
99 | */ | ||
100 | public DesignSpaceExplorer() { | ||
101 | setDesignspace(new DesignSpace()); | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * Adds a metamodel in the form of {@link EPackage}, which is needed for certain guidance. | ||
106 | * | ||
107 | * @param metaModelPackage | ||
108 | */ | ||
109 | public void addMetaModelPackage(EPackage metaModelPackage) { | ||
110 | metaModelPackages.add(metaModelPackage); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Defines the initial model of the exploration, and whether it is supposed to be used to execute the DSE process or | ||
115 | * it should be cloned. Please note, that in multithreaded mode any subsequent threads will be working on cloned | ||
116 | * models. | ||
117 | * | ||
118 | * @param model | ||
119 | * The root object of the EMF model. | ||
120 | * @param deepCopyModel | ||
121 | * If it is set to true, the exploration will run on a cloned model. | ||
122 | */ | ||
123 | public void setInitialModel(Notifier model, boolean deepCopyModel) { | ||
124 | this.model = model; | ||
125 | this.deepCopyModel = deepCopyModel; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * Defines the initial model of the exploration. The model will be cloned, which is desired in most cases as the | ||
130 | * given model won't be changed. | ||
131 | * | ||
132 | * @param model | ||
133 | * The root object of the EMF model. | ||
134 | */ | ||
135 | public void setInitialModel(Notifier model) { | ||
136 | setInitialModel(model, true); | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * Defines the initial model of the exploration. The given model won't be cloned, thus the exploration will modify | ||
141 | * it. | ||
142 | * | ||
143 | * @param model | ||
144 | * The root object of the EMF model. It won't be cloned. | ||
145 | */ | ||
146 | public void setInitialModelUncloned(Notifier model) { | ||
147 | setInitialModel(model, false); | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * Adds a {@link BatchTransformationRule}. | ||
152 | * | ||
153 | * @param rule | ||
154 | * The transformationRule. | ||
155 | */ | ||
156 | public void addTransformationRule(BatchTransformationRule<?, ?> rule) { | ||
157 | Preconditions.checkArgument(rule != null); | ||
158 | for (BatchTransformationRule<?, ?> rule2 : globalContext.getTransformations()) { | ||
159 | if (rule.getPrecondition().equals(rule2.getPrecondition())) { | ||
160 | throw new DSEException( | ||
161 | "Two transformation rule (" | ||
162 | + rule.getName() | ||
163 | + "; " | ||
164 | + rule2.getName() | ||
165 | + ") uses the same LHS VIATRA Query pattern (" | ||
166 | + rule.getPrecondition().getFullyQualifiedName() | ||
167 | + "), which may lead to hash collision." | ||
168 | + " Please wrap the pattern with an other pattern with the 'find' keyword (or duplicate the code), and use that for one of the rules LHS."); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | globalContext.getTransformations().add(rule); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * Adds a global constraint to the exploration process. Please see the {@link IGlobalConstraint} interface and its | ||
177 | * implementations for details. | ||
178 | * | ||
179 | * @param constraint | ||
180 | * The global constraint. | ||
181 | * @see IGlobalConstraint | ||
182 | */ | ||
183 | public void addGlobalConstraint(IGlobalConstraint constraint) { | ||
184 | globalContext.getGlobalConstraints().add(constraint); | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * Adds an objective the the exploration process. Please see the {@link IObjective} interface and its | ||
189 | * implementations for details. | ||
190 | * | ||
191 | * @param objective | ||
192 | * The objective. | ||
193 | * @see IObjective | ||
194 | */ | ||
195 | public void addObjective(IObjective objective) { | ||
196 | for (IObjective o : globalContext.getObjectives()) { | ||
197 | if (o.getName().equals(objective.getName())) { | ||
198 | throw new DSEException("Two objectives with the same name cannot be registered:" + o.getName()); | ||
199 | } | ||
200 | } | ||
201 | globalContext.getObjectives().add(objective); | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * Sets a {@link IStateCoderFactory} for which will be used for creating {@link IStateCoder}s. The default | ||
206 | * implementation is the {@link SimpleStateCoderFactory}, which works well in most of the cases. | ||
207 | * | ||
208 | * @param stateCoderFactory | ||
209 | * The factory. | ||
210 | */ | ||
211 | public final void setStateCoderFactory(IStateCoderFactory stateCoderFactory) { | ||
212 | globalContext.setStateCoderFactory(stateCoderFactory); | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * Defines the maximum processing threads that the design space exploration can use. Note, that this is only | ||
217 | * limiting the threads doing the actual calculation. By default this value will be set to the number of logical | ||
218 | * processors (including HyperThreading) in the computer, reported by {@link Runtime#availableProcessors()}. | ||
219 | * | ||
220 | * @param maxNumberOfThreads | ||
221 | * The number of maximum processing threads available to the design space exploration process. | ||
222 | */ | ||
223 | public void setMaxNumberOfThreads(int maxNumberOfThreads) { | ||
224 | globalContext.getThreadPool().setMaximumPoolSize(maxNumberOfThreads); | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * Sets the {@link IDesignSpace} implementation that is to be used during the design space exploration process. By | ||
229 | * default, the {@link DesignSpace} implementation is used. | ||
230 | * | ||
231 | * @param designspace | ||
232 | * The {@link IDesignSpace} implementation. | ||
233 | */ | ||
234 | public final void setDesignspace(IDesignSpace designspace) { | ||
235 | globalContext.setDesignSpace(designspace); | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * Sets the solution store for strategies. Please see the {@link SolutionStore} for how to configure it. | ||
240 | * | ||
241 | * @param solutionStore | ||
242 | * The parameterized {@link SolutionStore} implementation. | ||
243 | */ | ||
244 | public void setSolutionStore(SolutionStore solutionStore) { | ||
245 | globalContext.setSolutionStore(solutionStore); | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * Starts the design space exploration. It returns only when the strategy decides to stop the execution. | ||
250 | * | ||
251 | * @param strategy | ||
252 | * The strategy of the exploration. | ||
253 | */ | ||
254 | public void startExploration(IStrategy strategy) { | ||
255 | startExploration(strategy, true, -1); | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * Starts the design space exploration asynchronously. Completion of the process can be verified by calling | ||
260 | * {@link DesignSpaceExplorer#isDone()}. | ||
261 | * | ||
262 | * @param strategy | ||
263 | * The strategy of the exploration. | ||
264 | */ | ||
265 | public void startExplorationAsync(IStrategy strategy) { | ||
266 | startExploration(strategy, false, -1); | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * Starts the design space exploration with a timeout. It returns only when the strategy decides to stop the | ||
271 | * execution or the given timeout is elapsed. | ||
272 | * | ||
273 | * @param strategy | ||
274 | * The strategy of the exploration. | ||
275 | * @param timeout | ||
276 | * The number of milliseconds before the exploration is forced to stop. | ||
277 | * @return Returns true if the exploration stopped by the timeout. | ||
278 | */ | ||
279 | public boolean startExplorationWithTimeout(IStrategy strategy, long timeout) { | ||
280 | return startExploration(strategy, true, timeout); | ||
281 | } | ||
282 | |||
283 | /** | ||
284 | * Starts the design space exploration asynchronously with a timeout. Completion of the process can be verified by | ||
285 | * calling {@link DesignSpaceExplorer#isDone()}. | ||
286 | * | ||
287 | * @param strategy | ||
288 | * The strategy of the exploration. | ||
289 | * @param timeout | ||
290 | * The number of milliseconds before the exploration is forced to stop. | ||
291 | * @return Returns true if the exploration stopped by the timeout. | ||
292 | */ | ||
293 | public boolean startExplorationAsyncWithTimeout(IStrategy strategy, long timeout) { | ||
294 | return startExploration(strategy, false, timeout); | ||
295 | } | ||
296 | |||
297 | /** | ||
298 | * Starts the design space exploration. If {@code waitForTermination} is true, then it returns only when the | ||
299 | * strategy decides to stop the execution or there was a timeout, otherwise when the exploration process is started | ||
300 | * it returns immediately. In this case, process completion can be verified by calling | ||
301 | * {@link DesignSpaceExplorer#isDone()}. | ||
302 | * | ||
303 | * @param strategy | ||
304 | * The strategy of the exploration. | ||
305 | * @param waitForTermination | ||
306 | * True if the method must wait for the engine to stop, i.e. whether to start synchronously. | ||
307 | * @param timeout | ||
308 | * The number of milliseconds before the exploration is forced to stop. | ||
309 | * @return Returns true if the exploration stopped by the timeout. | ||
310 | */ | ||
311 | public boolean startExploration(IStrategy strategy, boolean waitForTermination, final long timeout) { | ||
312 | initExploration(strategy); | ||
313 | |||
314 | Timer timer = new Timer(); | ||
315 | final AtomicBoolean wasTimeout = new AtomicBoolean(false); | ||
316 | |||
317 | if (timeout > 0) { | ||
318 | TimerTask timerTask = new TimerTask() { | ||
319 | @Override | ||
320 | public void run() { | ||
321 | logger.info("Timeout, stopping threads..."); | ||
322 | globalContext.stopAllThreads(); | ||
323 | wasTimeout.set(true); | ||
324 | } | ||
325 | }; | ||
326 | timer.schedule(timerTask, timeout); | ||
327 | } | ||
328 | |||
329 | if (waitForTermination) { | ||
330 | waitForTerminaition(); | ||
331 | timer.cancel(); | ||
332 | } else { | ||
333 | logger.info("Design space exploration started asynchronously."); | ||
334 | } | ||
335 | |||
336 | return wasTimeout.get(); | ||
337 | |||
338 | } | ||
339 | |||
340 | private void initExploration(IStrategy strategy) { | ||
341 | Preconditions.checkArgument(model != null, MODEL_NOT_YET_GIVEN); | ||
342 | Preconditions.checkArgument(strategy != null, "A strategy must be given. Use the Strategies helper class."); | ||
343 | Preconditions.checkState(!globalContext.getTransformations().isEmpty(), | ||
344 | "At least one transformation rule must be added to start the exploration."); | ||
345 | |||
346 | if (globalContext.getStateCoderFactory() == null) { | ||
347 | if (getMetaModelPackages() == null || getMetaModelPackages().isEmpty()) { | ||
348 | throw new DSEException("Cannot initialize state coder." | ||
349 | + " Please specifiy the EPackages your model uses with addMetaModelPackage(EPackage)"); | ||
350 | } | ||
351 | globalContext.setStateCoderFactory(new SimpleStateCoderFactory(getMetaModelPackages())); | ||
352 | } | ||
353 | |||
354 | logger.info("DesignSpaceExplorer started exploration."); | ||
355 | |||
356 | if (deepCopyModel) { | ||
357 | globalContext.startFirstThread(strategy, model); | ||
358 | } else { | ||
359 | globalContext.startFirstThreadWithoutModelClone(strategy, model); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * Returns all of the found {@link Solution}s, trajectories. Call it after | ||
365 | * {@link DesignSpaceExplorer#startExploration()}. Calling this while the process is running returns the solutions | ||
366 | * that have been found <b>so far</b>. The returned {@link Solution} objects may change internal state after they | ||
367 | * have been returned, if a shorter trajectory has been found to the referred state. | ||
368 | * | ||
369 | * @return The found solutions. | ||
370 | */ | ||
371 | public Collection<Solution> getSolutions() { | ||
372 | return globalContext.getSolutionStore().getSolutions(); | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * Returns an arbitrary solution trajectory or null if the exploration failed to find any. | ||
377 | * | ||
378 | * @return An arbitrary solution trajectory. | ||
379 | */ | ||
380 | public SolutionTrajectory getArbitrarySolution() { | ||
381 | Collection<Solution> solutions = getSolutions(); | ||
382 | if (solutions.isEmpty()) { | ||
383 | return null; | ||
384 | } | ||
385 | return solutions.iterator().next().getArbitraryTrajectory(); | ||
386 | } | ||
387 | |||
388 | /** | ||
389 | * Returns the number of distinct states the exploration process has visited so far. | ||
390 | * | ||
391 | * @return the number of distinct states. | ||
392 | */ | ||
393 | public long getNumberOfStates() { | ||
394 | return globalContext.getDesignSpace().getNumberOfStates(); | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * Returns the number of distinct transitions the exploration process has discovered (but not necessarily traversed) | ||
399 | * so far. | ||
400 | * | ||
401 | * @return the number of distinct transitions. | ||
402 | */ | ||
403 | public long getNumberOfTransitions() { | ||
404 | return globalContext.getDesignSpace().getNumberOfTransitions(); | ||
405 | } | ||
406 | |||
407 | /** | ||
408 | * Returns the {@link EPackage}s, which were registered with the | ||
409 | * {@link DesignSpaceExplorer#addMetaModelPackage(EPackage)} method. | ||
410 | * | ||
411 | * @return The set of meta model packages. | ||
412 | */ | ||
413 | public Set<EPackage> getMetaModelPackages() { | ||
414 | return metaModelPackages; | ||
415 | } | ||
416 | |||
417 | /** | ||
418 | * Returns true if the {@link IExplorerThread strategy} decided to stop, and all the threads finished their work. | ||
419 | * | ||
420 | * @return true if the process has finished, false otherwise. | ||
421 | */ | ||
422 | public boolean isDone() { | ||
423 | return globalContext.isDone(); | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * Returns the {@link GlobalContext} which holds the configurations such as rule, objectives, etc. | ||
428 | * | ||
429 | * @return The global context. | ||
430 | */ | ||
431 | public GlobalContext getGlobalContext() { | ||
432 | return globalContext; | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * Registers a design space visualizer. Please see the corresponding interface {@link IDesignSpaceVisualizer}. | ||
437 | * | ||
438 | * @see IDesignSpaceVisualizer | ||
439 | * | ||
440 | * @param visualizer | ||
441 | */ | ||
442 | public void addDesignSpaceVisulaizer(IDesignSpaceVisualizer visualizer) { | ||
443 | globalContext.registerDesignSpaceVisualizer(visualizer); | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * Creates a string containing the state codes of all the found solutions and the found trajectories to these | ||
448 | * solutions with fitness values. | ||
449 | * | ||
450 | * @return A pretty string with the solutions. | ||
451 | */ | ||
452 | public String toStringSolutions() { | ||
453 | StringBuilder sb = new StringBuilder(); | ||
454 | Collection<Solution> solutions = getSolutions(); | ||
455 | sb.append("Number of solutions: "); | ||
456 | sb.append(solutions.size()); | ||
457 | sb.append("\n"); | ||
458 | for (Solution solution : solutions) { | ||
459 | sb.append("Solution: "); | ||
460 | sb.append(solution.getStateCode()); | ||
461 | sb.append("\n"); | ||
462 | for (SolutionTrajectory trajectory : solution.getTrajectories()) { | ||
463 | sb.append(" "); | ||
464 | sb.append(trajectory.toPrettyString()); | ||
465 | sb.append("\n"); | ||
466 | } | ||
467 | } | ||
468 | return sb.toString(); | ||
469 | } | ||
470 | |||
471 | /** | ||
472 | * A conflict resolver can filter rule activations the DSE engine will see. The primary use of this is symmetry | ||
473 | * reduction. This function is subject to change for better API. | ||
474 | * | ||
475 | * @param conflictResolver | ||
476 | */ | ||
477 | public void setConflictResolver(ConflictResolver conflictResolver) { | ||
478 | globalContext.setConflictResolver(conflictResolver); | ||
479 | } | ||
480 | |||
481 | /** | ||
482 | * Enumeration for different use cases of logging, including: | ||
483 | * <ul> | ||
484 | * <li>OFF - no error messages.</li> | ||
485 | * <li>WARN - only error and warn messages.</li> | ||
486 | * <li>BASIC - logs basic information on how the exploration is going.</li> | ||
487 | * <li>VERBOSE_STRATEGY - logs everything the exploration strategy is prepared for.</li> | ||
488 | * <li>VERBOSE_FULL - logs every transformation.</li> | ||
489 | * </ul> | ||
490 | * | ||
491 | * @author Andras Szabolcs Nagy | ||
492 | * | ||
493 | */ | ||
494 | public enum DseLoggingLevel { | ||
495 | OFF, WARN, BASIC, VERBOSE_STRATEGY, VERBOSE_FULL | ||
496 | } | ||
497 | |||
498 | /** | ||
499 | * Changes the level of logging. See {@link DseLoggingLevel} for details. | ||
500 | * | ||
501 | * @param dseLoggingLevel | ||
502 | */ | ||
503 | public static void turnOnLogging(DseLoggingLevel dseLoggingLevel) { | ||
504 | switch (dseLoggingLevel) { | ||
505 | case OFF: | ||
506 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.OFF); | ||
507 | Logger.getLogger(IStrategy.class).setLevel(Level.OFF); | ||
508 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.OFF); | ||
509 | break; | ||
510 | case WARN: | ||
511 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.WARN); | ||
512 | Logger.getLogger(IStrategy.class).setLevel(Level.WARN); | ||
513 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.WARN); | ||
514 | break; | ||
515 | case BASIC: | ||
516 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.INFO); | ||
517 | Logger.getLogger(IStrategy.class).setLevel(Level.INFO); | ||
518 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.WARN); | ||
519 | break; | ||
520 | case VERBOSE_STRATEGY: | ||
521 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.DEBUG); | ||
522 | Logger.getLogger(IStrategy.class).setLevel(Level.DEBUG); | ||
523 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.WARN); | ||
524 | break; | ||
525 | case VERBOSE_FULL: | ||
526 | Logger.getLogger(DesignSpaceExplorer.class).setLevel(Level.DEBUG); | ||
527 | Logger.getLogger(IStrategy.class).setLevel(Level.DEBUG); | ||
528 | Logger.getLogger(DesignSpaceManager.class).setLevel(Level.DEBUG); | ||
529 | break; | ||
530 | default: | ||
531 | throw new DSEException("Not supported logging level."); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | /** | ||
536 | * Changes the level of logging. See {@link DseLoggingLevel} for details. | ||
537 | * | ||
538 | * Also configures a basic console appender for log4j. | ||
539 | * | ||
540 | * @param dseLoggingLevel | ||
541 | */ | ||
542 | public static void turnOnLoggingWithBasicConfig(DseLoggingLevel dseLoggingLevel) { | ||
543 | BasicConfigurator.configure(); | ||
544 | Logger.getRootLogger().setLevel(Level.WARN); | ||
545 | turnOnLogging(dseLoggingLevel); | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * Stops the exploration and waits for termination. It has no effect if the exploration is already terminated or not | ||
550 | * even started. | ||
551 | */ | ||
552 | public void stopExploration() { | ||
553 | if (globalContext.isDone()) { | ||
554 | logger.info("Cannot stop exploration - design space exploration has already finished."); | ||
555 | } else if (globalContext.isNotStarted()) { | ||
556 | logger.info("Cannot stop exploration - design space exploration has not been started."); | ||
557 | } else { | ||
558 | globalContext.stopAllThreads(); | ||
559 | waitForTerminaition(); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | /** | ||
564 | * Stops the exploration asynchronously. It has no effect if the exploration is already terminated or not even | ||
565 | * started. | ||
566 | */ | ||
567 | public void stopExplorationAsync() { | ||
568 | if (globalContext.isDone()) { | ||
569 | logger.info("Cannot stop exploration - design space exploration has already finished."); | ||
570 | } else if (globalContext.isNotStarted()) { | ||
571 | logger.info("Cannot stop exploration - design space exploration has not been started."); | ||
572 | } else { | ||
573 | globalContext.stopAllThreads(); | ||
574 | } | ||
575 | } | ||
576 | |||
577 | /** | ||
578 | * Waits for termination. | ||
579 | */ | ||
580 | public void waitForTerminaition() { | ||
581 | globalContext.waitForTermination(); | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * Serializes all the found solutions by transforming the given initial model. | ||
586 | * </p>Files will be named <code>solution[id].xmi</code>. | ||
587 | * @param model The initial model. | ||
588 | */ | ||
589 | public void saveModels(Notifier model) { | ||
590 | this.saveModels(model, "solution", "xmi"); | ||
591 | } | ||
592 | |||
593 | /** | ||
594 | * Serializes all the found solutions by transforming the given initial model. | ||
595 | * </p>Files will be named <code>solution[id].[extension]</code>. | ||
596 | * @param model The initial model. | ||
597 | * @param extension The extension of the omitted file. | ||
598 | */ | ||
599 | public void saveModels(Notifier model, String extension) { | ||
600 | this.saveModels(model, "solution", extension); | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * Serializes all the found solutions by transforming the given initial model. | ||
605 | * </p>Files will be named <code>[fileNamePrefix][id].[extension]</code>. | ||
606 | * @param model The initial model. | ||
607 | * @param fileNamePrefix The prefix (optionally including a file path) of the omitted file. | ||
608 | * @param extension The extension of the omitted file. | ||
609 | */ | ||
610 | public void saveModels(Notifier model, String fileNamePrefix, String extension) { | ||
611 | globalContext.getSolutionStore().saveModels(model, new IdBasedSolutionNameProvider(fileNamePrefix, extension)); | ||
612 | } | ||
613 | |||
614 | /** | ||
615 | * Serializes all the found solutions by transforming the given initial model. | ||
616 | * </p>Files will be named using the {@link ISolutionNameProvider}. | ||
617 | * @param model The initial model. | ||
618 | */ | ||
619 | public void saveModels(Notifier model, ISolutionNameProvider solutionNameProvider) { | ||
620 | globalContext.getSolutionStore().saveModels(model, solutionNameProvider); | ||
621 | } | ||
622 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java new file mode 100644 index 00000000..3b375fac --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Objectives.java | |||
@@ -0,0 +1,153 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api; | ||
10 | |||
11 | import org.eclipse.viatra.dse.objectives.impl.CompositeObjective; | ||
12 | import org.eclipse.viatra.dse.objectives.impl.ConstraintsObjective; | ||
13 | import org.eclipse.viatra.dse.objectives.impl.AlwaysSatisfiedDummyHardObjective; | ||
14 | import org.eclipse.viatra.dse.objectives.impl.DepthHardObjective; | ||
15 | import org.eclipse.viatra.dse.objectives.impl.NeverSatisfiedDummyHardObjective; | ||
16 | import org.eclipse.viatra.dse.objectives.impl.NoRuleActivationsHardObjective; | ||
17 | import org.eclipse.viatra.dse.objectives.impl.TrajectoryCostSoftObjective; | ||
18 | |||
19 | /** | ||
20 | * | ||
21 | * Helper class for creating built-in objectives. | ||
22 | * | ||
23 | * @author Andras Szabolcs Nagy | ||
24 | * | ||
25 | */ | ||
26 | public class Objectives { | ||
27 | |||
28 | private Objectives() { | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * This objective uses VIATRA Queries to calculate fitness and/or goal constraints. Use methods on the returned | ||
33 | * objective to configure it. | ||
34 | * | ||
35 | * @param name | ||
36 | * @return The objective. | ||
37 | * @see ConstraintsObjective | ||
38 | */ | ||
39 | public static ConstraintsObjective createConstraintsObjective(String name) { | ||
40 | return new ConstraintsObjective(name); | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * This objective calculates fitness on the trajectory by adding either fix costs to the rules, or by calculating | ||
45 | * custom fitness on activation of rules. | ||
46 | * | ||
47 | * @param name | ||
48 | * @return The objective. | ||
49 | * @see TrajectoryCostSoftObjective | ||
50 | */ | ||
51 | public static TrajectoryCostSoftObjective createTrajcetoryCostObjective(String name) { | ||
52 | return new TrajectoryCostSoftObjective(name); | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * This objective adds a goal constraint that a solution state should not have any activations. | ||
57 | * | ||
58 | * @return The objective. | ||
59 | * @see NoRuleActivationsHardObjective | ||
60 | */ | ||
61 | public static NoRuleActivationsHardObjective createNoRuleActivationsHardConstraint() { | ||
62 | return new NoRuleActivationsHardObjective(); | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * This objective adds a goal constraint that a solution state should not have any activations. | ||
67 | * | ||
68 | * @param name | ||
69 | * @return The objective. | ||
70 | * @see NoRuleActivationsHardObjective | ||
71 | */ | ||
72 | public static NoRuleActivationsHardObjective createNoRuleActivationsHardConstraint(String name) { | ||
73 | return new NoRuleActivationsHardObjective(name); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * This objective can combine the calculated fitness value of other objectives. Weights are supported. | ||
78 | * | ||
79 | * @param name | ||
80 | * @return The objective. | ||
81 | * @see NoRuleActivationsHardObjective | ||
82 | */ | ||
83 | public static CompositeObjective createCompositeObjective(String name) { | ||
84 | return new CompositeObjective(name); | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid | ||
89 | * solution. | ||
90 | * | ||
91 | * @return The objective. | ||
92 | * @see AlwaysSatisfiedDummyHardObjective | ||
93 | */ | ||
94 | public static AlwaysSatisfiedDummyHardObjective createAlwaysSatisfiedDummyHardObjective() { | ||
95 | return new AlwaysSatisfiedDummyHardObjective(); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid | ||
100 | * solution. | ||
101 | * | ||
102 | * @param name | ||
103 | * @return The objective. | ||
104 | * @see AlwaysSatisfiedDummyHardObjective | ||
105 | */ | ||
106 | public static AlwaysSatisfiedDummyHardObjective createDummyHardObjective(String name) { | ||
107 | return new AlwaysSatisfiedDummyHardObjective(name); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * This hard objective is never fulfilled. Use it if all states should be regarded as an invalid solution. | ||
112 | * | ||
113 | * @return The objective. | ||
114 | * @see AlwaysSatisfiedDummyHardObjective | ||
115 | */ | ||
116 | public static NeverSatisfiedDummyHardObjective createNeverSatisfiedDummyHardObjective() { | ||
117 | return new NeverSatisfiedDummyHardObjective(); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * This hard objective is never fulfilled. Use it if all states should be regarded as an invalid solution. | ||
122 | * | ||
123 | * @return The objective. | ||
124 | * @see AlwaysSatisfiedDummyHardObjective | ||
125 | */ | ||
126 | public static NeverSatisfiedDummyHardObjective createNeverSatisfiedDummyHardObjective(String name) { | ||
127 | return new NeverSatisfiedDummyHardObjective(name); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * This hard objective is fulfilled if the length of the trajectory is in the specified interval (inclusive). Use | ||
132 | * {@link DepthHardObjective#withMinDepth(int)} and {@link DepthHardObjective#withMaxDepth(int)} to configure. | ||
133 | * | ||
134 | * @return The objective. | ||
135 | * @see DepthHardObjective | ||
136 | */ | ||
137 | public static DepthHardObjective createDepthHardObjective() { | ||
138 | return new DepthHardObjective(); | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * This hard objective is fulfilled if the length of the trajectory is in the specified interval (inclusive). Use | ||
143 | * {@link DepthHardObjective#withMinDepth(int)} and {@link DepthHardObjective#withMaxDepth(int)} to configure. | ||
144 | * | ||
145 | * @param name | ||
146 | * @return The objective. | ||
147 | * @see DepthHardObjective | ||
148 | */ | ||
149 | public static DepthHardObjective createDepthHardObjective(String name) { | ||
150 | return new DepthHardObjective(name); | ||
151 | } | ||
152 | |||
153 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java new file mode 100644 index 00000000..b776db7a --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Solution.java | |||
@@ -0,0 +1,60 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Iterator; | ||
14 | import java.util.Set; | ||
15 | |||
16 | public class Solution { | ||
17 | |||
18 | private Set<SolutionTrajectory> trajectories; | ||
19 | private final Object stateId; | ||
20 | |||
21 | public Solution(Object stateId, SolutionTrajectory trajectory) { | ||
22 | this.stateId = stateId; | ||
23 | trajectories = new HashSet<>(); | ||
24 | trajectories.add(trajectory); | ||
25 | } | ||
26 | |||
27 | public void addTrajectory(SolutionTrajectory trajectory) { | ||
28 | trajectories.add(trajectory); | ||
29 | } | ||
30 | |||
31 | public SolutionTrajectory getArbitraryTrajectory() { | ||
32 | return trajectories.iterator().next(); | ||
33 | } | ||
34 | |||
35 | public SolutionTrajectory getShortestTrajectory() { | ||
36 | Iterator<SolutionTrajectory> iterator = trajectories.iterator(); | ||
37 | SolutionTrajectory shortestTrajecotry = iterator.next(); | ||
38 | int minSize = shortestTrajecotry.getTrajectoryLength(); | ||
39 | |||
40 | while (iterator.hasNext()) { | ||
41 | SolutionTrajectory traj = iterator.next(); | ||
42 | int size = traj.getTrajectoryLength(); | ||
43 | if (size < minSize) { | ||
44 | shortestTrajecotry = traj; | ||
45 | minSize = size; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | return shortestTrajecotry; | ||
50 | } | ||
51 | |||
52 | public Collection<SolutionTrajectory> getTrajectories() { | ||
53 | return trajectories; | ||
54 | } | ||
55 | |||
56 | public Object getStateCode() { | ||
57 | return stateId; | ||
58 | } | ||
59 | |||
60 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java new file mode 100644 index 00000000..500dd7d2 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/SolutionTrajectory.java | |||
@@ -0,0 +1,345 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api; | ||
10 | |||
11 | import java.lang.reflect.InvocationTargetException; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.List; | ||
14 | import java.util.Objects; | ||
15 | import java.util.function.Consumer; | ||
16 | |||
17 | import org.eclipse.emf.common.notify.Notifier; | ||
18 | import org.eclipse.emf.edit.command.ChangeCommand; | ||
19 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
20 | import org.eclipse.viatra.dse.base.DseIdPoolHelper; | ||
21 | import org.eclipse.viatra.dse.designspace.api.IBacktrackListener; | ||
22 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
23 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
24 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
25 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
26 | import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine; | ||
27 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
28 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
29 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
30 | import org.eclipse.viatra.query.runtime.emf.EMFScope; | ||
31 | import org.eclipse.viatra.query.runtime.matchers.ViatraQueryRuntimeException; | ||
32 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
33 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
34 | |||
35 | import com.google.common.util.concurrent.UncheckedExecutionException; | ||
36 | |||
37 | /** | ||
38 | * A SolutionTrajectory represents a trajectory (i.e. sequence of transformation | ||
39 | * rule applications), which can transform the initial model to a desired state. | ||
40 | * An instance of this class holds the the actual rule sequence and the | ||
41 | * corresponding activation codes. Furthermore it can be used to perform the | ||
42 | * transformation on a given model (if possible). | ||
43 | * <p> | ||
44 | * It is also possible to undo the transformation if initialized with an editing | ||
45 | * domain. | ||
46 | * <p> | ||
47 | * The instance of this class can be reused for different models. | ||
48 | * | ||
49 | * @author Andras Szabolcs Nagy | ||
50 | * | ||
51 | */ | ||
52 | public class SolutionTrajectory { | ||
53 | |||
54 | private final List<Object> activationCodes; | ||
55 | private final List<BatchTransformationRule<?, ?>> transformationRules; | ||
56 | private final IStateCoderFactory stateCoderFactory; | ||
57 | private Fitness fitness; | ||
58 | private Solution solution; | ||
59 | |||
60 | private ViatraQueryEngine engine; | ||
61 | private Notifier model; | ||
62 | private EditingDomain editingDomain; | ||
63 | private IStateCoder stateCoder; | ||
64 | private IBacktrackListener listener; | ||
65 | |||
66 | private int currentIndex; | ||
67 | |||
68 | public SolutionTrajectory(final List<Object> activationCodes, | ||
69 | final List<BatchTransformationRule<?, ?>> transformationRules, final IStateCoderFactory stateCoderFactory, | ||
70 | final IBacktrackListener backtrackListener) { | ||
71 | Objects.requireNonNull(transformationRules, "Parameter transformationRules cannot be null!"); | ||
72 | Objects.requireNonNull(stateCoderFactory, "Parameter stateCoderFactory cannot be null!"); | ||
73 | Objects.requireNonNull(activationCodes, "Parameter activations cannot be null!"); | ||
74 | Preconditions.checkState(transformationRules.size() == activationCodes.size(), | ||
75 | "The two List parameters must be the same in size."); | ||
76 | |||
77 | this.activationCodes = activationCodes; | ||
78 | this.transformationRules = transformationRules; | ||
79 | this.stateCoderFactory = stateCoderFactory; | ||
80 | this.listener = backtrackListener; | ||
81 | currentIndex = 0; | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * Initialize this SolutionTrajectory for transforming the model along the | ||
86 | * trajectory. | ||
87 | * | ||
88 | * @param model The model. | ||
89 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
90 | */ | ||
91 | public void setModel(Notifier model) { | ||
92 | editingDomain = null; | ||
93 | EMFScope scope = new EMFScope(model); | ||
94 | this.engine = ViatraQueryEngine.on(scope); | ||
95 | this.model = model; | ||
96 | stateCoder = stateCoderFactory.createStateCoder(); | ||
97 | stateCoder.init(model); | ||
98 | currentIndex = 0; | ||
99 | DseIdPoolHelper.INSTANCE.disposeByThread(); | ||
100 | DseIdPoolHelper.INSTANCE.registerRules(rule -> { | ||
101 | int id = 0; | ||
102 | for (BatchTransformationRule<?, ?> r : transformationRules.subList(0, currentIndex)) { | ||
103 | if (r.equals(rule)) { | ||
104 | id++; | ||
105 | } | ||
106 | } | ||
107 | return id; | ||
108 | }, new HashSet<BatchTransformationRule<?, ?>>(transformationRules)); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * Initialize this SolutionTrajectory for transforming the given model along the | ||
113 | * trajectory. | ||
114 | * <p> | ||
115 | * The transformation will be reversible by creating an {@link EditingDomain} on | ||
116 | * the model. | ||
117 | * | ||
118 | * @param modelRoot The root of the model. | ||
119 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
120 | */ | ||
121 | public void setModelWithEditingDomain(Notifier modelRoot) { | ||
122 | setModel(modelRoot); | ||
123 | editingDomain = EMFHelper.createEditingDomain(model); | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Transforms the given model along the trajectory. | ||
128 | * | ||
129 | * @param modelRoot The root of the model. | ||
130 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
131 | */ | ||
132 | public void doTransformation(Notifier modelRoot) { | ||
133 | setModel(modelRoot); | ||
134 | doTransformation(); | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * Transforms the given model along the trajectory. | ||
139 | * <p> | ||
140 | * The transformation will be reversible by creating an {@link EditingDomain} on | ||
141 | * the model. | ||
142 | * | ||
143 | * @param modelRoot The root of the model. | ||
144 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
145 | */ | ||
146 | public void doTransformationUndoable(Notifier modelRoot) { | ||
147 | setModelWithEditingDomain(modelRoot); | ||
148 | doTransformation(); | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * Transforms the given model along the trajectory. To initialize the model call | ||
153 | * the {@link SolutionTrajectory#setModel(Notifier)} method. | ||
154 | * | ||
155 | * @throws Exception If the activation to fire is not found. | ||
156 | * Possible problems: wrong model, bad state | ||
157 | * serializer. | ||
158 | * @throws ViatraQueryRuntimeException If the VIATRA Query fails to initialize. | ||
159 | */ | ||
160 | public void doTransformation() { | ||
161 | while (doNextTransformation()) | ||
162 | ; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * Transforms the given model by one step to the solution (makes one step in the | ||
167 | * trajectory). To initialize the model call the | ||
168 | * {@link SolutionTrajectory#setModel(Notifier)} method. | ||
169 | * | ||
170 | * @throws ViatraQueryRuntimeException | ||
171 | */ | ||
172 | public boolean doNextTransformation() { | ||
173 | if (currentIndex >= activationCodes.size()) { | ||
174 | return false; | ||
175 | } else { | ||
176 | doNextTransformation(currentIndex); | ||
177 | currentIndex++; | ||
178 | return true; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | @SuppressWarnings("unchecked") | ||
183 | private void doNextTransformation(int index) { | ||
184 | Objects.requireNonNull(model, "The model cannot be null! Use the setModel method."); | ||
185 | |||
186 | // cast for the ".process(match)" method. | ||
187 | BatchTransformationRule<?, ?> tr = transformationRules.get(index); | ||
188 | Object activationCode = activationCodes.get(index); | ||
189 | |||
190 | ViatraQueryMatcher<?> matcher = tr.getPrecondition().getMatcher(engine); | ||
191 | |||
192 | boolean isActivationFound = false; | ||
193 | for (final IPatternMatch match : matcher.getAllMatches()) { | ||
194 | Object matchHash = stateCoder.createActivationCode(match); | ||
195 | if (matchHash.equals(activationCode)) { | ||
196 | @SuppressWarnings("rawtypes") | ||
197 | final Consumer action = tr.getAction(); | ||
198 | |||
199 | if (editingDomain == null) { | ||
200 | action.accept(match); | ||
201 | } else { | ||
202 | ChangeCommand cc = new ChangeCommand(model) { | ||
203 | @Override | ||
204 | protected void doExecute() { | ||
205 | action.accept(match); | ||
206 | } | ||
207 | }; | ||
208 | long start = System.nanoTime(); | ||
209 | try { | ||
210 | ((AdvancedViatraQueryEngine) engine).delayUpdatePropagation(() -> { | ||
211 | editingDomain.getCommandStack().execute(cc); | ||
212 | return null; | ||
213 | }); | ||
214 | } catch (InvocationTargetException e) { | ||
215 | throw new RuntimeException(e); | ||
216 | } | ||
217 | listener.forwardWorked(System.nanoTime() - start); | ||
218 | } | ||
219 | |||
220 | isActivationFound = true; | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | if (!isActivationFound) { | ||
225 | throw new UncheckedExecutionException( | ||
226 | "Activation was not found for transformation! Possible cause: wrong model, bad state coder. index: " | ||
227 | + index + " Activation code: " + activationCode, | ||
228 | null); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /** | ||
233 | * Call this method to undo the last transformation. | ||
234 | * | ||
235 | * @return True, if it was successful. | ||
236 | */ | ||
237 | public boolean undoLastTransformation() { | ||
238 | Objects.requireNonNull(editingDomain, "To be able to undo the transformation initialize with editing domain."); | ||
239 | long start = System.nanoTime(); | ||
240 | boolean result; | ||
241 | |||
242 | if (currentIndex > 0) { | ||
243 | try { | ||
244 | ((AdvancedViatraQueryEngine) engine).delayUpdatePropagation(() -> { | ||
245 | editingDomain.getCommandStack().undo(); | ||
246 | return null; | ||
247 | }); | ||
248 | } catch (InvocationTargetException e) { | ||
249 | throw new RuntimeException(e); | ||
250 | } | ||
251 | currentIndex--; | ||
252 | result = true; | ||
253 | } | ||
254 | result = false; | ||
255 | listener.backtrackWorked(System.nanoTime() - start); | ||
256 | return result; | ||
257 | } | ||
258 | |||
259 | /** | ||
260 | * Call this method to undo the transformation. | ||
261 | */ | ||
262 | public void undoTransformation() { | ||
263 | while (undoLastTransformation()) | ||
264 | ; | ||
265 | } | ||
266 | |||
267 | public List<Object> getActivationCodes() { | ||
268 | return activationCodes; | ||
269 | } | ||
270 | |||
271 | public List<BatchTransformationRule<?, ?>> getTransformationRules() { | ||
272 | return transformationRules; | ||
273 | } | ||
274 | |||
275 | public IStateCoderFactory getStateCoderFactory() { | ||
276 | return stateCoderFactory; | ||
277 | } | ||
278 | |||
279 | public ViatraQueryEngine getEngine() { | ||
280 | return engine; | ||
281 | } | ||
282 | |||
283 | public Notifier getModel() { | ||
284 | return model; | ||
285 | } | ||
286 | |||
287 | public IStateCoder getStateCoder() { | ||
288 | return stateCoder; | ||
289 | } | ||
290 | |||
291 | public int getCurrentIndex() { | ||
292 | return currentIndex; | ||
293 | } | ||
294 | |||
295 | public int getTrajectoryLength() { | ||
296 | return activationCodes.size(); | ||
297 | } | ||
298 | |||
299 | public Fitness getFitness() { | ||
300 | return fitness; | ||
301 | } | ||
302 | |||
303 | public void setFitness(Fitness fitness) { | ||
304 | this.fitness = fitness; | ||
305 | } | ||
306 | |||
307 | public String toPrettyString() { | ||
308 | StringBuilder sb = new StringBuilder(); | ||
309 | sb.append("Fitness: "); | ||
310 | sb.append(fitness.toString()); | ||
311 | sb.append(" | Trajectory ("); | ||
312 | sb.append(activationCodes.size()); | ||
313 | sb.append("): "); | ||
314 | for (Object object : activationCodes) { | ||
315 | sb.append(object.toString()); | ||
316 | sb.append(" | "); | ||
317 | } | ||
318 | return sb.toString(); | ||
319 | } | ||
320 | |||
321 | @Override | ||
322 | public int hashCode() { | ||
323 | return activationCodes.hashCode(); | ||
324 | } | ||
325 | |||
326 | @Override | ||
327 | public boolean equals(Object obj) { | ||
328 | if (this == obj) { | ||
329 | return true; | ||
330 | } | ||
331 | if (obj instanceof SolutionTrajectory) { | ||
332 | SolutionTrajectory that = (SolutionTrajectory) obj; | ||
333 | return activationCodes.equals(that.activationCodes); | ||
334 | } | ||
335 | return false; | ||
336 | } | ||
337 | |||
338 | public Solution getSolution() { | ||
339 | return solution; | ||
340 | } | ||
341 | |||
342 | public void setSolution(Solution solution) { | ||
343 | this.solution = solution; | ||
344 | } | ||
345 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java new file mode 100644 index 00000000..ed7a90da --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/Strategies.java | |||
@@ -0,0 +1,123 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api; | ||
10 | |||
11 | import org.eclipse.viatra.dse.api.strategy.impl.BestFirstStrategy; | ||
12 | import org.eclipse.viatra.dse.api.strategy.impl.BreadthFirstStrategy; | ||
13 | import org.eclipse.viatra.dse.api.strategy.impl.DepthFirstStrategy; | ||
14 | import org.eclipse.viatra.dse.api.strategy.impl.FixedPriorityStrategy; | ||
15 | import org.eclipse.viatra.dse.api.strategy.impl.HillClimbingStrategy; | ||
16 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
17 | |||
18 | /** | ||
19 | * Helper class for instantiating strategies. To implement a new strategy use the {@link IStrategy} interface. | ||
20 | * | ||
21 | * @author Andras Szabolcs Nagy | ||
22 | * | ||
23 | */ | ||
24 | public final class Strategies { | ||
25 | |||
26 | private Strategies() { | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * Creates a depth-first search exploration strategy without a depth limit. | ||
31 | * | ||
32 | * @return The strategy. | ||
33 | * @see DepthFirstStrategy | ||
34 | */ | ||
35 | public static DepthFirstStrategy createDfsStrategy() { | ||
36 | return new DepthFirstStrategy(); | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * Creates a depth-first search exploration strategy with a depth limit. A negative depth limit means no | ||
41 | * depth limit, zero means that it will check the initial state. | ||
42 | * | ||
43 | * @param depthLimit | ||
44 | * @return The strategy. | ||
45 | * @see DepthFirstStrategy | ||
46 | */ | ||
47 | public static DepthFirstStrategy createDfsStrategy(int depthLimit) { | ||
48 | return new DepthFirstStrategy(depthLimit); | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * Creates a fixed priority exploration strategy without a depth limit. It is a depth-first search exploration | ||
53 | * strategy but from a current state it only explores the activations with the highest priority. Priorities can be | ||
54 | * defined on the strategy itself. | ||
55 | * | ||
56 | * @return The strategy. | ||
57 | * @see FixedPriorityStrategy | ||
58 | */ | ||
59 | public static FixedPriorityStrategy createFixedPriorityStrategy() { | ||
60 | return createFixedPriorityStrategy(-1); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * Creates a fixed priority exploration strategy with a depth limit, where a zero or negative depth limit means no | ||
65 | * depth limit. It is a depth-first search exploration strategy but from a current state it only explores the | ||
66 | * activations with the highest priority. Priorities can be defined on the strategy itself. | ||
67 | * | ||
68 | * @param depthLimit | ||
69 | * @return The strategy. | ||
70 | * @see FixedPriorityStrategy | ||
71 | */ | ||
72 | public static FixedPriorityStrategy createFixedPriorityStrategy(int depthLimit) { | ||
73 | return new FixedPriorityStrategy().withDepthLimit(depthLimit); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * Creates a breadth-first search exploration strategy without a depth limit. | ||
78 | * | ||
79 | * @return The strategy. | ||
80 | * @see BreadthFirstStrategy | ||
81 | */ | ||
82 | public static BreadthFirstStrategy createBfsStrategy() { | ||
83 | return new BreadthFirstStrategy(); | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * Creates a breadth-first search exploration strategy with a depth limit. A zero or negative depth limit means no | ||
88 | * depth limit. | ||
89 | * | ||
90 | * @param depthLimit | ||
91 | * @return The strategy. | ||
92 | * @see BreadthFirstStrategy | ||
93 | */ | ||
94 | public static BreadthFirstStrategy createBfsStrategy(int depthLimit) { | ||
95 | return new BreadthFirstStrategy(depthLimit); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * Creates a hill climbing exploration strategy. By default, it explores all neighborhood states and chooses the | ||
100 | * best one to continue with until all neighborhood states are dominated by the current state. Other options are | ||
101 | * available on the strategy. | ||
102 | * | ||
103 | * @return The strategy. | ||
104 | * @see HillClimbingStrategy | ||
105 | */ | ||
106 | public static HillClimbingStrategy creatHillClimbingStrategy() { | ||
107 | return new HillClimbingStrategy(); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * See {@link BestFirstStrategy}. | ||
112 | */ | ||
113 | public static BestFirstStrategy createBestFirstStrategy() { | ||
114 | return new BestFirstStrategy(); | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * See {@link BestFirstStrategy}. | ||
119 | */ | ||
120 | public static BestFirstStrategy createBestFirstStrategy(int depthLimit) { | ||
121 | return new BestFirstStrategy(depthLimit); | ||
122 | } | ||
123 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java new file mode 100644 index 00000000..fe5604a1 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BestFirstStrategy.java | |||
@@ -0,0 +1,228 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api.strategy.impl; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.Collection; | ||
13 | import java.util.Iterator; | ||
14 | import java.util.PriorityQueue; | ||
15 | |||
16 | import org.apache.log4j.Logger; | ||
17 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
18 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
19 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
20 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
21 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
22 | |||
23 | /** | ||
24 | * This exploration strategy eventually explorers the whole design space but goes in the most promising directions | ||
25 | * first, based on the {@link Fitness}. | ||
26 | * | ||
27 | * There are a few parameter to tune such as | ||
28 | * <ul> | ||
29 | * <li>maximum depth</li> | ||
30 | * <li>continue the exploration from a state that satisfies the hard objectives (the default that it will | ||
31 | * backtrack),</li> | ||
32 | * <li>whether to continue the exploration from the newly explored state if it is at least equally good than the | ||
33 | * previous one or only if it is better (default is "at least equally good").</li> | ||
34 | * </ul> | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * | ||
38 | */ | ||
39 | public class BestFirstStrategy implements IStrategy { | ||
40 | |||
41 | private ThreadContext context; | ||
42 | private SolutionStore solutionStore; | ||
43 | |||
44 | private int maxDepth; | ||
45 | private boolean isInterrupted = false; | ||
46 | private boolean backTrackIfSolution = true; | ||
47 | private boolean onlyBetterFirst = false; | ||
48 | |||
49 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; | ||
50 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
51 | |||
52 | private static class TrajectoryWithFitness { | ||
53 | |||
54 | public Object[] trajectory; | ||
55 | public Fitness fitness; | ||
56 | |||
57 | public TrajectoryWithFitness(Object[] trajectory, Fitness fitness) { | ||
58 | super(); | ||
59 | this.trajectory = trajectory; | ||
60 | this.fitness = fitness; | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public String toString() { | ||
65 | return Arrays.toString(trajectory) + fitness.toString(); | ||
66 | } | ||
67 | |||
68 | } | ||
69 | |||
70 | /** | ||
71 | * Creates a new best-first search algorithm without depth limit. | ||
72 | */ | ||
73 | public BestFirstStrategy() { | ||
74 | this(-1); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Creates a new best-first search algorithm with depth limit. | ||
79 | * | ||
80 | * @param maxDepth | ||
81 | * A negative <code>maxDepth</code> means no depth limit, zero means the checking of the initial state. | ||
82 | */ | ||
83 | public BestFirstStrategy(int maxDepth) { | ||
84 | if (maxDepth < 0) { | ||
85 | this.maxDepth = Integer.MAX_VALUE; | ||
86 | } else { | ||
87 | this.maxDepth = maxDepth; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | public BestFirstStrategy continueIfHardObjectivesFulfilled() { | ||
92 | backTrackIfSolution = false; | ||
93 | return this; | ||
94 | } | ||
95 | |||
96 | public BestFirstStrategy goOnOnlyIfFitnessIsBetter() { | ||
97 | onlyBetterFirst = true; | ||
98 | return this; | ||
99 | } | ||
100 | |||
101 | @Override | ||
102 | public void initStrategy(ThreadContext context) { | ||
103 | this.context = context; | ||
104 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | ||
105 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | ||
106 | |||
107 | trajectoiresToExplore = new PriorityQueue<TrajectoryWithFitness>(11, | ||
108 | (o1, o2) -> objectiveComparatorHelper.compare(o2.fitness, o1.fitness)); | ||
109 | } | ||
110 | |||
111 | @Override | ||
112 | public void explore() { | ||
113 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | ||
114 | |||
115 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
116 | if (!globalConstraintsAreSatisfied) { | ||
117 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | final Fitness firstFittness = context.calculateFitness(); | ||
122 | if (firstFittness.isSatisifiesHardObjectives()) { | ||
123 | context.newSolution(); | ||
124 | logger.info("First state is a solution. Terminate."); | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | if (maxDepth == 0) { | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); | ||
133 | TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness); | ||
134 | trajectoiresToExplore.add(currentTrajectoryWithFittness); | ||
135 | |||
136 | mainLoop: while (!isInterrupted) { | ||
137 | |||
138 | if (currentTrajectoryWithFittness == null) { | ||
139 | if (trajectoiresToExplore.isEmpty()) { | ||
140 | logger.debug("State space is fully traversed."); | ||
141 | return; | ||
142 | } else { | ||
143 | currentTrajectoryWithFittness = trajectoiresToExplore.element(); | ||
144 | if (logger.isDebugEnabled()) { | ||
145 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness); | ||
146 | } | ||
147 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | Collection<Object> activationIds = context.getUntraversedActivationIds(); | ||
152 | Iterator<Object> iterator = activationIds.iterator(); | ||
153 | |||
154 | while (!isInterrupted && iterator.hasNext()) { | ||
155 | final Object nextActivation = iterator.next(); | ||
156 | if (!iterator.hasNext()) { | ||
157 | logger.debug("Last untraversed activation of the state."); | ||
158 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
159 | } | ||
160 | |||
161 | if (logger.isDebugEnabled()) { | ||
162 | logger.debug("Executing new activation: " + nextActivation); | ||
163 | } | ||
164 | context.executeAcitvationId(nextActivation); | ||
165 | if (context.isCurrentStateAlreadyTraversed()) { | ||
166 | logger.info("The new state is already visited."); | ||
167 | context.backtrack(); | ||
168 | } else if (!context.checkGlobalConstraints()) { | ||
169 | logger.debug("Global contraint is not satisifed."); | ||
170 | context.backtrack(); | ||
171 | } else { | ||
172 | final Fitness nextFitness = context.calculateFitness(); | ||
173 | if (nextFitness.isSatisifiesHardObjectives()) { | ||
174 | solutionStore.newSolution(context); | ||
175 | logger.debug("Found a solution."); | ||
176 | if (backTrackIfSolution) { | ||
177 | context.backtrack(); | ||
178 | continue; | ||
179 | } | ||
180 | } | ||
181 | if (context.getDepth() >= maxDepth) { | ||
182 | logger.debug("Reached max depth."); | ||
183 | context.backtrack(); | ||
184 | continue; | ||
185 | } | ||
186 | |||
187 | TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness( | ||
188 | context.getTrajectory().toArray(), nextFitness); | ||
189 | trajectoiresToExplore.add(nextTrajectoryWithFittness); | ||
190 | |||
191 | int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFittness.fitness, | ||
192 | nextTrajectoryWithFittness.fitness); | ||
193 | if (compare < 0) { | ||
194 | logger.debug("Better fitness, moving on: " + nextFitness); | ||
195 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | ||
196 | continue mainLoop; | ||
197 | } else if (compare == 0) { | ||
198 | if (onlyBetterFirst) { | ||
199 | logger.debug("Equally good fitness, backtrack: " + nextFitness); | ||
200 | context.backtrack(); | ||
201 | continue; | ||
202 | } else { | ||
203 | logger.debug("Equally good fitness, moving on: " + nextFitness); | ||
204 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | ||
205 | continue mainLoop; | ||
206 | } | ||
207 | } else { | ||
208 | logger.debug("Worse fitness."); | ||
209 | currentTrajectoryWithFittness = null; | ||
210 | continue mainLoop; | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | logger.debug("State is fully traversed."); | ||
216 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
217 | currentTrajectoryWithFittness = null; | ||
218 | |||
219 | } | ||
220 | logger.info("Interrupted."); | ||
221 | } | ||
222 | |||
223 | @Override | ||
224 | public void interruptStrategy() { | ||
225 | isInterrupted = true; | ||
226 | } | ||
227 | |||
228 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java new file mode 100644 index 00000000..6b7d9817 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/BreadthFirstStrategy.java | |||
@@ -0,0 +1,220 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api.strategy.impl; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.Iterator; | ||
13 | import java.util.concurrent.BrokenBarrierException; | ||
14 | import java.util.concurrent.ConcurrentLinkedQueue; | ||
15 | import java.util.concurrent.CyclicBarrier; | ||
16 | import java.util.concurrent.atomic.AtomicBoolean; | ||
17 | |||
18 | import org.apache.log4j.Logger; | ||
19 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
20 | import org.eclipse.viatra.dse.base.GlobalContext; | ||
21 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
22 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
23 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
24 | |||
25 | /** | ||
26 | * A breadth-first search algorithm implementation, that | ||
27 | * <ul> | ||
28 | * <li>can work with multiple threads,</li> | ||
29 | * <li>indeterministic,</li> | ||
30 | * <li>saves all states (trajectories) as solutions that fulfill all the hard objectives,</li> | ||
31 | * <li>can have a depth limit,</li> | ||
32 | * <li>will backtrack when a model satisfies the hard objectives (after saving it as a solution) and will not explore | ||
33 | * beyond that state.</li> | ||
34 | * </ul> | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * | ||
38 | */ | ||
39 | public class BreadthFirstStrategy implements IStrategy { | ||
40 | |||
41 | private static final class BfsSharedObject { | ||
42 | private final ConcurrentLinkedQueue<Object[]> trajectoryQueue1 = new ConcurrentLinkedQueue<>(); | ||
43 | private final ConcurrentLinkedQueue<Object[]> trajectoryQueue2 = new ConcurrentLinkedQueue<>(); | ||
44 | |||
45 | private final AtomicBoolean pushToQueue1 = new AtomicBoolean(false); | ||
46 | private final AtomicBoolean designSpaceTraversed = new AtomicBoolean(false); | ||
47 | |||
48 | public final CyclicBarrier barrier; | ||
49 | |||
50 | public BfsSharedObject(int numberOfThreads) { | ||
51 | barrier = new CyclicBarrier(numberOfThreads, () -> { | ||
52 | boolean oldValue = pushToQueue1.get(); | ||
53 | pushToQueue1.set(!oldValue); | ||
54 | if (trajectoryQueue1.isEmpty() && trajectoryQueue2.isEmpty()) { | ||
55 | designSpaceTraversed.set(true); | ||
56 | } | ||
57 | }); | ||
58 | } | ||
59 | |||
60 | public Object[] poll() { | ||
61 | if (pushToQueue1.get()) { | ||
62 | return trajectoryQueue2.poll(); | ||
63 | } else { | ||
64 | return trajectoryQueue1.poll(); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | public void push(Object[] trajectory) { | ||
69 | if (pushToQueue1.get()) { | ||
70 | trajectoryQueue1.add(trajectory); | ||
71 | } else { | ||
72 | trajectoryQueue2.add(trajectory); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | public boolean isDesignSpaceTraversed() { | ||
77 | return designSpaceTraversed.get(); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | private int maxDepth = 0; | ||
82 | private BfsSharedObject shared; | ||
83 | private boolean isInterrupted = false; | ||
84 | private ThreadContext context; | ||
85 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
86 | private SolutionStore solutionStore; | ||
87 | private boolean isFirstThread = false; | ||
88 | |||
89 | /** | ||
90 | * Creates a new breadth-first search algorithm without depth limit. | ||
91 | */ | ||
92 | public BreadthFirstStrategy() { | ||
93 | this.maxDepth = Integer.MAX_VALUE; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * Creates a new breadth-first search algorithm with depth limit. | ||
98 | * | ||
99 | * @param maxDepth | ||
100 | * A negative <code>maxDepth</code> means no depth limit, zero means the checking of the initial state. | ||
101 | */ | ||
102 | public BreadthFirstStrategy(int maxDepth) { | ||
103 | if (maxDepth < 0) { | ||
104 | this.maxDepth = Integer.MAX_VALUE; | ||
105 | } else { | ||
106 | this.maxDepth = maxDepth; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | @Override | ||
111 | public void initStrategy(ThreadContext context) { | ||
112 | this.context = context; | ||
113 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | ||
114 | |||
115 | GlobalContext globalContext = context.getGlobalContext(); | ||
116 | if (globalContext.getSharedObject() == null) { | ||
117 | isFirstThread = true; | ||
118 | shared = new BfsSharedObject(globalContext.getThreadPool().getMaximumPoolSize()); | ||
119 | globalContext.setSharedObject(shared); | ||
120 | logger.info("Breadth-first exploration strategy is inited."); | ||
121 | } else { | ||
122 | shared = (BfsSharedObject) globalContext.getSharedObject(); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | @Override | ||
127 | public void explore() { | ||
128 | |||
129 | if (isFirstThread) { | ||
130 | |||
131 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
132 | if (!globalConstraintsAreSatisfied) { | ||
133 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | Fitness fitness = context.calculateFitness(); | ||
138 | if (fitness.isSatisifiesHardObjectives()) { | ||
139 | context.newSolution(); | ||
140 | logger.info("First state is a solution. Terminate."); | ||
141 | return; | ||
142 | } | ||
143 | |||
144 | Object[] currentTrajectory = context.getTrajectory().toArray(new Object[0]); | ||
145 | |||
146 | shared.push(currentTrajectory); | ||
147 | |||
148 | startThreads(); | ||
149 | } else { | ||
150 | try { | ||
151 | shared.barrier.await(); | ||
152 | } catch (InterruptedException | BrokenBarrierException e) { | ||
153 | } | ||
154 | } | ||
155 | |||
156 | mainLoop: while (!isInterrupted && !shared.isDesignSpaceTraversed()) { | ||
157 | |||
158 | Object[] next = shared.poll(); | ||
159 | while (next == null) { | ||
160 | try { | ||
161 | logger.debug("Reached barrier."); | ||
162 | shared.barrier.await(); | ||
163 | } catch (InterruptedException | BrokenBarrierException e1) { | ||
164 | } | ||
165 | if (isInterrupted || shared.isDesignSpaceTraversed()) { | ||
166 | break mainLoop; | ||
167 | } | ||
168 | next = shared.poll(); | ||
169 | } | ||
170 | |||
171 | context.backtrackUntilRoot(); | ||
172 | |||
173 | context.executeTrajectory(next); | ||
174 | |||
175 | Collection<Object> activationIds = context.getCurrentActivationIds(); | ||
176 | int i = activationIds.size() - 1; | ||
177 | |||
178 | while (!isInterrupted && i >= 0) { | ||
179 | |||
180 | Iterator<Object> iterator = activationIds.iterator(); | ||
181 | int index = i--; | ||
182 | while (iterator.hasNext() && index > 0) { | ||
183 | index--; | ||
184 | iterator.next(); | ||
185 | } | ||
186 | Object activationIdToTry = iterator.next(); | ||
187 | |||
188 | context.executeAcitvationId(activationIdToTry); | ||
189 | |||
190 | if (context.isCurrentStateAlreadyTraversed()) { | ||
191 | logger.info("The new state is already visited."); | ||
192 | } else if (!context.checkGlobalConstraints()) { | ||
193 | logger.debug("Global contraint is not satisifed."); | ||
194 | } else if (context.calculateFitness().isSatisifiesHardObjectives()) { | ||
195 | solutionStore.newSolution(context); | ||
196 | logger.debug("Found a solution."); | ||
197 | } else if (context.getDepth() >= maxDepth) { | ||
198 | logger.debug("Reached max depth."); | ||
199 | } else { | ||
200 | Object[] currentTrajectory = context.getTrajectory().toArray(new Object[0]); | ||
201 | shared.push(currentTrajectory); | ||
202 | } | ||
203 | |||
204 | context.backtrack(); | ||
205 | } | ||
206 | |||
207 | } | ||
208 | } | ||
209 | |||
210 | private void startThreads() { | ||
211 | context.startAllThreads(() -> new BreadthFirstStrategy(maxDepth)); | ||
212 | } | ||
213 | |||
214 | @Override | ||
215 | public void interruptStrategy() { | ||
216 | isInterrupted = true; | ||
217 | shared.barrier.reset(); | ||
218 | } | ||
219 | |||
220 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java new file mode 100644 index 00000000..22a4a683 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/DepthFirstStrategy.java | |||
@@ -0,0 +1,188 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api.strategy.impl; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.Iterator; | ||
13 | import java.util.Random; | ||
14 | import java.util.concurrent.atomic.AtomicBoolean; | ||
15 | |||
16 | import org.apache.log4j.Logger; | ||
17 | import org.eclipse.viatra.dse.api.DSEException; | ||
18 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
19 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
20 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
21 | |||
22 | /** | ||
23 | * A depth-first search algorithm implementation, that | ||
24 | * <ul> | ||
25 | * <li>can work with multiple threads,</li> | ||
26 | * <li>randomly traverses the search space,</li> | ||
27 | * <li>saves all states (trajectories) as solutions that fulfill all the hard objectives,</li> | ||
28 | * <li>can have a depth limit,</li> | ||
29 | * <li>will backtrack when a model satisfies the hard objectives (after saving it as a solution), which can be modified | ||
30 | * by calling {@link #continueIfHardObjectivesFulfilled()}</li> | ||
31 | * </ul> | ||
32 | * | ||
33 | * @author Andras Szabolcs Nagy | ||
34 | * | ||
35 | */ | ||
36 | public class DepthFirstStrategy implements IStrategy { | ||
37 | |||
38 | private int maxDepth; | ||
39 | private AtomicBoolean isInterrupted = new AtomicBoolean(false); | ||
40 | private ThreadContext context; | ||
41 | |||
42 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
43 | |||
44 | private Random random = new Random(); | ||
45 | private boolean backTrackIfSolution = true; | ||
46 | |||
47 | /** | ||
48 | * Creates a new depth-first search algorithm without depth limit. | ||
49 | */ | ||
50 | public DepthFirstStrategy() { | ||
51 | this.maxDepth = Integer.MAX_VALUE; | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * Creates a new depth-first search algorithm with depth limit. | ||
56 | * | ||
57 | * @param maxDepth | ||
58 | * A negative <code>maxDepth</code> means no depth limit, zero means the checking of the initial state. | ||
59 | */ | ||
60 | public DepthFirstStrategy(int maxDepth) { | ||
61 | if (maxDepth < 0) { | ||
62 | this.maxDepth = Integer.MAX_VALUE; | ||
63 | } else { | ||
64 | this.maxDepth = maxDepth; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * If called, the algorithm will not backtrack after the hard objectives are fulfilled, instead it goes deeper in | ||
70 | * the search space. | ||
71 | */ | ||
72 | public DepthFirstStrategy continueIfHardObjectivesFulfilled() { | ||
73 | backTrackIfSolution = false; | ||
74 | return this; | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public void initStrategy(ThreadContext context) { | ||
79 | this.context = context; | ||
80 | |||
81 | if (context.getSharedObject() == null) { | ||
82 | context.setSharedObject(new Object()); | ||
83 | logger.info("Depth-first exploration strategy is initied."); | ||
84 | startThreads(); | ||
85 | } | ||
86 | |||
87 | } | ||
88 | |||
89 | private void startThreads() { | ||
90 | context.startAllThreads(() -> new DepthFirstStrategy(maxDepth)); | ||
91 | } | ||
92 | |||
93 | @Override | ||
94 | public void explore() { | ||
95 | |||
96 | mainloop: do { | ||
97 | |||
98 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
99 | if (!globalConstraintsAreSatisfied) { | ||
100 | boolean isSuccessfulUndo = context.backtrack(); | ||
101 | if (!isSuccessfulUndo) { | ||
102 | logger.info("Global contraint is not satisifed and cannot backtrack."); | ||
103 | break; | ||
104 | } else { | ||
105 | logger.debug("Global contraint is not satisifed, backtrack."); | ||
106 | continue; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | Fitness fitness = context.calculateFitness(); | ||
111 | if (fitness.isSatisifiesHardObjectives()) { | ||
112 | context.newSolution(); | ||
113 | if (backTrackIfSolution) { | ||
114 | boolean isSuccessfulUndo = context.backtrack(); | ||
115 | if (!isSuccessfulUndo) { | ||
116 | logger.info("Found a solution but cannot backtrack."); | ||
117 | break; | ||
118 | } else { | ||
119 | logger.debug("Found a solution, backtrack."); | ||
120 | continue; | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (context.getDepth() >= maxDepth) { | ||
126 | boolean isSuccessfulUndo = context.backtrack(); | ||
127 | if (!isSuccessfulUndo) { | ||
128 | logger.info("Reached max depth but cannot bactrack."); | ||
129 | break; | ||
130 | } else { | ||
131 | logger.debug("Reached max depth, bactrack."); | ||
132 | continue; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | if (isInterrupted.get()) { | ||
137 | logger.info("Interrupted, stop exploration."); | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | Object activationId = null; | ||
142 | Collection<Object> activationIds; | ||
143 | |||
144 | do { | ||
145 | activationIds = context.getUntraversedActivationIds(); | ||
146 | if (activationIds.isEmpty()) { | ||
147 | boolean isSuccessfulUndo = context.backtrack(); | ||
148 | if (!isSuccessfulUndo) { | ||
149 | logger.info("No more transitions from current state and cannot backtrack."); | ||
150 | break mainloop; | ||
151 | } else { | ||
152 | logger.debug("No more transitions from current state, backtrack."); | ||
153 | continue; | ||
154 | } | ||
155 | } | ||
156 | } while (activationIds.isEmpty()); | ||
157 | |||
158 | int index = random.nextInt(activationIds.size()); | ||
159 | |||
160 | Iterator<Object> iterator = activationIds.iterator(); | ||
161 | while (index-- > 0) { | ||
162 | iterator.next(); | ||
163 | } | ||
164 | activationId = iterator.next(); | ||
165 | |||
166 | context.executeAcitvationId(activationId); | ||
167 | |||
168 | boolean loopInTrajectory = context.isCurrentStateInTrajectory(); | ||
169 | if (loopInTrajectory) { | ||
170 | boolean isSuccessfulUndo = context.backtrack(); | ||
171 | if (!isSuccessfulUndo) { | ||
172 | throw new DSEException("The new state is present in the trajectoy but cannot bactkrack. Should never happen!"); | ||
173 | } else { | ||
174 | logger.info("The new state is already visited in the trajectory, backtrack."); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | } while (true); | ||
179 | |||
180 | logger.info("Terminated."); | ||
181 | } | ||
182 | |||
183 | @Override | ||
184 | public void interruptStrategy() { | ||
185 | isInterrupted.set(true); | ||
186 | } | ||
187 | |||
188 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java new file mode 100644 index 00000000..4ccda4ce --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/FixedPriorityStrategy.java | |||
@@ -0,0 +1,208 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api.strategy.impl; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.List; | ||
14 | import java.util.Map; | ||
15 | import java.util.Random; | ||
16 | import java.util.concurrent.atomic.AtomicBoolean; | ||
17 | |||
18 | import org.apache.log4j.Logger; | ||
19 | import org.eclipse.viatra.dse.api.DSEException; | ||
20 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
21 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
22 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
23 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
24 | |||
25 | import com.google.common.collect.Lists; | ||
26 | |||
27 | /** | ||
28 | * Works as {@link DepthFirstStrategy} but: | ||
29 | * <ul> | ||
30 | * <li>works only with single thread,</li> | ||
31 | * <li>in a given state, it only traverses the activations with locally the highest priority.</li> | ||
32 | * </ul> | ||
33 | * | ||
34 | * @author Andras Szabolcs Nagy | ||
35 | * | ||
36 | */ | ||
37 | public class FixedPriorityStrategy implements IStrategy { | ||
38 | |||
39 | private int maxDepth = Integer.MAX_VALUE; | ||
40 | private AtomicBoolean isInterrupted = new AtomicBoolean(false); | ||
41 | private ThreadContext context; | ||
42 | |||
43 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
44 | private Map<BatchTransformationRule<?, ?>, Integer> priorities = new HashMap<BatchTransformationRule<?, ?>, Integer>(); | ||
45 | |||
46 | private Random random = new Random(); | ||
47 | private Map<Object, List<Object>> bestPriorityInState = new HashMap<>(); | ||
48 | |||
49 | /** | ||
50 | * Adds a depth limit to the strategy. | ||
51 | * | ||
52 | * @param depthLimit | ||
53 | * The depth limit. | ||
54 | * @return The actual instance to enable a builder pattern like usage. | ||
55 | */ | ||
56 | public FixedPriorityStrategy withDepthLimit(int maxDepth) { | ||
57 | if (maxDepth < 0) { | ||
58 | this.maxDepth = Integer.MAX_VALUE; | ||
59 | } else { | ||
60 | this.maxDepth = maxDepth; | ||
61 | } | ||
62 | return this; | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * Assigns a priority to a rule. Unassigned rule will have a priority of 0. | ||
67 | * | ||
68 | * @param rule | ||
69 | * The transformation rule. | ||
70 | * @param priority | ||
71 | * The priority of the rule. Higher is better. | ||
72 | * @return The actual instance to enable a builder pattern like usage. | ||
73 | */ | ||
74 | public FixedPriorityStrategy withRulePriority(BatchTransformationRule<?, ?> rule, int priority) { | ||
75 | priorities.put(rule, priority); | ||
76 | return this; | ||
77 | } | ||
78 | |||
79 | public Map<BatchTransformationRule<?, ?>, Integer> getPriorities() { | ||
80 | return priorities; | ||
81 | } | ||
82 | |||
83 | @Override | ||
84 | public void initStrategy(ThreadContext context) { | ||
85 | this.context = context; | ||
86 | |||
87 | logger.info("Fixed priority exploration strategy is initied."); | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public void explore() { | ||
92 | |||
93 | mainloop: do { | ||
94 | |||
95 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
96 | if (!globalConstraintsAreSatisfied) { | ||
97 | boolean isSuccessfulUndo = context.backtrack(); | ||
98 | if (!isSuccessfulUndo) { | ||
99 | logger.info("Global contraint is not satisifed and cannot backtrack."); | ||
100 | break; | ||
101 | } else { | ||
102 | logger.debug("Global contraint is not satisifed, backtrack."); | ||
103 | continue; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | Fitness fitness = context.calculateFitness(); | ||
108 | if (fitness.isSatisifiesHardObjectives()) { | ||
109 | context.newSolution(); | ||
110 | boolean isSuccessfulUndo = context.backtrack(); | ||
111 | if (!isSuccessfulUndo) { | ||
112 | logger.info("Found a solution but cannot backtrack."); | ||
113 | break; | ||
114 | } else { | ||
115 | logger.debug("Found a solution, backtrack."); | ||
116 | continue; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | if (context.getDepth() >= maxDepth) { | ||
121 | boolean isSuccessfulUndo = context.backtrack(); | ||
122 | if (!isSuccessfulUndo) { | ||
123 | logger.info("Reached max depth but cannot bactrack."); | ||
124 | break; | ||
125 | } else { | ||
126 | logger.debug("Reached max depth, bactrack."); | ||
127 | continue; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | if (isInterrupted.get()) { | ||
132 | logger.info("Interrupted, stop exploration."); | ||
133 | break; | ||
134 | } | ||
135 | |||
136 | List<Object> transitions; | ||
137 | |||
138 | do { | ||
139 | |||
140 | transitions = bestPriorityInState.get(context.getCurrentStateId()); | ||
141 | |||
142 | if (transitions == null) { | ||
143 | Integer bestPriority = getBestPriority(context.getCurrentActivationIds()); | ||
144 | transitions = Lists.newArrayList(); | ||
145 | for (Object iTransition : context.getCurrentActivationIds()) { | ||
146 | Integer integer = priorities.get(context.getRuleByActivationId(iTransition)); | ||
147 | if (integer == null) { | ||
148 | integer = Integer.valueOf(0); | ||
149 | } | ||
150 | if (integer.equals(bestPriority)) { | ||
151 | transitions.add(iTransition); | ||
152 | } | ||
153 | } | ||
154 | bestPriorityInState.put(context.getCurrentStateId(), transitions); | ||
155 | } | ||
156 | |||
157 | if (transitions.isEmpty()) { | ||
158 | boolean isSuccessfulUndo = context.backtrack(); | ||
159 | if (!isSuccessfulUndo) { | ||
160 | logger.info("No more transitions from current state and cannot backtrack."); | ||
161 | break mainloop; | ||
162 | } else { | ||
163 | logger.debug("No more transitions from current state, backtrack."); | ||
164 | continue; | ||
165 | } | ||
166 | } | ||
167 | } while (transitions.isEmpty()); | ||
168 | |||
169 | int index = random.nextInt(transitions.size()); | ||
170 | Object transition = transitions.remove(index); | ||
171 | |||
172 | context.executeAcitvationId(transition); | ||
173 | |||
174 | boolean loopInTrajectory = context.isCurrentStateInTrajectory(); | ||
175 | if (loopInTrajectory) { | ||
176 | boolean isSuccessfulUndo = context.backtrack(); | ||
177 | if (!isSuccessfulUndo) { | ||
178 | throw new DSEException( | ||
179 | "The new state is present in the trajectoy but cannot bactkrack. Should never happen!"); | ||
180 | } else { | ||
181 | logger.info("The new state is already visited in the trajectory, backtrack."); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | } while (true); | ||
186 | |||
187 | logger.info("Terminated."); | ||
188 | } | ||
189 | |||
190 | @Override | ||
191 | public void interruptStrategy() { | ||
192 | isInterrupted.set(true); | ||
193 | } | ||
194 | |||
195 | private Integer getBestPriority(Collection<? extends Object> transitions) { | ||
196 | Integer bestPriority = Integer.MIN_VALUE; | ||
197 | for (Object iTransition : transitions) { | ||
198 | Integer priority = priorities.get(context.getRuleByActivationId(iTransition)); | ||
199 | if (priority == null) { | ||
200 | priority = Integer.valueOf(0); | ||
201 | } | ||
202 | if (priority > bestPriority) { | ||
203 | bestPriority = priority; | ||
204 | } | ||
205 | } | ||
206 | return bestPriority; | ||
207 | } | ||
208 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java new file mode 100644 index 00000000..0ccb0668 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/HillClimbingStrategy.java | |||
@@ -0,0 +1,142 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api.strategy.impl; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.Random; | ||
14 | import java.util.concurrent.atomic.AtomicBoolean; | ||
15 | |||
16 | import org.apache.log4j.Logger; | ||
17 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
18 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
19 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
20 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
21 | import org.eclipse.viatra.dse.objectives.TrajectoryFitness; | ||
22 | |||
23 | public class HillClimbingStrategy implements IStrategy { | ||
24 | |||
25 | private AtomicBoolean isInterrupted = new AtomicBoolean(false); | ||
26 | private ThreadContext context; | ||
27 | |||
28 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
29 | |||
30 | private Random random = new Random(); | ||
31 | private double percentOfOpenedStates; | ||
32 | private ObjectiveComparatorHelper objectiveComparatorHelper; | ||
33 | |||
34 | public HillClimbingStrategy() { | ||
35 | this(2); | ||
36 | } | ||
37 | |||
38 | public HillClimbingStrategy(double percentOfOpenedStates) { | ||
39 | this.percentOfOpenedStates = percentOfOpenedStates; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public void initStrategy(ThreadContext context) { | ||
44 | this.context = context; | ||
45 | objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | ||
46 | logger.info("Hill climbing exploration strategy is initied."); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public void explore() { | ||
51 | |||
52 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
53 | if (!globalConstraintsAreSatisfied) { | ||
54 | boolean isSuccessfulUndo = context.backtrack(); | ||
55 | if (!isSuccessfulUndo) { | ||
56 | logger.info("Global contraint is not satisifed and cannot backtrack."); | ||
57 | return; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | mainloop: do { | ||
62 | |||
63 | Fitness previousFitness = context.calculateFitness(); | ||
64 | |||
65 | logger.debug("Current depth: " + context.getDepth() + " Fitness: " + previousFitness); | ||
66 | |||
67 | Collection<Object> transitionsFromCurrentState = context.getCurrentActivationIds(); | ||
68 | |||
69 | while (transitionsFromCurrentState.isEmpty()) { | ||
70 | logger.debug("No transitions from current state: considered as a solution."); | ||
71 | saveSolutionAndBacktrack(); | ||
72 | continue mainloop; | ||
73 | } | ||
74 | |||
75 | ArrayList<Object> transitionsToTry = new ArrayList<>(transitionsFromCurrentState.size()); | ||
76 | for (Object transition : transitionsFromCurrentState) { | ||
77 | transitionsToTry.add(transition); | ||
78 | } | ||
79 | double numberOfTransitionsToTry = transitionsToTry.size() * percentOfOpenedStates; | ||
80 | |||
81 | for (; numberOfTransitionsToTry > 0 && !transitionsToTry.isEmpty(); numberOfTransitionsToTry--) { | ||
82 | int index = random.nextInt(transitionsToTry.size()); | ||
83 | Object transition = transitionsToTry.remove(index); | ||
84 | |||
85 | context.executeAcitvationId(transition); | ||
86 | |||
87 | if (!context.checkGlobalConstraints()) { | ||
88 | logger.debug("Global contraint is not satisifed, backtrack."); | ||
89 | context.backtrack(); | ||
90 | continue; | ||
91 | } | ||
92 | if (context.isCurrentStateInTrajectory()) { | ||
93 | logger.debug("Current state is in trajectory, backtrack."); | ||
94 | context.backtrack(); | ||
95 | continue; | ||
96 | } | ||
97 | |||
98 | Fitness fitness = context.calculateFitness(); | ||
99 | objectiveComparatorHelper.addTrajectoryFitness( | ||
100 | new TrajectoryFitness(context.getTrajectoryInfo().getLastActivationId(), fitness)); | ||
101 | context.backtrack(); | ||
102 | } | ||
103 | |||
104 | if (objectiveComparatorHelper.getTrajectoryFitnesses().isEmpty()) { | ||
105 | logger.debug("No viable transitions from current state: considered as a solution."); | ||
106 | saveSolutionAndBacktrack(); | ||
107 | continue; | ||
108 | } | ||
109 | |||
110 | TrajectoryFitness randomBestFitness = objectiveComparatorHelper.getRandomBest(); | ||
111 | objectiveComparatorHelper.clearTrajectoryFitnesses(); | ||
112 | |||
113 | int compare = objectiveComparatorHelper.compare(previousFitness, randomBestFitness.fitness); | ||
114 | |||
115 | if (compare > 0) { | ||
116 | saveSolutionAndBacktrack(); | ||
117 | continue; | ||
118 | } else { | ||
119 | previousFitness = randomBestFitness.fitness; | ||
120 | Object transition = randomBestFitness.trajectory[randomBestFitness.trajectory.length - 1]; | ||
121 | context.executeAcitvationId(transition); | ||
122 | } | ||
123 | |||
124 | } while (!isInterrupted.get()); | ||
125 | |||
126 | logger.info("Terminated."); | ||
127 | } | ||
128 | |||
129 | private void saveSolutionAndBacktrack() { | ||
130 | context.calculateFitness(); | ||
131 | context.newSolution(); | ||
132 | logger.debug("Found solution: " + context.getTrajectoryInfo().toString()); | ||
133 | logger.debug("Backtrack for more solutions, if needed."); | ||
134 | context.backtrackUntilRoot(); | ||
135 | } | ||
136 | |||
137 | @Override | ||
138 | public void interruptStrategy() { | ||
139 | isInterrupted.set(true); | ||
140 | } | ||
141 | |||
142 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java new file mode 100644 index 00000000..af8fb8cc --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/impl/RandomSearchStrategy.java | |||
@@ -0,0 +1,163 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api.strategy.impl; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.Iterator; | ||
13 | import java.util.Random; | ||
14 | import java.util.concurrent.atomic.AtomicBoolean; | ||
15 | import java.util.concurrent.atomic.AtomicInteger; | ||
16 | |||
17 | import org.apache.log4j.Logger; | ||
18 | import org.eclipse.viatra.dse.api.DSEException; | ||
19 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
20 | import org.eclipse.viatra.dse.base.GlobalContext; | ||
21 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
22 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
23 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
24 | |||
25 | public class RandomSearchStrategy implements IStrategy { | ||
26 | |||
27 | private static class SharedData { | ||
28 | public final AtomicInteger triesLeft; | ||
29 | public final int minDepth; | ||
30 | public final int maxDepth; | ||
31 | |||
32 | public SharedData(int minDepth, int maxDepth, int numberOfTries) { | ||
33 | this.minDepth = minDepth; | ||
34 | this.maxDepth = maxDepth; | ||
35 | this.triesLeft = new AtomicInteger(numberOfTries); | ||
36 | } | ||
37 | } | ||
38 | |||
39 | private int maxDepth = -1; | ||
40 | private Random rnd = new Random(); | ||
41 | private SharedData shared; | ||
42 | private TrajectoryInfo trajectoryInfo; | ||
43 | int nth; | ||
44 | private ThreadContext context; | ||
45 | private AtomicBoolean isInterrupted = new AtomicBoolean(false); | ||
46 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
47 | |||
48 | public RandomSearchStrategy(int minDepth, int maxDepth, int numberOfTries) { | ||
49 | shared = new SharedData(minDepth, maxDepth, numberOfTries); | ||
50 | } | ||
51 | |||
52 | private RandomSearchStrategy() { | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public void initStrategy(ThreadContext context) { | ||
57 | this.context = context; | ||
58 | trajectoryInfo = context.getTrajectoryInfo(); | ||
59 | GlobalContext gc = context.getGlobalContext(); | ||
60 | |||
61 | Object sharedObject = gc.getSharedObject(); | ||
62 | if (sharedObject == null) { | ||
63 | gc.setSharedObject(shared); | ||
64 | logger.info("Random exploration strategy is initied."); | ||
65 | startThreads(); | ||
66 | } else { | ||
67 | shared = (SharedData) sharedObject; | ||
68 | } | ||
69 | |||
70 | maxDepth = rnd.nextInt(shared.maxDepth - shared.minDepth) + shared.minDepth; | ||
71 | |||
72 | } | ||
73 | |||
74 | @Override | ||
75 | public void explore() { | ||
76 | |||
77 | do { | ||
78 | |||
79 | boolean globalConstraintsAreSatisfied = context.checkGlobalConstraints(); | ||
80 | if (!globalConstraintsAreSatisfied) { | ||
81 | boolean isSuccessfulUndo = context.backtrack(); | ||
82 | if (!isSuccessfulUndo) { | ||
83 | logger.info("Global contraint is not satisifed and cannot backtrack."); | ||
84 | break; | ||
85 | } else { | ||
86 | logger.debug("Global contraint is not satisifed, backtrack."); | ||
87 | continue; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | Fitness fitness = context.calculateFitness(); | ||
92 | if (fitness.isSatisifiesHardObjectives()) { | ||
93 | context.newSolution(); | ||
94 | boolean isSuccessfulUndo = context.backtrack(); | ||
95 | if (!isSuccessfulUndo) { | ||
96 | logger.info("Found a solution but cannot backtrack."); | ||
97 | break; | ||
98 | } else { | ||
99 | logger.debug("Found a solution, backtrack."); | ||
100 | continue; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | if (trajectoryInfo.getDepth() < maxDepth) { | ||
105 | |||
106 | Collection<Object> transitions = context.getCurrentActivationIds(); | ||
107 | int index = rnd.nextInt(transitions.size()); | ||
108 | Object transition = getByIndex(transitions, index); | ||
109 | context.executeAcitvationId(transition); | ||
110 | |||
111 | } else { | ||
112 | |||
113 | nth = shared.triesLeft.getAndDecrement(); | ||
114 | logger.debug(nth + " tries left"); | ||
115 | if (nth > 0) { | ||
116 | |||
117 | context.backtrackUntilRoot(); | ||
118 | maxDepth = rnd.nextInt(shared.maxDepth - shared.minDepth) + shared.minDepth; | ||
119 | |||
120 | } else { | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | boolean loopInTrajectory = context.isCurrentStateInTrajectory(); | ||
126 | if (loopInTrajectory) { | ||
127 | boolean isSuccessfulUndo = context.backtrack(); | ||
128 | if (!isSuccessfulUndo) { | ||
129 | throw new DSEException( | ||
130 | "The new state is present in the trajectoy but cannot bactkrack. Should never happen!"); | ||
131 | } else { | ||
132 | logger.info("The new state is already visited in the trajectory, backtrack."); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | } while (isInterrupted.get()); | ||
137 | |||
138 | logger.info("Terminated."); | ||
139 | } | ||
140 | |||
141 | @Override | ||
142 | public void interruptStrategy() { | ||
143 | isInterrupted.set(true); | ||
144 | } | ||
145 | |||
146 | private void startThreads() { | ||
147 | context.startAllThreads(RandomSearchStrategy::new); | ||
148 | } | ||
149 | |||
150 | private static Object getByIndex(Collection<Object> availableTransitions, int index) { | ||
151 | int i = 0; | ||
152 | Iterator<Object> iterator = availableTransitions.iterator(); | ||
153 | while (iterator.hasNext()) { | ||
154 | Object transition = iterator.next(); | ||
155 | if (i == index) { | ||
156 | return transition; | ||
157 | } else { | ||
158 | ++i; | ||
159 | } | ||
160 | } | ||
161 | throw new IndexOutOfBoundsException("size: " + availableTransitions.size() + ", index: " + index); | ||
162 | } | ||
163 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java new file mode 100644 index 00000000..8c164396 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategy.java | |||
@@ -0,0 +1,44 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api.strategy.interfaces; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
13 | |||
14 | /** | ||
15 | * This high level interface is responsible for defining basic operations of an exploration strategy. | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public interface IStrategy { | ||
21 | |||
22 | /** | ||
23 | * Initializes the strategy with a specific {@link ThreadContext}. | ||
24 | * | ||
25 | * @param context | ||
26 | * The context. | ||
27 | */ | ||
28 | void initStrategy(ThreadContext context); | ||
29 | |||
30 | /** | ||
31 | * This method explores the design space as the implementation specifies. It will be called only once, hence the | ||
32 | * exploration loop is run by the implementation. The termination condition is also specified by the implementation | ||
33 | * and when it returns the exploration thread will be disposed. | ||
34 | */ | ||
35 | void explore(); | ||
36 | |||
37 | /** | ||
38 | * The implementation of this interface should be ready to be interrupted. If this method is called, the | ||
39 | * {@link IStrategy#explore()} method should return ASAP. | ||
40 | * | ||
41 | * This method is also called by the {@link SolutionStore} class if enough solutions are found. | ||
42 | */ | ||
43 | void interruptStrategy(); | ||
44 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java new file mode 100644 index 00000000..b3352d13 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/api/strategy/interfaces/IStrategyFactory.java | |||
@@ -0,0 +1,13 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.api.strategy.interfaces; | ||
10 | |||
11 | public interface IStrategyFactory { | ||
12 | IStrategy createStrategy(); | ||
13 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java new file mode 100644 index 00000000..d3990c23 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ActivationCodesConflictSet.java | |||
@@ -0,0 +1,213 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.HashSet; | ||
14 | import java.util.Map; | ||
15 | import java.util.Objects; | ||
16 | import java.util.Set; | ||
17 | |||
18 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
19 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
20 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
21 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
22 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
23 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictSet; | ||
24 | |||
25 | public class ActivationCodesConflictSet implements ChangeableConflictSet { | ||
26 | |||
27 | private static class ActivationCodesMultiBiMap { | ||
28 | public Map<Activation<?>, Object> activationsToCodes = new HashMap<>(); | ||
29 | public Map<Object, Set<Activation<?>>> codesToActivations = new HashMap<>(); | ||
30 | |||
31 | public void addActivation(Activation<?> activation, Object activationCode) { | ||
32 | activationsToCodes.put(activation, activationCode); | ||
33 | codesToActivations.computeIfAbsent(activationCode, k -> new HashSet<>()).add(activation); | ||
34 | } | ||
35 | |||
36 | public void removeActivaion(Activation<?> activation) { | ||
37 | Object activationCode = activationsToCodes.remove(activation); | ||
38 | Set<Activation<?>> activations = codesToActivations.get(activationCode); | ||
39 | if (activations != null) { | ||
40 | activations.remove(activation); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | public void clear() { | ||
45 | activationsToCodes.clear(); | ||
46 | codesToActivations.clear(); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | protected ActivationCodesMultiBiMap activationCodes; | ||
51 | protected IStateCoder stateCoder; | ||
52 | |||
53 | protected Set<Activation<?>> newActivations = new HashSet<>(); | ||
54 | protected Set<Activation<?>> removedActivations = new HashSet<>(); | ||
55 | // private Logger logger = Logger.getLogger(getClass()); | ||
56 | |||
57 | private boolean isIncremental = false; | ||
58 | private ConflictSet nextActivationsConflictSet; | ||
59 | |||
60 | public void setIncremental(boolean isIncremental) { | ||
61 | this.isIncremental = isIncremental; | ||
62 | } | ||
63 | |||
64 | public ActivationCodesConflictSet(ConflictSet nextActivationsConflictSet, IStateCoder stateCoder) { | ||
65 | Objects.requireNonNull(nextActivationsConflictSet); | ||
66 | this.nextActivationsConflictSet = nextActivationsConflictSet; | ||
67 | this.stateCoder = stateCoder; | ||
68 | activationCodes = new ActivationCodesMultiBiMap(); | ||
69 | } | ||
70 | |||
71 | private Object createActivationCode(Activation<?> activation) { | ||
72 | return stateCoder.createActivationCode((IPatternMatch) activation.getAtom()); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public boolean removeActivation(Activation<?> activation) { | ||
77 | if (isIncremental) { | ||
78 | //* | ||
79 | removedActivations.add(activation); | ||
80 | newActivations.remove(activation); | ||
81 | /*/ | ||
82 | if(!removedActivations.add(activation)) { | ||
83 | logger.debug("Abnormal: already marked to remove: " + activation); | ||
84 | } else { | ||
85 | logger.debug("marked to remove: " + activation); | ||
86 | } | ||
87 | if(newActivations.remove(activation)) { | ||
88 | logger.debug("Abnormal: removed from new activations: " + activation); | ||
89 | } | ||
90 | //*/ | ||
91 | } | ||
92 | return false; | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | public boolean addActivation(Activation<?> activation) { | ||
97 | if (isIncremental) { | ||
98 | //* | ||
99 | newActivations.add(activation); | ||
100 | removedActivations.remove(activation); | ||
101 | /*/ | ||
102 | if (activation.isEnabled()) { | ||
103 | if (!newActivations.add(activation)) { | ||
104 | logger.debug("Abnormal: already added as new: " + activation); | ||
105 | } else { | ||
106 | logger.debug("activation added: " + activation); | ||
107 | } | ||
108 | } | ||
109 | if(removedActivations.remove(activation)) { | ||
110 | logger.debug("Abnormal: was already marked to remove: " + activation); | ||
111 | } | ||
112 | //*/ | ||
113 | } | ||
114 | return false; | ||
115 | } | ||
116 | |||
117 | public Object getActivationId(Activation<?> activation) { | ||
118 | return activationCodes.activationsToCodes.get(activation); | ||
119 | } | ||
120 | |||
121 | public Activation<?> getActivation(Object activationId) { | ||
122 | Set<Activation<?>> activationsSet = activationCodes.codesToActivations.get(activationId); | ||
123 | if (activationsSet == null || activationsSet.isEmpty()) { | ||
124 | return null; | ||
125 | } else { | ||
126 | return activationsSet.iterator().next(); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | public void updateActivationCodes() { | ||
131 | // logger.debug("Updating activation codes."); | ||
132 | |||
133 | if (isIncremental) { | ||
134 | for (Activation<?> activation : removedActivations) { | ||
135 | activationCodes.removeActivaion(activation); | ||
136 | // logger.debug("removed activation: " + activationId); | ||
137 | } | ||
138 | |||
139 | for (Activation<?> activation : newActivations) { | ||
140 | if (activation.getState().isInactive()) { | ||
141 | continue; | ||
142 | } | ||
143 | Object activationCode = createActivationCode(activation); | ||
144 | activationCodes.addActivation(activation, activationCode); | ||
145 | // logger.debug("new activation: " + activationId); | ||
146 | // Activation<?> similarActivation = activationIds.inverse().get(activationId); | ||
147 | // if (similarActivation != null) { | ||
148 | // logger.debug("Activation " + toStringAct(activation) + " is already present with id: " + activationId); | ||
149 | // if (similarActivation.isEnabled()) { | ||
150 | // logger.warn("Duplicate activation code: " + activationId); | ||
151 | // } else { | ||
152 | // logger.debug("Force put: " + activationId); | ||
153 | // } | ||
154 | // continue; | ||
155 | // } | ||
156 | // activationIds.put(activation, activationId); | ||
157 | } | ||
158 | removedActivations.clear(); | ||
159 | newActivations.clear(); | ||
160 | } else { | ||
161 | activationCodes.clear(); | ||
162 | for (Activation<?> activation : nextActivationsConflictSet.getNextActivations()) { | ||
163 | Object activationCode = createActivationCode(activation); | ||
164 | activationCodes.addActivation(activation, activationCode); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | |||
169 | } | ||
170 | |||
171 | protected void reinitWithActivations(ConflictSet nextActivationsConflictSet) { | ||
172 | this.nextActivationsConflictSet = nextActivationsConflictSet; | ||
173 | activationCodes.clear(); | ||
174 | for (Activation<?> activation : nextActivationsConflictSet.getNextActivations()) { | ||
175 | Object activationCode = createActivationCode(activation); | ||
176 | activationCodes.addActivation(activation, activationCode); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | @Override | ||
181 | public Activation<?> getNextActivation() { | ||
182 | throw new UnsupportedOperationException(); | ||
183 | } | ||
184 | |||
185 | @Override | ||
186 | public Set<Activation<?>> getNextActivations() { | ||
187 | throw new UnsupportedOperationException(); | ||
188 | } | ||
189 | |||
190 | @Override | ||
191 | public Set<Activation<?>> getConflictingActivations() { | ||
192 | throw new UnsupportedOperationException(); | ||
193 | } | ||
194 | |||
195 | @Override | ||
196 | public ConflictResolver getConflictResolver() { | ||
197 | throw new UnsupportedOperationException(); | ||
198 | } | ||
199 | |||
200 | @Override | ||
201 | public String toString() { | ||
202 | StringBuilder sb = new StringBuilder(); | ||
203 | for (Object activationCode : activationCodes.activationsToCodes.values()) { | ||
204 | sb.append(activationCode); | ||
205 | sb.append(" | "); | ||
206 | } | ||
207 | return sb.toString(); | ||
208 | } | ||
209 | |||
210 | public Collection<Object> getCurrentActivationCodes() { | ||
211 | return activationCodes.activationsToCodes.values(); | ||
212 | } | ||
213 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java new file mode 100644 index 00000000..133ef948 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DesignSpaceManager.java | |||
@@ -0,0 +1,577 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import java.lang.reflect.InvocationTargetException; | ||
12 | import java.util.ArrayList; | ||
13 | import java.util.Collection; | ||
14 | import java.util.HashMap; | ||
15 | import java.util.Iterator; | ||
16 | import java.util.List; | ||
17 | import java.util.Map; | ||
18 | import java.util.Random; | ||
19 | |||
20 | import org.apache.log4j.Logger; | ||
21 | import org.eclipse.emf.common.notify.Notifier; | ||
22 | import org.eclipse.emf.edit.command.ChangeCommand; | ||
23 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
24 | import org.eclipse.viatra.dse.api.DSEException; | ||
25 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
26 | import org.eclipse.viatra.dse.designspace.api.IBacktrackListener; | ||
27 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
28 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
29 | import org.eclipse.viatra.dse.objectives.ActivationFitnessProcessor; | ||
30 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
31 | import org.eclipse.viatra.dse.visualizer.IExploreEventHandler; | ||
32 | import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine; | ||
33 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
34 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
35 | import org.eclipse.viatra.transformation.evm.api.Context; | ||
36 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
37 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
38 | |||
39 | public class DesignSpaceManager implements IBacktrackListener { | ||
40 | |||
41 | private final IStateCoder stateCoder; | ||
42 | private final EditingDomain domain; | ||
43 | private Notifier model; | ||
44 | |||
45 | private IDesignSpace designSpace; | ||
46 | |||
47 | private final TrajectoryInfo trajectory; | ||
48 | |||
49 | // the occurence vector callback | ||
50 | private List<IExploreEventHandler> handlers; | ||
51 | |||
52 | // Dummy context for evm | ||
53 | private final Context evmContext = Context.create(); | ||
54 | |||
55 | private Logger logger = Logger.getLogger(this.getClass()); | ||
56 | |||
57 | private boolean isNewState = false; | ||
58 | private Map<BatchTransformationRule<?, ?>, ActivationFitnessProcessor> activationFitnessProcessors; | ||
59 | private Map<BatchTransformationRule<?, ?>, String> activationFitnessProcessorNames; | ||
60 | private ThreadContext context; | ||
61 | |||
62 | private ActivationCodesConflictSet activationCodes; | ||
63 | private ChangeableConflictSet conflictSet; | ||
64 | |||
65 | private AdvancedViatraQueryEngine engine; | ||
66 | |||
67 | private Random random = new Random(); | ||
68 | |||
69 | private long forwardTime = 0; | ||
70 | private long backtrackingTime = 0; | ||
71 | |||
72 | public DesignSpaceManager(ThreadContext context) { | ||
73 | |||
74 | this.context = context; | ||
75 | model = context.getModel(); | ||
76 | designSpace = context.getGlobalContext().getDesignSpace(); | ||
77 | domain = context.getEditingDomain(); | ||
78 | |||
79 | conflictSet = context.getConflictResolver().getLastCreatedConflictSet(); | ||
80 | |||
81 | stateCoder = context.getStateCoder(); | ||
82 | Object initialStateId = stateCoder.createStateCode(); | ||
83 | designSpace.addState(null, null, initialStateId); | ||
84 | |||
85 | activationCodes = context.getActivationCodesConflictSet(); | ||
86 | |||
87 | engine = (AdvancedViatraQueryEngine) context.getQueryEngine(); | ||
88 | |||
89 | this.trajectory = new TrajectoryInfo(initialStateId); | ||
90 | |||
91 | logger.debug("DesignSpaceManager initialized with initial model: " + initialStateId); | ||
92 | } | ||
93 | |||
94 | public void fireActivation(final Object transition) { | ||
95 | if (fireActivationSilent(transition)) { | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | StringBuilder sb = new StringBuilder(); | ||
100 | sb.append( | ||
101 | "A retrieved Transition SHOULD have a matching Activation. Possible causes: the state serializer is faulty; the algorithm choosed a wrong Transition."); | ||
102 | sb.append("\nSought transition: "); | ||
103 | sb.append(transition); | ||
104 | Object currentStateId = getCurrentState(); | ||
105 | sb.append("\nCurrent known state: "); | ||
106 | sb.append(currentStateId); | ||
107 | Object actualStateId = stateCoder.createStateCode(); | ||
108 | sb.append("\nActual state: "); | ||
109 | sb.append((actualStateId.equals(currentStateId) ? "same as current" : actualStateId)); | ||
110 | sb.append("\n"); | ||
111 | sb.append(trajectory); | ||
112 | sb.append("\nAvailable transitions:"); | ||
113 | for (Activation<?> act : conflictSet.getNextActivations()) { | ||
114 | IPatternMatch match = (IPatternMatch) act.getAtom(); | ||
115 | Object code = generateMatchCode(match); | ||
116 | sb.append("\n\t"); | ||
117 | sb.append(code); | ||
118 | } | ||
119 | |||
120 | throw new DSEException(sb.toString()); | ||
121 | } | ||
122 | |||
123 | public boolean tryFireActivation(final Object transition) { | ||
124 | return fireActivationSilent(transition); | ||
125 | } | ||
126 | |||
127 | private boolean fireActivationSilent(final Object transition) { | ||
128 | final Activation<?> activation = getActivationById(transition); | ||
129 | |||
130 | if (activation == null) { | ||
131 | return false; | ||
132 | } | ||
133 | |||
134 | BatchTransformationRule<?, ?> rule = getRuleByActivation(activation); | ||
135 | |||
136 | Map<String, Double> measureCosts = new HashMap<String, Double>(); | ||
137 | if (activationFitnessProcessors != null && activationFitnessProcessors.containsKey(rule)) { | ||
138 | IPatternMatch match = (IPatternMatch) activation.getAtom(); | ||
139 | ActivationFitnessProcessor processor = activationFitnessProcessors.get(rule); | ||
140 | double fitness = processor.process(match); | ||
141 | measureCosts.put(activationFitnessProcessorNames.get(rule), fitness); | ||
142 | } | ||
143 | |||
144 | ChangeCommand rc = new ChangeCommand(model) { | ||
145 | @Override | ||
146 | protected void doExecute() { | ||
147 | activation.fire(evmContext); | ||
148 | } | ||
149 | }; | ||
150 | |||
151 | Object previousState = trajectory.getCurrentStateId(); | ||
152 | |||
153 | long start = System.nanoTime(); | ||
154 | try { | ||
155 | engine.delayUpdatePropagation(() -> { | ||
156 | domain.getCommandStack().execute(rc); | ||
157 | return null; | ||
158 | }); | ||
159 | } catch (InvocationTargetException e) { | ||
160 | throw new RuntimeException(e); | ||
161 | } | ||
162 | forwardTime += System.nanoTime() - start; | ||
163 | |||
164 | Object newStateId = stateCoder.createStateCode(); | ||
165 | updateActivationCodes(); | ||
166 | |||
167 | if (designSpace != null) { | ||
168 | isNewState = !designSpace.isTraversed(newStateId); | ||
169 | designSpace.addState(previousState, transition, newStateId); | ||
170 | } | ||
171 | |||
172 | trajectory.addStep(transition, rule, newStateId, measureCosts); | ||
173 | |||
174 | if (handlers != null) { | ||
175 | for (IExploreEventHandler iExploreEventHandler : handlers) { | ||
176 | iExploreEventHandler.transitionFired(transition); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | logger.debug("Executed activation: " + transition);/* | ||
181 | * + " from state: " + previousState + " to " + newStateId); | ||
182 | */ | ||
183 | |||
184 | return true; | ||
185 | } | ||
186 | |||
187 | public boolean executeRandomActivationId() { | ||
188 | Collection<Object> transitions = getTransitionsFromCurrentState(); | ||
189 | int size = transitions.size(); | ||
190 | if (size == 0) { | ||
191 | return false; | ||
192 | } | ||
193 | |||
194 | int index = random.nextInt(size); | ||
195 | Iterator<Object> iterator = transitions.iterator(); | ||
196 | for (int i = 0; i < index; ++i) { | ||
197 | iterator.next(); | ||
198 | } | ||
199 | Object transition = iterator.next(); | ||
200 | |||
201 | fireActivation(transition); | ||
202 | return true; | ||
203 | } | ||
204 | |||
205 | public int executeTrajectory(Object[] trajectoryToExecute) { | ||
206 | return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, false, true); | ||
207 | } | ||
208 | |||
209 | public int executeTrajectory(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex) { | ||
210 | return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, false, true); | ||
211 | } | ||
212 | |||
213 | public int executeTrajectoryByTrying(Object[] trajectoryToExecute) { | ||
214 | return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, true, true); | ||
215 | } | ||
216 | |||
217 | public int executeTrajectoryByTrying(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex) { | ||
218 | return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, true, true); | ||
219 | } | ||
220 | |||
221 | public int executeTrajectoryWithoutStateCoding(Object[] trajectoryToExecute) { | ||
222 | return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, false, false); | ||
223 | } | ||
224 | |||
225 | public int executeTrajectoryWithoutStateCoding(Object[] trajectoryToExecute, int fromIncludedIndex, | ||
226 | int toExcludedIndex) { | ||
227 | return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, false, false); | ||
228 | } | ||
229 | |||
230 | public int executeTrajectoryByTryingWithoutStateCoding(Object[] trajectoryToExecute) { | ||
231 | return executeTrajectory(trajectoryToExecute, 0, trajectoryToExecute.length, true, false); | ||
232 | } | ||
233 | |||
234 | public int executeTrajectoryByTryingWithoutStateCoding(Object[] trajectoryToExecute, int fromIncludedIndex, | ||
235 | int toExcludedIndex) { | ||
236 | return executeTrajectory(trajectoryToExecute, fromIncludedIndex, toExcludedIndex, true, false); | ||
237 | } | ||
238 | |||
239 | private int executeTrajectory(Object[] trajectoryToExecute, int fromIncludedIndex, int toExcludedIndex, | ||
240 | boolean tryAllActivations, boolean createStateCode) { | ||
241 | logger.debug("Executing trajectory."); | ||
242 | int unsuccesfulIndex = -1; | ||
243 | if (tryAllActivations) { | ||
244 | unsuccesfulIndex = 0; | ||
245 | } | ||
246 | for (int i = fromIncludedIndex; i < toExcludedIndex; i++) { | ||
247 | Object activationId = trajectoryToExecute[i]; | ||
248 | final Activation<?> activation = getActivationById(activationId); | ||
249 | |||
250 | if (activation == null) { | ||
251 | logger.debug("Couldn't execute activation: " + activationId); | ||
252 | if (tryAllActivations) { | ||
253 | unsuccesfulIndex++; | ||
254 | continue; | ||
255 | } else { | ||
256 | unsuccesfulIndex = i; | ||
257 | logger.debug("Trajectory execution stopped at index " + i + "/" + trajectoryToExecute.length); | ||
258 | break; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | BatchTransformationRule<?, ?> rule = getRuleByActivation(activation); | ||
263 | |||
264 | Map<String, Double> measureCosts = new HashMap<String, Double>(); | ||
265 | if (activationFitnessProcessors != null && activationFitnessProcessors.containsKey(rule)) { | ||
266 | IPatternMatch match = (IPatternMatch) activation.getAtom(); | ||
267 | ActivationFitnessProcessor processor = activationFitnessProcessors.get(rule); | ||
268 | double fitness = processor.process(match); | ||
269 | measureCosts.put(activationFitnessProcessorNames.get(rule), fitness); | ||
270 | } | ||
271 | |||
272 | ChangeCommand rc = new ChangeCommand(model) { | ||
273 | @Override | ||
274 | protected void doExecute() { | ||
275 | activation.fire(evmContext); | ||
276 | } | ||
277 | }; | ||
278 | |||
279 | long start = System.nanoTime(); | ||
280 | try { | ||
281 | engine.delayUpdatePropagation(() -> { | ||
282 | domain.getCommandStack().execute(rc); | ||
283 | return null; | ||
284 | }); | ||
285 | } catch (InvocationTargetException e) { | ||
286 | throw new RuntimeException(e); | ||
287 | } | ||
288 | forwardTime += System.nanoTime() - start; | ||
289 | |||
290 | Object newStateId = null; | ||
291 | if (createStateCode) { | ||
292 | newStateId = stateCoder.createStateCode(); | ||
293 | } | ||
294 | updateActivationCodes(); | ||
295 | |||
296 | trajectory.addStep(activationId, rule, newStateId, measureCosts); | ||
297 | |||
298 | logger.debug("Activation executed: " + activationId); | ||
299 | } | ||
300 | if (!createStateCode) { | ||
301 | trajectory.modifyLastStateCode(stateCoder.createStateCode()); | ||
302 | } | ||
303 | logger.debug("Trajectory execution finished."); | ||
304 | return unsuccesfulIndex; | ||
305 | |||
306 | } | ||
307 | |||
308 | public Object getTransitionByActivation(Activation<?> activation) { | ||
309 | return activationCodes.getActivationId(activation); | ||
310 | } | ||
311 | |||
312 | public Activation<?> getActivationById(Object activationId) { | ||
313 | return activationCodes.getActivation(activationId); | ||
314 | } | ||
315 | |||
316 | public BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation) { | ||
317 | return context.getGlobalContext().getSpecificationRuleMap().get(activation.getInstance().getSpecification()); | ||
318 | } | ||
319 | |||
320 | public BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId) { | ||
321 | return getRuleByActivation(getActivationById(activationId)); | ||
322 | } | ||
323 | |||
324 | /** | ||
325 | * Returns true if the given state is not owned by this crawler. | ||
326 | * | ||
327 | **/ | ||
328 | public boolean isNewModelStateAlreadyTraversed() { | ||
329 | return !isNewState; | ||
330 | } | ||
331 | |||
332 | public List<Object> getTrajectoryFromRoot() { | ||
333 | return trajectory.getTrajectory(); | ||
334 | } | ||
335 | |||
336 | public Collection<Object> getTransitionsFromCurrentState() { | ||
337 | return activationCodes.getCurrentActivationCodes(); | ||
338 | } | ||
339 | |||
340 | public Collection<Object> getUntraversedTransitionsFromCurrentState() { | ||
341 | if (designSpace == null) { | ||
342 | throw new DSEException("Unsupported without a design space"); | ||
343 | } | ||
344 | Object currentState = trajectory.getCurrentStateId(); | ||
345 | Collection<Object> traversedIds = designSpace.getActivationIds(currentState); | ||
346 | |||
347 | List<Object> untraversedTransitions = new ArrayList<>(); | ||
348 | for (Object activationId : activationCodes.getCurrentActivationCodes()) { | ||
349 | if (!traversedIds.contains(activationId)) { | ||
350 | untraversedTransitions.add(activationId); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | return untraversedTransitions; | ||
355 | } | ||
356 | |||
357 | public boolean undoLastTransformation() { | ||
358 | |||
359 | if (!trajectory.canStepBack()) { | ||
360 | return false; | ||
361 | } | ||
362 | |||
363 | long start = System.nanoTime(); | ||
364 | try { | ||
365 | engine.delayUpdatePropagation(() -> { | ||
366 | domain.getCommandStack().undo(); | ||
367 | return null; | ||
368 | }); | ||
369 | } catch (InvocationTargetException e) { | ||
370 | throw new RuntimeException(e); | ||
371 | } | ||
372 | backtrackingTime += System.nanoTime() - start; | ||
373 | updateActivationCodes(); | ||
374 | |||
375 | Object lastActivationId = trajectory.getLastActivationId(); | ||
376 | |||
377 | trajectory.backtrack(); | ||
378 | |||
379 | if (handlers != null) { | ||
380 | for (IExploreEventHandler iExploreEventHandler : handlers) { | ||
381 | iExploreEventHandler.undo(lastActivationId); | ||
382 | } | ||
383 | } | ||
384 | |||
385 | logger.debug("Backtrack."); | ||
386 | |||
387 | return true; | ||
388 | } | ||
389 | |||
390 | public void backtrackXTimes(int steps) { | ||
391 | long start = System.nanoTime(); | ||
392 | try { | ||
393 | engine.delayUpdatePropagation(() -> { | ||
394 | for (int i = steps; i > 0; i--) { | ||
395 | domain.getCommandStack().undo(); | ||
396 | trajectory.backtrack(); | ||
397 | } | ||
398 | return null; | ||
399 | }); | ||
400 | } catch (InvocationTargetException e) { | ||
401 | throw new RuntimeException(e); | ||
402 | } | ||
403 | backtrackingTime += System.nanoTime() - start; | ||
404 | updateActivationCodes(); | ||
405 | logger.debug("Backtracked " + steps + " times."); | ||
406 | } | ||
407 | |||
408 | public int backtrackUntilLastCommonActivation(Object[] newTrajectory) { | ||
409 | long start = System.nanoTime(); | ||
410 | Iterator<Object> currentTrajectoryIterator = trajectory.getTrajectory().iterator(); | ||
411 | if (!currentTrajectoryIterator.hasNext()) { | ||
412 | return 0; | ||
413 | } | ||
414 | int indexOfLastCommonActivation = 0; | ||
415 | for (Object activationCode : newTrajectory) { | ||
416 | if (currentTrajectoryIterator.hasNext()) { | ||
417 | Object activationCodeFromCurrent = currentTrajectoryIterator.next(); | ||
418 | if (activationCodeFromCurrent.equals(activationCode)) { | ||
419 | indexOfLastCommonActivation++; | ||
420 | } else { | ||
421 | break; | ||
422 | } | ||
423 | } else { | ||
424 | // current trajectory is smaller | ||
425 | break; | ||
426 | } | ||
427 | } | ||
428 | int numberOfBacktracks = trajectory.getDepth() - indexOfLastCommonActivation; | ||
429 | if (numberOfBacktracks > 0) { | ||
430 | try { | ||
431 | engine.delayUpdatePropagation(() -> { | ||
432 | for (int i = numberOfBacktracks; i > 0; i--) { | ||
433 | domain.getCommandStack().undo(); | ||
434 | trajectory.backtrack(); | ||
435 | } | ||
436 | return null; | ||
437 | }); | ||
438 | } catch (InvocationTargetException e) { | ||
439 | throw new RuntimeException(e); | ||
440 | } | ||
441 | } | ||
442 | backtrackingTime += System.nanoTime() - start; | ||
443 | updateActivationCodes(); | ||
444 | logger.debug("Backtracked " + numberOfBacktracks + " times."); | ||
445 | return indexOfLastCommonActivation; | ||
446 | } | ||
447 | |||
448 | public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory) { | ||
449 | executeTrajectoryWithMinimalBacktrack(trajectory, trajectory.length); | ||
450 | } | ||
451 | |||
452 | public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex) { | ||
453 | int fromIndex = backtrackUntilLastCommonActivation(trajectory); | ||
454 | executeTrajectory(trajectory, fromIndex, toExcludedIndex, false, true); | ||
455 | } | ||
456 | |||
457 | public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory) { | ||
458 | executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory, trajectory.length); | ||
459 | } | ||
460 | |||
461 | public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex) { | ||
462 | int fromIndex = backtrackUntilLastCommonActivation(trajectory); | ||
463 | executeTrajectory(trajectory, fromIndex, toExcludedIndex, false, false); | ||
464 | Object stateCode = stateCoder.createStateCode(); | ||
465 | this.trajectory.modifyLastStateCode(stateCode); | ||
466 | } | ||
467 | |||
468 | public void undoUntilRoot() { | ||
469 | long start = System.nanoTime(); | ||
470 | try { | ||
471 | engine.delayUpdatePropagation(() -> { | ||
472 | while (trajectory.canStepBack()) { | ||
473 | domain.getCommandStack().undo(); | ||
474 | trajectory.backtrack(); | ||
475 | } | ||
476 | return null; | ||
477 | }); | ||
478 | } catch (InvocationTargetException e) { | ||
479 | throw new RuntimeException(e); | ||
480 | } | ||
481 | backtrackingTime += System.nanoTime() - start; | ||
482 | updateActivationCodes(); | ||
483 | logger.debug("Backtracked to root."); | ||
484 | } | ||
485 | |||
486 | private Object generateMatchCode(IPatternMatch match) { | ||
487 | return stateCoder.createActivationCode(match); | ||
488 | } | ||
489 | |||
490 | public Object getCurrentState() { | ||
491 | return trajectory.getCurrentStateId(); | ||
492 | } | ||
493 | |||
494 | public SolutionTrajectory createSolutionTrajectroy() { | ||
495 | return trajectory.createSolutionTrajectory(context.getGlobalContext().getStateCoderFactory(), this); | ||
496 | } | ||
497 | |||
498 | public TrajectoryInfo getTrajectoryInfo() { | ||
499 | return trajectory; | ||
500 | } | ||
501 | |||
502 | public void setDesignSpace(IDesignSpace designSpace) { | ||
503 | this.designSpace = designSpace; | ||
504 | } | ||
505 | |||
506 | public IDesignSpace getDesignSpace() { | ||
507 | return designSpace; | ||
508 | } | ||
509 | |||
510 | public void registerExploreEventHandler(IExploreEventHandler handler) { | ||
511 | if (handler == null) { | ||
512 | return; | ||
513 | } | ||
514 | if (handlers == null) { | ||
515 | handlers = new ArrayList<IExploreEventHandler>(); | ||
516 | } | ||
517 | handlers.add(handler); | ||
518 | } | ||
519 | |||
520 | public void deregisterExploreEventHandler(IExploreEventHandler handler) { | ||
521 | if (handler == null) { | ||
522 | return; | ||
523 | } | ||
524 | if (handlers != null) { | ||
525 | handlers.remove(handler); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | public void registerActivationCostProcessor(String name, BatchTransformationRule<?, ?> rule, | ||
530 | ActivationFitnessProcessor activationFitnessProcessor) { | ||
531 | if (activationFitnessProcessors == null || activationFitnessProcessorNames == null) { | ||
532 | activationFitnessProcessors = new HashMap<BatchTransformationRule<?, ?>, ActivationFitnessProcessor>(); | ||
533 | activationFitnessProcessorNames = new HashMap<BatchTransformationRule<?, ?>, String>(); | ||
534 | } | ||
535 | activationFitnessProcessors.put(rule, activationFitnessProcessor); | ||
536 | activationFitnessProcessorNames.put(rule, name); | ||
537 | } | ||
538 | |||
539 | public boolean isCurentStateInTrajectory() { | ||
540 | Object currentStateId = trajectory.getCurrentStateId(); | ||
541 | List<Object> stateTrajectory = trajectory.getStateTrajectory(); | ||
542 | int size = stateTrajectory.size(); | ||
543 | for (int i = 0; i < size - 1; i++) { | ||
544 | Object stateId = stateTrajectory.get(i); | ||
545 | if (currentStateId.equals(stateId)) { | ||
546 | return true; | ||
547 | } | ||
548 | } | ||
549 | return false; | ||
550 | } | ||
551 | |||
552 | public IStateCoder getStateCoder() { | ||
553 | return stateCoder; | ||
554 | } | ||
555 | |||
556 | private void updateActivationCodes() { | ||
557 | activationCodes.updateActivationCodes(); | ||
558 | } | ||
559 | |||
560 | public long getForwardTime() { | ||
561 | return forwardTime; | ||
562 | } | ||
563 | |||
564 | public long getBacktrackingTime() { | ||
565 | return backtrackingTime; | ||
566 | } | ||
567 | |||
568 | @Override | ||
569 | public void forwardWorked(long nanos) { | ||
570 | forwardTime += nanos; | ||
571 | } | ||
572 | |||
573 | @Override | ||
574 | public void backtrackWorked(long nanos) { | ||
575 | backtrackingTime += nanos; | ||
576 | } | ||
577 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java new file mode 100644 index 00000000..35504b56 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictResolver.java | |||
@@ -0,0 +1,35 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
12 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
13 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
14 | |||
15 | public class DseConflictResolver implements ConflictResolver { | ||
16 | |||
17 | private ConflictResolver activationOrderingconflictResolver; | ||
18 | private IStateCoder stateCoder; | ||
19 | private DseConflictSet lastCreatedConflictSet; | ||
20 | |||
21 | public DseConflictResolver(ConflictResolver activationOrderingConflictResolver, IStateCoder stateCoder) { | ||
22 | this.activationOrderingconflictResolver = activationOrderingConflictResolver; | ||
23 | this.stateCoder = stateCoder; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public ChangeableConflictSet createConflictSet() { | ||
28 | lastCreatedConflictSet = new DseConflictSet(this, activationOrderingconflictResolver, stateCoder); | ||
29 | return lastCreatedConflictSet; | ||
30 | } | ||
31 | |||
32 | public DseConflictSet getLastCreatedConflictSet() { | ||
33 | return lastCreatedConflictSet; | ||
34 | } | ||
35 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java new file mode 100644 index 00000000..cba595f4 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseConflictSet.java | |||
@@ -0,0 +1,83 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import java.util.Set; | ||
12 | |||
13 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
14 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
15 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
16 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
17 | |||
18 | public class DseConflictSet implements ChangeableConflictSet { | ||
19 | |||
20 | private ActivationCodesConflictSet activationCodesConflictSet; | ||
21 | private ChangeableConflictSet activationOrderingConflictSet; | ||
22 | private ChangeableConflictSet prevActivationOrderingConflictSet; | ||
23 | private ConflictResolver resolver; | ||
24 | |||
25 | public DseConflictSet(ConflictResolver resolver, ConflictResolver activationOrderingConflictResolver, | ||
26 | IStateCoder stateCoder) { | ||
27 | this.resolver = resolver; | ||
28 | activationOrderingConflictSet = activationOrderingConflictResolver.createConflictSet(); | ||
29 | activationCodesConflictSet = new ActivationCodesConflictSet(activationOrderingConflictSet, stateCoder); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Activation<?> getNextActivation() { | ||
34 | return activationOrderingConflictSet.getNextActivation(); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public Set<Activation<?>> getNextActivations() { | ||
39 | return activationOrderingConflictSet.getNextActivations(); | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public Set<Activation<?>> getConflictingActivations() { | ||
44 | return activationOrderingConflictSet.getConflictingActivations(); | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public ConflictResolver getConflictResolver() { | ||
49 | return resolver; | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public boolean addActivation(Activation<?> activation) { | ||
54 | activationCodesConflictSet.addActivation(activation); | ||
55 | return activationOrderingConflictSet.addActivation(activation); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public boolean removeActivation(Activation<?> activation) { | ||
60 | activationCodesConflictSet.removeActivation(activation); | ||
61 | return activationOrderingConflictSet.removeActivation(activation); | ||
62 | } | ||
63 | |||
64 | public ActivationCodesConflictSet getActivationCodesConflictSet() { | ||
65 | return activationCodesConflictSet; | ||
66 | } | ||
67 | |||
68 | public void changeActivationOrderingConflictSet(ChangeableConflictSet newActivationOrderingConflictSet) { | ||
69 | for (Activation<?> activation : activationOrderingConflictSet.getConflictingActivations()) { | ||
70 | newActivationOrderingConflictSet.addActivation(activation); | ||
71 | } | ||
72 | activationCodesConflictSet.reinitWithActivations(newActivationOrderingConflictSet); | ||
73 | ChangeableConflictSet tmp = activationOrderingConflictSet; | ||
74 | activationOrderingConflictSet = newActivationOrderingConflictSet; | ||
75 | prevActivationOrderingConflictSet = tmp; | ||
76 | } | ||
77 | |||
78 | public void changeActivationOrderingConflictSetBack() { | ||
79 | ChangeableConflictSet newActivationOrderingConflictSet = | ||
80 | prevActivationOrderingConflictSet.getConflictResolver().createConflictSet(); | ||
81 | changeActivationOrderingConflictSet(newActivationOrderingConflictSet); | ||
82 | } | ||
83 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java new file mode 100644 index 00000000..838c1d1b --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseEvmRuleBase.java | |||
@@ -0,0 +1,21 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import org.eclipse.viatra.transformation.evm.api.Agenda; | ||
12 | import org.eclipse.viatra.transformation.evm.api.RuleBase; | ||
13 | import org.eclipse.viatra.transformation.evm.api.event.EventRealm; | ||
14 | |||
15 | public class DseEvmRuleBase extends RuleBase { | ||
16 | |||
17 | public DseEvmRuleBase(EventRealm eventRealm, Agenda agenda) { | ||
18 | super(eventRealm, agenda); | ||
19 | } | ||
20 | |||
21 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java new file mode 100644 index 00000000..f6fee7be --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/DseIdPoolHelper.java | |||
@@ -0,0 +1,68 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.concurrent.ConcurrentHashMap; | ||
14 | |||
15 | import org.eclipse.viatra.dse.api.DSEException; | ||
16 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
17 | |||
18 | public enum DseIdPoolHelper { | ||
19 | |||
20 | INSTANCE; | ||
21 | |||
22 | public static interface IGetRuleExecutions { | ||
23 | int getRuleExecutions(BatchTransformationRule<?, ?> rule); | ||
24 | } | ||
25 | |||
26 | public static class IdProvider { | ||
27 | |||
28 | private final BatchTransformationRule<?, ?> rule; | ||
29 | private IGetRuleExecutions getRuleExecutions; | ||
30 | |||
31 | public IdProvider(IGetRuleExecutions getRuleExecutions, BatchTransformationRule<?, ?> rule) { | ||
32 | this.getRuleExecutions = getRuleExecutions; | ||
33 | this.rule = rule; | ||
34 | } | ||
35 | |||
36 | public int getId() { | ||
37 | return getRuleExecutions.getRuleExecutions(rule); | ||
38 | } | ||
39 | |||
40 | } | ||
41 | |||
42 | private ConcurrentHashMap<Thread, HashMap<BatchTransformationRule<?, ?>, IdProvider>> idProviders = new ConcurrentHashMap<>(); | ||
43 | |||
44 | public int getId(BatchTransformationRule<?, ?> rule) { | ||
45 | Thread currentThread = Thread.currentThread(); | ||
46 | HashMap<BatchTransformationRule<?, ?>, IdProvider> ruleMap = idProviders.get(currentThread); | ||
47 | if (ruleMap == null) { | ||
48 | throw new DSEException("There is no registered id provider"); | ||
49 | } | ||
50 | IdProvider idProvider = ruleMap.get(rule); | ||
51 | return idProvider.getId(); | ||
52 | } | ||
53 | |||
54 | public void registerRules(IGetRuleExecutions getRuleExecutions, Collection<BatchTransformationRule<?, ?>> rules) { | ||
55 | Thread currentThread = Thread.currentThread(); | ||
56 | HashMap<BatchTransformationRule<?, ?>, IdProvider> ruleMap = new HashMap<>(); | ||
57 | for (BatchTransformationRule<?, ?> rule : rules) { | ||
58 | IdProvider idProvider = new IdProvider(getRuleExecutions, rule); | ||
59 | ruleMap.put(rule, idProvider); | ||
60 | } | ||
61 | idProviders.put(currentThread, ruleMap); | ||
62 | } | ||
63 | |||
64 | public void disposeByThread() { | ||
65 | Thread currentThread = Thread.currentThread(); | ||
66 | idProviders.remove(currentThread); | ||
67 | } | ||
68 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java new file mode 100644 index 00000000..f2231e5c --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ExplorerThread.java | |||
@@ -0,0 +1,88 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import org.apache.log4j.Logger; | ||
12 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
13 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
14 | import org.eclipse.viatra.transformation.evm.api.RuleEngine; | ||
15 | |||
16 | /** | ||
17 | * This class implements the {@link Runnable} interface, to able to run an exploration strategy in a separate thread. It | ||
18 | * is also responsible to initialize the exploration, start the exploration (call the {@link IStrategy#explore()} | ||
19 | * method), catch any exception during exploration and to shutdown the thread correctly. | ||
20 | * | ||
21 | * @author Földenyi Miklos & Nagy Andras Szabolcs | ||
22 | * | ||
23 | */ | ||
24 | public class ExplorerThread implements Runnable { | ||
25 | |||
26 | private final ThreadContext threadContext; | ||
27 | |||
28 | private IStrategy strategy; | ||
29 | |||
30 | public ExplorerThread(final ThreadContext context) { | ||
31 | this.threadContext = context; | ||
32 | strategy = threadContext.getStrategy(); | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * Signals the {@link IStrategy} instance that execution should be stopped. By contract, the strategy is to | ||
37 | * stop execution at the next stage of execution where stopping and exiting is appropriate. | ||
38 | */ | ||
39 | public void stopRunning() { | ||
40 | strategy.interruptStrategy(); | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Starts the design space exploration. Returns only when the {@link IStrategy#explore()} method returns. | ||
45 | */ | ||
46 | public void run() { | ||
47 | GlobalContext globalContext = threadContext.getGlobalContext(); | ||
48 | try { | ||
49 | |||
50 | threadContext.init(); | ||
51 | |||
52 | strategy.initStrategy(threadContext); | ||
53 | |||
54 | strategy.explore(); | ||
55 | |||
56 | threadContext.backtrackUntilRoot(); | ||
57 | |||
58 | } catch (Throwable e) { | ||
59 | Logger.getLogger(IStrategy.class).error("Thread stopped unexpectedly!", e); | ||
60 | globalContext.registerException(e); | ||
61 | } finally { | ||
62 | globalContext.strategyFinished(this); | ||
63 | dispose(); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * Disposes of this strategy. Recursively calls dispose on the underlying {@link RuleEngine} and | ||
69 | * {@link ViatraQueryEngine}. Calling this is only required if the design space exploration was launched in thread, as | ||
70 | * the underlying engines get collected on the stop of the running {@link Thread}. | ||
71 | */ | ||
72 | public void dispose() { | ||
73 | threadContext.getRuleEngine().dispose(); | ||
74 | DseIdPoolHelper.INSTANCE.disposeByThread(); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Returns the associated {@link ThreadContext} that houses all the thread specific data about the exploration | ||
79 | * process, and is also the gateway to the {@link GlobalContext} which stores data relevant to the design space | ||
80 | * exploration process as a whole. | ||
81 | * | ||
82 | * @return the relevant {@link ThreadContext}. | ||
83 | */ | ||
84 | public ThreadContext getThreadContext() { | ||
85 | return threadContext; | ||
86 | } | ||
87 | |||
88 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java new file mode 100644 index 00000000..7325ead3 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/GlobalContext.java | |||
@@ -0,0 +1,374 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.HashSet; | ||
15 | import java.util.List; | ||
16 | import java.util.Map; | ||
17 | import java.util.Set; | ||
18 | import java.util.concurrent.ConcurrentLinkedQueue; | ||
19 | import java.util.concurrent.atomic.AtomicBoolean; | ||
20 | |||
21 | import org.apache.log4j.Logger; | ||
22 | import org.eclipse.emf.common.notify.Notifier; | ||
23 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
24 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory; | ||
25 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
26 | import org.eclipse.viatra.dse.multithreading.DSEThreadPool; | ||
27 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
28 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
29 | import org.eclipse.viatra.dse.objectives.LeveledObjectivesHelper; | ||
30 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
31 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
32 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
33 | import org.eclipse.viatra.dse.visualizer.IDesignSpaceVisualizer; | ||
34 | import org.eclipse.viatra.transformation.evm.api.RuleSpecification; | ||
35 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
36 | import org.eclipse.viatra.transformation.evm.specific.ConflictResolvers; | ||
37 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
38 | |||
39 | import com.google.common.base.Preconditions; | ||
40 | import com.google.common.collect.ImmutableList; | ||
41 | |||
42 | /** | ||
43 | * Creates new contexts for strategies. It is needed because of the multithreading. | ||
44 | * | ||
45 | * @author Andras Szabolcs Nagy | ||
46 | * | ||
47 | */ | ||
48 | public class GlobalContext { | ||
49 | |||
50 | // **** fields and methods for multi threading *****// | ||
51 | // *************************************************// | ||
52 | |||
53 | public enum ExplorationProcessState { | ||
54 | NOT_STARTED, | ||
55 | RUNNING, | ||
56 | STOPPING, | ||
57 | COMPLETED | ||
58 | } | ||
59 | |||
60 | private ConcurrentLinkedQueue<Throwable> exceptions = new ConcurrentLinkedQueue<Throwable>(); | ||
61 | |||
62 | private volatile ExplorationProcessState state = ExplorationProcessState.NOT_STARTED; | ||
63 | private final Set<ExplorerThread> runningThreads = new HashSet<ExplorerThread>(); | ||
64 | private DSEThreadPool threadPool = new DSEThreadPool(); | ||
65 | private int numberOfStartedThreads = 0; | ||
66 | private IDesignSpace designSpace; | ||
67 | |||
68 | private AtomicBoolean firstThreadContextInited = new AtomicBoolean(false); | ||
69 | private AtomicBoolean firstThreadContextIniting = new AtomicBoolean(false); | ||
70 | |||
71 | private Map<RuleSpecification<?>, BatchTransformationRule<?,?>> specificationRuleMap; | ||
72 | |||
73 | private Object terminationSnycObject = new Object(); | ||
74 | |||
75 | private Logger logger = Logger.getLogger(IStrategy.class); | ||
76 | |||
77 | private boolean isAlreadyInited; | ||
78 | |||
79 | public void waitForTermination() { | ||
80 | synchronized (terminationSnycObject) { | ||
81 | while (!isDone()) { | ||
82 | try { | ||
83 | terminationSnycObject.wait(); | ||
84 | } catch (InterruptedException e) { | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * Starts a new thread to explore the design space. | ||
92 | * | ||
93 | * @param originalThreadContext The context of the thread which starts the new thread. | ||
94 | * @param model The model to start from. | ||
95 | * @param cloneModel It should be true in most cases. | ||
96 | * @param strategy The strategy, the thread will use. | ||
97 | * @return The {@link ExplorerThread} | ||
98 | */ | ||
99 | private synchronized ExplorerThread tryStartNewThread(ThreadContext originalThreadContext, Notifier model, | ||
100 | IStrategy strategy) { | ||
101 | |||
102 | if(!isAlreadyInited) { | ||
103 | isAlreadyInited = true; | ||
104 | init(); | ||
105 | } | ||
106 | |||
107 | if (state != ExplorationProcessState.COMPLETED && state != ExplorationProcessState.STOPPING | ||
108 | && threadPool.canStartNewThread()) { | ||
109 | |||
110 | ThreadContext newThreadContext = new ThreadContext(this, strategy, model); | ||
111 | |||
112 | // TODO : clone undo list? slave strategy can't go further back... | ||
113 | ExplorerThread explorerThread = new ExplorerThread(newThreadContext); | ||
114 | newThreadContext.setExplorerThread(explorerThread); | ||
115 | |||
116 | boolean isSuccessful = threadPool.tryStartNewStrategy(explorerThread); | ||
117 | |||
118 | if (isSuccessful) { | ||
119 | runningThreads.add(explorerThread); | ||
120 | |||
121 | state = ExplorationProcessState.RUNNING; | ||
122 | ++numberOfStartedThreads; | ||
123 | |||
124 | logger.info("New thread started, active threads: " + runningThreads.size()); | ||
125 | |||
126 | return explorerThread; | ||
127 | } | ||
128 | } | ||
129 | return null; | ||
130 | } | ||
131 | |||
132 | public synchronized ExplorerThread tryStartNewThread(ThreadContext originalThreadContext, IStrategy strategy) { | ||
133 | return tryStartNewThread(originalThreadContext, EMFHelper.clone(originalThreadContext.getModel()), strategy); | ||
134 | } | ||
135 | |||
136 | public synchronized ExplorerThread tryStartNewThreadWithoutModelClone(ThreadContext originalThreadContext, | ||
137 | IStrategy strategy) { | ||
138 | return tryStartNewThread(originalThreadContext, originalThreadContext.getModel(), strategy); | ||
139 | } | ||
140 | |||
141 | public synchronized ExplorerThread startFirstThread(IStrategy strategy, Notifier model) { | ||
142 | Preconditions.checkState(!isAlreadyInited, "First thread is already started."); | ||
143 | return tryStartNewThread(null, EMFHelper.clone(model), strategy); | ||
144 | } | ||
145 | |||
146 | public synchronized ExplorerThread startFirstThreadWithoutModelClone(IStrategy strategy, Notifier model) { | ||
147 | Preconditions.checkState(!isAlreadyInited, "First thread is already started."); | ||
148 | return tryStartNewThread(null, model, strategy); | ||
149 | } | ||
150 | |||
151 | public synchronized void startAllThreads(ThreadContext originalThreadContext, IStrategyFactory strategyFactory) { | ||
152 | while (canStartNewThread()) { | ||
153 | tryStartNewThread(originalThreadContext, strategyFactory.createStrategy()); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * Starts a new thread to explore the design space. | ||
159 | * | ||
160 | * @param strategyBase | ||
161 | * The {@link Strategy}. | ||
162 | * @param tedToClone | ||
163 | * The model to clone. Hint: context.getTed() | ||
164 | */ | ||
165 | |||
166 | public synchronized void strategyFinished(ExplorerThread strategy) { | ||
167 | runningThreads.remove(strategy); | ||
168 | |||
169 | logger.info("Thread finished, active threads: " + runningThreads.size()); | ||
170 | |||
171 | // is the first part necessary? | ||
172 | if (runningThreads.isEmpty()) { | ||
173 | state = ExplorationProcessState.COMPLETED; | ||
174 | threadPool.shutdown(); | ||
175 | |||
176 | // if the main thread (which started the exploration) | ||
177 | // is waiting for the solution, than wake it up | ||
178 | synchronized (terminationSnycObject) { | ||
179 | terminationSnycObject.notify(); | ||
180 | logger.info("Exploration terminated."); | ||
181 | } | ||
182 | |||
183 | } | ||
184 | } | ||
185 | |||
186 | public synchronized boolean isDone() { | ||
187 | return state == ExplorationProcessState.COMPLETED && runningThreads.isEmpty(); | ||
188 | } | ||
189 | |||
190 | public synchronized boolean isNotStarted() { | ||
191 | return state == ExplorationProcessState.NOT_STARTED; | ||
192 | } | ||
193 | |||
194 | public boolean canStartNewThread() { | ||
195 | return (state == ExplorationProcessState.NOT_STARTED || state == ExplorationProcessState.RUNNING) | ||
196 | && threadPool.canStartNewThread(); | ||
197 | } | ||
198 | |||
199 | public synchronized void stopAllThreads() { | ||
200 | if (state == ExplorationProcessState.RUNNING) { | ||
201 | state = ExplorationProcessState.STOPPING; | ||
202 | logger.info("Stopping all threads."); | ||
203 | for (ExplorerThread strategy : runningThreads) { | ||
204 | strategy.stopRunning(); | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | public void registerException(Throwable e) { | ||
210 | exceptions.add(e); | ||
211 | } | ||
212 | |||
213 | // ******* fields and methods for exploration *******// | ||
214 | // **************************************************// | ||
215 | |||
216 | private List<IObjective> objectives = new ArrayList<IObjective>(); | ||
217 | private IObjective[][] leveledObjectives; | ||
218 | private List<IGlobalConstraint> globalConstraints = new ArrayList<IGlobalConstraint>(); | ||
219 | private Set<BatchTransformationRule<?, ?>> transformations = new HashSet<BatchTransformationRule<?, ?>>(); | ||
220 | private IStateCoderFactory stateCoderFactory; | ||
221 | private SolutionStore solutionStore = new SolutionStore(1); | ||
222 | private Object sharedObject; | ||
223 | private List<IDesignSpaceVisualizer> visualizers; | ||
224 | |||
225 | private ConflictResolver conflictResolver = ConflictResolvers.createArbitraryResolver(); | ||
226 | |||
227 | private void init() { | ||
228 | leveledObjectives = new LeveledObjectivesHelper(objectives).initLeveledObjectives(); | ||
229 | |||
230 | specificationRuleMap = new HashMap<>(); | ||
231 | for (BatchTransformationRule<?,?> rule : transformations) { | ||
232 | specificationRuleMap.put(rule.getRuleSpecification(), rule); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | public List<IDesignSpaceVisualizer> getVisualizers() { | ||
237 | return ImmutableList.copyOf(visualizers); | ||
238 | } | ||
239 | |||
240 | public void registerDesignSpaceVisualizer(IDesignSpaceVisualizer visualizer) { | ||
241 | if (visualizer == null) { | ||
242 | return; | ||
243 | } | ||
244 | if (visualizers == null) { | ||
245 | visualizers = new ArrayList<IDesignSpaceVisualizer>(); | ||
246 | } | ||
247 | visualizers.add(visualizer); | ||
248 | } | ||
249 | |||
250 | public void deregisterDesignSpaceVisualizer(IDesignSpaceVisualizer visualizer) { | ||
251 | if (visualizer == null) { | ||
252 | return; | ||
253 | } | ||
254 | if (visualizers != null) { | ||
255 | visualizers.remove(visualizer); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | public boolean isDesignSpaceVisualizerRegistered(IDesignSpaceVisualizer visualizer) { | ||
260 | if (visualizers != null) { | ||
261 | return visualizers.contains(visualizer); | ||
262 | } | ||
263 | return false; | ||
264 | } | ||
265 | |||
266 | public void initVisualizersForThread(ThreadContext threadContext) { | ||
267 | if (visualizers != null && !visualizers.isEmpty()) { | ||
268 | for (IDesignSpaceVisualizer visualizer : visualizers) { | ||
269 | visualizer.init(threadContext); | ||
270 | threadContext.getDesignSpaceManager().registerExploreEventHandler(visualizer); | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | public boolean isExceptionHappendInOtherThread() { | ||
276 | return !exceptions.isEmpty(); | ||
277 | } | ||
278 | |||
279 | public Collection<Throwable> getExceptions() { | ||
280 | return exceptions; | ||
281 | } | ||
282 | |||
283 | public IStateCoderFactory getStateCoderFactory() { | ||
284 | return stateCoderFactory; | ||
285 | } | ||
286 | |||
287 | public void setStateCoderFactory(IStateCoderFactory stateCoderFactory) { | ||
288 | this.stateCoderFactory = stateCoderFactory; | ||
289 | } | ||
290 | |||
291 | public Set<BatchTransformationRule<?, ?>> getTransformations() { | ||
292 | return transformations; | ||
293 | } | ||
294 | |||
295 | public void setTransformations(Set<BatchTransformationRule<?, ?>> transformations) { | ||
296 | this.transformations = transformations; | ||
297 | } | ||
298 | |||
299 | public DSEThreadPool getThreadPool() { | ||
300 | return threadPool; | ||
301 | } | ||
302 | |||
303 | public IDesignSpace getDesignSpace() { | ||
304 | return designSpace; | ||
305 | } | ||
306 | |||
307 | public void setDesignSpace(IDesignSpace designSpace) { | ||
308 | this.designSpace = designSpace; | ||
309 | } | ||
310 | |||
311 | public int getNumberOfStartedThreads() { | ||
312 | return numberOfStartedThreads; | ||
313 | } | ||
314 | |||
315 | public Object getSharedObject() { | ||
316 | return sharedObject; | ||
317 | } | ||
318 | |||
319 | public void setSharedObject(Object sharedObject) { | ||
320 | this.sharedObject = sharedObject; | ||
321 | } | ||
322 | |||
323 | public ExplorationProcessState getState() { | ||
324 | return state; | ||
325 | } | ||
326 | |||
327 | public List<IObjective> getObjectives() { | ||
328 | return objectives; | ||
329 | } | ||
330 | |||
331 | public void setObjectives(List<IObjective> objectives) { | ||
332 | this.objectives = objectives; | ||
333 | } | ||
334 | |||
335 | public List<IGlobalConstraint> getGlobalConstraints() { | ||
336 | return globalConstraints; | ||
337 | } | ||
338 | |||
339 | public void setGlobalConstraints(List<IGlobalConstraint> globalConstraints) { | ||
340 | this.globalConstraints = globalConstraints; | ||
341 | } | ||
342 | |||
343 | AtomicBoolean getFirstThreadContextInited() { | ||
344 | return firstThreadContextInited; | ||
345 | } | ||
346 | |||
347 | AtomicBoolean getFirstThreadContextIniting() { | ||
348 | return firstThreadContextIniting; | ||
349 | } | ||
350 | |||
351 | public IObjective[][] getLeveledObjectives() { | ||
352 | return leveledObjectives; | ||
353 | } | ||
354 | |||
355 | public void setSolutionStore(SolutionStore solutionStore) { | ||
356 | this.solutionStore = solutionStore; | ||
357 | } | ||
358 | |||
359 | public SolutionStore getSolutionStore() { | ||
360 | return solutionStore; | ||
361 | } | ||
362 | |||
363 | public Map<RuleSpecification<?>, BatchTransformationRule<?, ?>> getSpecificationRuleMap() { | ||
364 | return specificationRuleMap; | ||
365 | } | ||
366 | |||
367 | public void setConflictResolver(ConflictResolver conflictResolver) { | ||
368 | this.conflictResolver = conflictResolver; | ||
369 | } | ||
370 | |||
371 | public ConflictResolver getConflictResolver() { | ||
372 | return conflictResolver; | ||
373 | } | ||
374 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java new file mode 100644 index 00000000..d630964f --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/IDseStrategyContext.java | |||
@@ -0,0 +1,117 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.List; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import org.eclipse.emf.common.notify.Notifier; | ||
16 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
17 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
18 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory; | ||
19 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
20 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
21 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
22 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
23 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
24 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
25 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
26 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
27 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
28 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
29 | import org.eclipse.viatra.transformation.evm.api.RuleEngine; | ||
30 | import org.eclipse.viatra.transformation.evm.api.RuleSpecification; | ||
31 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
32 | |||
33 | /** | ||
34 | * This interface is only to overview the required methods for exploration strategies. It is not used explicitly. | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * | ||
38 | */ | ||
39 | public interface IDseStrategyContext { | ||
40 | |||
41 | void init(); | ||
42 | |||
43 | Notifier getModel(); | ||
44 | EditingDomain getEditingDomain(); | ||
45 | ViatraQueryEngine getQueryEngine(); | ||
46 | RuleEngine getRuleEngine(); | ||
47 | IStrategy getStrategy(); | ||
48 | ExplorerThread getExplorerThread(); | ||
49 | List<IObjective> getObjectives(); | ||
50 | IObjective[][] getLeveledObjectives(); | ||
51 | List<IGlobalConstraint> getGlobalConstraints(); | ||
52 | |||
53 | SolutionStore getSolutionStore(); | ||
54 | void newSolution(); | ||
55 | // TODO void newSolution(TrajectoryFitness trajectoryFitness); | ||
56 | |||
57 | |||
58 | ObjectiveComparatorHelper getObjectiveComparatorHelper(); | ||
59 | |||
60 | GlobalContext getGlobalContext(); | ||
61 | Set<BatchTransformationRule<?, ?>> getRules(); | ||
62 | BatchTransformationRule<?, ?> getRuleByRuleSpecification(RuleSpecification<?> ruleSpecification); | ||
63 | ExplorerThread tryStartNewThread(IStrategy strategy); /*IDseStrategyContext originalContext*/ | ||
64 | ExplorerThread tryStartNewThreadWithoutModelClone(IStrategy strategy); | ||
65 | void startAllThreads(IStrategyFactory strategyFactory); | ||
66 | Object getSharedObject(); | ||
67 | void setSharedObject(Object sharedObject); | ||
68 | |||
69 | |||
70 | DesignSpaceManager getDesignSpaceManager(); | ||
71 | IStateCoder getStateCoder(); | ||
72 | IDesignSpace getDesignSpace(); | ||
73 | TrajectoryInfo getTrajectoryInfo(); | ||
74 | List<Object> getTrajectory(); | ||
75 | List<Object> getTrajectoryCopied(); | ||
76 | int getDepth(); | ||
77 | Object getCurrentStateId(); | ||
78 | |||
79 | Object getTransitionByActivation(Activation<?> activation); | ||
80 | Activation<?> getActivationById(Object activationId); | ||
81 | BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation); | ||
82 | BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId); | ||
83 | |||
84 | Collection<Object> getCurrentActivationIds(); | ||
85 | Collection<Object> getUntraversedActivationIds(); | ||
86 | // TODO Object getArbitraryActivationId(); | ||
87 | // TODO Object getArbitraryUntraversedActivationId(); | ||
88 | |||
89 | void executeAcitvationId(Object activationId); | ||
90 | boolean tryExecuteAcitvationId(Object activationId); | ||
91 | boolean executeRandomActivationId(); | ||
92 | void executeTrajectory(Object[] activationIds); | ||
93 | void executeTrajectory(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex); | ||
94 | int executeTrajectoryByTrying(Object[] activationIds); | ||
95 | int executeTrajectoryByTrying(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex); | ||
96 | int executeTrajectoryWithoutStateCoding(Object[] activationIds); | ||
97 | int executeTrajectoryWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex); | ||
98 | int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds); | ||
99 | int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex); | ||
100 | void executeTrajectoryWithMinimalBacktrack(Object[] trajectory); | ||
101 | void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex); | ||
102 | void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory); | ||
103 | void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex); | ||
104 | |||
105 | boolean backtrack(); | ||
106 | // TODO int backtrack(int times); | ||
107 | void backtrackUntilLastCommonActivation(Object[] trajectory); | ||
108 | void backtrackUntilRoot(); | ||
109 | |||
110 | Fitness calculateFitness(); | ||
111 | Fitness getLastFitness(); | ||
112 | boolean checkGlobalConstraints(); | ||
113 | boolean isCurrentStateAlreadyTraversed(); | ||
114 | // this needs states stored: | ||
115 | boolean isCurrentStateInTrajectory(); | ||
116 | |||
117 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java new file mode 100644 index 00000000..8c0a715a --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/SingletonSetConflictResolver.java | |||
@@ -0,0 +1,53 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import org.eclipse.viatra.transformation.evm.api.RuleEngine; | ||
12 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
13 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
14 | |||
15 | /** | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class SingletonSetConflictResolver implements ConflictResolver { | ||
21 | |||
22 | protected ChangeableConflictSet conflictSet; | ||
23 | protected ConflictResolver conflictResolver; | ||
24 | protected ConflictResolver prevConflictResolver; | ||
25 | protected RuleEngine ruleEngine; | ||
26 | |||
27 | public SingletonSetConflictResolver(ConflictResolver conflictResolver) { | ||
28 | this.conflictResolver = conflictResolver; | ||
29 | conflictSet = conflictResolver.createConflictSet(); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public ChangeableConflictSet createConflictSet() { | ||
34 | return conflictSet; | ||
35 | } | ||
36 | |||
37 | public void changeConflictResolver(ConflictResolver conflictResolver) { | ||
38 | ConflictResolver tmp = this.conflictResolver; | ||
39 | this.conflictResolver = conflictResolver; | ||
40 | prevConflictResolver = tmp; | ||
41 | conflictSet = conflictResolver.createConflictSet(); | ||
42 | ruleEngine.setConflictResolver(this); | ||
43 | } | ||
44 | |||
45 | public void changeConflictResolverBack() { | ||
46 | changeConflictResolver(prevConflictResolver); | ||
47 | } | ||
48 | |||
49 | public void setRuleEngine(RuleEngine ruleEngine) { | ||
50 | this.ruleEngine = ruleEngine; | ||
51 | ruleEngine.setConflictResolver(this); | ||
52 | } | ||
53 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java new file mode 100644 index 00000000..b62442ce --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/base/ThreadContext.java | |||
@@ -0,0 +1,542 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.base; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.List; | ||
14 | import java.util.Set; | ||
15 | import java.util.concurrent.atomic.AtomicBoolean; | ||
16 | |||
17 | import org.apache.log4j.Logger; | ||
18 | import org.eclipse.emf.common.notify.Notifier; | ||
19 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
20 | import org.eclipse.viatra.dse.api.DSEException; | ||
21 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
22 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategyFactory; | ||
23 | import org.eclipse.viatra.dse.designspace.api.IDesignSpace; | ||
24 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
25 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
26 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
27 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
28 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
29 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | ||
30 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
31 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
32 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
33 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
34 | import org.eclipse.viatra.query.runtime.emf.EMFScope; | ||
35 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
36 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
37 | import org.eclipse.viatra.transformation.evm.api.Activation; | ||
38 | import org.eclipse.viatra.transformation.evm.api.RuleEngine; | ||
39 | import org.eclipse.viatra.transformation.evm.api.RuleSpecification; | ||
40 | import org.eclipse.viatra.transformation.evm.api.event.EventFilter; | ||
41 | import org.eclipse.viatra.transformation.evm.api.resolver.ChangeableConflictSet; | ||
42 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictResolver; | ||
43 | import org.eclipse.viatra.transformation.evm.api.resolver.ConflictSet; | ||
44 | import org.eclipse.viatra.transformation.evm.specific.RuleEngines; | ||
45 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
46 | |||
47 | /** | ||
48 | * This class holds all the information that is related to a single processing thread of the DesignSpaceExploration | ||
49 | * process. For any attributes related to the Design Space Exploration process as a whole, see {@link GlobalContext}. | ||
50 | * | ||
51 | * @author Miklos Foldenyi | ||
52 | * | ||
53 | */ | ||
54 | public class ThreadContext implements IDseStrategyContext{ | ||
55 | |||
56 | private final GlobalContext globalContext; | ||
57 | private final IStrategy strategy; | ||
58 | private ExplorerThread explorerThread; | ||
59 | private RuleEngine ruleEngine; | ||
60 | private ViatraQueryEngine queryEngine; | ||
61 | private EditingDomain domain; | ||
62 | private Notifier model; | ||
63 | private DesignSpaceManager designSpaceManager; | ||
64 | private List<IObjective> objectives; | ||
65 | private List<IGlobalConstraint> globalConstraints; | ||
66 | private Fitness lastFitness; | ||
67 | private ObjectiveComparatorHelper objectiveComparatorHelper; | ||
68 | private IStateCoder stateCoder; | ||
69 | private DseConflictResolver dseConflictResolver; | ||
70 | private DseConflictSet dseConflictSet; | ||
71 | private ActivationCodesConflictSet activationCodesConflictSet; | ||
72 | |||
73 | /** | ||
74 | * This value is true after the {@link ThreadContext} has been initialized in it's own thread. | ||
75 | */ | ||
76 | private AtomicBoolean inited = new AtomicBoolean(false); | ||
77 | |||
78 | private boolean isFirstThread = false; | ||
79 | private IObjective[][] leveledObjectives; | ||
80 | |||
81 | private static class GetRuleExecutionsImpl implements DseIdPoolHelper.IGetRuleExecutions { | ||
82 | |||
83 | private List<BatchTransformationRule<?, ?>> executedRules; | ||
84 | |||
85 | public GetRuleExecutionsImpl(List<BatchTransformationRule<?, ?>> executedRulesView) { | ||
86 | this.executedRules = executedRulesView; | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public int getRuleExecutions(BatchTransformationRule<?, ?> rule) { | ||
91 | int nextId = 0; | ||
92 | for (BatchTransformationRule<?, ?> r : executedRules) { | ||
93 | if (r.equals(rule)) { | ||
94 | nextId ++; | ||
95 | } | ||
96 | } | ||
97 | return nextId; | ||
98 | } | ||
99 | |||
100 | } | ||
101 | |||
102 | public DseConflictResolver getConflictResolver() { | ||
103 | return dseConflictResolver; | ||
104 | } | ||
105 | |||
106 | public ConflictSet getConflictSet() { | ||
107 | return dseConflictSet; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Creates a {@link ThreadContext} and sets it up to be initialized on the given {@link TransactionalEditingDomain} | ||
112 | * | ||
113 | * @param globalContext | ||
114 | * @param strategyBase | ||
115 | * @param domain | ||
116 | * @param trajectoryInfoToClone | ||
117 | * @param parentGuidance | ||
118 | */ | ||
119 | public ThreadContext(final GlobalContext globalContext, IStrategy strategy, Notifier model) { | ||
120 | Preconditions.checkArgument(model != null, "Cannot initialize ThreadContext on a null model."); | ||
121 | this.globalContext = globalContext; | ||
122 | this.strategy = strategy; | ||
123 | this.model = model; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Initializes the {@link ThreadContext} by initializing the underlying {@link ViatraQueryEngine} and | ||
128 | * {@link RuleEngine}. {@link Guidance} initialization is also happening within this method. | ||
129 | * | ||
130 | * @throws DSEException | ||
131 | */ | ||
132 | public void init() { | ||
133 | |||
134 | AtomicBoolean isFirst = globalContext.getFirstThreadContextIniting(); | ||
135 | AtomicBoolean isFirstReady = globalContext.getFirstThreadContextInited(); | ||
136 | if (!isFirstReady.get()) { | ||
137 | if (!isFirst.compareAndSet(false, true)) { | ||
138 | try { | ||
139 | do { | ||
140 | Thread.sleep(5); | ||
141 | } while (!isFirstReady.get()); | ||
142 | } catch (InterruptedException e) { | ||
143 | } | ||
144 | } else { | ||
145 | isFirstThread = true; | ||
146 | } | ||
147 | } | ||
148 | // prohibit re-initialization | ||
149 | Preconditions.checkArgument(!inited.getAndSet(true), "This Thread context has been initialized already!"); | ||
150 | |||
151 | try { | ||
152 | // initialize query engine | ||
153 | final EMFScope scope = new EMFScope(model); | ||
154 | queryEngine = ViatraQueryEngine.on(scope); | ||
155 | |||
156 | |||
157 | stateCoder = getGlobalContext().getStateCoderFactory().createStateCoder(); | ||
158 | stateCoder.init(model); | ||
159 | stateCoder.createStateCode(); | ||
160 | |||
161 | ConflictResolver activationOrderingCconflictResolver = globalContext.getConflictResolver(); | ||
162 | dseConflictResolver = new DseConflictResolver(activationOrderingCconflictResolver, stateCoder); | ||
163 | |||
164 | ruleEngine = RuleEngines.createViatraQueryRuleEngine(queryEngine); | ||
165 | ruleEngine.setConflictResolver(dseConflictResolver); | ||
166 | for (BatchTransformationRule<?, ?> tr : globalContext.getTransformations()) { | ||
167 | ruleEngine.addRule(tr.getRuleSpecification(), (EventFilter<IPatternMatch>) tr.getFilter()); | ||
168 | } | ||
169 | dseConflictSet = dseConflictResolver.getLastCreatedConflictSet(); | ||
170 | activationCodesConflictSet = dseConflictSet.getActivationCodesConflictSet(); | ||
171 | activationCodesConflictSet.updateActivationCodes(); | ||
172 | |||
173 | |||
174 | } catch (ViatraQueryException e) { | ||
175 | throw new DSEException("Failed to create unmanaged ViatraQueryEngine on the model.", e); | ||
176 | } | ||
177 | |||
178 | if (isFirstThread) { | ||
179 | |||
180 | objectives = globalContext.getObjectives(); | ||
181 | leveledObjectives = globalContext.getLeveledObjectives(); | ||
182 | globalConstraints = globalContext.getGlobalConstraints(); | ||
183 | |||
184 | } else { | ||
185 | objectives = new ArrayList<IObjective>(); | ||
186 | |||
187 | IObjective[][] leveledObjectivesToCopy = globalContext.getLeveledObjectives(); | ||
188 | leveledObjectives = new IObjective[leveledObjectivesToCopy.length][]; | ||
189 | for (int i = 0; i < leveledObjectivesToCopy.length; i++) { | ||
190 | leveledObjectives[i] = new IObjective[leveledObjectivesToCopy[i].length]; | ||
191 | for (int j = 0; j < leveledObjectivesToCopy[i].length; j++) { | ||
192 | leveledObjectives[i][j] = leveledObjectivesToCopy[i][j].createNew(); | ||
193 | objectives.add(leveledObjectives[i][j]); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | globalConstraints = new ArrayList<IGlobalConstraint>(); | ||
198 | for (IGlobalConstraint globalConstraint : globalContext.getGlobalConstraints()) { | ||
199 | globalConstraints.add(globalConstraint.createNew()); | ||
200 | } | ||
201 | |||
202 | } | ||
203 | // create the thread specific DesignSpaceManager | ||
204 | this.domain = EMFHelper.createEditingDomain(model); | ||
205 | designSpaceManager = new DesignSpaceManager(this); | ||
206 | |||
207 | boolean isThereHardObjective = false; | ||
208 | for (IObjective objective : objectives) { | ||
209 | objective.init(this); | ||
210 | if (objective.isHardObjective()) { | ||
211 | isThereHardObjective = true; | ||
212 | } | ||
213 | } | ||
214 | if (!isThereHardObjective) { | ||
215 | Logger.getLogger(IStrategy.class).warn( | ||
216 | "No hard objective is specified: all reachable state is a solution. Use a dummy hard objective to be explicit."); | ||
217 | } | ||
218 | |||
219 | for (IGlobalConstraint globalConstraint : globalConstraints) { | ||
220 | globalConstraint.init(this); | ||
221 | } | ||
222 | |||
223 | DseIdPoolHelper.INSTANCE.registerRules(new GetRuleExecutionsImpl(getDesignSpaceManager().getTrajectoryInfo().getRules()), getRules()); | ||
224 | |||
225 | globalContext.initVisualizersForThread(this); | ||
226 | |||
227 | if (isFirstThread) { | ||
228 | isFirstReady.set(true); | ||
229 | } | ||
230 | |||
231 | } | ||
232 | |||
233 | public Fitness calculateFitness() { | ||
234 | Fitness result = new Fitness(); | ||
235 | |||
236 | boolean satisifiesHardObjectives = true; | ||
237 | |||
238 | for (IObjective objective : objectives) { | ||
239 | Double fitness = objective.getFitness(this); | ||
240 | result.put(objective.getName(), fitness); | ||
241 | if (objective.isHardObjective() && !objective.satisifiesHardObjective(fitness)) { | ||
242 | satisifiesHardObjectives = false; | ||
243 | } | ||
244 | } | ||
245 | |||
246 | result.setSatisifiesHardObjectives(satisifiesHardObjectives); | ||
247 | |||
248 | lastFitness = result; | ||
249 | |||
250 | return result; | ||
251 | } | ||
252 | |||
253 | public boolean checkGlobalConstraints() { | ||
254 | for (IGlobalConstraint globalConstraint : globalContext.getGlobalConstraints()) { | ||
255 | if (!globalConstraint.checkGlobalConstraint(this)) { | ||
256 | return false; | ||
257 | } | ||
258 | } | ||
259 | return true; | ||
260 | } | ||
261 | |||
262 | public RuleEngine getRuleEngine() { | ||
263 | return ruleEngine; | ||
264 | } | ||
265 | |||
266 | public GlobalContext getGlobalContext() { | ||
267 | return globalContext; | ||
268 | } | ||
269 | |||
270 | public DesignSpaceManager getDesignSpaceManager() { | ||
271 | return designSpaceManager; | ||
272 | } | ||
273 | |||
274 | public EditingDomain getEditingDomain() { | ||
275 | return domain; | ||
276 | } | ||
277 | |||
278 | public Notifier getModel() { | ||
279 | return model; | ||
280 | } | ||
281 | |||
282 | public ViatraQueryEngine getQueryEngine() { | ||
283 | return queryEngine; | ||
284 | } | ||
285 | |||
286 | public IStrategy getStrategy() { | ||
287 | return strategy; | ||
288 | } | ||
289 | |||
290 | public ExplorerThread getExplorerThread() { | ||
291 | return explorerThread; | ||
292 | } | ||
293 | |||
294 | public void setExplorerThread(ExplorerThread explorerThread) { | ||
295 | this.explorerThread = explorerThread; | ||
296 | } | ||
297 | |||
298 | public Fitness getLastFitness() { | ||
299 | return lastFitness; | ||
300 | } | ||
301 | |||
302 | public ObjectiveComparatorHelper getObjectiveComparatorHelper() { | ||
303 | if (objectiveComparatorHelper == null) { | ||
304 | objectiveComparatorHelper = new ObjectiveComparatorHelper(leveledObjectives); | ||
305 | } | ||
306 | return objectiveComparatorHelper; | ||
307 | } | ||
308 | |||
309 | public IObjective[][] getLeveledObjectives() { | ||
310 | return leveledObjectives; | ||
311 | } | ||
312 | |||
313 | public List<IObjective> getObjectives() { | ||
314 | return objectives; | ||
315 | } | ||
316 | |||
317 | public List<IGlobalConstraint> getGlobalConstraints() { | ||
318 | return globalConstraints; | ||
319 | } | ||
320 | |||
321 | @Override | ||
322 | public SolutionStore getSolutionStore() { | ||
323 | return globalContext.getSolutionStore(); | ||
324 | } | ||
325 | |||
326 | @Override | ||
327 | public void newSolution() { | ||
328 | globalContext.getSolutionStore().newSolution(this); | ||
329 | } | ||
330 | |||
331 | @Override | ||
332 | public Object getSharedObject() { | ||
333 | return globalContext.getSharedObject(); | ||
334 | } | ||
335 | |||
336 | @Override | ||
337 | public void setSharedObject(Object sharedObject) { | ||
338 | globalContext.setSharedObject(sharedObject); | ||
339 | } | ||
340 | |||
341 | @Override | ||
342 | public Set<BatchTransformationRule<?, ?>> getRules() { | ||
343 | return globalContext.getTransformations(); | ||
344 | } | ||
345 | |||
346 | @Override | ||
347 | public BatchTransformationRule<?, ?> getRuleByRuleSpecification(RuleSpecification<?> ruleSpecification) { | ||
348 | return globalContext.getSpecificationRuleMap().get(ruleSpecification); | ||
349 | } | ||
350 | |||
351 | @Override | ||
352 | public ExplorerThread tryStartNewThread(IStrategy strategy) { | ||
353 | return globalContext.tryStartNewThread(this, strategy); | ||
354 | } | ||
355 | |||
356 | @Override | ||
357 | public ExplorerThread tryStartNewThreadWithoutModelClone(IStrategy strategy) { | ||
358 | return globalContext.tryStartNewThreadWithoutModelClone(this, strategy); | ||
359 | } | ||
360 | |||
361 | @Override | ||
362 | public void startAllThreads(IStrategyFactory strategyFactory) { | ||
363 | globalContext.startAllThreads(this, strategyFactory); | ||
364 | } | ||
365 | |||
366 | @Override | ||
367 | public IStateCoder getStateCoder() { | ||
368 | return stateCoder; | ||
369 | } | ||
370 | |||
371 | @Override | ||
372 | public IDesignSpace getDesignSpace() { | ||
373 | return globalContext.getDesignSpace(); | ||
374 | } | ||
375 | |||
376 | @Override | ||
377 | public TrajectoryInfo getTrajectoryInfo() { | ||
378 | return designSpaceManager.getTrajectoryInfo(); | ||
379 | } | ||
380 | |||
381 | @Override | ||
382 | public List<Object> getTrajectory() { | ||
383 | return designSpaceManager.getTrajectoryInfo().getTrajectory(); | ||
384 | } | ||
385 | |||
386 | @Override | ||
387 | public List<Object> getTrajectoryCopied() { | ||
388 | return new ArrayList<Object>(getTrajectory()); | ||
389 | } | ||
390 | |||
391 | @Override | ||
392 | public int getDepth() { | ||
393 | return designSpaceManager.getTrajectoryInfo().getDepth(); | ||
394 | } | ||
395 | |||
396 | @Override | ||
397 | public Object getCurrentStateId() { | ||
398 | return designSpaceManager.getTrajectoryInfo().getCurrentStateId(); | ||
399 | } | ||
400 | |||
401 | @Override | ||
402 | public Object getTransitionByActivation(Activation<?> activation) { | ||
403 | return designSpaceManager.getTransitionByActivation(activation); | ||
404 | } | ||
405 | |||
406 | @Override | ||
407 | public Activation<?> getActivationById(Object activationId) { | ||
408 | return designSpaceManager.getActivationById(activationId); | ||
409 | } | ||
410 | |||
411 | @Override | ||
412 | public BatchTransformationRule<?, ?> getRuleByActivation(Activation<?> activation) { | ||
413 | return designSpaceManager.getRuleByActivation(activation); | ||
414 | } | ||
415 | |||
416 | @Override | ||
417 | public BatchTransformationRule<?, ?> getRuleByActivationId(Object activationId) { | ||
418 | return designSpaceManager.getRuleByActivationId(activationId); | ||
419 | } | ||
420 | |||
421 | @Override | ||
422 | public Collection<Object> getCurrentActivationIds() { | ||
423 | return designSpaceManager.getTransitionsFromCurrentState(); | ||
424 | } | ||
425 | |||
426 | @Override | ||
427 | public Collection<Object> getUntraversedActivationIds() { | ||
428 | return designSpaceManager.getUntraversedTransitionsFromCurrentState(); | ||
429 | } | ||
430 | |||
431 | @Override | ||
432 | public void executeAcitvationId(Object activationId) { | ||
433 | designSpaceManager.fireActivation(activationId); | ||
434 | } | ||
435 | |||
436 | @Override | ||
437 | public boolean tryExecuteAcitvationId(Object activationId) { | ||
438 | return designSpaceManager.tryFireActivation(activationId); | ||
439 | } | ||
440 | |||
441 | @Override | ||
442 | public boolean executeRandomActivationId() { | ||
443 | return designSpaceManager.executeRandomActivationId(); | ||
444 | } | ||
445 | |||
446 | @Override | ||
447 | public void executeTrajectory(Object[] activationIds) { | ||
448 | designSpaceManager.executeTrajectory(activationIds); | ||
449 | } | ||
450 | |||
451 | @Override | ||
452 | public void executeTrajectory(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) { | ||
453 | designSpaceManager.executeTrajectory(activationIds, fromIncludedIndex, toExcludedIndex); | ||
454 | } | ||
455 | |||
456 | @Override | ||
457 | public int executeTrajectoryByTrying(Object[] activationIds) { | ||
458 | return designSpaceManager.executeTrajectoryByTrying(activationIds); | ||
459 | } | ||
460 | |||
461 | @Override | ||
462 | public int executeTrajectoryByTrying(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) { | ||
463 | return designSpaceManager.executeTrajectoryByTrying(activationIds, fromIncludedIndex, toExcludedIndex); | ||
464 | } | ||
465 | |||
466 | @Override | ||
467 | public int executeTrajectoryWithoutStateCoding(Object[] activationIds) { | ||
468 | return designSpaceManager.executeTrajectoryWithoutStateCoding(activationIds); | ||
469 | } | ||
470 | |||
471 | @Override | ||
472 | public int executeTrajectoryWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) { | ||
473 | return designSpaceManager.executeTrajectoryWithoutStateCoding(activationIds, fromIncludedIndex, toExcludedIndex); | ||
474 | } | ||
475 | |||
476 | @Override | ||
477 | public int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds) { | ||
478 | return designSpaceManager.executeTrajectoryByTryingWithoutStateCoding(activationIds); | ||
479 | } | ||
480 | |||
481 | @Override | ||
482 | public int executeTrajectoryByTryingWithoutStateCoding(Object[] activationIds, int fromIncludedIndex, int toExcludedIndex) { | ||
483 | return designSpaceManager.executeTrajectoryByTryingWithoutStateCoding(activationIds, fromIncludedIndex, toExcludedIndex); | ||
484 | } | ||
485 | |||
486 | @Override | ||
487 | public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory) { | ||
488 | designSpaceManager.executeTrajectoryWithMinimalBacktrack(trajectory); | ||
489 | } | ||
490 | |||
491 | @Override | ||
492 | public void executeTrajectoryWithMinimalBacktrack(Object[] trajectory, int toExcludedIndex) { | ||
493 | designSpaceManager.executeTrajectoryWithMinimalBacktrack(trajectory, toExcludedIndex); | ||
494 | } | ||
495 | |||
496 | @Override | ||
497 | public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory) { | ||
498 | designSpaceManager.executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory); | ||
499 | } | ||
500 | |||
501 | @Override | ||
502 | public void executeTrajectoryWithMinimalBacktrackWithoutStateCoding(Object[] trajectory, int toExcludedIndex) { | ||
503 | designSpaceManager.executeTrajectoryWithMinimalBacktrackWithoutStateCoding(trajectory, toExcludedIndex); | ||
504 | } | ||
505 | |||
506 | @Override | ||
507 | public boolean backtrack() { | ||
508 | return designSpaceManager.undoLastTransformation(); | ||
509 | } | ||
510 | |||
511 | @Override | ||
512 | public void backtrackUntilLastCommonActivation(Object[] trajectory) { | ||
513 | designSpaceManager.backtrackUntilLastCommonActivation(trajectory); | ||
514 | } | ||
515 | |||
516 | @Override | ||
517 | public void backtrackUntilRoot() { | ||
518 | designSpaceManager.undoUntilRoot(); | ||
519 | } | ||
520 | |||
521 | @Override | ||
522 | public boolean isCurrentStateAlreadyTraversed() { | ||
523 | return designSpaceManager.isNewModelStateAlreadyTraversed(); | ||
524 | } | ||
525 | |||
526 | @Override | ||
527 | public boolean isCurrentStateInTrajectory() { | ||
528 | return designSpaceManager.isCurentStateInTrajectory(); | ||
529 | } | ||
530 | |||
531 | public ActivationCodesConflictSet getActivationCodesConflictSet() { | ||
532 | return activationCodesConflictSet; | ||
533 | } | ||
534 | |||
535 | public void changeActivationOrdering(ChangeableConflictSet activationOrderingConflictSet) { | ||
536 | this.dseConflictSet.changeActivationOrderingConflictSet(activationOrderingConflictSet); | ||
537 | } | ||
538 | |||
539 | public void changeActivationOrderingBack() { | ||
540 | this.dseConflictSet.changeActivationOrderingConflictSetBack(); | ||
541 | } | ||
542 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java new file mode 100644 index 00000000..bc0f08d4 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/DesignSpace.java | |||
@@ -0,0 +1,106 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.designspace.api; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.Collections; | ||
14 | import java.util.HashMap; | ||
15 | import java.util.HashSet; | ||
16 | import java.util.List; | ||
17 | import java.util.Map; | ||
18 | import java.util.Random; | ||
19 | import java.util.Set; | ||
20 | |||
21 | public class DesignSpace implements IDesignSpace { | ||
22 | |||
23 | Set<Object> statesView; | ||
24 | |||
25 | Set<Object> rootStates; | ||
26 | Set<Object> rootStatesView; | ||
27 | |||
28 | Map<Object, List<Object>> statesAndActivations; | ||
29 | |||
30 | Random random = new Random(); | ||
31 | |||
32 | public DesignSpace() { | ||
33 | rootStates = new HashSet<>(); | ||
34 | rootStatesView = Collections.unmodifiableSet(rootStates); | ||
35 | |||
36 | statesAndActivations = new HashMap<>(); | ||
37 | statesView = statesAndActivations.keySet(); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public synchronized Collection<Object> getStates() { | ||
42 | return statesView; | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public synchronized Collection<Object> getRoots() { | ||
47 | return rootStatesView; | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public synchronized void addState(Object sourceStateId, Object firedActivationId, Object newStateId) { | ||
52 | |||
53 | List<Object> activationIds = statesAndActivations.get(newStateId); | ||
54 | |||
55 | if (activationIds == null) { | ||
56 | activationIds = new ArrayList<Object>(); | ||
57 | statesAndActivations.put(newStateId, activationIds); | ||
58 | |||
59 | if (sourceStateId == null) { | ||
60 | rootStates.add(newStateId); | ||
61 | return; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | activationIds = statesAndActivations.get(sourceStateId); | ||
66 | |||
67 | if (activationIds == null) { | ||
68 | activationIds = new ArrayList<Object>(); | ||
69 | activationIds.add(firedActivationId); | ||
70 | statesAndActivations.put(sourceStateId, activationIds); | ||
71 | } else { | ||
72 | activationIds.add(firedActivationId); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | public synchronized boolean isTraversed(Object stateId) { | ||
77 | return statesAndActivations.containsKey(stateId); | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public synchronized Collection<Object> getActivationIds(Object stateId) { | ||
82 | return statesAndActivations.get(stateId); | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public synchronized Object getRandomActivationId(Object stateId) { | ||
87 | List<Object> activations = statesAndActivations.get(stateId); | ||
88 | int index = random.nextInt(activations.size()); | ||
89 | return activations.get(index); | ||
90 | } | ||
91 | |||
92 | @Override | ||
93 | public synchronized long getNumberOfStates() { | ||
94 | return statesAndActivations.size(); | ||
95 | } | ||
96 | |||
97 | @Override | ||
98 | public synchronized long getNumberOfTransitions() { | ||
99 | int numberOfTransitions = 0; | ||
100 | for (List<Object> activations : statesAndActivations.values()) { | ||
101 | numberOfTransitions += activations.size(); | ||
102 | } | ||
103 | return numberOfTransitions; | ||
104 | } | ||
105 | |||
106 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java new file mode 100644 index 00000000..5c688276 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IBacktrackListener.java | |||
@@ -0,0 +1,7 @@ | |||
1 | package org.eclipse.viatra.dse.designspace.api; | ||
2 | |||
3 | public interface IBacktrackListener { | ||
4 | void forwardWorked(long nanos); | ||
5 | |||
6 | void backtrackWorked(long nanos); | ||
7 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java new file mode 100644 index 00000000..a1d64bbf --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/IDesignSpace.java | |||
@@ -0,0 +1,27 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.designspace.api; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | public interface IDesignSpace { | ||
14 | |||
15 | Collection<Object> getStates(); | ||
16 | Collection<Object> getRoots(); | ||
17 | void addState(Object sourceStateId, Object firedActivationId, Object newStateId); | ||
18 | |||
19 | boolean isTraversed(Object stateId); | ||
20 | |||
21 | Collection<Object> getActivationIds(Object stateId); | ||
22 | Object getRandomActivationId(Object stateId); | ||
23 | |||
24 | long getNumberOfStates(); | ||
25 | long getNumberOfTransitions(); | ||
26 | |||
27 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java new file mode 100644 index 00000000..acd88416 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/designspace/api/TrajectoryInfo.java | |||
@@ -0,0 +1,154 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.designspace.api; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collections; | ||
13 | import java.util.List; | ||
14 | import java.util.Map; | ||
15 | import java.util.Objects; | ||
16 | |||
17 | import org.eclipse.viatra.dse.api.DSEException; | ||
18 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
19 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
20 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
21 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
22 | |||
23 | public class TrajectoryInfo { | ||
24 | |||
25 | private final List<Object> trajectory; | ||
26 | private final List<Object> trajectoryView; | ||
27 | private final List<BatchTransformationRule<?, ?>> rules; | ||
28 | private final List<BatchTransformationRule<?, ?>> rulesView; | ||
29 | private final List<Object> stateIds; | ||
30 | private final List<Object> stateIdsView; | ||
31 | private final List<Map<String, Double>> measuredCosts; | ||
32 | |||
33 | public TrajectoryInfo(Object initialStateId) { | ||
34 | Objects.requireNonNull(initialStateId); | ||
35 | |||
36 | stateIds = new ArrayList<>(); | ||
37 | stateIds.add(initialStateId); | ||
38 | |||
39 | trajectory = new ArrayList<>(); | ||
40 | rules = new ArrayList<>(); | ||
41 | measuredCosts = new ArrayList<>(); | ||
42 | |||
43 | trajectoryView = Collections.unmodifiableList(trajectory); | ||
44 | stateIdsView = Collections.unmodifiableList(stateIds); | ||
45 | rulesView = Collections.unmodifiableList(rules); | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * Copy constructor | ||
50 | * | ||
51 | * @since 0.17 | ||
52 | */ | ||
53 | public TrajectoryInfo(TrajectoryInfo other) { | ||
54 | this(other.stateIds, other.trajectory, other.rules, other.measuredCosts); | ||
55 | } | ||
56 | |||
57 | protected TrajectoryInfo(List<Object> stateIds, List<Object> trajectory, List<BatchTransformationRule<?, ?>> rules, List<Map<String, Double>> measuredCosts) { | ||
58 | |||
59 | this.stateIds = new ArrayList<>(stateIds); | ||
60 | this.trajectory = new ArrayList<>(trajectory); | ||
61 | this.rules = new ArrayList<>(rules); | ||
62 | trajectoryView = Collections.unmodifiableList(trajectory); | ||
63 | stateIdsView = Collections.unmodifiableList(stateIds); | ||
64 | rulesView = Collections.unmodifiableList(rules); | ||
65 | this.measuredCosts = new ArrayList<>(measuredCosts); | ||
66 | } | ||
67 | |||
68 | public void addStep(Object activationId, BatchTransformationRule<?, ?> rule, Object newStateId, Map<String, Double> measuredCosts) { | ||
69 | stateIds.add(newStateId); | ||
70 | trajectory.add(activationId); | ||
71 | rules.add(rule); | ||
72 | this.measuredCosts.add(measuredCosts); | ||
73 | } | ||
74 | |||
75 | public void backtrack() { | ||
76 | int size = trajectory.size(); | ||
77 | |||
78 | if (size == 0) { | ||
79 | throw new DSEException("Cannot step back any further!"); | ||
80 | } | ||
81 | |||
82 | trajectory.remove(size - 1); | ||
83 | rules.remove(size - 1); | ||
84 | stateIds.remove(size); | ||
85 | measuredCosts.remove(size - 1); | ||
86 | } | ||
87 | |||
88 | public Object getInitialStateId() { | ||
89 | return stateIds.get(0); | ||
90 | } | ||
91 | |||
92 | public Object getCurrentStateId() { | ||
93 | return stateIds.get(stateIds.size() - 1); | ||
94 | } | ||
95 | |||
96 | public Object getLastActivationId() { | ||
97 | return trajectory.get(trajectory.size() - 1); | ||
98 | } | ||
99 | |||
100 | public List<Object> getTrajectory() { | ||
101 | return trajectoryView; | ||
102 | } | ||
103 | |||
104 | public List<Object> getStateTrajectory() { | ||
105 | return stateIdsView; | ||
106 | } | ||
107 | |||
108 | public List<BatchTransformationRule<?, ?>> getRules() { | ||
109 | return rulesView; | ||
110 | } | ||
111 | |||
112 | public int getDepth() { | ||
113 | return trajectory.size(); | ||
114 | } | ||
115 | |||
116 | public List<Map<String, Double>> getMeasuredCosts() { | ||
117 | return measuredCosts; | ||
118 | } | ||
119 | |||
120 | public SolutionTrajectory createSolutionTrajectory(final IStateCoderFactory stateCoderFactory, final IBacktrackListener listener) { | ||
121 | |||
122 | List<Object> activationIds = new ArrayList<>(trajectory); | ||
123 | List<BatchTransformationRule<?, ?>> copiedRules = new ArrayList<>(rules); | ||
124 | |||
125 | return new SolutionTrajectory(activationIds, copiedRules, stateCoderFactory, listener); | ||
126 | } | ||
127 | |||
128 | public boolean canStepBack() { | ||
129 | return !trajectory.isEmpty(); | ||
130 | } | ||
131 | |||
132 | @Override | ||
133 | public String toString() { | ||
134 | StringBuilder sb = new StringBuilder("Trajectory:\n"); | ||
135 | for (Object activationId : trajectory) { | ||
136 | sb.append(activationId); | ||
137 | sb.append("\n"); | ||
138 | } | ||
139 | return sb.toString(); | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * This method is only used by the {@link DesignSpaceManager}. | ||
144 | * @param stateCode | ||
145 | * @return false if the initial state code is the last one, otherwise true. | ||
146 | */ | ||
147 | public boolean modifyLastStateCode(Object stateCode) { | ||
148 | if (stateIds.size() == 1) { | ||
149 | return false; | ||
150 | } | ||
151 | stateIds.set(stateIds.size() - 1, stateCode); | ||
152 | return true; | ||
153 | } | ||
154 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java new file mode 100644 index 00000000..17e96a75 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/multithreading/DSEThreadPool.java | |||
@@ -0,0 +1,58 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.multithreading; | ||
10 | |||
11 | import java.util.concurrent.RejectedExecutionException; | ||
12 | import java.util.concurrent.SynchronousQueue; | ||
13 | import java.util.concurrent.ThreadPoolExecutor; | ||
14 | import java.util.concurrent.TimeUnit; | ||
15 | |||
16 | import org.apache.log4j.Logger; | ||
17 | import org.eclipse.viatra.dse.api.DesignSpaceExplorer; | ||
18 | import org.eclipse.viatra.dse.base.ExplorerThread; | ||
19 | |||
20 | /** | ||
21 | * | ||
22 | * @author Andras Szabolcs Nagy | ||
23 | * | ||
24 | */ | ||
25 | public class DSEThreadPool extends ThreadPoolExecutor { | ||
26 | |||
27 | private static final long THREAD_KEEP_ALIVE_IN_SECONDS = 60; | ||
28 | |||
29 | public DSEThreadPool() { | ||
30 | // Based on the Executors.newCachedThreadPool() | ||
31 | super(0, getProcNumber(), THREAD_KEEP_ALIVE_IN_SECONDS, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); | ||
32 | } | ||
33 | |||
34 | // helper for constructor | ||
35 | private static int getProcNumber() { | ||
36 | return Runtime.getRuntime().availableProcessors(); | ||
37 | } | ||
38 | |||
39 | public boolean tryStartNewStrategy(ExplorerThread strategy) { | ||
40 | |||
41 | if (!canStartNewThread()) { | ||
42 | return false; | ||
43 | } | ||
44 | |||
45 | try { | ||
46 | submit(strategy); | ||
47 | } catch (RejectedExecutionException e) { | ||
48 | Logger.getLogger(DesignSpaceExplorer.class).info("Couldn't start new thread.", e); | ||
49 | return false; | ||
50 | } | ||
51 | |||
52 | return true; | ||
53 | } | ||
54 | |||
55 | public boolean canStartNewThread() { | ||
56 | return getMaximumPoolSize() > getActiveCount(); | ||
57 | } | ||
58 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java new file mode 100644 index 00000000..c06d2916 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ActivationFitnessProcessor.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives; | ||
10 | |||
11 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
12 | |||
13 | public interface ActivationFitnessProcessor { | ||
14 | public double process(IPatternMatch match); | ||
15 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java new file mode 100644 index 00000000..b1bd9349 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Comparators.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives; | ||
10 | |||
11 | import java.util.Comparator; | ||
12 | |||
13 | /** | ||
14 | * This helper class holds comparators for objective implementations. | ||
15 | * | ||
16 | * @author Andras Szabolcs Nagy | ||
17 | * | ||
18 | */ | ||
19 | public class Comparators { | ||
20 | |||
21 | private Comparators() { /*Utility class constructor*/ } | ||
22 | |||
23 | public static final Comparator<Double> HIGHER_IS_BETTER = (o1, o2) -> o1.compareTo(o2); | ||
24 | |||
25 | public static final Comparator<Double> LOWER_IS_BETTER = (o1, o2) -> o2.compareTo(o1); | ||
26 | |||
27 | private static final Double ZERO = Double.valueOf(0); | ||
28 | |||
29 | public static final Comparator<Double> DIFFERENCE_TO_ZERO_IS_BETTER = (o1, o2) -> ZERO.compareTo(Math.abs(o1)-Math.abs(o2)); | ||
30 | |||
31 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java new file mode 100644 index 00000000..8beef3bd --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/Fitness.java | |||
@@ -0,0 +1,29 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | |||
13 | public class Fitness extends HashMap<String, Double>{ | ||
14 | |||
15 | private boolean satisifiesHardObjectives; | ||
16 | |||
17 | public boolean isSatisifiesHardObjectives() { | ||
18 | return satisifiesHardObjectives; | ||
19 | } | ||
20 | |||
21 | public void setSatisifiesHardObjectives(boolean satisifiesHardObjectives) { | ||
22 | this.satisifiesHardObjectives = satisifiesHardObjectives; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public String toString() { | ||
27 | return super.toString() + " hardObjectives=" + satisifiesHardObjectives; | ||
28 | } | ||
29 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java new file mode 100644 index 00000000..2f7f0347 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IGlobalConstraint.java | |||
@@ -0,0 +1,58 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | |||
13 | /** | ||
14 | * | ||
15 | * Implementation of this interface represents a global constraint of the DSE problem, which can halt an exploration | ||
16 | * continuing from a state which dissatisfies the global constraint. | ||
17 | * <p> | ||
18 | * Certain global constraints can have inner state for the validation. In this case a new instance is necessary for | ||
19 | * every new thread, and the {@code createNew} method should not return the same instance more than once. | ||
20 | * | ||
21 | * @author Andras Szabolcs Nagy | ||
22 | * | ||
23 | */ | ||
24 | public interface IGlobalConstraint { | ||
25 | |||
26 | /** | ||
27 | * Returns the name of the global constraint. | ||
28 | * | ||
29 | * @return The name of the global constraint. | ||
30 | */ | ||
31 | String getName(); | ||
32 | |||
33 | /** | ||
34 | * Checks whether the current state satisfies the global constraint. | ||
35 | * | ||
36 | * @param context | ||
37 | * The {@link ThreadContext} which contains the necessary information. | ||
38 | * @return True if the state is valid and exploration can be continued from the actual state. | ||
39 | */ | ||
40 | boolean checkGlobalConstraint(ThreadContext context); | ||
41 | |||
42 | /** | ||
43 | * Initializes the global constraint. It is called exactly once for every thread starts. | ||
44 | * | ||
45 | * @param context | ||
46 | * The {@link ThreadContext}. | ||
47 | */ | ||
48 | void init(ThreadContext context); | ||
49 | |||
50 | /** | ||
51 | * Returns an instance of the {@link IGlobalConstraint}. If it returns the same instance, all the methods has to be | ||
52 | * thread save as they are called concurrently. | ||
53 | * | ||
54 | * @return An instance of the global constraint. | ||
55 | */ | ||
56 | IGlobalConstraint createNew(); | ||
57 | |||
58 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java new file mode 100644 index 00000000..849dd4e8 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/IObjective.java | |||
@@ -0,0 +1,110 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives; | ||
10 | |||
11 | import java.util.Comparator; | ||
12 | |||
13 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
14 | |||
15 | /** | ||
16 | * | ||
17 | * Implementation of this interface represents a single objective of the DSE problem, which can assess a solution | ||
18 | * (trajectory) in a single number. It has a name and a comparator which orders two solution based on the calculated | ||
19 | * value. | ||
20 | * <p> | ||
21 | * Objectives can be either hard or soft objectives. Hard objectives can be satisfied or unsatisfied. If all of the hard | ||
22 | * objectives are satisfied on a single solution, then it is considered to be a valid (or goal) solution. | ||
23 | * <p> | ||
24 | * Certain objectives can have inner state for calculating the fitness value. In this case a new instance is necessary | ||
25 | * for every new thread, and the {@code createNew} method should not return the same instance more than once. | ||
26 | * | ||
27 | * @author Andras Szabolcs Nagy | ||
28 | * | ||
29 | */ | ||
30 | public interface IObjective { | ||
31 | |||
32 | /** | ||
33 | * Returns the name of the objective. | ||
34 | * | ||
35 | * @return The name of the objective. | ||
36 | */ | ||
37 | String getName(); | ||
38 | |||
39 | /** | ||
40 | * Sets the {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is to | ||
41 | * minimize or maximize (or minimize or maximize a delta from a given number). | ||
42 | * | ||
43 | * @param comparator The comparator. | ||
44 | */ | ||
45 | void setComparator(Comparator<Double> comparator); | ||
46 | |||
47 | /** | ||
48 | * Returns a {@link Comparator} which is used to compare fitness (doubles). It determines whether the objective is | ||
49 | * to minimize or maximize (or minimize or maximize a delta from a given number). | ||
50 | * | ||
51 | * @return The comparator. | ||
52 | */ | ||
53 | Comparator<Double> getComparator(); | ||
54 | |||
55 | /** | ||
56 | * Calculates the value of the objective on a given solution (trajectory). | ||
57 | * | ||
58 | * @param context | ||
59 | * The {@link ThreadContext} | ||
60 | * @return The objective value in double. | ||
61 | */ | ||
62 | Double getFitness(ThreadContext context); | ||
63 | |||
64 | /** | ||
65 | * Initializes the objective. It is called exactly once for every thread starts. | ||
66 | * | ||
67 | * @param context | ||
68 | * The {@link ThreadContext}. | ||
69 | */ | ||
70 | void init(ThreadContext context); | ||
71 | |||
72 | /** | ||
73 | * Returns an instance of the {@link IObjective}. If it returns the same instance, all the methods has to be thread | ||
74 | * save as they are called concurrently. | ||
75 | * | ||
76 | * @return An instance of the objective. | ||
77 | */ | ||
78 | IObjective createNew(); | ||
79 | |||
80 | /** | ||
81 | * Returns true if the objective is a hard objective. In such a case the method | ||
82 | * {@link IObjective#satisifiesHardObjective(Double)} is called. | ||
83 | * | ||
84 | * @return True if the objective is a hard objective. | ||
85 | * @see IObjective#satisifiesHardObjective(Double) | ||
86 | * @see IObjective | ||
87 | */ | ||
88 | boolean isHardObjective(); | ||
89 | |||
90 | /** | ||
91 | * Determines if the given fitness value satisfies the hard objective. | ||
92 | * | ||
93 | * @param fitness | ||
94 | * The fitness value of a solution. | ||
95 | * @return True if it satisfies the hard objective or it is a soft constraint. | ||
96 | * @see IObjective | ||
97 | */ | ||
98 | boolean satisifiesHardObjective(Double fitness); | ||
99 | |||
100 | /** | ||
101 | * Set the level of the objective. | ||
102 | */ | ||
103 | void setLevel(int level); | ||
104 | |||
105 | /** | ||
106 | * Gets the level of the objective. | ||
107 | */ | ||
108 | int getLevel(); | ||
109 | |||
110 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java new file mode 100644 index 00000000..2d81629b --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/LeveledObjectivesHelper.java | |||
@@ -0,0 +1,114 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Arrays; | ||
13 | import java.util.Comparator; | ||
14 | import java.util.List; | ||
15 | |||
16 | public class LeveledObjectivesHelper { | ||
17 | |||
18 | private List<IObjective> objectives = new ArrayList<IObjective>(); | ||
19 | private IObjective[][] leveledObjectives; | ||
20 | |||
21 | public LeveledObjectivesHelper(List<IObjective> objectives) { | ||
22 | this.objectives = objectives; | ||
23 | } | ||
24 | |||
25 | public IObjective[][] initLeveledObjectives() { | ||
26 | if (objectives.isEmpty()) { | ||
27 | leveledObjectives = new IObjective[0][0]; | ||
28 | return leveledObjectives; | ||
29 | } | ||
30 | |||
31 | int level = objectives.get(0).getLevel(); | ||
32 | boolean oneLevelOnly = true; | ||
33 | for (IObjective objective : objectives) { | ||
34 | if (objective.getLevel() != level) { | ||
35 | oneLevelOnly = false; | ||
36 | break; | ||
37 | } | ||
38 | } | ||
39 | |||
40 | if (oneLevelOnly) { | ||
41 | leveledObjectives = new IObjective[1][objectives.size()]; | ||
42 | for (int i = 0; i < objectives.size(); i++) { | ||
43 | leveledObjectives[0][i] = objectives.get(i); | ||
44 | } | ||
45 | return leveledObjectives; | ||
46 | } | ||
47 | |||
48 | IObjective[] objectivesArray = getSortedByLevelObjectives(objectives); | ||
49 | |||
50 | int numberOfLevels = getNumberOfObjectiveLevels(objectivesArray); | ||
51 | |||
52 | leveledObjectives = new IObjective[numberOfLevels][]; | ||
53 | |||
54 | fillLeveledObjectives(objectivesArray); | ||
55 | |||
56 | return leveledObjectives; | ||
57 | } | ||
58 | |||
59 | private void fillLeveledObjectives(IObjective[] objectivesArray) { | ||
60 | int actLevel = objectivesArray[0].getLevel(); | ||
61 | int levelIndex = 0; | ||
62 | int lastIndex = 0; | ||
63 | int corrigationForLastLevel = 0; | ||
64 | boolean oneObjectiveAtLastLevel = false; | ||
65 | for (int i = 0; i < objectivesArray.length; i++) { | ||
66 | if (i == objectivesArray.length - 1) { | ||
67 | corrigationForLastLevel = 1; | ||
68 | if (objectivesArray[i - 1].getLevel() != objectivesArray[i].getLevel()) { | ||
69 | oneObjectiveAtLastLevel = true; | ||
70 | corrigationForLastLevel = 0; | ||
71 | } | ||
72 | } | ||
73 | if (objectivesArray[i].getLevel() != actLevel || corrigationForLastLevel == 1 || oneObjectiveAtLastLevel) { | ||
74 | leveledObjectives[levelIndex] = new IObjective[i - lastIndex + corrigationForLastLevel]; | ||
75 | for (int j = lastIndex; j < i + corrigationForLastLevel; j++) { | ||
76 | leveledObjectives[levelIndex][j - lastIndex] = objectivesArray[j]; | ||
77 | } | ||
78 | if (oneObjectiveAtLastLevel) { | ||
79 | leveledObjectives[levelIndex + 1] = new IObjective[1]; | ||
80 | leveledObjectives[levelIndex + 1][0] = objectivesArray[i]; | ||
81 | } | ||
82 | actLevel = objectivesArray[i].getLevel(); | ||
83 | levelIndex++; | ||
84 | lastIndex = i; | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | private int getNumberOfObjectiveLevels(IObjective[] objectivesArray) { | ||
90 | |||
91 | int actLevel = objectivesArray[0].getLevel(); | ||
92 | int numberOfLevels = 1; | ||
93 | |||
94 | for (int i = 1; i < objectivesArray.length; i++) { | ||
95 | if (objectivesArray[i].getLevel() != actLevel) { | ||
96 | numberOfLevels++; | ||
97 | actLevel = objectivesArray[i].getLevel(); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | return numberOfLevels; | ||
102 | } | ||
103 | |||
104 | private IObjective[] getSortedByLevelObjectives(List<IObjective> objectives) { | ||
105 | IObjective[] objectivesArray = objectives.toArray(new IObjective[objectives.size()]); | ||
106 | Arrays.sort(objectivesArray, Comparator.comparingInt(IObjective::getLevel)); | ||
107 | return objectivesArray; | ||
108 | } | ||
109 | |||
110 | public IObjective[][] getLeveledObjectives() { | ||
111 | return leveledObjectives; | ||
112 | } | ||
113 | |||
114 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java new file mode 100644 index 00000000..39139bb0 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/ObjectiveComparatorHelper.java | |||
@@ -0,0 +1,217 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Arrays; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.List; | ||
15 | import java.util.Map; | ||
16 | import java.util.Random; | ||
17 | |||
18 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
19 | |||
20 | /** | ||
21 | * This class is responsible to compare and sort fitness values. {@link TrajectoryFitness} instances can be added to an | ||
22 | * instance of this class, that it can sort them. | ||
23 | * | ||
24 | * @author András Szabolcs Nagy | ||
25 | */ | ||
26 | public class ObjectiveComparatorHelper { | ||
27 | |||
28 | private IObjective[][] leveledObjectives; | ||
29 | private List<TrajectoryFitness> trajectoryFitnesses = new ArrayList<TrajectoryFitness>(); | ||
30 | private Random random = new Random(); | ||
31 | private boolean computeCrowdingDistance = false; | ||
32 | |||
33 | public ObjectiveComparatorHelper(IObjective[][] leveledObjectives) { | ||
34 | this.leveledObjectives = leveledObjectives; | ||
35 | } | ||
36 | |||
37 | public void setComputeCrowdingDistance(boolean computeCrowdingDistance) { | ||
38 | this.computeCrowdingDistance = computeCrowdingDistance; | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * Compares two fitnesses based on hierarchical dominance. Returns -1 if the second parameter {@code o2} is a better | ||
43 | * solution ({@code o2} dominates {@code o1}), 1 if the first parameter {@code o1} is better ({@code o1} dominates | ||
44 | * {@code o2}) and returns 0 if they are non-dominating each other. | ||
45 | */ | ||
46 | public int compare(Fitness o1, Fitness o2) { | ||
47 | |||
48 | levelsLoop: for (int i = 0; i < leveledObjectives.length; i++) { | ||
49 | |||
50 | boolean o1HasBetterFitness = false; | ||
51 | boolean o2HasBetterFitness = false; | ||
52 | |||
53 | for (IObjective objective : leveledObjectives[i]) { | ||
54 | String objectiveName = objective.getName(); | ||
55 | int sgn = objective.getComparator().compare(o1.get(objectiveName), o2.get(objectiveName)); | ||
56 | |||
57 | if (sgn < 0) { | ||
58 | o2HasBetterFitness = true; | ||
59 | } | ||
60 | if (sgn > 0) { | ||
61 | o1HasBetterFitness = true; | ||
62 | } | ||
63 | if (o1HasBetterFitness && o2HasBetterFitness) { | ||
64 | continue levelsLoop; | ||
65 | } | ||
66 | } | ||
67 | if (o2HasBetterFitness && !o1HasBetterFitness) { | ||
68 | return -1; | ||
69 | } else if (!o2HasBetterFitness && o1HasBetterFitness) { | ||
70 | return 1; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | |||
76 | } | ||
77 | |||
78 | /** | ||
79 | * Adds a {@link TrajectoryFitness} to an inner list to compare later. | ||
80 | * | ||
81 | * @param trajectoryFitness | ||
82 | */ | ||
83 | public void addTrajectoryFitness(TrajectoryFitness trajectoryFitness) { | ||
84 | trajectoryFitnesses.add(trajectoryFitness); | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * Clears the inner {@link TrajectoryFitness} list. | ||
89 | */ | ||
90 | public void clearTrajectoryFitnesses() { | ||
91 | trajectoryFitnesses.clear(); | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Returns the inner {@link TrajectoryFitness} list. | ||
96 | */ | ||
97 | public List<TrajectoryFitness> getTrajectoryFitnesses() { | ||
98 | return trajectoryFitnesses; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * Returns a random {@link TrajectoryFitness} from the pareto front. | ||
103 | */ | ||
104 | public TrajectoryFitness getRandomBest() { | ||
105 | List<TrajectoryFitness> paretoFront = getParetoFront(); | ||
106 | int randomIndex = random.nextInt(paretoFront.size()); | ||
107 | return paretoFront.get(randomIndex); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Returns the pareto front of the previously added {@link TrajectoryFitness}. | ||
112 | */ | ||
113 | public List<TrajectoryFitness> getParetoFront() { | ||
114 | return getFronts().get(0); | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * Returns the previously added {@link TrajectoryFitness} instances in fronts. | ||
119 | */ | ||
120 | public List<? extends List<TrajectoryFitness>> getFronts() { | ||
121 | Preconditions.checkArgument(!trajectoryFitnesses.isEmpty(), "No trajectory fitnesses were added."); | ||
122 | List<ArrayList<TrajectoryFitness>> fronts = new ArrayList<ArrayList<TrajectoryFitness>>(); | ||
123 | |||
124 | Map<TrajectoryFitness, ArrayList<TrajectoryFitness>> dominatedInstances = new HashMap<TrajectoryFitness, ArrayList<TrajectoryFitness>>(); | ||
125 | Map<TrajectoryFitness, Integer> dominatingInstances = new HashMap<TrajectoryFitness, Integer>(); | ||
126 | |||
127 | // calculate dominations | ||
128 | for (TrajectoryFitness TrajectoryFitnessP : trajectoryFitnesses) { | ||
129 | dominatedInstances.put(TrajectoryFitnessP, new ArrayList<TrajectoryFitness>()); | ||
130 | dominatingInstances.put(TrajectoryFitnessP, 0); | ||
131 | |||
132 | for (TrajectoryFitness TrajectoryFitnessQ : trajectoryFitnesses) { | ||
133 | int dominates = compare(TrajectoryFitnessP.fitness, TrajectoryFitnessQ.fitness); | ||
134 | if (dominates > 0) { | ||
135 | dominatedInstances.get(TrajectoryFitnessP).add(TrajectoryFitnessQ); | ||
136 | } else if (dominates < 0) { | ||
137 | dominatingInstances.put(TrajectoryFitnessP, dominatingInstances.get(TrajectoryFitnessP) + 1); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | if (dominatingInstances.get(TrajectoryFitnessP) == 0) { | ||
142 | // p belongs to the first front | ||
143 | TrajectoryFitnessP.rank = 1; | ||
144 | if (fronts.isEmpty()) { | ||
145 | ArrayList<TrajectoryFitness> firstDominationFront = new ArrayList<TrajectoryFitness>(); | ||
146 | firstDominationFront.add(TrajectoryFitnessP); | ||
147 | fronts.add(firstDominationFront); | ||
148 | } else { | ||
149 | List<TrajectoryFitness> firstDominationFront = fronts.get(0); | ||
150 | firstDominationFront.add(TrajectoryFitnessP); | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | |||
155 | // create fronts | ||
156 | int i = 1; | ||
157 | while (fronts.size() == i) { | ||
158 | ArrayList<TrajectoryFitness> nextDominationFront = new ArrayList<TrajectoryFitness>(); | ||
159 | for (TrajectoryFitness TrajectoryFitnessP : fronts.get(i - 1)) { | ||
160 | for (TrajectoryFitness TrajectoryFitnessQ : dominatedInstances.get(TrajectoryFitnessP)) { | ||
161 | dominatingInstances.put(TrajectoryFitnessQ, dominatingInstances.get(TrajectoryFitnessQ) - 1); | ||
162 | if (dominatingInstances.get(TrajectoryFitnessQ) == 0) { | ||
163 | TrajectoryFitnessQ.rank = i + 1; | ||
164 | nextDominationFront.add(TrajectoryFitnessQ); | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | i++; | ||
169 | if (!nextDominationFront.isEmpty()) { | ||
170 | if (computeCrowdingDistance) { | ||
171 | crowdingDistanceAssignment(nextDominationFront, leveledObjectives); | ||
172 | } | ||
173 | fronts.add(nextDominationFront); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | return fronts; | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * Executes the crowding distance assignment for the specified front. | ||
182 | * | ||
183 | * @param front | ||
184 | */ | ||
185 | public static void crowdingDistanceAssignment(List<TrajectoryFitness> front, IObjective[][] leveledObjectives) { | ||
186 | |||
187 | for (TrajectoryFitness InstanceData : front) { | ||
188 | // initialize crowding distance | ||
189 | InstanceData.crowdingDistance = 0; | ||
190 | } | ||
191 | |||
192 | for (final IObjective[] objectives : leveledObjectives) { | ||
193 | for (final IObjective objective : objectives) { | ||
194 | |||
195 | final String m = objective.getName(); | ||
196 | TrajectoryFitness[] sortedFront = front.toArray(new TrajectoryFitness[0]); | ||
197 | // sort using m-th objective value | ||
198 | Arrays.sort(sortedFront, (o1, o2) -> objective.getComparator().compare(o1.fitness.get(m), o2.fitness.get(m))); | ||
199 | // so that boundary points are always selected | ||
200 | sortedFront[0].crowdingDistance = Double.POSITIVE_INFINITY; | ||
201 | sortedFront[sortedFront.length - 1].crowdingDistance = Double.POSITIVE_INFINITY; | ||
202 | // If minimal and maximal fitness value for this objective are | ||
203 | // equal, then do not change crowding distance | ||
204 | if (sortedFront[0].fitness.get(m) != sortedFront[sortedFront.length - 1].fitness.get(m)) { | ||
205 | for (int i = 1; i < sortedFront.length - 1; i++) { | ||
206 | double newCrowdingDistance = sortedFront[i].crowdingDistance; | ||
207 | newCrowdingDistance += (sortedFront[i + 1].fitness.get(m) - sortedFront[i - 1].fitness.get(m)) | ||
208 | / (sortedFront[sortedFront.length - 1].fitness.get(m) - sortedFront[0].fitness.get(m)); | ||
209 | |||
210 | sortedFront[i].crowdingDistance = newCrowdingDistance; | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java new file mode 100644 index 00000000..f783afac --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/TrajectoryFitness.java | |||
@@ -0,0 +1,84 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.List; | ||
13 | |||
14 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
15 | |||
16 | /** | ||
17 | * This class represents a trajectory and its fitness. | ||
18 | * @author Andras Szabolcs Nagy | ||
19 | * | ||
20 | */ | ||
21 | public class TrajectoryFitness { | ||
22 | |||
23 | public Object[] trajectory; | ||
24 | public Fitness fitness; | ||
25 | |||
26 | public int rank; | ||
27 | public double crowdingDistance; | ||
28 | |||
29 | private int hash; | ||
30 | |||
31 | public int survive; | ||
32 | |||
33 | /** | ||
34 | * Creates a {@link TrajectoryFitness} with the full trajectory. | ||
35 | * @param trajectory The trajectory. | ||
36 | * @param fitness The fitness. | ||
37 | */ | ||
38 | public TrajectoryFitness(Object[] trajectory, Fitness fitness) { | ||
39 | this.fitness = fitness; | ||
40 | this.trajectory = trajectory; | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Creates a {@link TrajectoryFitness} with the full trajectory. | ||
45 | * @param trajectoryInfo The trajectory. | ||
46 | * @param fitness The fitness. | ||
47 | */ | ||
48 | public TrajectoryFitness(TrajectoryInfo trajectoryInfo, Fitness fitness) { | ||
49 | this.fitness = fitness; | ||
50 | List<Object> fullTraj = trajectoryInfo.getTrajectory(); | ||
51 | trajectory = fullTraj.toArray(new Object[fullTraj.size()]); | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * Creates a {@link TrajectoryFitness} with the given activation id} | ||
56 | * @param transition The transition. | ||
57 | * @param fitness The fitness. | ||
58 | */ | ||
59 | public TrajectoryFitness(Object transition, Fitness fitness) { | ||
60 | this.fitness = fitness; | ||
61 | trajectory = new Object[] {transition}; | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public boolean equals(Object obj) { | ||
66 | if (obj instanceof TrajectoryFitness) { | ||
67 | return Arrays.equals(trajectory, ((TrajectoryFitness) obj).trajectory); | ||
68 | } | ||
69 | return false; | ||
70 | } | ||
71 | |||
72 | @Override | ||
73 | public int hashCode() { | ||
74 | if (hash == 0 && trajectory.length > 0) { | ||
75 | hash = Arrays.hashCode(trajectory); | ||
76 | } | ||
77 | return hash; | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public String toString() { | ||
82 | return Arrays.toString(trajectory) + fitness.toString(); | ||
83 | } | ||
84 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java new file mode 100644 index 00000000..9898a3b5 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/AlwaysSatisfiedDummyHardObjective.java | |||
@@ -0,0 +1,52 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
13 | |||
14 | /** | ||
15 | * This hard objective is fulfilled in any circumstances. Use it if all states should be regarded as a valid solution. | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class AlwaysSatisfiedDummyHardObjective extends BaseObjective { | ||
21 | |||
22 | private static final String DEFAULT_NAME = "AlwaysSatisfiedDummyHardObjective"; | ||
23 | |||
24 | public AlwaysSatisfiedDummyHardObjective() { | ||
25 | super(DEFAULT_NAME); | ||
26 | } | ||
27 | |||
28 | public AlwaysSatisfiedDummyHardObjective(String name) { | ||
29 | super(name); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Double getFitness(ThreadContext context) { | ||
34 | return 0d; | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public boolean isHardObjective() { | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public boolean satisifiesHardObjective(Double fitness) { | ||
44 | return true; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public IObjective createNew() { | ||
49 | return this; | ||
50 | } | ||
51 | |||
52 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java new file mode 100644 index 00000000..0a1de875 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/BaseObjective.java | |||
@@ -0,0 +1,150 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | import java.util.Comparator; | ||
12 | import java.util.Objects; | ||
13 | |||
14 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
15 | import org.eclipse.viatra.dse.objectives.Comparators; | ||
16 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
17 | |||
18 | /** | ||
19 | * This abstract class implements the basic functionality of an objective ({@link IObjective} namely its name, | ||
20 | * comparator, level and fitness hard constraint. | ||
21 | * | ||
22 | * @author Andras Szabolcs Nagy | ||
23 | * | ||
24 | */ | ||
25 | public abstract class BaseObjective implements IObjective { | ||
26 | |||
27 | protected final String name; | ||
28 | protected Comparator<Double> comparator = Comparators.HIGHER_IS_BETTER; | ||
29 | protected int level = 0; | ||
30 | |||
31 | protected double fitnessConstraint; | ||
32 | protected boolean isThereFitnessConstraint = false; | ||
33 | protected Comparator<Double> fitnessConstraintComparator; | ||
34 | |||
35 | public BaseObjective(String name) { | ||
36 | Objects.requireNonNull(name, "Name of the objective cannot be null."); | ||
37 | this.name = name; | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public String getName() { | ||
42 | return name; | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public void setComparator(Comparator<Double> comparator) { | ||
47 | this.comparator = comparator; | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public Comparator<Double> getComparator() { | ||
52 | return comparator; | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public void setLevel(int level) { | ||
57 | this.level = level; | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public int getLevel() { | ||
62 | return level; | ||
63 | } | ||
64 | |||
65 | public BaseObjective withLevel(int level) { | ||
66 | setLevel(level); | ||
67 | return this; | ||
68 | } | ||
69 | |||
70 | public BaseObjective withComparator(Comparator<Double> comparator) { | ||
71 | setComparator(comparator); | ||
72 | return this; | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the | ||
77 | * current state as a solution. | ||
78 | * | ||
79 | * @param fitnessConstraint | ||
80 | * Solutions should be better than this value. | ||
81 | * @param fitnessConstraintComparator | ||
82 | * {@link Comparator} to determine if the current state is better than the given value. | ||
83 | * @return The actual instance to enable builder pattern like usage. | ||
84 | */ | ||
85 | public BaseObjective withHardConstraintOnFitness(double fitnessConstraint, | ||
86 | Comparator<Double> fitnessConstraintComparator) { | ||
87 | this.fitnessConstraint = fitnessConstraint; | ||
88 | this.fitnessConstraintComparator = fitnessConstraintComparator; | ||
89 | this.isThereFitnessConstraint = true; | ||
90 | return this; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * Adds a hard constraint on the fitness value. For example, the fitness value must be better than 10 to accept the | ||
95 | * current state as a solution. The provided comparator will be used. | ||
96 | * | ||
97 | * @param fitnessConstraint | ||
98 | * Solutions should be better than this value. | ||
99 | * @return The actual instance to enable builder pattern like usage. | ||
100 | */ | ||
101 | public BaseObjective withHardConstraintOnFitness(double fitnessConstraint) { | ||
102 | return withHardConstraintOnFitness(fitnessConstraint, null); | ||
103 | } | ||
104 | |||
105 | @Override | ||
106 | public void init(ThreadContext context) { | ||
107 | if (fitnessConstraintComparator == null) { | ||
108 | fitnessConstraintComparator = comparator; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | @Override | ||
113 | public boolean isHardObjective() { | ||
114 | return isThereFitnessConstraint; | ||
115 | } | ||
116 | |||
117 | @Override | ||
118 | public boolean satisifiesHardObjective(Double fitness) { | ||
119 | if (isThereFitnessConstraint) { | ||
120 | int compare = fitnessConstraintComparator.compare(fitness, fitnessConstraint); | ||
121 | if (compare < 0) { | ||
122 | return false; | ||
123 | } | ||
124 | } | ||
125 | return true; | ||
126 | } | ||
127 | |||
128 | @Override | ||
129 | public int hashCode() { | ||
130 | return name.hashCode(); | ||
131 | } | ||
132 | |||
133 | @Override | ||
134 | public boolean equals(Object obj) { | ||
135 | if (this == obj) { | ||
136 | return true; | ||
137 | } | ||
138 | if (obj instanceof BaseObjective) { | ||
139 | BaseObjective baseObjective = (BaseObjective) obj; | ||
140 | return name.equals(baseObjective.getName()); | ||
141 | } | ||
142 | return false; | ||
143 | } | ||
144 | |||
145 | @Override | ||
146 | public String toString() { | ||
147 | return name; | ||
148 | } | ||
149 | |||
150 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java new file mode 100644 index 00000000..cc48d22e --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java | |||
@@ -0,0 +1,137 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | import java.util.Objects; | ||
14 | |||
15 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
16 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
17 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
18 | |||
19 | /** | ||
20 | * This objective collects a list of other objectives. It returns the weighted sum of the objectives. | ||
21 | * | ||
22 | * @author Andras Szabolcs Nagy | ||
23 | * | ||
24 | */ | ||
25 | public class CompositeObjective extends BaseObjective { | ||
26 | |||
27 | public static final String DEFAULT_NAME = "CompositeObjective"; | ||
28 | protected List<IObjective> objectives; | ||
29 | protected List<Double> weights; | ||
30 | protected boolean hardObjective; | ||
31 | |||
32 | public CompositeObjective(String name, List<IObjective> objectives, List<Double> weights) { | ||
33 | super(name); | ||
34 | Objects.requireNonNull(objectives, "The list of objectives cannot be null."); | ||
35 | Objects.requireNonNull(weights, "The list of weights cannot be null."); | ||
36 | Preconditions.checkState(objectives.size() == weights.size(), "The size of the objectives and weights must match."); | ||
37 | this.objectives = objectives; | ||
38 | this.weights = weights; | ||
39 | } | ||
40 | |||
41 | public CompositeObjective(List<IObjective> objectives, List<Double> weights) { | ||
42 | this(DEFAULT_NAME, objectives, weights); | ||
43 | } | ||
44 | |||
45 | public CompositeObjective(String name) { | ||
46 | this(name, new ArrayList<IObjective>(), new ArrayList<Double>()); | ||
47 | } | ||
48 | |||
49 | public CompositeObjective() { | ||
50 | this(DEFAULT_NAME, new ArrayList<IObjective>(), new ArrayList<Double>()); | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * Adds a new objective. | ||
55 | * | ||
56 | * @param objective | ||
57 | * @return The actual instance to enable builder pattern like usage. | ||
58 | */ | ||
59 | public CompositeObjective withObjective(IObjective objective) { | ||
60 | objectives.add(objective); | ||
61 | weights.add(1d); | ||
62 | return this; | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * Adds a new objective. | ||
67 | * | ||
68 | * @param objective | ||
69 | * @return The actual instance to enable builder pattern like usage. | ||
70 | */ | ||
71 | public CompositeObjective withObjective(IObjective objective, double weight) { | ||
72 | objectives.add(objective); | ||
73 | weights.add(weight); | ||
74 | return this; | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public Double getFitness(ThreadContext context) { | ||
79 | |||
80 | double result = 0; | ||
81 | |||
82 | for (int i = 0; i < objectives.size(); i++) { | ||
83 | IObjective objective = objectives.get(i); | ||
84 | Double weight = weights.get(i); | ||
85 | result += objective.getFitness(context) * weight; | ||
86 | } | ||
87 | return result; | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public void init(ThreadContext context) { | ||
92 | super.init(context); | ||
93 | hardObjective = false; | ||
94 | for (IObjective objective : objectives) { | ||
95 | objective.init(context); | ||
96 | if (objective.isHardObjective()) { | ||
97 | hardObjective = true; | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | |||
102 | @Override | ||
103 | public IObjective createNew() { | ||
104 | |||
105 | List<IObjective> newObjectives = new ArrayList<IObjective>(); | ||
106 | |||
107 | for (IObjective objective : objectives) { | ||
108 | newObjectives.add(objective.createNew()); | ||
109 | } | ||
110 | |||
111 | CompositeObjective objective = new CompositeObjective(name, newObjectives, weights); | ||
112 | if (isThereFitnessConstraint) { | ||
113 | objective.withHardConstraintOnFitness(fitnessConstraint, fitnessConstraintComparator); | ||
114 | } | ||
115 | |||
116 | return objective.withComparator(comparator).withLevel(level); | ||
117 | } | ||
118 | |||
119 | @Override | ||
120 | public boolean isHardObjective() { | ||
121 | return hardObjective; | ||
122 | } | ||
123 | |||
124 | @Override | ||
125 | public boolean satisifiesHardObjective(Double fitness) { | ||
126 | |||
127 | boolean hardObjectiveSatisfied = true; | ||
128 | |||
129 | for (IObjective objective : objectives) { | ||
130 | hardObjectiveSatisfied = objective.satisifiesHardObjective(fitness) ? hardObjectiveSatisfied : false; | ||
131 | } | ||
132 | |||
133 | hardObjectiveSatisfied = super.satisifiesHardObjective(fitness) ? hardObjectiveSatisfied : false; | ||
134 | |||
135 | return hardObjectiveSatisfied; | ||
136 | } | ||
137 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java new file mode 100644 index 00000000..77d416f5 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ConstraintsObjective.java | |||
@@ -0,0 +1,316 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | import java.util.Objects; | ||
14 | |||
15 | import org.eclipse.viatra.dse.api.DSEException; | ||
16 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
17 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
18 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
19 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
20 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
21 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
22 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
23 | |||
24 | /** | ||
25 | * This objective serves as soft and as hard objective at the same time by defining two lists of VIATRA Query | ||
26 | * specifications. | ||
27 | * | ||
28 | * As a soft objective, it collects a list of VIATRA Query specifications, which have predefined weights. Then the | ||
29 | * fitness value of an arbitrary solution is calculated in the following way: | ||
30 | * <p> | ||
31 | * <code>fitness = sum( pattern[i].countMatches() * weight[i] )</code> | ||
32 | * <p> | ||
33 | * As a hard objective it collects a separate list of VIATRA Query specifications. If every one of them has a match the | ||
34 | * hard constraint is considered to be fulfilled. | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * @see IObjective | ||
38 | * | ||
39 | */ | ||
40 | public class ConstraintsObjective extends BaseObjective { | ||
41 | |||
42 | public static final String DEFAULT_NAME = "ConstraintsObjective"; | ||
43 | |||
44 | public static class QueryConstraint { | ||
45 | public final String name; | ||
46 | public final IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query; | ||
47 | public final Double weight; | ||
48 | public final ModelQueryType type; | ||
49 | |||
50 | public QueryConstraint(String name, | ||
51 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query, Double weight, | ||
52 | ModelQueryType type) { | ||
53 | this.name = name; | ||
54 | this.query = query; | ||
55 | this.weight = weight; | ||
56 | this.type = type; | ||
57 | } | ||
58 | |||
59 | public QueryConstraint(String name, | ||
60 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query, Double weight) { | ||
61 | this(name, query, weight, ModelQueryType.MUST_HAVE_MATCH); | ||
62 | } | ||
63 | |||
64 | public QueryConstraint(String name, | ||
65 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> query, ModelQueryType type) { | ||
66 | this(name, query, 0d, type); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | protected List<QueryConstraint> softConstraints; | ||
71 | protected List<QueryConstraint> hardConstraints; | ||
72 | |||
73 | protected List<ViatraQueryMatcher<? extends IPatternMatch>> softMatchers; | ||
74 | protected List<ViatraQueryMatcher<? extends IPatternMatch>> hardMatchers; | ||
75 | protected List<Integer> softMatches; | ||
76 | protected List<Integer> hardMatches; | ||
77 | |||
78 | public ConstraintsObjective(String name, List<QueryConstraint> softConstraints, | ||
79 | List<QueryConstraint> hardConstraints) { | ||
80 | super(name); | ||
81 | Objects.requireNonNull(softConstraints, "The list of soft constraints cannot be null."); | ||
82 | Objects.requireNonNull(hardConstraints, "The list of hard constraints cannot be null."); | ||
83 | |||
84 | this.softConstraints = softConstraints; | ||
85 | this.hardConstraints = hardConstraints; | ||
86 | } | ||
87 | |||
88 | public ConstraintsObjective(String name, List<QueryConstraint> hardConstraints) { | ||
89 | this(name, new ArrayList<QueryConstraint>(), hardConstraints); | ||
90 | } | ||
91 | |||
92 | public ConstraintsObjective(List<QueryConstraint> hardConstraints) { | ||
93 | this(DEFAULT_NAME, new ArrayList<QueryConstraint>(), hardConstraints); | ||
94 | } | ||
95 | |||
96 | public ConstraintsObjective(String name) { | ||
97 | this(name, new ArrayList<QueryConstraint>(), new ArrayList<QueryConstraint>()); | ||
98 | } | ||
99 | |||
100 | public ConstraintsObjective() { | ||
101 | this(DEFAULT_NAME, new ArrayList<QueryConstraint>(), new ArrayList<QueryConstraint>()); | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * Adds a new soft constraint. | ||
106 | * | ||
107 | * @param name | ||
108 | * A name for the soft constraint. | ||
109 | * @param softConstraint | ||
110 | * A VIATRA Query pattern specification. | ||
111 | * @param weight | ||
112 | * The weight of the pattern. | ||
113 | * @return The actual instance to enable builder pattern like usage. | ||
114 | */ | ||
115 | public ConstraintsObjective withSoftConstraint(String name, | ||
116 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> softConstraint, double weight) { | ||
117 | softConstraints.add(new QueryConstraint(name, softConstraint, weight)); | ||
118 | return this; | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * Adds a new soft constraint with the name of the query specification's fully qualified name. | ||
123 | * | ||
124 | * @param softConstraint | ||
125 | * A VIATRA Query pattern specification. | ||
126 | * @param weight | ||
127 | * The weight of the pattern. | ||
128 | * @return The actual instance to enable builder pattern like usage. | ||
129 | */ | ||
130 | public ConstraintsObjective withSoftConstraint( | ||
131 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> softConstraint, double weight) { | ||
132 | return withSoftConstraint(softConstraint.getFullyQualifiedName(), softConstraint, weight); | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * Adds a new hard constraint. | ||
137 | * | ||
138 | * @param name | ||
139 | * A name for the hard constraint. | ||
140 | * @param softConstraint | ||
141 | * A VIATRA Query pattern specification. | ||
142 | * @param type | ||
143 | * {@link ModelQueryType}, which determines whether the constraint should have at least one match or none | ||
144 | * at all. | ||
145 | * @return The actual instance to enable builder pattern like usage. | ||
146 | */ | ||
147 | public ConstraintsObjective withHardConstraint(String name, | ||
148 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint, | ||
149 | ModelQueryType type) { | ||
150 | hardConstraints.add(new QueryConstraint(name, hardConstraint, type)); | ||
151 | return this; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * Adds a new hard constraint with the default {@link ModelQueryType#MUST_HAVE_MATCH}. | ||
156 | * | ||
157 | * @param name | ||
158 | * A name for the hard constraint. | ||
159 | * @param softConstraint | ||
160 | * A VIATRA Query pattern specification. | ||
161 | * @return The actual instance to enable builder pattern like usage. | ||
162 | */ | ||
163 | public ConstraintsObjective withHardConstraint(String name, | ||
164 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint) { | ||
165 | hardConstraints.add(new QueryConstraint(name, hardConstraint, ModelQueryType.MUST_HAVE_MATCH)); | ||
166 | return this; | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Adds a new hard constraint with the name of the query specification's fully qualified name and the default | ||
171 | * {@link ModelQueryType#MUST_HAVE_MATCH}. | ||
172 | * | ||
173 | * @param softConstraint | ||
174 | * A VIATRA Query pattern specification. | ||
175 | * @return The actual instance to enable builder pattern like usage. | ||
176 | */ | ||
177 | public ConstraintsObjective withHardConstraint( | ||
178 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint) { | ||
179 | return withHardConstraint(hardConstraint.getFullyQualifiedName(), hardConstraint, | ||
180 | ModelQueryType.MUST_HAVE_MATCH); | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * Adds a new hard constraint with the name of the query specification's fully qualified name. | ||
185 | * | ||
186 | * @param softConstraint | ||
187 | * A VIATRA Query pattern specification. | ||
188 | * @param type | ||
189 | * {@link ModelQueryType}, which determines whether the constraint should have at least one match or none | ||
190 | * at all. | ||
191 | * @return The actual instance to enable builder pattern like usage. | ||
192 | */ | ||
193 | public ConstraintsObjective withHardConstraint( | ||
194 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hardConstraint, | ||
195 | ModelQueryType type) { | ||
196 | return withHardConstraint(hardConstraint.getFullyQualifiedName(), hardConstraint, type); | ||
197 | } | ||
198 | |||
199 | @Override | ||
200 | public Double getFitness(ThreadContext context) { | ||
201 | |||
202 | if (softConstraints.isEmpty()) { | ||
203 | return 0d; | ||
204 | } | ||
205 | |||
206 | double result = 0; | ||
207 | |||
208 | for (int i = 0; i < softConstraints.size(); i++) { | ||
209 | int countMatches = softMatchers.get(i).countMatches(); | ||
210 | result += countMatches * softConstraints.get(i).weight; | ||
211 | softMatches.set(i, Integer.valueOf(countMatches)); | ||
212 | } | ||
213 | |||
214 | return result; | ||
215 | } | ||
216 | |||
217 | @Override | ||
218 | public void init(ThreadContext context) { | ||
219 | |||
220 | super.init(context); | ||
221 | |||
222 | softMatches = new ArrayList<Integer>(softConstraints.size()); | ||
223 | softMatchers = new ArrayList<ViatraQueryMatcher<? extends IPatternMatch>>(softConstraints.size()); | ||
224 | hardMatches = new ArrayList<Integer>(hardConstraints.size()); | ||
225 | hardMatchers = new ArrayList<ViatraQueryMatcher<? extends IPatternMatch>>(hardConstraints.size()); | ||
226 | for (int i = 0; i < softConstraints.size(); i++) { | ||
227 | softMatches.add(0); | ||
228 | } | ||
229 | for (int i = 0; i < hardConstraints.size(); i++) { | ||
230 | hardMatches.add(0); | ||
231 | } | ||
232 | |||
233 | try { | ||
234 | ViatraQueryEngine queryEngine = context.getQueryEngine(); | ||
235 | |||
236 | for (QueryConstraint qc : softConstraints) { | ||
237 | softMatchers.add(qc.query.getMatcher(queryEngine)); | ||
238 | } | ||
239 | |||
240 | for (QueryConstraint qc : hardConstraints) { | ||
241 | hardMatchers.add(qc.query.getMatcher(queryEngine)); | ||
242 | } | ||
243 | |||
244 | } catch (ViatraQueryException e) { | ||
245 | throw new DSEException("Couldn't initialize the VIATRA Query matcher, see inner exception", e); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | @Override | ||
250 | public IObjective createNew() { | ||
251 | new ArrayList<Double>(softConstraints.size()); | ||
252 | ConstraintsObjective result = new ConstraintsObjective(name, softConstraints, hardConstraints); | ||
253 | if (isThereFitnessConstraint) { | ||
254 | result.withHardConstraintOnFitness(fitnessConstraint, fitnessConstraintComparator); | ||
255 | } | ||
256 | return result.withComparator(comparator).withLevel(level); | ||
257 | } | ||
258 | |||
259 | @Override | ||
260 | public boolean isHardObjective() { | ||
261 | return !hardConstraints.isEmpty() || super.isHardObjective(); | ||
262 | } | ||
263 | |||
264 | @Override | ||
265 | public boolean satisifiesHardObjective(Double fitness) { | ||
266 | |||
267 | boolean result = true; | ||
268 | |||
269 | for (int i = 0; i < hardConstraints.size(); i++) { | ||
270 | ModelQueryType type = hardConstraints.get(i).type; | ||
271 | int countMatches = hardMatchers.get(i).countMatches(); | ||
272 | hardMatches.set(i, Integer.valueOf(countMatches)); | ||
273 | if ((type.equals(ModelQueryType.MUST_HAVE_MATCH) && countMatches <= 0) | ||
274 | || (type.equals(ModelQueryType.NO_MATCH) && countMatches > 0)) { | ||
275 | result = false; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | result = super.satisifiesHardObjective(fitness) ? result : false; | ||
280 | |||
281 | return result; | ||
282 | } | ||
283 | |||
284 | public List<QueryConstraint> getSoftConstraints() { | ||
285 | return softConstraints; | ||
286 | } | ||
287 | |||
288 | public List<QueryConstraint> getHardConstraints() { | ||
289 | return hardConstraints; | ||
290 | } | ||
291 | |||
292 | public String getSoftName(int index) { | ||
293 | return softConstraints.get(index).name; | ||
294 | } | ||
295 | |||
296 | public String getHardName(int index) { | ||
297 | return hardConstraints.get(index).name; | ||
298 | } | ||
299 | |||
300 | public List<Integer> getSoftMatches() { | ||
301 | return softMatches; | ||
302 | } | ||
303 | |||
304 | public List<Integer> getHardMatches() { | ||
305 | return hardMatches; | ||
306 | } | ||
307 | |||
308 | public List<String> getSoftNames() { | ||
309 | List<String> softNames = new ArrayList<>(softConstraints.size()); | ||
310 | for (QueryConstraint qc : softConstraints) { | ||
311 | softNames.add(qc.name); | ||
312 | } | ||
313 | return softNames; | ||
314 | } | ||
315 | |||
316 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java new file mode 100644 index 00000000..b21da397 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/DepthHardObjective.java | |||
@@ -0,0 +1,89 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
13 | |||
14 | /** | ||
15 | * This hard objective is fulfilled if the trajectory is in the specified interval (inclusive). | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class DepthHardObjective extends BaseObjective { | ||
21 | |||
22 | private static final String DEFAULT_NAME = "DepthHardObjective"; | ||
23 | protected int minDepth; | ||
24 | protected int maxDepth; | ||
25 | private ThreadContext context; | ||
26 | |||
27 | public DepthHardObjective() { | ||
28 | this(DEFAULT_NAME, 0, Integer.MAX_VALUE); | ||
29 | } | ||
30 | |||
31 | public DepthHardObjective(String name) { | ||
32 | this(name, 0, Integer.MAX_VALUE); | ||
33 | } | ||
34 | |||
35 | public DepthHardObjective(int minDepth) { | ||
36 | this(DEFAULT_NAME, minDepth, Integer.MAX_VALUE); | ||
37 | } | ||
38 | |||
39 | public DepthHardObjective(String name, int minDepth) { | ||
40 | this(name, minDepth, Integer.MAX_VALUE); | ||
41 | } | ||
42 | |||
43 | public DepthHardObjective(int minDepth, int maxDepth) { | ||
44 | this(DEFAULT_NAME, minDepth, maxDepth); | ||
45 | } | ||
46 | |||
47 | public DepthHardObjective(String name, int minDepth, int maxDepth) { | ||
48 | super(name); | ||
49 | this.minDepth = minDepth; | ||
50 | this.maxDepth = maxDepth; | ||
51 | } | ||
52 | |||
53 | public DepthHardObjective withMinDepth(int minDepth) { | ||
54 | this.minDepth = minDepth; | ||
55 | return this; | ||
56 | } | ||
57 | |||
58 | public DepthHardObjective withMaxDepth(int maxDepth) { | ||
59 | this.maxDepth = maxDepth; | ||
60 | return this; | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public void init(ThreadContext context) { | ||
65 | super.init(context); | ||
66 | this.context = context; | ||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public Double getFitness(ThreadContext context) { | ||
71 | return 0d; | ||
72 | } | ||
73 | |||
74 | @Override | ||
75 | public boolean isHardObjective() { | ||
76 | return true; | ||
77 | } | ||
78 | |||
79 | @Override | ||
80 | public boolean satisifiesHardObjective(Double fitness) { | ||
81 | return minDepth <= context.getDepth() && context.getDepth() <= maxDepth; | ||
82 | } | ||
83 | |||
84 | @Override | ||
85 | public IObjective createNew() { | ||
86 | return new DepthHardObjective(name, minDepth, maxDepth); | ||
87 | } | ||
88 | |||
89 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java new file mode 100644 index 00000000..7616b4a2 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueriesGlobalConstraint.java | |||
@@ -0,0 +1,116 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | import java.util.Objects; | ||
14 | |||
15 | import org.eclipse.viatra.dse.api.DSEException; | ||
16 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
17 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint; | ||
18 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
19 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
20 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
21 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
22 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
23 | |||
24 | /** | ||
25 | * This global constraint collects a list of VIATRA Query pattern and checks if any of them has a match on along a trajectory. | ||
26 | * If any of the patterns has a match then it is unsatisfied and the exploration should backtrack. | ||
27 | * | ||
28 | * @author Andras Szabolcs Nagy | ||
29 | * | ||
30 | */ | ||
31 | public class ModelQueriesGlobalConstraint implements IGlobalConstraint { | ||
32 | |||
33 | public static final String GLOBAL_CONSTRAINT = "GlobalConstraint"; | ||
34 | protected String name; | ||
35 | protected List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> constraints; | ||
36 | protected List<ViatraQueryMatcher<? extends IPatternMatch>> matchers = new ArrayList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
37 | protected ModelQueryType type = ModelQueryType.NO_MATCH; | ||
38 | |||
39 | public ModelQueriesGlobalConstraint(String name, | ||
40 | List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> constraints) { | ||
41 | Objects.requireNonNull(name, "Name of the global constraint cannot be null."); | ||
42 | Objects.requireNonNull(constraints, "The list of constraints cannot be null."); | ||
43 | |||
44 | this.name = name; | ||
45 | this.constraints = constraints; | ||
46 | } | ||
47 | |||
48 | public ModelQueriesGlobalConstraint( | ||
49 | List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> constraints) { | ||
50 | this(GLOBAL_CONSTRAINT, constraints); | ||
51 | } | ||
52 | |||
53 | public ModelQueriesGlobalConstraint(String name) { | ||
54 | this(name, new ArrayList<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>>()); | ||
55 | } | ||
56 | |||
57 | public ModelQueriesGlobalConstraint() { | ||
58 | this(GLOBAL_CONSTRAINT, | ||
59 | new ArrayList<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>>()); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * Adds a new VIATRA Query pattern. | ||
64 | * | ||
65 | * @param constraint | ||
66 | * A VIATRA Query pattern. | ||
67 | * @return The actual instance to enable builder pattern like usage. | ||
68 | */ | ||
69 | public ModelQueriesGlobalConstraint withConstraint( | ||
70 | IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> constraint) { | ||
71 | constraints.add(constraint); | ||
72 | return this; | ||
73 | } | ||
74 | |||
75 | public ModelQueriesGlobalConstraint withType(ModelQueryType type) { | ||
76 | this.type = type; | ||
77 | return this; | ||
78 | } | ||
79 | |||
80 | @Override | ||
81 | public String getName() { | ||
82 | return name; | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public boolean checkGlobalConstraint(ThreadContext context) { | ||
87 | for (ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { | ||
88 | if ((type.equals(ModelQueryType.NO_MATCH) && matcher.countMatches() > 0) | ||
89 | || (type.equals(ModelQueryType.MUST_HAVE_MATCH) && matcher.countMatches() == 0)) { | ||
90 | return false; | ||
91 | } | ||
92 | } | ||
93 | return true; | ||
94 | } | ||
95 | |||
96 | @Override | ||
97 | public void init(ThreadContext context) { | ||
98 | try { | ||
99 | ViatraQueryEngine queryEngine = context.getQueryEngine(); | ||
100 | |||
101 | for (IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification : constraints) { | ||
102 | ViatraQueryMatcher<? extends IPatternMatch> matcher = querySpecification.getMatcher(queryEngine); | ||
103 | matchers.add(matcher); | ||
104 | } | ||
105 | |||
106 | } catch (ViatraQueryException e) { | ||
107 | throw new DSEException("Couldn't get the VIATRA Query matcher, see inner exception", e); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | @Override | ||
112 | public IGlobalConstraint createNew() { | ||
113 | return new ModelQueriesGlobalConstraint(name, constraints); | ||
114 | } | ||
115 | |||
116 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java new file mode 100644 index 00000000..76390352 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/ModelQueryType.java | |||
@@ -0,0 +1,14 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | public enum ModelQueryType { | ||
12 | MUST_HAVE_MATCH, | ||
13 | NO_MATCH | ||
14 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java new file mode 100644 index 00000000..27cf139c --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NeverSatisfiedDummyHardObjective.java | |||
@@ -0,0 +1,52 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
13 | |||
14 | /** | ||
15 | * This hard objective is never fulfilled. Use it if all states should be regarded as an invalid solution. | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class NeverSatisfiedDummyHardObjective extends BaseObjective { | ||
21 | |||
22 | private static final String DEFAULT_NAME = "NeverSatisfiedDummyHardObjective"; | ||
23 | |||
24 | public NeverSatisfiedDummyHardObjective() { | ||
25 | super(DEFAULT_NAME); | ||
26 | } | ||
27 | |||
28 | public NeverSatisfiedDummyHardObjective(String name) { | ||
29 | super(name); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Double getFitness(ThreadContext context) { | ||
34 | return 0d; | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public boolean isHardObjective() { | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public boolean satisifiesHardObjective(Double fitness) { | ||
44 | return false; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public IObjective createNew() { | ||
49 | return this; | ||
50 | } | ||
51 | |||
52 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java new file mode 100644 index 00000000..756d94ec --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/NoRuleActivationsHardObjective.java | |||
@@ -0,0 +1,59 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
12 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
13 | |||
14 | /** | ||
15 | * This hard objective is satisfied if there are no rule activations from the current state (returning 1 in this case). | ||
16 | * | ||
17 | * @author Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public class NoRuleActivationsHardObjective extends BaseObjective { | ||
21 | |||
22 | protected static final String DEFAULT_NAME = "NoMoreActivationHardObjective"; | ||
23 | private ThreadContext context; | ||
24 | |||
25 | public NoRuleActivationsHardObjective(String name) { | ||
26 | super(name); | ||
27 | } | ||
28 | |||
29 | public NoRuleActivationsHardObjective() { | ||
30 | this(DEFAULT_NAME); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public Double getFitness(ThreadContext context) { | ||
35 | return 0d; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public void init(ThreadContext context) { | ||
40 | super.init(context); | ||
41 | this.context = context; | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public IObjective createNew() { | ||
46 | return new NoRuleActivationsHardObjective(name); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public boolean isHardObjective() { | ||
51 | return true; | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public boolean satisifiesHardObjective(Double fitness) { | ||
56 | return context.getConflictSet().getNextActivations().isEmpty(); | ||
57 | } | ||
58 | |||
59 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java new file mode 100644 index 00000000..25ff45ae --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/TrajectoryCostSoftObjective.java | |||
@@ -0,0 +1,148 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.objectives.impl; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | import java.util.List; | ||
13 | import java.util.Map; | ||
14 | import java.util.Map.Entry; | ||
15 | import java.util.Objects; | ||
16 | |||
17 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
18 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
19 | import org.eclipse.viatra.dse.designspace.api.TrajectoryInfo; | ||
20 | import org.eclipse.viatra.dse.objectives.ActivationFitnessProcessor; | ||
21 | import org.eclipse.viatra.dse.objectives.Comparators; | ||
22 | import org.eclipse.viatra.dse.objectives.IObjective; | ||
23 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
24 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule; | ||
25 | |||
26 | /** | ||
27 | * This soft objective calculates a fitness value based on the length of the trajectory. Costs to the rules can be | ||
28 | * assigned. | ||
29 | * | ||
30 | * @author Andras Szabolcs Nagy | ||
31 | * | ||
32 | */ | ||
33 | public class TrajectoryCostSoftObjective extends BaseObjective { | ||
34 | |||
35 | public static final String DEFAULT_NAME = "TrajectoryCostObjective"; | ||
36 | protected Map<BatchTransformationRule<?, ?>, Double> fixCosts; | ||
37 | protected Map<BatchTransformationRule<?, ?>, ActivationFitnessProcessor> activationCostProcessors; | ||
38 | protected double trajectoryLengthWeight = 0.0; | ||
39 | protected boolean calculateTrajectoryLengthWeight; | ||
40 | |||
41 | public TrajectoryCostSoftObjective(String name) { | ||
42 | super(name); | ||
43 | comparator = Comparators.LOWER_IS_BETTER; | ||
44 | } | ||
45 | |||
46 | public TrajectoryCostSoftObjective() { | ||
47 | this(DEFAULT_NAME); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * Sets the cost of a rule. | ||
52 | * | ||
53 | * @param rule | ||
54 | * @param cost | ||
55 | * @return The actual instance to enable builder pattern like usage. | ||
56 | */ | ||
57 | public TrajectoryCostSoftObjective withRuleCost(BatchTransformationRule<?, ?> rule, double cost) { | ||
58 | Objects.requireNonNull(rule); | ||
59 | if (fixCosts == null) { | ||
60 | fixCosts = new HashMap<BatchTransformationRule<?, ?>, Double>(); | ||
61 | } | ||
62 | Preconditions.checkArgument(!fixCosts.containsKey(rule)); | ||
63 | fixCosts.put(rule, cost); | ||
64 | return this; | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * Sets an activation processor for a rule. | ||
69 | * | ||
70 | * @param rule | ||
71 | * @param activationCostProcessor | ||
72 | * @return The actual instance to enable builder pattern like usage. | ||
73 | */ | ||
74 | public TrajectoryCostSoftObjective withActivationCost(BatchTransformationRule<?, ?> rule, | ||
75 | ActivationFitnessProcessor activationCostProcessor) { | ||
76 | Objects.requireNonNull(rule); | ||
77 | Objects.requireNonNull(activationCostProcessor); | ||
78 | if (activationCostProcessors == null) { | ||
79 | activationCostProcessors = new HashMap<BatchTransformationRule<?, ?>, ActivationFitnessProcessor>(); | ||
80 | } | ||
81 | Preconditions.checkArgument(!activationCostProcessors.containsKey(rule)); | ||
82 | activationCostProcessors.put(rule, activationCostProcessor); | ||
83 | return this; | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * The length of the trajectory multiplied with given parameter will be added to the fitness value. | ||
88 | * | ||
89 | * @param trajectoryLengthWeight | ||
90 | * The weight of a transformation rule application. | ||
91 | * @return The actual instance to enable builder pattern like usage. | ||
92 | */ | ||
93 | public TrajectoryCostSoftObjective withTrajectoryLengthWeight(double trajectoryLengthWeight) { | ||
94 | this.trajectoryLengthWeight = trajectoryLengthWeight; | ||
95 | this.calculateTrajectoryLengthWeight = true; | ||
96 | return this; | ||
97 | } | ||
98 | |||
99 | @Override | ||
100 | public Double getFitness(ThreadContext context) { | ||
101 | |||
102 | DesignSpaceManager dsm = context.getDesignSpaceManager(); | ||
103 | TrajectoryInfo trajectoryInfo = dsm.getTrajectoryInfo(); | ||
104 | List<Object> trajectory = trajectoryInfo.getTrajectory(); | ||
105 | List<BatchTransformationRule<?, ?>> rules = trajectoryInfo.getRules(); | ||
106 | |||
107 | double result = 0; | ||
108 | |||
109 | for (int i = 0; i < trajectory.size(); i++) { | ||
110 | BatchTransformationRule<?, ?> rule = rules.get(i); | ||
111 | |||
112 | Double cost = fixCosts.get(rule); | ||
113 | if (cost != null) { | ||
114 | result += cost; | ||
115 | } | ||
116 | |||
117 | Map<String, Double> costs = trajectoryInfo.getMeasuredCosts().get(i); | ||
118 | if (costs != null) { | ||
119 | cost = costs.get(name); | ||
120 | if (cost != null) { | ||
121 | result += cost; | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | if (calculateTrajectoryLengthWeight) { | ||
127 | result += trajectory.size() * trajectoryLengthWeight; | ||
128 | } | ||
129 | |||
130 | return result; | ||
131 | } | ||
132 | |||
133 | @Override | ||
134 | public void init(ThreadContext context) { | ||
135 | super.init(context); | ||
136 | DesignSpaceManager dsm = context.getDesignSpaceManager(); | ||
137 | if (activationCostProcessors != null) { | ||
138 | for (Entry<BatchTransformationRule<?, ?>, ActivationFitnessProcessor> entry : activationCostProcessors.entrySet()) { | ||
139 | dsm.registerActivationCostProcessor(name, entry.getKey(), entry.getValue()); | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | |||
144 | @Override | ||
145 | public IObjective createNew() { | ||
146 | return this; | ||
147 | } | ||
148 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java new file mode 100644 index 00000000..8d74e856 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionFoundHandler.java | |||
@@ -0,0 +1,40 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.solutionstore; | ||
10 | |||
11 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
12 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | ||
13 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
14 | import org.eclipse.viatra.dse.solutionstore.SolutionStore.ISolutionSaver; | ||
15 | |||
16 | /** | ||
17 | * Contains callback methods which are called when a solution is found by the exploration {@link IStrategy}. | ||
18 | * | ||
19 | * @author Andras Szabolcs Nagy | ||
20 | * | ||
21 | */ | ||
22 | public interface ISolutionFoundHandler { | ||
23 | |||
24 | /** | ||
25 | * Called when a solution is saved by the {@link ISolutionSaver}. Later, this solution can be omitted from the final | ||
26 | * set of solutions. | ||
27 | * | ||
28 | * @param context | ||
29 | * @param trajectory | ||
30 | */ | ||
31 | void solutionFound(ThreadContext context, SolutionTrajectory trajectory); | ||
32 | |||
33 | /** | ||
34 | * Called when the exploration found a solution but it was not saved because of certain conditions. | ||
35 | * | ||
36 | * @param context | ||
37 | * @param trajectory | ||
38 | */ | ||
39 | void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory); | ||
40 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java new file mode 100644 index 00000000..36e6b5b7 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ISolutionNameProvider.java | |||
@@ -0,0 +1,18 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.solutionstore; | ||
10 | |||
11 | /** | ||
12 | * Provides file name when a model is searialzed. | ||
13 | * @author Andras Szabolcs Nagy | ||
14 | * | ||
15 | */ | ||
16 | public interface ISolutionNameProvider { | ||
17 | String getName(); | ||
18 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java new file mode 100644 index 00000000..43460015 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/IdBasedSolutionNameProvider.java | |||
@@ -0,0 +1,37 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.solutionstore; | ||
10 | |||
11 | /** | ||
12 | * Provides file name with a String <code>[prefix][id].[extension]</code> pattern. | ||
13 | * @author Andras Szabolcs Nagy | ||
14 | * | ||
15 | */ | ||
16 | public class IdBasedSolutionNameProvider implements ISolutionNameProvider { | ||
17 | |||
18 | private int id = 1; | ||
19 | private String prefix; | ||
20 | private String extension; | ||
21 | |||
22 | public IdBasedSolutionNameProvider(String prefix, String extension) { | ||
23 | this.extension = extension; | ||
24 | this.prefix = prefix; | ||
25 | |||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public String getName() { | ||
30 | StringBuilder sb = new StringBuilder(prefix); | ||
31 | sb.append(id++); | ||
32 | sb.append('.'); | ||
33 | sb.append(extension); | ||
34 | return sb.toString(); | ||
35 | } | ||
36 | |||
37 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java new file mode 100644 index 00000000..118f0c75 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/LogSolutionHandler.java | |||
@@ -0,0 +1,28 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.solutionstore; | ||
10 | |||
11 | import org.apache.log4j.Logger; | ||
12 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
13 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
14 | |||
15 | public class LogSolutionHandler implements ISolutionFoundHandler { | ||
16 | |||
17 | Logger logger = Logger.getLogger(LogSolutionHandler.class); | ||
18 | |||
19 | @Override | ||
20 | public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
21 | logger.info("Solution registered: " + trajectory.toPrettyString()); | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { | ||
26 | logger.debug("Not good enough solution: " + trajectory.toPrettyString()); | ||
27 | } | ||
28 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java new file mode 100644 index 00000000..bbbe60de --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/ModelSaverSolutionFoundHandler.java | |||
@@ -0,0 +1,55 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.solutionstore; | ||
10 | |||
11 | import java.util.HashSet; | ||
12 | |||
13 | import org.eclipse.emf.common.notify.Notifier; | ||
14 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
15 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
16 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
17 | |||
18 | public class ModelSaverSolutionFoundHandler implements ISolutionFoundHandler { | ||
19 | |||
20 | private HashSet<Object> savedSolutions = new HashSet<Object>(); | ||
21 | private ISolutionNameProvider solutionNameProvider; | ||
22 | |||
23 | public ModelSaverSolutionFoundHandler() { | ||
24 | solutionNameProvider = new IdBasedSolutionNameProvider("solution", "xmi"); | ||
25 | } | ||
26 | |||
27 | public ModelSaverSolutionFoundHandler(String extension) { | ||
28 | solutionNameProvider = new IdBasedSolutionNameProvider("solution", extension); | ||
29 | } | ||
30 | |||
31 | public ModelSaverSolutionFoundHandler(String prefix, String extension) { | ||
32 | solutionNameProvider = new IdBasedSolutionNameProvider(prefix, extension); | ||
33 | } | ||
34 | |||
35 | public ModelSaverSolutionFoundHandler(ISolutionNameProvider solutionNameProvider) { | ||
36 | this.solutionNameProvider = solutionNameProvider; | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
45 | Object stateCode = trajectory.getSolution().getStateCode(); | ||
46 | |||
47 | if (savedSolutions.contains(stateCode)) { | ||
48 | return; | ||
49 | } | ||
50 | |||
51 | savedSolutions.add(stateCode); | ||
52 | Notifier clonedModel = EMFHelper.clone(context.getModel()); | ||
53 | EMFHelper.saveModel(clonedModel, solutionNameProvider.getName()); | ||
54 | } | ||
55 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java new file mode 100644 index 00000000..578ae277 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/solutionstore/SolutionStore.java | |||
@@ -0,0 +1,311 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2016, Andras Szabolcs Nagy, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.solutionstore; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collection; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.List; | ||
15 | import java.util.Map; | ||
16 | import java.util.Map.Entry; | ||
17 | import java.util.concurrent.atomic.AtomicBoolean; | ||
18 | import java.util.concurrent.atomic.AtomicInteger; | ||
19 | |||
20 | import org.apache.log4j.Level; | ||
21 | import org.apache.log4j.Logger; | ||
22 | import org.eclipse.emf.common.notify.Notifier; | ||
23 | import org.eclipse.viatra.dse.api.DSEException; | ||
24 | import org.eclipse.viatra.dse.api.Solution; | ||
25 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
26 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
27 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
28 | import org.eclipse.viatra.dse.objectives.Fitness; | ||
29 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | ||
30 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
31 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
32 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
33 | |||
34 | /** | ||
35 | * | ||
36 | * @author Andras Szabolcs Nagy | ||
37 | * | ||
38 | */ | ||
39 | public class SolutionStore { | ||
40 | |||
41 | public interface ISolutionSaver { | ||
42 | void setSolutionsCollection(Map<Object, Solution> solutions); | ||
43 | boolean saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory); | ||
44 | } | ||
45 | |||
46 | public interface IEnoughSolutions extends ISolutionFoundHandler { | ||
47 | boolean enoughSolutions(); | ||
48 | } | ||
49 | |||
50 | public static class ANumberOfEnoughSolutions implements IEnoughSolutions { | ||
51 | |||
52 | private final AtomicInteger foundSolutions; | ||
53 | private final AtomicBoolean foundEnoughSolutions; | ||
54 | |||
55 | public ANumberOfEnoughSolutions(int number) { | ||
56 | foundSolutions = new AtomicInteger(number); | ||
57 | foundEnoughSolutions = new AtomicBoolean(false); | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public boolean enoughSolutions() { | ||
62 | return foundEnoughSolutions.get(); | ||
63 | } | ||
64 | |||
65 | @Override | ||
66 | public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
67 | int solutionsToFind = foundSolutions.decrementAndGet(); | ||
68 | if (solutionsToFind == 0) { | ||
69 | foundEnoughSolutions.set(true); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | @Override | ||
74 | public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { | ||
75 | } | ||
76 | } | ||
77 | |||
78 | public static class SimpleSolutionSaver implements ISolutionSaver { | ||
79 | |||
80 | private Map<Object, Solution> solutions; | ||
81 | |||
82 | @Override | ||
83 | public void setSolutionsCollection(Map<Object, Solution> solutions) { | ||
84 | this.solutions = solutions; | ||
85 | } | ||
86 | |||
87 | @Override | ||
88 | public boolean saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
89 | Solution solution = solutions.get(id); | ||
90 | if (solution != null) { | ||
91 | if (solution.getTrajectories().contains(solutionTrajectory)) { | ||
92 | return false; | ||
93 | } else { | ||
94 | solution.addTrajectory(solutionTrajectory); | ||
95 | solutionTrajectory.setSolution(solution); | ||
96 | } | ||
97 | } else { | ||
98 | solution = new Solution(id, solutionTrajectory); | ||
99 | solutions.put(id, solution); | ||
100 | solutionTrajectory.setSolution(solution); | ||
101 | } | ||
102 | return true; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | public static class BestSolutionSaver implements ISolutionSaver { | ||
107 | |||
108 | private Map<Object, Solution> solutions; | ||
109 | private Map<SolutionTrajectory, Fitness> trajectories = new HashMap<>(); | ||
110 | |||
111 | @Override | ||
112 | public void setSolutionsCollection(Map<Object, Solution> solutions) { | ||
113 | this.solutions = solutions; | ||
114 | } | ||
115 | |||
116 | @Override | ||
117 | public boolean saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
118 | |||
119 | Fitness lastFitness = context.getLastFitness(); | ||
120 | ObjectiveComparatorHelper comparatorHelper = context.getObjectiveComparatorHelper(); | ||
121 | |||
122 | List<SolutionTrajectory> dominatedTrajectories = new ArrayList<>(); | ||
123 | |||
124 | for (Entry<SolutionTrajectory, Fitness> entry : trajectories.entrySet()) { | ||
125 | int isLastFitnessBetter = comparatorHelper.compare(lastFitness, entry.getValue()); | ||
126 | if (isLastFitnessBetter < 0) { | ||
127 | return false; | ||
128 | } | ||
129 | if (isLastFitnessBetter > 0) { | ||
130 | dominatedTrajectories.add(entry.getKey()); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | boolean solutionSaved = false; | ||
135 | |||
136 | Solution solution = solutions.get(id); | ||
137 | if (solution != null) { | ||
138 | if (!solution.getTrajectories().contains(solutionTrajectory)) { | ||
139 | solution.addTrajectory(solutionTrajectory); | ||
140 | solutionTrajectory.setSolution(solution); | ||
141 | solutionSaved = true; | ||
142 | trajectories.put(solutionTrajectory, lastFitness); | ||
143 | } | ||
144 | } else { | ||
145 | solution = new Solution(id, solutionTrajectory); | ||
146 | solutions.put(id, solution); | ||
147 | solutionTrajectory.setSolution(solution); | ||
148 | solutionSaved = true; | ||
149 | trajectories.put(solutionTrajectory, lastFitness); | ||
150 | } | ||
151 | |||
152 | for (SolutionTrajectory st : dominatedTrajectories) { | ||
153 | trajectories.remove(st); | ||
154 | Solution s = st.getSolution(); | ||
155 | if (!s.getTrajectories().remove(st)) { | ||
156 | throw new DSEException("Should not happen."); | ||
157 | } | ||
158 | if (s.getTrajectories().isEmpty()) { | ||
159 | Object stateCode = s.getStateCode(); | ||
160 | solutions.remove(stateCode); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | return solutionSaved; | ||
165 | } | ||
166 | |||
167 | } | ||
168 | |||
169 | protected boolean acceptOnlyGoalSolutions = true; | ||
170 | protected final Map<Object, Solution> solutions = new HashMap<Object, Solution>(); | ||
171 | protected ISolutionSaver solutionSaver = new SimpleSolutionSaver(); | ||
172 | protected List<ISolutionFoundHandler> solutionFoundHandlers = new ArrayList<ISolutionFoundHandler>(1); | ||
173 | |||
174 | protected final IEnoughSolutions enoughSolutions; | ||
175 | |||
176 | public SolutionStore() { | ||
177 | this(new IEnoughSolutions() { | ||
178 | @Override | ||
179 | public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
180 | } | ||
181 | |||
182 | @Override | ||
183 | public boolean enoughSolutions() { | ||
184 | return false; | ||
185 | } | ||
186 | |||
187 | @Override | ||
188 | public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { | ||
189 | } | ||
190 | }); | ||
191 | } | ||
192 | |||
193 | public SolutionStore(int numOfSolutionsToFind) { | ||
194 | this(new ANumberOfEnoughSolutions(numOfSolutionsToFind)); | ||
195 | } | ||
196 | |||
197 | public SolutionStore(IEnoughSolutions enoughSolutionsImpl) { | ||
198 | enoughSolutions = enoughSolutionsImpl; | ||
199 | } | ||
200 | |||
201 | public synchronized void newSolution(ThreadContext context) { | ||
202 | solutionSaver.setSolutionsCollection(solutions); | ||
203 | Fitness fitness = context.getLastFitness(); | ||
204 | DesignSpaceManager dsm = context.getDesignSpaceManager(); | ||
205 | Object id = dsm.getCurrentState(); | ||
206 | IStateCoderFactory stateCoderFactory = context.getGlobalContext().getStateCoderFactory(); | ||
207 | SolutionTrajectory solutionTrajectory = dsm.getTrajectoryInfo().createSolutionTrajectory(stateCoderFactory, context.getDesignSpaceManager()); | ||
208 | solutionTrajectory.setFitness(fitness); | ||
209 | |||
210 | if (acceptOnlyGoalSolutions && !fitness.isSatisifiesHardObjectives()) { | ||
211 | unsavedSolutionCallbacks(context, solutionTrajectory); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | boolean solutionSaved = solutionSaver.saveSolution(context, id, solutionTrajectory); | ||
216 | |||
217 | if (solutionSaved) { | ||
218 | enoughSolutions.solutionFound(context, solutionTrajectory); | ||
219 | |||
220 | savedSolutionCallbacks(context, solutionTrajectory); | ||
221 | |||
222 | if (enoughSolutions.enoughSolutions()) { | ||
223 | context.getGlobalContext().stopAllThreads(); | ||
224 | } | ||
225 | } else { | ||
226 | unsavedSolutionCallbacks(context, solutionTrajectory); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | private void unsavedSolutionCallbacks(ThreadContext context, SolutionTrajectory solutionTrajectory) { | ||
231 | for (ISolutionFoundHandler handler : solutionFoundHandlers) { | ||
232 | handler.solutionTriedToSave(context, solutionTrajectory); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | private void savedSolutionCallbacks(ThreadContext context, SolutionTrajectory solutionTrajectory) { | ||
237 | for (ISolutionFoundHandler handler : solutionFoundHandlers) { | ||
238 | handler.solutionFound(context, solutionTrajectory); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | public synchronized Collection<Solution> getSolutions() { | ||
243 | return solutions.values(); | ||
244 | } | ||
245 | |||
246 | public synchronized void registerSolutionFoundHandler(ISolutionFoundHandler handler) { | ||
247 | if (solutionFoundHandlers == null) { | ||
248 | solutionFoundHandlers = new ArrayList<ISolutionFoundHandler>(1); | ||
249 | } | ||
250 | solutionFoundHandlers.add(handler); | ||
251 | } | ||
252 | |||
253 | public SolutionStore logSolutionsWhenFound() { | ||
254 | registerSolutionFoundHandler(new LogSolutionHandler()); | ||
255 | Logger.getLogger(LogSolutionHandler.class).setLevel(Level.INFO); | ||
256 | return this; | ||
257 | } | ||
258 | |||
259 | public SolutionStore saveModelWhenFound() { | ||
260 | registerSolutionFoundHandler(new ModelSaverSolutionFoundHandler()); | ||
261 | return this; | ||
262 | } | ||
263 | |||
264 | public SolutionStore saveModelWhenFound(String extension) { | ||
265 | registerSolutionFoundHandler(new ModelSaverSolutionFoundHandler(extension)); | ||
266 | return this; | ||
267 | } | ||
268 | |||
269 | public SolutionStore saveModelWhenFound(String prefix, String extension) { | ||
270 | registerSolutionFoundHandler(new ModelSaverSolutionFoundHandler(prefix, extension)); | ||
271 | return this; | ||
272 | } | ||
273 | |||
274 | public SolutionStore saveModelWhenFound(ISolutionNameProvider solutionNameProvider) { | ||
275 | registerSolutionFoundHandler(new ModelSaverSolutionFoundHandler(solutionNameProvider)); | ||
276 | return this; | ||
277 | } | ||
278 | |||
279 | public SolutionStore acceptGoalSolutionsOnly() { | ||
280 | acceptOnlyGoalSolutions = true; | ||
281 | return this; | ||
282 | } | ||
283 | |||
284 | public SolutionStore acceptAnySolutions() { | ||
285 | acceptOnlyGoalSolutions = false; | ||
286 | return this; | ||
287 | } | ||
288 | |||
289 | public SolutionStore withSolutionSaver(ISolutionSaver solutionSaver) { | ||
290 | this.solutionSaver = solutionSaver; | ||
291 | return this; | ||
292 | } | ||
293 | |||
294 | public SolutionStore storeBestSolutionsOnly() { | ||
295 | this.solutionSaver = new BestSolutionSaver(); | ||
296 | return this; | ||
297 | } | ||
298 | |||
299 | public void saveModels(Notifier model, ISolutionNameProvider solutionNameProvider) { | ||
300 | try { | ||
301 | for (Solution solution : solutions.values()) { | ||
302 | SolutionTrajectory trajectory = solution.getArbitraryTrajectory(); | ||
303 | trajectory.doTransformationUndoable(model); | ||
304 | EMFHelper.saveModel(model, solutionNameProvider.getName()); | ||
305 | trajectory.undoTransformation(); | ||
306 | } | ||
307 | } catch (ViatraQueryException e) { | ||
308 | Logger.getLogger(SolutionStore.class).error("Exception happened during model saving.", e); | ||
309 | } | ||
310 | } | ||
311 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java new file mode 100644 index 00000000..f163f1a5 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoder.java | |||
@@ -0,0 +1,82 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecode; | ||
10 | |||
11 | import org.eclipse.emf.common.notify.Notifier; | ||
12 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
13 | |||
14 | /** | ||
15 | * <p> | ||
16 | * To be able to efficiently explore a design space, a state that has been explored before through an other trajectory | ||
17 | * needs to be recognized and ignored accordingly. | ||
18 | * </p> | ||
19 | * | ||
20 | * <p> | ||
21 | * This is done by generating a pseudo-unique value (object) that is only depended on the relevant parts of the model's | ||
22 | * internal state, that is, the values of two states can only be equal if the states themselves can be considered equal. | ||
23 | * </p> | ||
24 | * | ||
25 | * <p> | ||
26 | * The processing engine however assumes, that any two states that share this pseudo-unique value has the same | ||
27 | * characteristics, meaning they have the same amount and type of outgoing transitions available, and firing the | ||
28 | * appropriate transitions from both states also result in states that share their pseudo-unique identifier. If this | ||
29 | * condition is not satisfied, the exploration process's result will be non-deterministic, and in consequence, solutions | ||
30 | * can be lost. | ||
31 | * </p> | ||
32 | * | ||
33 | * <p> | ||
34 | * In addition to providing pseudo-unique identifiers to model states, the state coder must provide pseud-unique | ||
35 | * identifiers to the outgoing transitions as well, but they only need to be unique on the scope of the particular | ||
36 | * state, not globally. Global addressing thus can be achieved by considering the pseudo-unique identifier of the state | ||
37 | * and the pseudo-unique identifier of the transition together if needed. | ||
38 | * </p> | ||
39 | * | ||
40 | * <p> | ||
41 | * Both identifiers can be arbitrary objects, and equality is checked by calling {@link Object#equals(Object)} on the | ||
42 | * two identifiers. | ||
43 | * </p> | ||
44 | * | ||
45 | * <p> | ||
46 | * For any particular implementation an {@link IStateCoderFactory} implementation must also be supplied that handles the | ||
47 | * creation of {@link IStateCoder} instances. | ||
48 | * </p> | ||
49 | * | ||
50 | * <p> | ||
51 | * Usually it is unnecessary to represent everything from the model in a state code, only the parts which are modified | ||
52 | * by the transformation rules. | ||
53 | * </p> | ||
54 | * | ||
55 | * @author Miklos Foldenyi, Andras Szabolcs Nagy | ||
56 | * | ||
57 | */ | ||
58 | public interface IStateCoder { | ||
59 | |||
60 | /** | ||
61 | * Initializes the state coder on the given model. | ||
62 | * | ||
63 | * @param notifier | ||
64 | */ | ||
65 | void init(Notifier notifier); | ||
66 | |||
67 | /** | ||
68 | * Returns a pseudo-unique identifier that describes the underlying model's current internal state. | ||
69 | * | ||
70 | * @return an arbitrary {@link Object} that can be used as the identifier. | ||
71 | */ | ||
72 | Object createStateCode(); | ||
73 | |||
74 | /** | ||
75 | * Returns a pseudo-unique identifier that describes the given {@link IPatternMatch} in the context of the | ||
76 | * underlying model's current internal state. | ||
77 | * | ||
78 | * @return an arbitrary {@link Object} that can be used as the identifier in the given state. | ||
79 | */ | ||
80 | Object createActivationCode(IPatternMatch match); | ||
81 | |||
82 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java new file mode 100644 index 00000000..cf8bdf8d --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecode/IStateCoderFactory.java | |||
@@ -0,0 +1,29 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecode; | ||
10 | |||
11 | /** | ||
12 | * Interface for a factory class that creates instances of {@link IStateCoder} objects. This is required because state | ||
13 | * coders have to be created on-demand if the design space exploration process decides that a new thread is to be | ||
14 | * spawned. Since each thread requires it's own working model instance and a state coder is linked to the underlying | ||
15 | * model, a new {@link IStateCoder} needs to be created per processing thread. | ||
16 | * | ||
17 | * @author Miklos Foldenyi, Andras Szabolcs Nagy | ||
18 | * | ||
19 | */ | ||
20 | public interface IStateCoderFactory { | ||
21 | |||
22 | /** | ||
23 | * Creates a new {@link IStateCoder} instance specific to this {@link IStateCoderFactory}. | ||
24 | * | ||
25 | * @return the new {@link IStateCoder} instance specific to this working model. | ||
26 | */ | ||
27 | IStateCoder createStateCoder(); | ||
28 | |||
29 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java new file mode 100644 index 00000000..afcba7b6 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProvider.java | |||
@@ -0,0 +1,45 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | import org.eclipse.emf.common.notify.Notifier; | ||
14 | import org.eclipse.emf.ecore.EClass; | ||
15 | import org.eclipse.emf.ecore.EObject; | ||
16 | |||
17 | /** | ||
18 | * Implementation of this interface is responsible to provide {@link EObject}s of a given {@link EClass} for | ||
19 | * {@link TheStateCoder} | ||
20 | * | ||
21 | * @author Andras Szabolcs Nagy | ||
22 | * | ||
23 | */ | ||
24 | public interface IObjectsProvider { | ||
25 | |||
26 | /** | ||
27 | * Initialize the {@link IObjectsProvider} on a given model and {@link StatecodingDependencyGraph}. | ||
28 | * | ||
29 | * @param notifier | ||
30 | * The root of the model. | ||
31 | * @param statecodingDependencyGraph | ||
32 | * The state coding dependency graph. | ||
33 | */ | ||
34 | void init(Notifier notifier, StatecodingDependencyGraph statecodingDependencyGraph); | ||
35 | |||
36 | /** | ||
37 | * Returns the instances of an {@link EClass} in a model. | ||
38 | * | ||
39 | * @param eClass | ||
40 | * The class of the objects. | ||
41 | * @return The collection of the instances. | ||
42 | */ | ||
43 | Collection<EObject> getEObjects(EClass eClass); | ||
44 | |||
45 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java new file mode 100644 index 00000000..931eb1a2 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IObjectsProviderFactory.java | |||
@@ -0,0 +1,25 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | /** | ||
12 | * Interface for creating {@link IObjectsProvider} instances. | ||
13 | * | ||
14 | * @author Andras Szabolcs Nagy | ||
15 | */ | ||
16 | public interface IObjectsProviderFactory { | ||
17 | |||
18 | /** | ||
19 | * Creates an {@link IObjectsProvider} implementation. | ||
20 | * | ||
21 | * @return The newly created {@link IObjectsProvider}. | ||
22 | */ | ||
23 | IObjectsProvider createObjectsProvider(); | ||
24 | |||
25 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java new file mode 100644 index 00000000..e38d45d3 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProvider.java | |||
@@ -0,0 +1,60 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashSet; | ||
13 | import java.util.Set; | ||
14 | |||
15 | import org.apache.log4j.Logger; | ||
16 | import org.eclipse.emf.common.notify.Notifier; | ||
17 | import org.eclipse.emf.ecore.EClass; | ||
18 | import org.eclipse.emf.ecore.EObject; | ||
19 | import org.eclipse.viatra.dse.api.DSEException; | ||
20 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
21 | import org.eclipse.viatra.query.runtime.base.api.IndexingLevel; | ||
22 | import org.eclipse.viatra.query.runtime.base.api.NavigationHelper; | ||
23 | import org.eclipse.viatra.query.runtime.emf.EMFScope; | ||
24 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
25 | |||
26 | public class IncrementalObjectProvider implements IObjectsProvider { | ||
27 | |||
28 | private Logger logger = Logger.getLogger(getClass()); | ||
29 | private NavigationHelper baseIndex; | ||
30 | |||
31 | @Override | ||
32 | public void init(Notifier notifier, StatecodingDependencyGraph statecodingDependencyGraph) { | ||
33 | |||
34 | try { | ||
35 | EMFScope scope = new EMFScope(notifier); | ||
36 | ViatraQueryEngine queryEngine = ViatraQueryEngine.on(scope); | ||
37 | |||
38 | Set<EClass> classes = new HashSet<EClass>(); | ||
39 | // Set<EReference> references = new HashSet<EReference>(); | ||
40 | for (StatecodingNode node : statecodingDependencyGraph.getNodes()) { | ||
41 | classes.add(node.getClazz()); | ||
42 | // for (StatecodingDependency dependency : node.getStatecodingDependencies()) { | ||
43 | // // TODO inverse reference | ||
44 | // references.add(dependency.eReference); | ||
45 | // } | ||
46 | } | ||
47 | baseIndex = EMFScope.extractUnderlyingEMFIndex(queryEngine); | ||
48 | baseIndex.registerEClasses(classes, IndexingLevel.FULL); | ||
49 | } catch (ViatraQueryException e) { | ||
50 | logger.error("Failed to initialize VIATRA Query engine on the given notifier", e); | ||
51 | throw new DSEException("Failed to initialize VIATRA Query engine on the given notifier"); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public Collection<EObject> getEObjects(EClass eClass) { | ||
57 | return baseIndex.getAllInstances(eClass); | ||
58 | } | ||
59 | |||
60 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java new file mode 100644 index 00000000..97011436 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/IncrementalObjectProviderFactory.java | |||
@@ -0,0 +1,18 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | public class IncrementalObjectProviderFactory implements IObjectsProviderFactory { | ||
12 | |||
13 | @Override | ||
14 | public IncrementalObjectProvider createObjectsProvider() { | ||
15 | return new IncrementalObjectProvider(); | ||
16 | } | ||
17 | |||
18 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java new file mode 100644 index 00000000..67b1982d --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependency.java | |||
@@ -0,0 +1,33 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | import org.eclipse.emf.ecore.EReference; | ||
12 | |||
13 | public class StatecodingDependency { | ||
14 | |||
15 | protected EReference eReference; | ||
16 | protected StatecodingNode node; | ||
17 | protected boolean isContained; | ||
18 | protected StatecodingDependencyType type; | ||
19 | |||
20 | public StatecodingDependency(EReference eReference, StatecodingNode node, boolean isContained, | ||
21 | StatecodingDependencyType type) { | ||
22 | super(); | ||
23 | this.eReference = eReference; | ||
24 | this.node = node; | ||
25 | this.isContained = isContained; | ||
26 | this.type = type; | ||
27 | } | ||
28 | |||
29 | public StatecodingDependency(EReference eReference, StatecodingNode node) { | ||
30 | this(eReference, node, false, StatecodingDependencyType.NORMAL); | ||
31 | } | ||
32 | |||
33 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java new file mode 100644 index 00000000..6f7255a3 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyGraph.java | |||
@@ -0,0 +1,44 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | |||
14 | import org.eclipse.emf.ecore.EClass; | ||
15 | |||
16 | public class StatecodingDependencyGraph { | ||
17 | |||
18 | private List<StatecodingNode> nodes = new ArrayList<StatecodingNode>(); | ||
19 | |||
20 | public StatecodingNode createNode(EClass clazz) { | ||
21 | StatecodingNode node = new StatecodingNode(clazz); | ||
22 | node.setGraph(this); | ||
23 | addNode(node); | ||
24 | return node; | ||
25 | } | ||
26 | |||
27 | public void addNode(StatecodingNode node) { | ||
28 | nodes.add(node); | ||
29 | } | ||
30 | |||
31 | public StatecodingNode getNodeByClass(EClass eClass) { | ||
32 | for (StatecodingNode node : nodes) { | ||
33 | if (node.getClazz().equals(eClass)) { | ||
34 | return node; | ||
35 | } | ||
36 | } | ||
37 | return null; | ||
38 | } | ||
39 | |||
40 | public List<StatecodingNode> getNodes() { | ||
41 | return nodes; | ||
42 | } | ||
43 | |||
44 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java new file mode 100644 index 00000000..bdd4677d --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingDependencyType.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | public enum StatecodingDependencyType { | ||
12 | |||
13 | NORMAL, | ||
14 | INVERSE | ||
15 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java new file mode 100644 index 00000000..91fc28cf --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNode.java | |||
@@ -0,0 +1,100 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Comparator; | ||
13 | import java.util.List; | ||
14 | import java.util.Set; | ||
15 | import java.util.TreeSet; | ||
16 | |||
17 | import org.eclipse.emf.ecore.EAttribute; | ||
18 | import org.eclipse.emf.ecore.EClass; | ||
19 | import org.eclipse.emf.ecore.EReference; | ||
20 | |||
21 | public class StatecodingNode { | ||
22 | |||
23 | private StatecodingDependencyGraph graph; | ||
24 | |||
25 | private final EClass clazz; | ||
26 | private Set<EAttribute> attributes = new TreeSet<EAttribute>(Comparator.comparing(EAttribute::getName)); | ||
27 | private List<StatecodingDependency> dependencies = new ArrayList<StatecodingDependency>(); | ||
28 | private boolean stateCodeIsId = false; | ||
29 | private StatecodingNodeType statecodingNodeType = StatecodingNodeType.CREATE_AND_DELETE; | ||
30 | |||
31 | public StatecodingNode(EClass clazz) { | ||
32 | this.clazz = clazz; | ||
33 | } | ||
34 | |||
35 | public StatecodingNode withAttribute(EAttribute attribute) { | ||
36 | attributes.add(attribute); | ||
37 | return this; | ||
38 | } | ||
39 | |||
40 | public StatecodingNode withType(StatecodingNodeType type) { | ||
41 | statecodingNodeType = type; | ||
42 | return this; | ||
43 | } | ||
44 | |||
45 | public StatecodingNode withUniqueness() { | ||
46 | stateCodeIsId = true; | ||
47 | return this; | ||
48 | } | ||
49 | |||
50 | public StatecodingNode withDependency(EReference reference, StatecodingNode node) { | ||
51 | dependencies.add(new StatecodingDependency(reference, node)); | ||
52 | return this; | ||
53 | } | ||
54 | |||
55 | public StatecodingNode withInverseDependency(EReference reference, StatecodingNode node) { | ||
56 | dependencies.add(new StatecodingDependency(reference, node, false, StatecodingDependencyType.INVERSE)); | ||
57 | return this; | ||
58 | } | ||
59 | |||
60 | public void addDependency(StatecodingDependency statecodingDependency) { | ||
61 | dependencies.add(statecodingDependency); | ||
62 | } | ||
63 | |||
64 | public EClass getClazz() { | ||
65 | return clazz; | ||
66 | } | ||
67 | |||
68 | public boolean isStateCodeIsId() { | ||
69 | return stateCodeIsId; | ||
70 | } | ||
71 | |||
72 | public void setStateCodeIsId(boolean stateCodeIsId) { | ||
73 | this.stateCodeIsId = stateCodeIsId; | ||
74 | } | ||
75 | |||
76 | public StatecodingNodeType getStatecodingNodeType() { | ||
77 | return statecodingNodeType; | ||
78 | } | ||
79 | |||
80 | public void setStatecodingNodeType(StatecodingNodeType statecodingNodeType) { | ||
81 | this.statecodingNodeType = statecodingNodeType; | ||
82 | } | ||
83 | |||
84 | public Set<EAttribute> getAttributes() { | ||
85 | return attributes; | ||
86 | } | ||
87 | |||
88 | public List<StatecodingDependency> getStatecodingDependencies() { | ||
89 | return dependencies; | ||
90 | } | ||
91 | |||
92 | public StatecodingDependencyGraph getGraph() { | ||
93 | return graph; | ||
94 | } | ||
95 | |||
96 | public void setGraph(StatecodingDependencyGraph graph) { | ||
97 | this.graph = graph; | ||
98 | } | ||
99 | |||
100 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java new file mode 100644 index 00000000..c902a7a6 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/StatecodingNodeType.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | public enum StatecodingNodeType { | ||
12 | |||
13 | FIXED, | ||
14 | ONLY_CREATE, | ||
15 | ONLY_DELETE, | ||
16 | CREATE_AND_DELETE | ||
17 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java new file mode 100644 index 00000000..4601ff08 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoder.java | |||
@@ -0,0 +1,215 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.Collection; | ||
13 | import java.util.List; | ||
14 | import java.util.Set; | ||
15 | |||
16 | import org.eclipse.emf.common.notify.Notifier; | ||
17 | import org.eclipse.emf.common.util.EList; | ||
18 | import org.eclipse.emf.ecore.EAttribute; | ||
19 | import org.eclipse.emf.ecore.EObject; | ||
20 | import org.eclipse.viatra.dse.api.DSEException; | ||
21 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
22 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
23 | |||
24 | public class TheStateCoder implements IStateCoder { | ||
25 | |||
26 | private StatecodingDependencyGraph sdg; | ||
27 | private IObjectsProvider objectProvider; | ||
28 | |||
29 | public TheStateCoder(StatecodingDependencyGraph sdg, IObjectsProvider objectProvider) { | ||
30 | this.sdg = sdg; | ||
31 | this.objectProvider = objectProvider; | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public void init(Notifier notifier) { | ||
36 | // TODO checks | ||
37 | // TODO node sorting based on traversal - in factory | ||
38 | |||
39 | // this.notifier = notifier; | ||
40 | // try { | ||
41 | // EMFScope scope = new EMFScope(notifier); | ||
42 | // queryEngine = ViatraQueryEngine.on(scope); | ||
43 | // } catch (ViatraQueryException e1) { | ||
44 | // logger.error("Failed to initialize VIATRA Query engine on the given notifier", e1); | ||
45 | // throw new DSEException("Failed to initialize VIATRA Query engine on the given notifier"); | ||
46 | // } | ||
47 | |||
48 | objectProvider.init(notifier, sdg); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public String createStateCode() { | ||
53 | |||
54 | StringBuilder sb = new StringBuilder(); | ||
55 | |||
56 | // TODO sort | ||
57 | for (StatecodingNode node : sdg.getNodes()) { | ||
58 | sb.append(node.getClazz().getName()); | ||
59 | sb.append(':'); | ||
60 | sb.append(addStateCode(node)); | ||
61 | sb.append('|'); | ||
62 | } | ||
63 | sb.deleteCharAt(sb.length() - 1); | ||
64 | |||
65 | return sb.toString(); | ||
66 | |||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public Object createActivationCode(IPatternMatch match) { | ||
71 | // TODO root object | ||
72 | // TODO parameterless? | ||
73 | |||
74 | int i = 0; | ||
75 | StringBuilder sb = new StringBuilder(); | ||
76 | Object object; | ||
77 | do { | ||
78 | object = match.get(i++); | ||
79 | if (object != null) { | ||
80 | if (object instanceof EObject) { | ||
81 | EObject eObject = (EObject) object; | ||
82 | sb.append(addStateCode(sdg.getNodeByClass(eObject.eClass()), eObject)); | ||
83 | } else { | ||
84 | // TODO toString or not to toString | ||
85 | } | ||
86 | } | ||
87 | } while (object != null); | ||
88 | |||
89 | return sb.toString(); | ||
90 | } | ||
91 | |||
92 | public String addStateCode(StatecodingNode node, EObject eObject) { | ||
93 | StringBuilder sb = new StringBuilder(); | ||
94 | |||
95 | Set<EAttribute> attributes = node.getAttributes(); | ||
96 | if (!attributes.isEmpty()) { | ||
97 | for (EAttribute eAttribute : attributes) { | ||
98 | // attributes are sorted | ||
99 | // TODO handle collection | ||
100 | sb.append(eObject.eGet(eAttribute)); | ||
101 | sb.append(';'); | ||
102 | } | ||
103 | sb.deleteCharAt(sb.length() - 1); | ||
104 | } | ||
105 | |||
106 | List<StatecodingDependency> dependencies = node.getStatecodingDependencies(); | ||
107 | int dependenciesSize = dependencies.size(); | ||
108 | if (dependenciesSize > 0) { | ||
109 | String[] codeParts = new String[dependenciesSize]; | ||
110 | int i = 0; | ||
111 | for (StatecodingDependency dependency : dependencies) { | ||
112 | String code = addStateCodeFromDependency(dependency, eObject); | ||
113 | codeParts[i++] = code; | ||
114 | } | ||
115 | Arrays.sort(codeParts); | ||
116 | |||
117 | sb.append("("); | ||
118 | sb.append(codeParts[0]); | ||
119 | for (i = 1; i < codeParts.length; i++) { | ||
120 | sb.append(';'); | ||
121 | sb.append(codeParts[i]); | ||
122 | } | ||
123 | sb.append(")"); | ||
124 | } | ||
125 | return sb.toString(); | ||
126 | } | ||
127 | |||
128 | public String addStateCode(StatecodingNode node) { | ||
129 | Collection<EObject> eObjects = objectProvider.getEObjects(node.getClazz()); | ||
130 | int size = eObjects.size(); | ||
131 | |||
132 | if (size > 0) { | ||
133 | String[] codeParts = new String[size]; | ||
134 | int i = 0; | ||
135 | for (EObject eObject : eObjects) { | ||
136 | String code = addStateCode(node, eObject); | ||
137 | codeParts[i++] = code; | ||
138 | } | ||
139 | Arrays.sort(codeParts); | ||
140 | |||
141 | StringBuilder sb = new StringBuilder(); | ||
142 | sb.append(codeParts[0]); | ||
143 | for (i = 1; i < codeParts.length; i++) { | ||
144 | sb.append(';'); | ||
145 | sb.append(codeParts[i]); | ||
146 | } | ||
147 | return sb.toString(); | ||
148 | } | ||
149 | |||
150 | return ""; | ||
151 | } | ||
152 | |||
153 | public String addStateCodeFromDependency(StatecodingDependency sd, EObject eObject) { | ||
154 | |||
155 | if (sd.type.equals(StatecodingDependencyType.NORMAL)) { | ||
156 | |||
157 | Object eReferred = eObject.eGet(sd.eReference); | ||
158 | if (eReferred == null) { | ||
159 | return ""; | ||
160 | } else if (eReferred instanceof EList<?>) { | ||
161 | EList<?> refferedList = (EList<?>) eReferred; | ||
162 | // TODO test | ||
163 | if (!refferedList.isEmpty()) { | ||
164 | |||
165 | String[] codeParts = new String[refferedList.size()]; | ||
166 | int i = 0; | ||
167 | for (Object referredEObject : refferedList) { | ||
168 | String code = addStateCode(sd.node, (EObject) referredEObject); | ||
169 | codeParts[i++] = code; | ||
170 | } | ||
171 | Arrays.sort(codeParts); | ||
172 | |||
173 | StringBuilder sb = new StringBuilder(); | ||
174 | sb.append('['); | ||
175 | sb.append(codeParts[0]); | ||
176 | for (i = 1; i < codeParts.length; i++) { | ||
177 | sb.append(';'); | ||
178 | sb.append(codeParts[i]); | ||
179 | } | ||
180 | sb.append(']'); | ||
181 | return sb.toString(); | ||
182 | |||
183 | } | ||
184 | } else if (eReferred instanceof EObject) { | ||
185 | return addStateCode(sd.node, (EObject) eReferred); | ||
186 | } else { | ||
187 | throw new DSEException("The EObject " + eObject.toString() + " does not have a feature " | ||
188 | + eReferred.toString() + "."); | ||
189 | } | ||
190 | |||
191 | } else { | ||
192 | for (EObject dependentEObject : objectProvider.getEObjects(sd.node.getClazz())) { | ||
193 | Object eReferred = dependentEObject.eGet(sd.eReference); | ||
194 | if (eReferred == null) { | ||
195 | continue; | ||
196 | } else if (eReferred instanceof EList<?>) { | ||
197 | // TODO this is slow, use VIATRA Query | ||
198 | for (Object referredEObject : ((EList<?>) eReferred)) { | ||
199 | if (referredEObject.equals(eObject)) { | ||
200 | return addStateCode(sd.node, (EObject) dependentEObject); | ||
201 | } | ||
202 | } | ||
203 | } else if (eReferred.equals(eObject)) { | ||
204 | // Probably never happens? | ||
205 | return addStateCode(sd.node, (EObject) dependentEObject); | ||
206 | } else { | ||
207 | throw new DSEException("The EObject " + eObject.toString() + " does not have a feature " | ||
208 | + eReferred.toString() + "."); | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | |||
213 | return ""; | ||
214 | } | ||
215 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java new file mode 100644 index 00000000..eeb6e48f --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/TheStateCoderFactory.java | |||
@@ -0,0 +1,40 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding; | ||
10 | |||
11 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
12 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
13 | |||
14 | public class TheStateCoderFactory implements IStateCoderFactory { | ||
15 | |||
16 | private StatecodingDependencyGraph sdg; | ||
17 | private IObjectsProviderFactory objectProviderFactory; | ||
18 | |||
19 | public TheStateCoderFactory(StatecodingDependencyGraph sdg) { | ||
20 | this(sdg, new IncrementalObjectProviderFactory()); | ||
21 | } | ||
22 | |||
23 | public TheStateCoderFactory(StatecodingDependencyGraph sdg, IObjectsProviderFactory objectProviderFactory) { | ||
24 | this.sdg = sdg; | ||
25 | this.objectProviderFactory = objectProviderFactory; | ||
26 | |||
27 | // TODO cyclic dependency? - exception | ||
28 | |||
29 | // TODO make plan for traversal | ||
30 | |||
31 | // TODO If the type is FIXED and all dependency is FIXED then do not create state code for it (them) | ||
32 | // This is not true :( e.g. matchmaking - they are fixed, but the references must be encoded | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public IStateCoder createStateCoder() { | ||
37 | return new TheStateCoder(sdg, objectProviderFactory.createObjectsProvider()); | ||
38 | } | ||
39 | |||
40 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java new file mode 100644 index 00000000..0f0759ae --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java | |||
@@ -0,0 +1,250 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding.simple; | ||
10 | |||
11 | import java.util.Arrays; | ||
12 | import java.util.Collection; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.HashSet; | ||
15 | import java.util.List; | ||
16 | import java.util.Map; | ||
17 | import java.util.Set; | ||
18 | |||
19 | import org.eclipse.emf.common.notify.Notifier; | ||
20 | import org.eclipse.emf.ecore.EAttribute; | ||
21 | import org.eclipse.emf.ecore.EClass; | ||
22 | import org.eclipse.emf.ecore.EObject; | ||
23 | import org.eclipse.emf.ecore.EReference; | ||
24 | import org.eclipse.emf.ecore.EStructuralFeature; | ||
25 | import org.eclipse.emf.ecore.EStructuralFeature.Setting; | ||
26 | import org.eclipse.viatra.dse.api.DSEException; | ||
27 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
28 | import org.eclipse.viatra.dse.util.EMFHelper.MetaModelElements; | ||
29 | import org.eclipse.viatra.dse.util.ValueComparableEObjectStringMap; | ||
30 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
31 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
32 | import org.eclipse.viatra.query.runtime.base.api.FeatureListener; | ||
33 | import org.eclipse.viatra.query.runtime.base.api.IndexingLevel; | ||
34 | import org.eclipse.viatra.query.runtime.base.api.InstanceListener; | ||
35 | import org.eclipse.viatra.query.runtime.base.api.NavigationHelper; | ||
36 | import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper; | ||
37 | import org.eclipse.viatra.query.runtime.emf.EMFScope; | ||
38 | import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; | ||
39 | |||
40 | /** | ||
41 | * | ||
42 | * @author Andras Szabolcs Nagy | ||
43 | * | ||
44 | */ | ||
45 | public class SimpleStateCoder implements IStateCoder { | ||
46 | |||
47 | private Set<EClass> classes; | ||
48 | private Set<EStructuralFeature> features; | ||
49 | private NavigationHelper navigationHelper; | ||
50 | |||
51 | private Map<EClass, Map<EObject, String>> objectCodes; | ||
52 | private int maxDepth; | ||
53 | |||
54 | private Set<EObject> changedOrNewEObjects = new HashSet<EObject>(); | ||
55 | private Set<EObject> deletedClasses = new HashSet<EObject>(); | ||
56 | |||
57 | public SimpleStateCoder(MetaModelElements metaModelElements) { | ||
58 | this.maxDepth = 1; | ||
59 | |||
60 | classes = metaModelElements.classes; | ||
61 | features = new HashSet<EStructuralFeature>(metaModelElements.attributes); | ||
62 | features.addAll(metaModelElements.references); | ||
63 | } | ||
64 | |||
65 | @Override | ||
66 | public void init(Notifier notifier) { | ||
67 | try { | ||
68 | EMFScope scope = new EMFScope(notifier); | ||
69 | ViatraQueryEngine queryEngine = ViatraQueryEngine.on(scope); | ||
70 | EMFBaseIndexWrapper baseIndex = (EMFBaseIndexWrapper) queryEngine.getBaseIndex(); | ||
71 | navigationHelper = baseIndex.getNavigationHelper(); | ||
72 | navigationHelper.registerObservedTypes(classes, null, features, IndexingLevel.FULL); | ||
73 | } catch (ViatraQueryException e) { | ||
74 | throw new DSEException(e); | ||
75 | } | ||
76 | |||
77 | objectCodes = new HashMap<EClass, Map<EObject, String>>(); | ||
78 | for (EClass eClass : classes) { | ||
79 | Map<EObject, String> codes = new ValueComparableEObjectStringMap(); | ||
80 | |||
81 | objectCodes.put(eClass, codes); | ||
82 | |||
83 | for (EObject eObject : navigationHelper.getDirectInstances(eClass)) { | ||
84 | codes.put(eObject, createObjectCodeWithDepth(eObject, maxDepth)); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | navigationHelper.addFeatureListener(features, new FeatureListener() { | ||
89 | |||
90 | @Override | ||
91 | public void featureInserted(EObject host, EStructuralFeature feature, Object value) { | ||
92 | changedOrNewEObjects.add(host); | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | public void featureDeleted(EObject host, EStructuralFeature feature, Object value) { | ||
97 | changedOrNewEObjects.add(host); | ||
98 | if (value instanceof EObject) { | ||
99 | changedOrNewEObjects.add((EObject) value); | ||
100 | } | ||
101 | } | ||
102 | }); | ||
103 | |||
104 | navigationHelper.addInstanceListener(classes, new InstanceListener() { | ||
105 | |||
106 | @Override | ||
107 | public void instanceInserted(EClass clazz, EObject instance) { | ||
108 | changedOrNewEObjects.add(instance); | ||
109 | } | ||
110 | |||
111 | @Override | ||
112 | public void instanceDeleted(EClass clazz, EObject instance) { | ||
113 | deletedClasses.add(instance); | ||
114 | } | ||
115 | }); | ||
116 | } | ||
117 | |||
118 | private String createObjectCodeWithDepth(EObject eObject, int depth) { | ||
119 | |||
120 | StringBuilder sb = new StringBuilder(); | ||
121 | |||
122 | Collection<EAttribute> attributes = eObject.eClass().getEAllAttributes(); | ||
123 | for (EAttribute eAttribute : attributes) { | ||
124 | Object value = eObject.eGet(eAttribute); | ||
125 | sb.append(value); | ||
126 | sb.append(','); | ||
127 | } | ||
128 | if (!attributes.isEmpty()) { | ||
129 | sb.deleteCharAt(sb.length() - 1); | ||
130 | } | ||
131 | if (depth > 0) { | ||
132 | sb.append('-'); | ||
133 | Collection<EReference> eReferences = eObject.eClass().getEAllReferences(); | ||
134 | for (EReference eReference : eReferences) { | ||
135 | Object value = eObject.eGet(eReference); | ||
136 | if (value == null) { | ||
137 | sb.append("null,"); | ||
138 | } else if (value instanceof EObject) { | ||
139 | sb.append(createObjectCodeWithDepth((EObject) value, depth - 1)); | ||
140 | sb.append(','); | ||
141 | } else { | ||
142 | List<EObject> referencedEObjects = (List<EObject>) value; | ||
143 | if (!referencedEObjects.isEmpty()) { | ||
144 | |||
145 | String[] codes = new String[referencedEObjects.size()]; | ||
146 | int index = 0; | ||
147 | for (EObject referencedEObject : referencedEObjects) { | ||
148 | codes[index++] = createObjectCodeWithDepth(referencedEObject, depth - 1); | ||
149 | } | ||
150 | Arrays.sort(codes); | ||
151 | sb.append('('); | ||
152 | for (String code : codes) { | ||
153 | sb.append(code); | ||
154 | } | ||
155 | sb.append("),"); | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | sb.deleteCharAt(sb.length() - 1); | ||
160 | } | ||
161 | return sb.toString(); | ||
162 | } | ||
163 | |||
164 | @Override | ||
165 | public Object createStateCode() { | ||
166 | |||
167 | refreshObjectCodes(); | ||
168 | |||
169 | StringBuilder sb = new StringBuilder(); | ||
170 | |||
171 | for (EClass eClass : classes) { | ||
172 | |||
173 | Set<EObject> instances = navigationHelper.getDirectInstances(eClass); | ||
174 | |||
175 | if (!instances.isEmpty()) { | ||
176 | |||
177 | sb.append(eClass.getName()); | ||
178 | sb.append(':'); | ||
179 | |||
180 | String[] codesToSort = new String[instances.size()]; | ||
181 | int index = 0; | ||
182 | Map<EObject, String> codes = objectCodes.get(eClass); | ||
183 | for (EObject eObject : instances) { | ||
184 | codesToSort[index++] = codes.get(eObject); | ||
185 | } | ||
186 | Arrays.sort(codesToSort); | ||
187 | for (String string : codesToSort) { | ||
188 | sb.append(string); | ||
189 | sb.append(';'); | ||
190 | } | ||
191 | sb.deleteCharAt(sb.length() - 1); | ||
192 | sb.append('|'); | ||
193 | } | ||
194 | } | ||
195 | if (sb.length() != 0) { | ||
196 | sb.deleteCharAt(sb.length() - 1); | ||
197 | } | ||
198 | return sb.toString(); | ||
199 | } | ||
200 | |||
201 | private void refreshObjectCodes() { | ||
202 | for (EObject eObject : deletedClasses) { | ||
203 | EClass eClass = eObject.eClass(); | ||
204 | objectCodes.get(eClass).remove(eObject); | ||
205 | } | ||
206 | deletedClasses.clear(); | ||
207 | |||
208 | Set<EObject> objectsToRecode = new HashSet<EObject>(); | ||
209 | for (EObject eObject : changedOrNewEObjects) { | ||
210 | objectsToRecode.add(eObject); | ||
211 | for (Setting setting : navigationHelper.getInverseReferences(eObject)) { | ||
212 | objectsToRecode.add(setting.getEObject()); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | for (EObject eObject : objectsToRecode) { | ||
217 | EClass eClass = eObject.eClass(); | ||
218 | objectCodes.get(eClass).put(eObject, createObjectCodeWithDepth(eObject, maxDepth)); | ||
219 | } | ||
220 | changedOrNewEObjects.clear(); | ||
221 | } | ||
222 | |||
223 | @Override | ||
224 | public Object createActivationCode(IPatternMatch match) { | ||
225 | |||
226 | StringBuilder sb = new StringBuilder(); | ||
227 | String[] tokens = match.specification().getFullyQualifiedName().split("\\."); | ||
228 | sb.append(tokens[tokens.length - 1]); | ||
229 | sb.append(':'); | ||
230 | Object param; | ||
231 | for (int i = 0; (param = match.get(i)) != null; i++) { | ||
232 | EObject eObject = (EObject) param; | ||
233 | |||
234 | Collection<EAttribute> attributes = eObject.eClass().getEAllAttributes(); | ||
235 | for (EAttribute eAttribute : attributes) { | ||
236 | Object value = eObject.eGet(eAttribute); | ||
237 | sb.append(value); | ||
238 | sb.append(','); | ||
239 | } | ||
240 | if (!attributes.isEmpty()) { | ||
241 | sb.deleteCharAt(sb.length() - 1); | ||
242 | } | ||
243 | |||
244 | sb.append('|'); | ||
245 | } | ||
246 | sb.deleteCharAt(sb.length() - 1); | ||
247 | return sb.toString().intern(); | ||
248 | } | ||
249 | |||
250 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java new file mode 100644 index 00000000..d776e8a8 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoderFactory.java | |||
@@ -0,0 +1,38 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.statecoding.simple; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | import java.util.HashSet; | ||
13 | |||
14 | import org.eclipse.emf.ecore.EPackage; | ||
15 | import org.eclipse.viatra.dse.statecode.IStateCoder; | ||
16 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory; | ||
17 | import org.eclipse.viatra.dse.util.EMFHelper; | ||
18 | import org.eclipse.viatra.dse.util.EMFHelper.MetaModelElements; | ||
19 | |||
20 | /** | ||
21 | * | ||
22 | * @author Andras Szabolcs Nagy | ||
23 | * | ||
24 | */ | ||
25 | public class SimpleStateCoderFactory implements IStateCoderFactory { | ||
26 | |||
27 | private MetaModelElements metaModelElements; | ||
28 | |||
29 | public SimpleStateCoderFactory(Collection<EPackage> metaModelPackages) { | ||
30 | metaModelElements = EMFHelper.getAllMetaModelElements(new HashSet<EPackage>(metaModelPackages)); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public IStateCoder createStateCoder() { | ||
35 | return new SimpleStateCoder(metaModelElements); | ||
36 | } | ||
37 | |||
38 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java new file mode 100644 index 00000000..14b3acfb --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/EMFHelper.java | |||
@@ -0,0 +1,424 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.util; | ||
10 | |||
11 | import java.io.IOException; | ||
12 | import java.util.Collections; | ||
13 | import java.util.Comparator; | ||
14 | import java.util.HashMap; | ||
15 | import java.util.HashSet; | ||
16 | import java.util.List; | ||
17 | import java.util.Map; | ||
18 | import java.util.Objects; | ||
19 | import java.util.Set; | ||
20 | import java.util.TreeSet; | ||
21 | |||
22 | import org.apache.log4j.Logger; | ||
23 | import org.eclipse.emf.common.command.BasicCommandStack; | ||
24 | import org.eclipse.emf.common.notify.Notifier; | ||
25 | import org.eclipse.emf.common.util.EList; | ||
26 | import org.eclipse.emf.common.util.URI; | ||
27 | import org.eclipse.emf.ecore.EAttribute; | ||
28 | import org.eclipse.emf.ecore.EClass; | ||
29 | import org.eclipse.emf.ecore.EClassifier; | ||
30 | import org.eclipse.emf.ecore.ENamedElement; | ||
31 | import org.eclipse.emf.ecore.EObject; | ||
32 | import org.eclipse.emf.ecore.EPackage; | ||
33 | import org.eclipse.emf.ecore.EReference; | ||
34 | import org.eclipse.emf.ecore.resource.Resource; | ||
35 | import org.eclipse.emf.ecore.resource.ResourceSet; | ||
36 | import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; | ||
37 | import org.eclipse.emf.ecore.util.EcoreUtil.Copier; | ||
38 | import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; | ||
39 | import org.eclipse.emf.edit.command.AddCommand; | ||
40 | import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; | ||
41 | import org.eclipse.emf.edit.domain.EditingDomain; | ||
42 | import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; | ||
43 | |||
44 | /** | ||
45 | * This class contains static helper methods. | ||
46 | * @author Andras Szabolcs Nagy | ||
47 | */ | ||
48 | public final class EMFHelper { | ||
49 | |||
50 | private static final Logger logger = Logger.getLogger(EMFHelper.class); | ||
51 | |||
52 | private EMFHelper() { | ||
53 | } | ||
54 | |||
55 | public static class EmfHelperException extends RuntimeException { | ||
56 | private static final long serialVersionUID = 7635796550669616626L; | ||
57 | |||
58 | public EmfHelperException(String string) { | ||
59 | super(string); | ||
60 | } | ||
61 | public EmfHelperException(String string, Throwable e) { | ||
62 | super(string, e); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * Gets the {@link EditingDomain} of either an {@link EObject}, {@link Resource} or {@link ResourceSet}. | ||
68 | * @param notifier The {@link Notifier}. | ||
69 | * @return The EditingDomain. | ||
70 | */ | ||
71 | public static EditingDomain getEditingDomain(Notifier notifier) { | ||
72 | Objects.requireNonNull(notifier); | ||
73 | if (notifier instanceof EObject) { | ||
74 | EObject eObject = (EObject) notifier; | ||
75 | return AdapterFactoryEditingDomain.getEditingDomainFor(eObject); | ||
76 | } else if (notifier instanceof Resource) { | ||
77 | Resource resource = (Resource) notifier; | ||
78 | EList<EObject> contents = resource.getContents(); | ||
79 | if (contents.isEmpty()) { | ||
80 | return null; | ||
81 | } | ||
82 | return AdapterFactoryEditingDomain.getEditingDomainFor(contents.get(0)); | ||
83 | } else if (notifier instanceof ResourceSet) { | ||
84 | ResourceSet resourceSet = (ResourceSet) notifier; | ||
85 | if (resourceSet.getResources().isEmpty()) { | ||
86 | return null; | ||
87 | } | ||
88 | return getEditingDomain(resourceSet.getResources().get(0)); | ||
89 | } | ||
90 | |||
91 | return null; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Creates (or gets if already exists) an {@link EditingDomain} over the given {@link Notifier}, | ||
96 | * either an {@link EObject}, {@link Resource} or {@link ResourceSet}. | ||
97 | * @param notifier The {@link Notifier}. | ||
98 | * @return The EditingDomain. | ||
99 | */ | ||
100 | public static EditingDomain createEditingDomain(Notifier notifier) { | ||
101 | |||
102 | EditingDomain domain = getEditingDomain(notifier); | ||
103 | if (domain != null) { | ||
104 | return domain; | ||
105 | } | ||
106 | |||
107 | registerExtensionForXmiSerializer("dummyext"); | ||
108 | |||
109 | if (notifier instanceof EObject) { | ||
110 | EObject eObject = (EObject) notifier; | ||
111 | |||
112 | domain = new AdapterFactoryEditingDomain(null, new BasicCommandStack()); | ||
113 | Resource resource = domain.getResourceSet().createResource(URI.createFileURI("dummy.dummyext")); | ||
114 | domain.getCommandStack().execute(new AddCommand(domain, resource.getContents(), eObject)); | ||
115 | |||
116 | return domain; | ||
117 | |||
118 | } else if (notifier instanceof Resource) { | ||
119 | Resource resource = (Resource) notifier; | ||
120 | |||
121 | ResourceSet resourceSet = resource.getResourceSet(); | ||
122 | if (resourceSet != null) { | ||
123 | return new AdapterFactoryEditingDomain(null, new BasicCommandStack(), resourceSet); | ||
124 | } else { | ||
125 | domain = new AdapterFactoryEditingDomain(null, new BasicCommandStack(), (ResourceSet) null); | ||
126 | resourceSet = domain.getResourceSet(); | ||
127 | domain.getCommandStack().execute(new AddCommand(domain, resourceSet.getResources(), resource)); | ||
128 | return domain; | ||
129 | } | ||
130 | |||
131 | } else if (notifier instanceof ResourceSet) { | ||
132 | return new AdapterFactoryEditingDomain(null, new BasicCommandStack(), (ResourceSet) notifier); | ||
133 | } else { | ||
134 | throw new EmfHelperException("Not supported argument type."); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * Saves the EMF model (EObject or Resource) into the given file. An {@link XMIResourceFactoryImpl} will be | ||
140 | * registered if not already. | ||
141 | * | ||
142 | * Doesn't throw exception but logs an error if the save was unsuccessful. | ||
143 | * | ||
144 | * @param model Can be an {@link EObject} or a {@link Resource}. | ||
145 | * @param fileName | ||
146 | */ | ||
147 | public static void saveModel(Notifier model, String fileName) { | ||
148 | |||
149 | Objects.requireNonNull(model); | ||
150 | Preconditions.checkArgument(fileName != null && !fileName.isEmpty(), "File name is null or empty."); | ||
151 | |||
152 | int extensionIndex = fileName.lastIndexOf('.'); | ||
153 | |||
154 | Preconditions.checkState(extensionIndex > -1 && extensionIndex != fileName.length() - 1, "Bad file extension."); | ||
155 | |||
156 | String ext = fileName.substring(extensionIndex + 1); | ||
157 | |||
158 | registerExtensionForXmiSerializer(ext); | ||
159 | |||
160 | URI uri = URI.createFileURI(fileName); | ||
161 | Resource resource; | ||
162 | |||
163 | if (model instanceof ResourceSet) { | ||
164 | throw new EmfHelperException("Unsupported type: ResourceSet"); | ||
165 | } else if (model instanceof Resource) { | ||
166 | resource = (Resource) model; | ||
167 | } else if (model instanceof EObject) { | ||
168 | EObject root = (EObject) model; | ||
169 | ResourceSet resSet = new ResourceSetImpl(); | ||
170 | resource = resSet.createResource(uri); | ||
171 | resource.getContents().add(root); | ||
172 | } else { | ||
173 | throw new EmfHelperException("Unkown type: " + model.getClass()); | ||
174 | } | ||
175 | |||
176 | resource.setURI(uri); | ||
177 | saveResource(resource); | ||
178 | } | ||
179 | |||
180 | private static void saveResource(Resource resource) { | ||
181 | try { | ||
182 | resource.save(Collections.emptyMap()); | ||
183 | } catch (IOException e) { | ||
184 | logger.error(e); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Loads a model as a {@link Resource}. In headless mode, don't forget to call XYZPackage.eINSTANCE. | ||
190 | */ | ||
191 | public static Resource loadModel(String fileName) throws IOException { | ||
192 | Preconditions.checkArgument(fileName != null && !fileName.isEmpty(), "File name is null or empty."); | ||
193 | int extensionIndex = fileName.lastIndexOf('.'); | ||
194 | Preconditions.checkState(extensionIndex > -1 && extensionIndex != fileName.length() - 1, "Bad file extension."); | ||
195 | |||
196 | String ext = fileName.substring(extensionIndex + 1); | ||
197 | registerExtensionForXmiSerializer(ext); | ||
198 | |||
199 | ResourceSetImpl rSet = new ResourceSetImpl(); | ||
200 | URI fileUri = URI.createFileURI(fileName); | ||
201 | Resource resource = rSet.createResource(fileUri); | ||
202 | |||
203 | resource.load(null); | ||
204 | return resource; | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * Retrieves the root EObject from a Resource or ResourceSet. | ||
209 | * <ul> | ||
210 | * <li>Returns null if there is no content.</li> | ||
211 | * <li>Returns the notifier itself if it is an EObject.</li> | ||
212 | * <li>Logs a warn if there are multiple roots.</li> | ||
213 | * </ul> | ||
214 | * | ||
215 | * @param notifier | ||
216 | * @return The root EObject or null. | ||
217 | */ | ||
218 | public static EObject getRootEObject(Notifier notifier) { | ||
219 | if (notifier instanceof EObject) { | ||
220 | return (EObject) notifier; | ||
221 | } else if (notifier instanceof Resource) { | ||
222 | Resource resource = (Resource) notifier; | ||
223 | List<EObject> contents = resource.getContents(); | ||
224 | if (contents.size() > 1) { | ||
225 | logger.warn("Resource has more than one root."); | ||
226 | } | ||
227 | if (contents.isEmpty()) { | ||
228 | return null; | ||
229 | } else { | ||
230 | return contents.get(0); | ||
231 | } | ||
232 | } else if (notifier instanceof ResourceSet) { | ||
233 | ResourceSet resourceSet = (ResourceSet) notifier; | ||
234 | List<Resource> resources = resourceSet.getResources(); | ||
235 | if (resources.size() > 1) { | ||
236 | logger.warn("ResourceSet has more than one resources."); | ||
237 | } | ||
238 | if (resources.isEmpty()) { | ||
239 | return null; | ||
240 | } else { | ||
241 | return getRootEObject(resources.get(0)); | ||
242 | } | ||
243 | } else { | ||
244 | throw new EmfHelperException("Unkown type: " + notifier.getClass()); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * Registers an {@link XMIResourceFactoryImpl} for the given extension. | ||
250 | * @param ext The extension as a String. | ||
251 | */ | ||
252 | public static void registerExtensionForXmiSerializer(String ext) { | ||
253 | Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; | ||
254 | Map<String, Object> m = reg.getExtensionToFactoryMap(); | ||
255 | m.computeIfAbsent(ext, e -> new XMIResourceFactoryImpl()); | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * Clones the given model. Either an {@link EObject}, {@link Resource} or {@link ResourceSet}. | ||
260 | * @param notifier The root container of the model. | ||
261 | * @return The cloned model. | ||
262 | */ | ||
263 | public static Notifier clone(Notifier notifier) { | ||
264 | Copier copier = new Copier(); | ||
265 | Notifier clonedModel = clone(notifier, copier, null); | ||
266 | copier.copyReferences(); | ||
267 | return clonedModel; | ||
268 | } | ||
269 | |||
270 | private static Notifier clone(Notifier notifier, Copier copier, ResourceSet resourceSetToCloneTo) { | ||
271 | Objects.requireNonNull(copier); | ||
272 | |||
273 | if (notifier instanceof EObject) { | ||
274 | EObject eObject = (EObject) notifier; | ||
275 | return copier.copy(eObject); | ||
276 | } else if (notifier instanceof Resource) { | ||
277 | Resource resource = (Resource) notifier; | ||
278 | ResourceSet rSetTemp = resourceSetToCloneTo; | ||
279 | if (resourceSetToCloneTo == null) { | ||
280 | rSetTemp = new ResourceSetImpl(); | ||
281 | } | ||
282 | Resource clonedResource = rSetTemp.createResource(URI.createFileURI("dummy.dummyext")); | ||
283 | |||
284 | for (EObject eObject : resource.getContents()) { | ||
285 | EObject clonedEObject = copier.copy(eObject); | ||
286 | clonedResource.getContents().add(clonedEObject); | ||
287 | } | ||
288 | |||
289 | return clonedResource; | ||
290 | } else if (notifier instanceof ResourceSet) { | ||
291 | ResourceSet resourceSet = (ResourceSet) notifier; | ||
292 | ResourceSetImpl clonedResourceSet = new ResourceSetImpl(); | ||
293 | |||
294 | for (Resource resource : resourceSet.getResources()) { | ||
295 | clone(resource, copier, clonedResourceSet); | ||
296 | } | ||
297 | |||
298 | return clonedResourceSet; | ||
299 | } else { | ||
300 | throw new EmfHelperException("Not supported argument type."); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | public static class ENamedElementComparator implements Comparator<ENamedElement> { | ||
305 | @Override | ||
306 | public int compare(ENamedElement eClass1, ENamedElement eClass2) { | ||
307 | return eClass1.getName().compareTo(eClass2.getName()); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * This class is used to store | ||
313 | * <ul> | ||
314 | * <li>{@link EClass}es,</li> | ||
315 | * <li>{@link EAttribute}s,</li> | ||
316 | * <li>{@link EReference}s,</li> | ||
317 | * <li>EAttributes by EClasses,</li> | ||
318 | * <li>EReferences by EClasses</li> | ||
319 | * </ul> | ||
320 | * for a given set of {@link EPackage}s. | ||
321 | * | ||
322 | */ | ||
323 | public static class MetaModelElements { | ||
324 | public Set<EPackage> metaModelPackages; | ||
325 | public Set<EClass> classes; | ||
326 | public Set<EAttribute> attributes; | ||
327 | public Set<EReference> references; | ||
328 | public Map<EClass, Set<EAttribute>> attributesOfClass; | ||
329 | public Map<EClass, Set<EReference>> referencesOfClass; | ||
330 | } | ||
331 | |||
332 | /** | ||
333 | * Traverses the full metamodel on the given {@link EPackage}s and returns all the classes, attributes and | ||
334 | * references it contains. | ||
335 | * | ||
336 | * @param metaModelPackages | ||
337 | * The set of {@link EPackage}s. | ||
338 | * @return A {@link MetaModelElements} instance containing the metamodel elements. | ||
339 | */ | ||
340 | public static MetaModelElements getAllMetaModelElements(Set<EPackage> metaModelPackages) { | ||
341 | return getMetaModelElements(metaModelPackages, true, true, true); | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * Return a {@link MetaModelElements} instance populated with its {@link MetaModelElements#classes}. | ||
346 | * | ||
347 | * @param metaModelPackages | ||
348 | * The set of {@link EPackage}s. | ||
349 | * @return AA {@link MetaModelElements} instance. | ||
350 | */ | ||
351 | public static MetaModelElements getClasses(Set<EPackage> metaModelPackages) { | ||
352 | return getMetaModelElements(metaModelPackages, true, false, false); | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * Return a {@link MetaModelElements} instance populated with its {@link MetaModelElements#references} and | ||
357 | * {@link MetaModelElements#referencesOfClass}. | ||
358 | * | ||
359 | * @param metaModelPackages | ||
360 | * The set of {@link EPackage}s. | ||
361 | * @return AA {@link MetaModelElements} instance. | ||
362 | */ | ||
363 | public static MetaModelElements getReferences(Set<EPackage> metaModelPackages) { | ||
364 | return getMetaModelElements(metaModelPackages, false, true, false); | ||
365 | } | ||
366 | |||
367 | /** | ||
368 | * Return a {@link MetaModelElements} instance populated with its {@link MetaModelElements#attributes} and | ||
369 | * {@link MetaModelElements#attributesOfClass}. | ||
370 | * | ||
371 | * @param metaModelPackages | ||
372 | * The set of {@link EPackage}s. | ||
373 | * @return AA {@link MetaModelElements} instance. | ||
374 | */ | ||
375 | public static MetaModelElements getAttrbiutes(Set<EPackage> metaModelPackages) { | ||
376 | return getMetaModelElements(metaModelPackages, false, false, true); | ||
377 | } | ||
378 | |||
379 | private static MetaModelElements getMetaModelElements(Set<EPackage> metaModelPackages, boolean getClasses, | ||
380 | boolean getReferences, boolean getAttrbiutes) { | ||
381 | |||
382 | Comparator<ENamedElement> comparator = new ENamedElementComparator(); | ||
383 | |||
384 | MetaModelElements result = new MetaModelElements(); | ||
385 | result.metaModelPackages = metaModelPackages; | ||
386 | if (getClasses) { | ||
387 | result.classes = new TreeSet<EClass>(comparator); | ||
388 | } | ||
389 | if (getReferences) { | ||
390 | result.references = new HashSet<EReference>(); | ||
391 | result.referencesOfClass = new HashMap<EClass, Set<EReference>>(); | ||
392 | } | ||
393 | if (getAttrbiutes) { | ||
394 | result.attributes = new HashSet<EAttribute>(); | ||
395 | result.attributesOfClass = new HashMap<EClass, Set<EAttribute>>(); | ||
396 | } | ||
397 | for (EPackage ePackage : metaModelPackages) { | ||
398 | for (EClassifier eClassifier : ePackage.getEClassifiers()) { | ||
399 | if (eClassifier instanceof EClass) { | ||
400 | EClass eClass = ((EClass) eClassifier); | ||
401 | if (getClasses) { | ||
402 | result.classes.add(eClass); | ||
403 | } | ||
404 | if (getReferences) { | ||
405 | result.referencesOfClass.put(eClass, new TreeSet<EReference>(comparator)); | ||
406 | for (EReference eReference : eClass.getEAllReferences()) { | ||
407 | result.references.add(eReference); | ||
408 | result.referencesOfClass.get(eClass).add(eReference); | ||
409 | } | ||
410 | } | ||
411 | if (getAttrbiutes) { | ||
412 | result.attributesOfClass.put(eClass, new TreeSet<EAttribute>(comparator)); | ||
413 | for (EAttribute eAttribute : eClass.getEAllAttributes()) { | ||
414 | result.attributes.add(eAttribute); | ||
415 | result.attributesOfClass.get(eClass).add(eAttribute); | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | return result; | ||
422 | } | ||
423 | |||
424 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java new file mode 100644 index 00000000..0c5d7eba --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/Hasher.java | |||
@@ -0,0 +1,86 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.util; | ||
10 | |||
11 | import java.math.BigInteger; | ||
12 | import java.security.MessageDigest; | ||
13 | import java.security.NoSuchAlgorithmException; | ||
14 | |||
15 | import org.eclipse.viatra.dse.api.DSEException; | ||
16 | |||
17 | /** | ||
18 | * Utility class that encapsulates a {@link MessageDigest} instance to aid calculating hash values more easily, and to | ||
19 | * reuse a {@link MessageDigest} instance. | ||
20 | * | ||
21 | */ | ||
22 | public final class Hasher { | ||
23 | private MessageDigest md; | ||
24 | |||
25 | private static final int HEX = 16; | ||
26 | |||
27 | private Hasher(MessageDigest md) { | ||
28 | this.md = md; | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * Calculates and returns a hash value. | ||
33 | * | ||
34 | * @param data | ||
35 | * the data to be hashed in a {@link String}. | ||
36 | * @return the hash value in some {@link String} representation. | ||
37 | */ | ||
38 | public String hash(String data) { | ||
39 | md.update(data.getBytes(), 0, data.length()); | ||
40 | return new String(md.digest()); | ||
41 | } | ||
42 | |||
43 | @SuppressWarnings("unused") | ||
44 | private String alternateHashBest(String data) { | ||
45 | md.update(data.getBytes(), 0, data.length()); | ||
46 | return new String(md.digest()); | ||
47 | } | ||
48 | |||
49 | @SuppressWarnings("unused") | ||
50 | private String alternateHashSecondBest(String data) { | ||
51 | md.update(data.getBytes(), 0, data.length()); | ||
52 | return new BigInteger(1, md.digest()).toString(HEX); | ||
53 | } | ||
54 | |||
55 | @SuppressWarnings("unused") | ||
56 | private String alternateHashThirdBest(String data) { | ||
57 | md.update(data.getBytes(), 0, data.length()); | ||
58 | byte[] array = md.digest(); | ||
59 | StringBuilder sb = new StringBuilder(); | ||
60 | for (int i = 0; i < array.length; i++) { | ||
61 | sb.append(Integer.toHexString((int) array[i])); | ||
62 | } | ||
63 | return sb.toString(); | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * Returns a {@link Hasher} with an internal {@link MessageDigest} that is based on the protocol named | ||
68 | * {@code protocoll}. | ||
69 | * | ||
70 | * @param protocoll | ||
71 | * the name of the hash algorythm. | ||
72 | * @return the initialized {@link Hasher} | ||
73 | * | ||
74 | * @throws DSEException | ||
75 | * on initialization failure. | ||
76 | */ | ||
77 | public static Hasher getHasher(String protocoll) { | ||
78 | try { | ||
79 | return new Hasher(MessageDigest.getInstance(protocoll)); | ||
80 | } catch (NoSuchAlgorithmException e) { | ||
81 | throw new DSEException(e); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | public static final String SHA1_PROTOCOLL = "SHA-1"; | ||
86 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java new file mode 100644 index 00000000..49af05d1 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/util/ValueComparableEObjectStringMap.java | |||
@@ -0,0 +1,63 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.util; | ||
10 | |||
11 | import java.util.Comparator; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.Map; | ||
14 | import java.util.TreeMap; | ||
15 | |||
16 | import org.eclipse.emf.ecore.EObject; | ||
17 | |||
18 | import com.google.common.base.Functions; | ||
19 | import com.google.common.collect.Ordering; | ||
20 | |||
21 | /** | ||
22 | * | ||
23 | * This custom {@link TreeMap} implementation enables to store {@link EObject}-{@link String} pairs sorted by values | ||
24 | * (strings). It works as expected if the map is modified in any way, hence the map will still be sorted by values on | ||
25 | * the new set of entries. | ||
26 | * | ||
27 | * It is allowed to have two entries with the same EObject key (and also with same values). | ||
28 | * | ||
29 | * The short coming of the class is that EObjects are compared to each other by their | ||
30 | * {@link System#identityHashCode(Object)}, which may lead to unexpected errors. | ||
31 | * | ||
32 | * @author Andras Szabolcs Nagy | ||
33 | * | ||
34 | */ | ||
35 | public class ValueComparableEObjectStringMap extends TreeMap<EObject, String> { | ||
36 | |||
37 | private static final class EObjectComparator implements Comparator<EObject> { | ||
38 | @Override | ||
39 | public int compare(EObject o1, EObject o2) { | ||
40 | return Integer.valueOf(System.identityHashCode(o1)).compareTo(Integer.valueOf(System.identityHashCode(o2))); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | private final Map<EObject, String> innerMap; | ||
45 | |||
46 | public ValueComparableEObjectStringMap() { | ||
47 | this(new HashMap<EObject, String>()); | ||
48 | } | ||
49 | |||
50 | private ValueComparableEObjectStringMap(Map<EObject, String> innerMap) { | ||
51 | super(Ordering.natural().onResultOf(Functions.forMap(innerMap)).compound(new EObjectComparator())); | ||
52 | this.innerMap = innerMap; | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public String put(EObject keyEObject, String stringValue) { | ||
57 | if (innerMap.containsKey(keyEObject)) { | ||
58 | remove(keyEObject); | ||
59 | } | ||
60 | innerMap.put(keyEObject, stringValue); | ||
61 | return super.put(keyEObject, stringValue); | ||
62 | } | ||
63 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java new file mode 100644 index 00000000..bb8000d5 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/DesignSpaceVisualizerOptions.java | |||
@@ -0,0 +1,56 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.visualizer; | ||
10 | |||
11 | public class DesignSpaceVisualizerOptions { | ||
12 | |||
13 | public boolean showExplorationTrace = true; | ||
14 | public boolean showStateCodes = true; | ||
15 | public boolean showTransitionCodes = true; | ||
16 | |||
17 | public DesignSpaceVisualizerOptions withOutExploraionTrace() { | ||
18 | showExplorationTrace = false; | ||
19 | return this; | ||
20 | } | ||
21 | |||
22 | public DesignSpaceVisualizerOptions withOutstateCodes() { | ||
23 | showStateCodes = false; | ||
24 | return this; | ||
25 | } | ||
26 | |||
27 | public DesignSpaceVisualizerOptions withOutTransitionCodes() { | ||
28 | showTransitionCodes = false; | ||
29 | return this; | ||
30 | } | ||
31 | |||
32 | public boolean isShowExplorationTrace() { | ||
33 | return showExplorationTrace; | ||
34 | } | ||
35 | |||
36 | public void setShowExplorationTrace(boolean showExplorationTrace) { | ||
37 | this.showExplorationTrace = showExplorationTrace; | ||
38 | } | ||
39 | |||
40 | public boolean isShowStateCodes() { | ||
41 | return showStateCodes; | ||
42 | } | ||
43 | |||
44 | public void setShowStateCodes(boolean showStateCodes) { | ||
45 | this.showStateCodes = showStateCodes; | ||
46 | } | ||
47 | |||
48 | public boolean isShowTransitionCodes() { | ||
49 | return showTransitionCodes; | ||
50 | } | ||
51 | |||
52 | public void setShowTransitionCodes(boolean showTransitionCodes) { | ||
53 | this.showTransitionCodes = showTransitionCodes; | ||
54 | } | ||
55 | |||
56 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java new file mode 100644 index 00000000..da598b91 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IDesignSpaceVisualizer.java | |||
@@ -0,0 +1,39 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.visualizer; | ||
10 | |||
11 | import org.eclipse.viatra.dse.api.DesignSpaceExplorer; | ||
12 | import org.eclipse.viatra.dse.base.ThreadContext; | ||
13 | |||
14 | /** | ||
15 | * | ||
16 | * An implementation of this interface is notified about the traversal of the design space from every traversing thread, | ||
17 | * if registered to the {@link DesignSpaceExplorer}. Its purpose is to able to visualize the design space (a directed | ||
18 | * graph with IDs of the nodes and transitions) and to able to visualize the order of the exploration (the trace of a | ||
19 | * thread). | ||
20 | * | ||
21 | * @author Andras Szabolcs Nagy | ||
22 | * | ||
23 | */ | ||
24 | public interface IDesignSpaceVisualizer extends IExploreEventHandler { | ||
25 | |||
26 | /** | ||
27 | * Initializes the instance with a starting thread's context. Can be called multiple times and concurrently. | ||
28 | * | ||
29 | * @see DesignSpaceVisualizerOptions | ||
30 | * @param context | ||
31 | */ | ||
32 | void init(ThreadContext context); | ||
33 | |||
34 | /** | ||
35 | * Saves the captured data. | ||
36 | */ | ||
37 | void save(); | ||
38 | |||
39 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java new file mode 100644 index 00000000..9f902f31 --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/visualizer/IExploreEventHandler.java | |||
@@ -0,0 +1,40 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package org.eclipse.viatra.dse.visualizer; | ||
10 | |||
11 | import org.eclipse.viatra.dse.base.DesignSpaceManager; | ||
12 | |||
13 | /** | ||
14 | * An implementation of this interface is notified about every move in the design space (firing a rule activation or | ||
15 | * undoing it) of a single thread, if registered to the corresponding {@link DesignSpaceManager}. Its methods are called | ||
16 | * synchronously, therefore the implementation can have an impact on the performance. Also note, if the same instance is | ||
17 | * registered to multiple threads ({@link DesignSpaceManager}), it has to be thread safe. | ||
18 | * | ||
19 | * @author Andras Szabolcs Nagy | ||
20 | * | ||
21 | */ | ||
22 | public interface IExploreEventHandler { | ||
23 | |||
24 | /** | ||
25 | * Called by the {@link DesignSpaceManager}, after a rule activation (transition) is fired. Multiple calls with the | ||
26 | * same transition can occur. | ||
27 | * | ||
28 | * @param transition The fired transition. | ||
29 | */ | ||
30 | void transitionFired(Object transition); | ||
31 | |||
32 | /** | ||
33 | * Called by the {@link DesignSpaceManager}, after undoing the previously fired rule activation (transition). | ||
34 | * Multiple calls with the same transition can occur. | ||
35 | * | ||
36 | * @param transition The undone transition. | ||
37 | */ | ||
38 | void undo(Object transition); | ||
39 | |||
40 | } | ||