aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu
diff options
context:
space:
mode:
Diffstat (limited to 'Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu')
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/Modality.java31
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ModelGenerationMethodProvider.xtend97
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ModelGenerationStatistics.xtend52
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/MultiplicityGoalConstraintCalculator.xtend46
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/PropagationModality.java8
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/TypeInferenceMethod.xtend44
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/AbstractPolyhedronSaturationOperator.xtend53
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/CbcPolyhedronSolver.xtend241
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ExtendedLinearExpressionBuilderFactory.xtend140
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ExtendedPolyhedronScopePropagatorStrategy.xtend63
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/LinearTypeConstraintHint.xtend32
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/MultiplicityGoalConstraintCalculator.xtend57
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagator.xtend522
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagatorStrategy.xtend92
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronSolver.xtend186
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend156
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RemainingMultiplicityCalculator.xtend111
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagator.xtend161
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagatorStrategy.xtend71
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/TypeHierarchyScopePropagator.xtend85
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/Z3PolyhedronSolver.xtend272
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/CanonisedFormulae.xtend2
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/formulacanonization/FormulaCanoniser.xtend36
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/Interval.xtend584
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalAggregationMode.java99
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalAggregationOperator.xtend48
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalHullAggregatorOperator.xtend87
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/IntervalRedBlackNode.xtend177
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/RedBlackNode.java1392
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/Reference.java51
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/aggregators/IntervalAggregatorFactory.xtend50
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/interval/aggregators/intervalHull.xtend74
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeIndexer.xtend321
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/GenericTypeRefinementGenerator.xtend186
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PConstraintTransformer.xtend275
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PExpressionGenerator.xtend116
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternGenerator.xtend303
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternProvider.xtend172
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDeclarationIndexer.xtend158
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDefinitionIndexer.xtend184
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationRefinementGenerator.xtend174
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexer.xtend126
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexerWithPreliminaryTypeAnalysis.xtend144
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementGenerator.xtend83
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeRefinementWithPreliminaryTypeAnalysis.xtend6
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/UnfinishedIndexer.xtend172
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/UnitPropagationPreconditionGenerator.xtend302
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/GoalConstraintProvider.xtend89
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/RefinementRuleProvider.xtend825
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/util/ParseUtil.xtend29
50 files changed, 7497 insertions, 1288 deletions
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
3public enum Modality { 3public 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra
2
3import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel
4import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
5import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery
6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.RefinementRuleProvider
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
10import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace
11import java.util.Collection
12import java.util.List
13import java.util.Set
14import org.eclipse.viatra.query.runtime.api.IPatternMatch
15import org.eclipse.viatra.query.runtime.api.IQuerySpecification
16import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
17import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
18import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule
19import org.eclipse.xtend.lib.annotations.Data
20
21class 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}
48enum TypeInferenceMethod {
49 Generic, PreliminaryAnalysis
50}
51
52class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra
2
3class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra
2
3import org.eclipse.emf.common.notify.Notifier
4import org.eclipse.viatra.query.runtime.api.IQuerySpecification
5import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine
6import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
7import org.eclipse.viatra.query.runtime.emf.EMFScope
8
9class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra;
2
3public 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra
2
3import com.google.common.collect.ImmutableMap
4import com.google.common.collect.ImmutableSet
5import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel
6import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
7import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.CachingSimplePolyhedronScopePropagatorStrategy
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.CbcPolyhedronSolver
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator
12import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronScopePropagator
13import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraintCalculator
14import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator
15import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy
16import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.TypeHierarchyScopePropagator
17import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Z3PolyhedronSolver
18import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns
19import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries
20import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider
21import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.UnitPropagationPatternGenerator
22import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider
23import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.RefinementRuleProvider
24import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
25import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace
26import java.util.Collection
27import java.util.List
28import java.util.Map
29import java.util.Set
30import org.eclipse.viatra.query.runtime.api.GenericQueryGroup
31import org.eclipse.viatra.query.runtime.api.IPatternMatch
32import org.eclipse.viatra.query.runtime.api.IQuerySpecification
33import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine
34import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
35import org.eclipse.viatra.query.runtime.emf.EMFScope
36import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint
37import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
38import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule
39import org.eclipse.xtend.lib.annotations.Data
40
41enum 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.google.common.collect.ImmutableList
4import org.eclipse.xtend.lib.annotations.Accessors
5
6abstract 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.google.common.collect.ImmutableList
4import com.google.common.collect.ImmutableMap
5import hu.bme.mit.inf.dslreasoner.ilp.cbc.CbcResult
6import hu.bme.mit.inf.dslreasoner.ilp.cbc.CbcSolver
7import java.util.HashSet
8import java.util.List
9import java.util.Map
10import java.util.Set
11import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
12
13@FinalFieldsConstructor
14class 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
28class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.google.common.collect.ImmutableList
4import com.google.common.collect.ImmutableMap
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
6import java.util.ArrayList
7import java.util.HashMap
8import java.util.HashSet
9import java.util.List
10import java.util.Map
11import java.util.Set
12import org.eclipse.viatra.query.runtime.api.IPatternMatch
13import org.eclipse.xtend.lib.annotations.Accessors
14import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
15
16interface BoundSaturationListener {
17 def void boundsSaturated(Integer lower, Integer upper)
18}
19
20interface ExtendedLinearExpressionBuilderFactory {
21 def ExtendedLinearExpressionBuilder createBuilder()
22
23 def Dimension getDimension(IPatternMatch patternMatch)
24}
25
26interface 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
36class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics
5import java.util.Collection
6import java.util.Map
7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
8
9interface PolyhedronExtensionOperator {
10 def void extendPolyhedron(ExtendedLinearExpressionBuilderFactory factory)
11}
12
13class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternGenerator
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
6import java.util.Map
7import org.eclipse.viatra.query.runtime.api.IPatternMatch
8import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
9import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
10
11interface LinearTypeExpressionBuilderFactory {
12 def ViatraQueryMatcher<? extends IPatternMatch> createMatcher(String queryName)
13
14 def LinearTypeExpressionBuilder createBuilder()
15}
16
17interface LinearTypeExpressionBuilder {
18 def LinearTypeExpressionBuilder add(int scale, Type type)
19
20 def LinearBoundedExpression build()
21}
22
23@FunctionalInterface
24interface RelationConstraintUpdater {
25 def void update(PartialInterpretation p)
26}
27
28interface 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import org.eclipse.emf.common.notify.Notifier
4import org.eclipse.viatra.query.runtime.api.IQuerySpecification
5import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine
6import org.eclipse.viatra.query.runtime.emf.EMFScope
7
8class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.google.common.collect.ImmutableList
4import com.google.common.collect.ImmutableMap
5import com.google.common.collect.ImmutableSet
6import com.google.common.collect.Maps
7import com.google.common.collect.Sets
8import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
9import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.UnifinishedMultiplicityQueries
12import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
13import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
14import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation
15import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope
16import java.util.ArrayDeque
17import java.util.ArrayList
18import java.util.Collection
19import java.util.HashMap
20import java.util.HashSet
21import java.util.List
22import java.util.Map
23import java.util.Set
24import org.eclipse.viatra.query.runtime.api.IPatternMatch
25import org.eclipse.viatra.query.runtime.api.IQuerySpecification
26import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine
27import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
28import org.eclipse.viatra.query.runtime.emf.EMFScope
29import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
30
31class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.google.common.cache.Cache
4import com.google.common.cache.CacheBuilder
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics
8import java.util.Map
9import org.eclipse.xtend.lib.annotations.Accessors
10import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
11
12@FinalFieldsConstructor
13abstract 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
49class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import java.util.List
4import java.util.Map
5import org.eclipse.xtend.lib.annotations.Accessors
6import org.eclipse.xtend.lib.annotations.Data
7import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
8
9interface PolyhedronSolver {
10 def PolyhedronSaturationOperator createSaturationOperator(Polyhedron polyhedron)
11}
12
13enum PolyhedronSaturationResult {
14 SATURATED,
15 EMPTY,
16 UNKNOWN
17}
18
19interface PolyhedronSaturationOperator extends AutoCloseable {
20 def Polyhedron getPolyhedron()
21
22 def PolyhedronSaturationResult saturate()
23}
24
25@FinalFieldsConstructor
26@Accessors
27class 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
101abstract 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
119class 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
145abstract class LinearBoundedExpression extends Bounds {
146}
147
148@Accessors
149class 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
169class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.google.common.collect.ImmutableList
4import com.google.common.collect.ImmutableSet
5import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion
6import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion
7import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.UpperMultiplicityAssertion
8import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference
9import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
10import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
11import java.util.HashMap
12import java.util.List
13import org.eclipse.xtend.lib.annotations.Data
14
15@Data
16class RelationConstraints {
17 val List<RelationMultiplicityConstraint> multiplicityConstraints
18}
19
20@Data
21class 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
101class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
4import java.util.Iterator
5import org.eclipse.viatra.query.runtime.api.IPatternMatch
6import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
7import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
8
9@FinalFieldsConstructor
10abstract 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
29class 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
57package 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
73class 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
95class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation
8import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope
10import java.util.HashMap
11import java.util.HashSet
12import java.util.Map
13import java.util.Set
14import org.eclipse.xtend.lib.annotations.Accessors
15
16class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import org.eclipse.xtend.lib.annotations.Data
4import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
5
6enum PolyhedralScopePropagatorConstraints {
7 TypeHierarchy,
8 Relational
9}
10
11enum PolyhedralScopePropagatorSolver {
12 Z3Real,
13 Z3Integer,
14 Cbc,
15 Clp
16}
17
18abstract 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics
4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope
6
7class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.microsoft.z3.AlgebraicNum
4import com.microsoft.z3.ArithExpr
5import com.microsoft.z3.Context
6import com.microsoft.z3.Expr
7import com.microsoft.z3.IntNum
8import com.microsoft.z3.Optimize
9import com.microsoft.z3.RatNum
10import com.microsoft.z3.Status
11import com.microsoft.z3.Symbol
12import java.math.BigDecimal
13import java.math.MathContext
14import java.math.RoundingMode
15import java.util.Map
16import org.eclipse.xtend.lib.annotations.Accessors
17import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
18
19class 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
41class 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
59class 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
11class CanonisedFormulae { 11class 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
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.FunctionDefinition 5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.FunctionDefinition
6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition 6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition
7import java.util.List 7import java.util.List
8import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Term
9import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.SymbolicValue
10import 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 */
12class FormulaCanoniser { 19class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval
2
3import java.math.BigDecimal
4import java.math.MathContext
5import java.math.RoundingMode
6import org.eclipse.xtend.lib.annotations.Data
7
8abstract 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval;
2
3import java.util.function.BinaryOperator;
4
5public 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval
2
3import java.util.stream.Stream
4import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator
5import org.eclipse.xtend.lib.annotations.Accessors
6import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
7
8@FinalFieldsConstructor
9class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval
2
3import java.math.BigDecimal
4import java.math.MathContext
5import java.util.SortedMap
6import java.util.TreeMap
7import java.util.stream.Stream
8import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator
9
10abstract 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval
2
3abstract 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 */
24package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval;
25
26import java.lang.reflect.Array;
27import java.util.Collection;
28import java.util.Comparator;
29import java.util.HashSet;
30import java.util.Iterator;
31import 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 */
63public 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 */
24package 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 */
31class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.aggregators
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.Interval
4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.IntervalAggregationMode
5import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.IntervalAggregationOperator
6import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.AggregatorType
7import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.BoundAggregator
8import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IAggregatorFactory
9import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
10
11@AggregatorType(parameterTypes=#[Interval], returnTypes=#[Interval])
12abstract 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
28class intervalSum extends IntervalAggregatorFactory {
29 new() {
30 super(IntervalAggregationMode.SUM)
31 }
32}
33
34class intervalMin extends IntervalAggregatorFactory {
35 new() {
36 super(IntervalAggregationMode.MIN)
37 }
38}
39
40class intervalMax extends IntervalAggregatorFactory {
41 new() {
42 super(IntervalAggregationMode.MAX)
43 }
44}
45
46class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.aggregators
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.Interval
4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.IntervalHullAggregatorOperator
5import java.math.BigDecimal
6import java.math.BigInteger
7import java.math.MathContext
8import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.AggregatorType
9import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.BoundAggregator
10import 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])
14class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2 2
3import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type 3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
5import org.eclipse.emf.ecore.EClass 4import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality 5import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult 6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult
9 7
10class GenericTypeIndexer extends TypeIndexer { 8class 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
11import java.util.HashMap 11import java.util.HashMap
12 12
13class GenericTypeRefinementGenerator extends TypeRefinementGenerator { 13class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2
3import hu.bme.mit.inf.dslreasoner.viatra2logic.XExpressionExtractor
4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
5import org.eclipse.emf.ecore.EAttribute
6import org.eclipse.emf.ecore.EEnumLiteral
7import org.eclipse.emf.ecore.EReference
8import org.eclipse.viatra.query.runtime.emf.types.EClassTransitiveInstancesKey
9import org.eclipse.viatra.query.runtime.emf.types.EDataTypeInSlotsKey
10import org.eclipse.viatra.query.runtime.emf.types.EStructuralFeatureInstancesKey
11import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint
12import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable
13import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality
14import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter
15import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExpressionEvaluation
16import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality
17import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall
18import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint
19import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure
20import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.ConstantValue
21import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall
22import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint
23import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.VariableMapping
24import java.util.List
25import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeReference
26import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.PrimitiveTypeReference
27import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference
28import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference
29import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference
30import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference
31import java.util.Map
32
33class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2
3import java.util.Map
4import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable
5import org.eclipse.xtext.xbase.XBinaryOperation
6import org.eclipse.xtext.xbase.XExpression
7import org.eclipse.xtext.xbase.XFeatureCall
8import org.eclipse.xtext.xbase.XMemberFeatureCall
9import org.eclipse.xtext.xbase.XNumberLiteral
10import org.eclipse.xtext.xbase.XUnaryOperation
11import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.PrimitiveTypeReference
12import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference
13
14class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2 2
3import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion 3import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion
4import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference 4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference
6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference 5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference
7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference 6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference
@@ -17,31 +16,55 @@ import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.Transform
17import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality 16import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
18import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult 17import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult
19import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod 18import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod
19import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint
20import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraints
21import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy
20import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 22import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
23import java.util.Collection
21import java.util.HashMap 24import java.util.HashMap
22import java.util.Map 25import java.util.Map
23import org.eclipse.emf.ecore.EAttribute 26import org.eclipse.emf.ecore.EAttribute
24import org.eclipse.emf.ecore.EReference 27import org.eclipse.emf.ecore.EReference
28import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint
25import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery 29import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
26import org.eclipse.xtend.lib.annotations.Accessors 30import org.eclipse.xtend.lib.annotations.Accessors
31import org.eclipse.xtend.lib.annotations.Data
32import org.eclipse.xtend2.lib.StringConcatenationClient
27 33
28import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* 34import 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
42interface 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
30class PatternGenerator { 50class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2 2
3import com.google.common.collect.ImmutableSet
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation 4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration 5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type 7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
6import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem 8import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics 10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysis 11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysis
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult 12import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod 13import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod
14import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint
15import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraints
16import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationMultiplicityConstraint
17import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.util.ParseUtil 18import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.util.ParseUtil
12import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 19import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
13import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace 20import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace
21import java.util.Collection
22import java.util.HashMap
14import java.util.Map 23import java.util.Map
24import java.util.Set
15import org.eclipse.viatra.query.runtime.api.IPatternMatch 25import org.eclipse.viatra.query.runtime.api.IPatternMatch
16import org.eclipse.viatra.query.runtime.api.IQuerySpecification 26import org.eclipse.viatra.query.runtime.api.IQuerySpecification
17import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher 27import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
28import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint
18import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery 29import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
19import org.eclipse.xtend.lib.annotations.Data 30import org.eclipse.xtend.lib.annotations.Data
20 31
21import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* 32import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
22import java.util.Collection
23import 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
50class 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
57class 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
35class PatternProvider { 73class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2 2
3import com.google.common.collect.ImmutableMap
4import com.google.common.collect.ImmutableSet
3import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.UpperMultiplicityAssertion 5import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.UpperMultiplicityAssertion
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation 6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration 7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
6import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem 8import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality 9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
10import java.util.Collection
8import java.util.HashMap 11import java.util.HashMap
9import java.util.List 12import java.util.List
10import java.util.Map 13import java.util.Map
@@ -14,41 +17,40 @@ import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
14 17
15class RelationDeclarationIndexer { 18class 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
5import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery 5import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery
6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality 6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
7import java.util.Map 7import java.util.Map
8import org.eclipse.emf.ecore.EAttribute
9import org.eclipse.emf.ecore.EEnumLiteral
10import org.eclipse.emf.ecore.EReference
11import org.eclipse.viatra.query.runtime.emf.types.EClassTransitiveInstancesKey
12import org.eclipse.viatra.query.runtime.emf.types.EDataTypeInSlotsKey
13import org.eclipse.viatra.query.runtime.emf.types.EStructuralFeatureInstancesKey
14import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint
15import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable 8import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable
16import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality
17import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter
18import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality
19import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall
20import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure 9import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure
21import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.ConstantValue 10import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction
22import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall
23import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint
24import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery 11import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
25 12
26import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* 13import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
27import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint
28 14
29class RelationDefinitionIndexer { 15class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2 2
3import com.google.common.collect.ImmutableList
4import com.google.common.collect.ImmutableMap
5import com.google.common.collect.ImmutableSet
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation 6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration 7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
5import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem 8import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality 9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
10import java.util.Collection
7import java.util.LinkedList 11import java.util.LinkedList
8import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference 12import java.util.Map
13import java.util.Set
14import org.eclipse.xtend2.lib.StringConcatenationClient
9 15
10class RelationRefinementGenerator { 16class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2 2
3import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
5import org.eclipse.emf.ecore.EClass
6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult
9import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference
10import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference 3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference
11import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference 5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference
12import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference 6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference
13import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference 7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference
8import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
9import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult
12import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
14import java.math.BigDecimal 13import java.math.BigDecimal
14import org.eclipse.emf.ecore.EClass
15import org.eclipse.xtend.lib.annotations.Accessors
16import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
15 17
18@FinalFieldsConstructor
16abstract class TypeIndexer { 19abstract 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
4import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem 4import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
5import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality 5import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult 6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeRefinementPrecondition
8import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
9import org.eclipse.emf.ecore.EClass
10 7
11class TypeIndexerWithPreliminaryTypeAnalysis extends TypeIndexer{ 8class 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
26abstract class TypeRefinementGenerator { 26abstract 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
10import java.util.HashMap 10import java.util.HashMap
11 11
12class TypeRefinementWithPreliminaryTypeAnalysis extends TypeRefinementGenerator{ 12class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2 2
3import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion 3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
4import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem 4import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
5import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransformedViatraWellformednessConstraint 5import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationMultiplicityConstraint
7import java.util.LinkedHashMap
8import java.util.List
6import java.util.Map 9import java.util.Map
7import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery 10import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
11import org.eclipse.xtend.lib.annotations.Data
8 12
9import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* 13import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
10import java.util.LinkedHashMap 14
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality 15@Data
12import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference 16class UnifinishedMultiplicityQueryNames {
17 val String existingMultiplicityQueryName
18 val String existingInverseMultiplicityQueryName
19}
13 20
14class UnfinishedIndexer { 21class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition
5import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
6import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.PropagationModality
9import java.util.Map
10import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint
11import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable
12import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExpressionEvaluation
13import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
14
15import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
16import java.util.LinkedList
17import java.util.List
18import org.eclipse.xtend.lib.annotations.Data
19import java.util.HashMap
20import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall
21import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall
22import java.util.Comparator
23import java.util.ArrayList
24import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction
25import 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
34class 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
62class UnitPropagationPreconditionFinalResult {
63 CharSequence definitions
64 HashMap<PConstraint,String> constraint2MustPreconditionName
65 HashMap<PConstraint,String> constraint2CurrentPreconditionName
66}
67
68class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules
2 2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.MultiplicityGoalConstraintCalculator 3import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
6import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator
4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns 8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns
5import java.util.ArrayList 9import java.util.ArrayList
10import java.util.HashMap
11import java.util.LinkedList
12import java.util.List
13import java.util.Map
6 14
7class GoalConstraintProvider { 15class 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 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules
2 2
3import com.google.common.collect.ImmutableList
4import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.InverseRelationAssertion
5import hu.bme.mit.inf.dslreasoner.ecore2logic.ecore2logicannotations.LowerMultiplicityAssertion
6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference
7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement 8import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement
9import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.LogiclanguageFactory 10import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.LogiclanguageFactory
11import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.PrimitiveTypeReference
12import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation 13import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration 14import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
15import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference
7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type 16import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
17import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics 18import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator 19import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns 20import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ObjectCreationPrecondition 21import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ObjectCreationPrecondition
22import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialBooleanInterpretation
12import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation 23import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
24import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialIntegerInterpretation
13import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 25import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
26import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRealInterpretation
14import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation 27import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation
28import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialStringInterpretation
29import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation
15import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationFactory 30import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationFactory
31import java.lang.reflect.Field
32import java.util.HashMap
33import java.util.Iterator
16import java.util.LinkedHashMap 34import java.util.LinkedHashMap
35import java.util.LinkedList
36import java.util.List
37import java.util.Map
38import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine
17import org.eclipse.viatra.query.runtime.api.GenericPatternMatch 39import org.eclipse.viatra.query.runtime.api.GenericPatternMatch
40import org.eclipse.viatra.query.runtime.api.IPatternMatch
18import org.eclipse.viatra.query.runtime.api.IQuerySpecification 41import org.eclipse.viatra.query.runtime.api.IQuerySpecification
42import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine
19import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher 43import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
44import org.eclipse.viatra.query.runtime.emf.EMFScope
45import org.eclipse.viatra.query.runtime.rete.matcher.ReteBackendFactory
20import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule 46import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule
21import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRuleFactory 47import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRuleFactory
48import org.eclipse.xtend.lib.annotations.Data
49import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
50import org.eclipse.xtext.xbase.lib.Functions.Function0
22 51
23class RefinementRuleProvider { 52class 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
736class 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
198class FixedMetamodelProvider implements IMetamodelProvider { 198class 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) {