aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver
diff options
context:
space:
mode:
Diffstat (limited to 'Solvers/VIATRA-Solver')
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF7
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/build.properties3
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/plugin.xml28
-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.xtend151
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ScopePropagator.xtend156
-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.xtend216
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/MultiplicityGoalConstraintCalculator.xtend (renamed from Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/MultiplicityGoalConstraintCalculator.xtend)16
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagator.xtend516
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronSolver.xtend123
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/RelationConstraintCalculator.xtend134
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagator.xtend109
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagatorStrategy.xtend64
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/TypeHierarchyScopePropagator.xtend77
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/Z3PolyhedronSolver.xtend248
-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/PatternGenerator.xtend150
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/PatternProvider.xtend139
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationDefinitionIndexer.xtend2
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/RelationRefinementGenerator.xtend102
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/patterns/TypeIndexer.xtend122
-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.xtend225
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/GoalConstraintProvider.xtend2
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/RefinementRuleProvider.xtend42
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend188
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend22
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend421
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend68
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend137
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend4
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend275
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend75
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/META-INF/MANIFEST.MF3
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend252
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend54
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java79
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend184
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend66
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend25
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend24
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend78
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend74
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend52
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend120
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend27
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend12
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend22
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend137
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend45
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend35
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend62
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend164
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend10
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend52
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java60
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend48
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend85
71 files changed, 7176 insertions, 1802 deletions
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF
index 23e3ad13..f9090901 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF
@@ -4,6 +4,9 @@ Bundle-Name: Logic2viatra
4Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery;singleton:=true 4Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery;singleton:=true
5Bundle-Version: 1.0.0.qualifier 5Bundle-Version: 1.0.0.qualifier
6Export-Package: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra, 6Export-Package: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra,
7 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality,
8 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval,
9 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.aggregators,
7 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns, 10 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns,
8 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries 11 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries
9Require-Bundle: hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0", 12Require-Bundle: hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0",
@@ -20,7 +23,9 @@ Require-Bundle: hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0",
20 com.google.inject;bundle-version="3.0.0", 23 com.google.inject;bundle-version="3.0.0",
21 org.eclipse.xtext;bundle-version="2.10.0", 24 org.eclipse.xtext;bundle-version="2.10.0",
22 org.eclipse.viatra.transformation.runtime.emf;bundle-version="1.5.0", 25 org.eclipse.viatra.transformation.runtime.emf;bundle-version="1.5.0",
23 org.eclipse.xtext.xbase;bundle-version="2.10.0" 26 org.eclipse.xtext.xbase;bundle-version="2.10.0",
27 com.microsoft.z3;bundle-version="4.8.5",
28 hu.bme.mit.inf.dslreasoner.ilp.cbc;bundle-version="1.0.0"
24Bundle-RequiredExecutionEnvironment: JavaSE-1.8 29Bundle-RequiredExecutionEnvironment: JavaSE-1.8
25Import-Package: org.apache.log4j 30Import-Package: org.apache.log4j
26Automatic-Module-Name: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery 31Automatic-Module-Name: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/build.properties b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/build.properties
index 585df5ce..9ffc994a 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/build.properties
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/build.properties
@@ -4,6 +4,5 @@ bin.includes = META-INF/,\
4source.. = src/,\ 4source.. = src/,\
5 patterns/,\ 5 patterns/,\
6 vql-gen/,\ 6 vql-gen/,\
7 xtend-gen/,\ 7 xtend-gen/
8 src-gen/
9output.. = bin/ 8output.. = bin/
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/plugin.xml b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/plugin.xml
index 05e00983..6e4d96ca 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/plugin.xml
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/plugin.xml
@@ -1,14 +1,14 @@
1<?xml version="1.0" encoding="UTF-8"?><plugin> 1<?xml version="1.0" encoding="UTF-8"?><plugin>
2 <extension id="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis" point="org.eclipse.viatra.query.runtime.queryspecification"> 2 <extension id="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis" point="org.eclipse.viatra.query.runtime.queryspecification">
3 <group group="org.eclipse.viatra.query.runtime.extensibility.SingletonExtensionFactory:hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis" id="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis"> 3 <group group="org.eclipse.viatra.query.runtime.extensibility.SingletonExtensionFactory:hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis" id="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.TypeAnalysis">
4 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.hasDefinedSupertype"/> 4 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.hasDefinedSupertype"/>
5 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.dontHaveDefinedSupertype"/> 5 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.dontHaveDefinedSupertype"/>
6 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeConstructor"/> 6 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeConstructor"/>
7 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeRefinementTarget"/> 7 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeRefinementTarget"/>
8 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.incompatibleSuperType"/> 8 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.incompatibleSuperType"/>
9 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.incompatibleTopType"/> 9 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.incompatibleTopType"/>
10 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeRefinementNegativeConstraint"/> 10 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementTypeRefinementNegativeConstraint"/>
11 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementMayTypeNegativeConstraint"/> 11 <query-specification fqn="hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.queries.newElementMayTypeNegativeConstraint"/>
12 </group> 12 </group>
13 </extension> 13 </extension>
14</plugin> 14</plugin>
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/Modality.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/Modality.java
index d2132cea..f3a6ec32 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/Modality.java
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/Modality.java
@@ -2,21 +2,46 @@ package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra;
2 2
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
index f43ab96d..23632d4d 100644
--- 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
@@ -1,8 +1,19 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra
2 2
3import com.google.common.collect.ImmutableMap
3import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel 4import 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.logic.model.logicproblem.LogicProblem
5import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery 6import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.CbcPolyhedronSolver
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronScopePropagator
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraintCalculator
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator
12import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy
13import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.TypeHierarchyScopePropagator
14import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Z3PolyhedronSolver
15import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns
16import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries
6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider 17import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider 18import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.RefinementRuleProvider 19import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.RefinementRuleProvider
@@ -10,6 +21,7 @@ import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.par
10import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace 21import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace
11import java.util.Collection 22import java.util.Collection
12import java.util.List 23import java.util.List
24import java.util.Map
13import java.util.Set 25import java.util.Set
14import org.eclipse.viatra.query.runtime.api.IPatternMatch 26import org.eclipse.viatra.query.runtime.api.IPatternMatch
15import org.eclipse.viatra.query.runtime.api.IQuerySpecification 27import org.eclipse.viatra.query.runtime.api.IQuerySpecification
@@ -20,63 +32,99 @@ import org.eclipse.xtend.lib.annotations.Data
20 32
21class ModelGenerationStatistics { 33class ModelGenerationStatistics {
22 public var long transformationExecutionTime = 0 34 public var long transformationExecutionTime = 0
35
23 synchronized def addExecutionTime(long amount) { 36 synchronized def addExecutionTime(long amount) {
24 transformationExecutionTime+=amount 37 transformationExecutionTime += amount
38 }
39
40 public var long scopePropagationTime = 0
41
42 synchronized def addScopePropagationTime(long amount) {
43 scopePropagationTime += amount
44 }
45
46 public var long preliminaryTypeAnalisisTime = 0
47
48 public var int decisionsTried = 0
49
50 synchronized def incrementDecisionCount() {
51 decisionsTried++
52 }
53
54 public var int scopePropagatorInvocations
55
56 synchronized def incrementScopePropagationCount() {
57 scopePropagatorInvocations++
25 } 58 }
26 public var long PreliminaryTypeAnalisisTime = 0
27} 59}
60
28@Data class ModelGenerationMethod { 61@Data class ModelGenerationMethod {
29 ModelGenerationStatistics statistics 62 ModelGenerationStatistics statistics
30 63
31 Collection<? extends BatchTransformationRule<?,?>> objectRefinementRules 64 Collection<? extends BatchTransformationRule<?, ?>> objectRefinementRules
32 Collection<? extends BatchTransformationRule<?,?>> relationRefinementRules 65 Collection<? extends BatchTransformationRule<?, ?>> relationRefinementRules
33 66
34 List<MultiplicityGoalConstraintCalculator> unfinishedMultiplicities 67 List<MultiplicityGoalConstraintCalculator> unfinishedMultiplicities
35 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF 68
36 69 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF
37 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWF 70
38 71 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWF
39 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allPatterns 72
73 Map<String, ModalPatternQueries> modalRelationQueries
74
75 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allPatterns
40} 76}
77
41enum TypeInferenceMethod { 78enum TypeInferenceMethod {
42 Generic, PreliminaryAnalysis 79 Generic,
80 PreliminaryAnalysis
43} 81}
44 82
45class ModelGenerationMethodProvider { 83class ModelGenerationMethodProvider {
46 private val PatternProvider patternProvider = new PatternProvider 84 val PatternProvider patternProvider = new PatternProvider
47 private val RefinementRuleProvider refinementRuleProvider = new RefinementRuleProvider 85 val RefinementRuleProvider refinementRuleProvider = new RefinementRuleProvider
48 private val GoalConstraintProvider goalConstraintProvider = new GoalConstraintProvider 86 val GoalConstraintProvider goalConstraintProvider = new GoalConstraintProvider
49 87 val relationConstraintCalculator = new RelationConstraintCalculator
50 public def ModelGenerationMethod createModelGenerationMethod( 88
89 def ModelGenerationMethod createModelGenerationMethod(
51 LogicProblem logicProblem, 90 LogicProblem logicProblem,
52 PartialInterpretation emptySolution, 91 PartialInterpretation emptySolution,
53 ReasonerWorkspace workspace, 92 ReasonerWorkspace workspace,
54 boolean nameNewElements, 93 boolean nameNewElements,
55 TypeInferenceMethod typeInferenceMethod, 94 TypeInferenceMethod typeInferenceMethod,
56 ScopePropagator scopePropagator, 95 ScopePropagatorStrategy scopePropagatorStrategy,
57 DocumentationLevel debugLevel 96 DocumentationLevel debugLevel
58 ) { 97 ) {
59 val statistics = new ModelGenerationStatistics 98 val statistics = new ModelGenerationStatistics
60 val writeFiles = (debugLevel === DocumentationLevel.NORMAL || debugLevel === DocumentationLevel.FULL) 99 val writeFiles = (debugLevel === DocumentationLevel.NORMAL || debugLevel === DocumentationLevel.FULL)
61 100
62 val Set<PQuery> existingQueries = logicProblem 101 val Set<PQuery> existingQueries = logicProblem.relations.map[annotations].flatten.filter(TransfomedViatraQuery).
63 .relations 102 map[it.patternPQuery as PQuery].toSet
64 .map[annotations] 103
65 .flatten 104 val relationConstraints = relationConstraintCalculator.calculateRelationConstraints(logicProblem)
66 .filter(TransfomedViatraQuery) 105 val queries = patternProvider.generateQueries(logicProblem, emptySolution, statistics, existingQueries,
67 .map[it.patternPQuery as PQuery] 106 workspace, typeInferenceMethod, scopePropagatorStrategy, relationConstraints, writeFiles)
68 .toSet 107 val scopePropagator = createScopePropagator(scopePropagatorStrategy, emptySolution, queries, statistics)
69 108 scopePropagator.propagateAllScopeConstraints
70 val queries = patternProvider.generateQueries(logicProblem,emptySolution,statistics,existingQueries,workspace,typeInferenceMethod,writeFiles) 109 val objectRefinementRules = refinementRuleProvider.createObjectRefinementRules(queries, scopePropagator,
71 val //LinkedHashMap<Pair<Relation, ? extends Type>, BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>>> 110 nameNewElements, statistics)
72 objectRefinementRules = refinementRuleProvider.createObjectRefinementRules(queries,scopePropagator,nameNewElements,statistics) 111 val relationRefinementRules = refinementRuleProvider.createRelationRefinementRules(queries, scopePropagator,
73 val relationRefinementRules = refinementRuleProvider.createRelationRefinementRules(queries,statistics) 112 statistics)
74 113
75 val unfinishedMultiplicities = goalConstraintProvider.getUnfinishedMultiplicityQueries(queries) 114 val unfinishedMultiplicities = goalConstraintProvider.getUnfinishedMultiplicityQueries(queries)
76 val unfinishedWF = queries.getUnfinishedWFQueries.values 115 val unfinishedWF = queries.getUnfinishedWFQueries.values
77 116
117 val modalRelationQueriesBuilder = ImmutableMap.builder
118 for (entry : queries.modalRelationQueries.entrySet) {
119 val annotation = entry.key.annotations.filter(TransfomedViatraQuery).head
120 if (annotation !== null) {
121 modalRelationQueriesBuilder.put(annotation.patternFullyQualifiedName, entry.value)
122 }
123 }
124 val modalRelationQueries = modalRelationQueriesBuilder.build
125
78 val invalidWF = queries.getInvalidWFQueries.values 126 val invalidWF = queries.getInvalidWFQueries.values
79 127
80 return new ModelGenerationMethod( 128 return new ModelGenerationMethod(
81 statistics, 129 statistics,
82 objectRefinementRules.values, 130 objectRefinementRules.values,
@@ -84,7 +132,38 @@ class ModelGenerationMethodProvider {
84 unfinishedMultiplicities, 132 unfinishedMultiplicities,
85 unfinishedWF, 133 unfinishedWF,
86 invalidWF, 134 invalidWF,
135 modalRelationQueries,
87 queries.allQueries 136 queries.allQueries
88 ) 137 )
89 } 138 }
139
140 private def createScopePropagator(ScopePropagatorStrategy scopePropagatorStrategy,
141 PartialInterpretation emptySolution, GeneratedPatterns queries, ModelGenerationStatistics statistics) {
142 switch (scopePropagatorStrategy) {
143 case ScopePropagatorStrategy.Count:
144 new ScopePropagator(emptySolution, statistics)
145 case ScopePropagatorStrategy.BasicTypeHierarchy:
146 new TypeHierarchyScopePropagator(emptySolution, statistics)
147 ScopePropagatorStrategy.Polyhedral: {
148 val types = queries.refineObjectQueries.keySet.map[newType].toSet
149 val solver = switch (scopePropagatorStrategy.solver) {
150 case Z3Integer:
151 new Z3PolyhedronSolver(false, scopePropagatorStrategy.timeoutSeconds)
152 case Z3Real:
153 new Z3PolyhedronSolver(true, scopePropagatorStrategy.timeoutSeconds)
154 case Cbc:
155 new CbcPolyhedronSolver(false, scopePropagatorStrategy.timeoutSeconds, true)
156 case Clp:
157 new CbcPolyhedronSolver(true, scopePropagatorStrategy.timeoutSeconds, true)
158 default:
159 throw new IllegalArgumentException("Unknown polyhedron solver: " +
160 scopePropagatorStrategy.solver)
161 }
162 new PolyhedronScopePropagator(emptySolution, statistics, types, queries.multiplicityConstraintQueries,
163 queries.hasElementInContainmentQuery, solver, scopePropagatorStrategy.requiresUpperBoundIndexing)
164 }
165 default:
166 throw new IllegalArgumentException("Unknown scope propagator strategy: " + scopePropagatorStrategy)
167 }
168 }
90} 169}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ScopePropagator.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ScopePropagator.xtend
deleted file mode 100644
index 38633c07..00000000
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ScopePropagator.xtend
+++ /dev/null
@@ -1,156 +0,0 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope
6import java.util.HashMap
7import java.util.Map
8import java.util.Set
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
10import java.util.HashSet
11
12class ScopePropagator {
13 PartialInterpretation partialInterpretation
14 Map<PartialTypeInterpratation,Scope> type2Scope
15
16 val Map<Scope, Set<Scope>> superScopes
17 val Map<Scope, Set<Scope>> subScopes
18
19 public new(PartialInterpretation p) {
20 partialInterpretation = p
21 type2Scope = new HashMap
22 for(scope : p.scopes) {
23 type2Scope.put(scope.targetTypeInterpretation,scope)
24 }
25
26 superScopes = new HashMap
27 subScopes = new HashMap
28 for(scope : p.scopes) {
29 superScopes.put(scope,new HashSet)
30 subScopes.put(scope,new HashSet)
31 }
32
33 for(scope : p.scopes) {
34 val target = scope.targetTypeInterpretation
35 if(target instanceof PartialComplexTypeInterpretation) {
36 val supertypeInterpretations = target.supertypeInterpretation
37 for(supertypeInterpretation : supertypeInterpretations) {
38 val supertypeScope = type2Scope.get(supertypeInterpretation)
39 superScopes.get(scope).add(supertypeScope)
40 subScopes.get(supertypeScope).add(scope)
41 }
42 }
43 }
44 }
45
46 def public propagateAllScopeConstraints() {
47 var boolean hadChanged
48 do{
49 hadChanged = false
50 for(superScopeEntry : superScopes.entrySet) {
51 val sub = superScopeEntry.key
52 hadChanged = propagateLowerLimitUp(sub,partialInterpretation) || hadChanged
53 hadChanged = propagateUpperLimitDown(sub,partialInterpretation) || hadChanged
54 for(sup: superScopeEntry.value) {
55 hadChanged = propagateLowerLimitUp(sub,sup) || hadChanged
56 hadChanged = propagateUpperLimitDown(sub,sup) || hadChanged
57 }
58 }
59 } while(hadChanged)
60// println('''All constraints are propagated.''')
61 }
62
63 def public propagateAdditionToType(PartialTypeInterpratation t) {
64// println('''Adding to «(t as PartialComplexTypeInterpretation).interpretationOf.name»''')
65 val targetScope = type2Scope.get(t)
66 targetScope.removeOne
67 val sups = superScopes.get(targetScope)
68 sups.forEach[removeOne]
69 if(this.partialInterpretation.minNewElements > 0) {
70 this.partialInterpretation.minNewElements = this.partialInterpretation.minNewElements-1
71 }
72 if(this.partialInterpretation.maxNewElements > 0) {
73 this.partialInterpretation.maxNewElements = this.partialInterpretation.maxNewElements-1
74 } else if(this.partialInterpretation.maxNewElements === 0) {
75 throw new IllegalArgumentException('''Inconsistent object creation: lower node limit is 0!''')
76 }
77
78// subScopes.get(targetScope).forEach[propagateUpperLimitDown(it,targetScope)]
79// for(sup: sups) {
80// subScopes.get(sup).forEach[propagateUpperLimitDown(it,sup)]
81// }
82// for(scope : type2Scope.values) {
83// propagateUpperLimitDown(scope,partialInterpretation)
84// }
85
86 propagateAllScopeConstraints
87
88// println('''Target Scope: «targetScope.minNewElements» - «targetScope.maxNewElements»''')
89// println(''' «this.partialInterpretation.minNewElements» - «this.partialInterpretation.maxNewElements»''')
90// this.partialInterpretation.scopes.forEach[println(''' «(it.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name»: «it.minNewElements»-«it.maxNewElements»''')]
91// println('''All constraints are propagated upon increasing «(t as PartialComplexTypeInterpretation).interpretationOf.name»''')
92 }
93
94 private def propagateLowerLimitUp(Scope subScope, Scope superScope) {
95 if(subScope.minNewElements>superScope.minNewElements) {
96// println('''
97// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> «(superScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name»
98// superScope.minNewElements «superScope.minNewElements» = subScope.minNewElements «subScope.minNewElements»
99// ''')
100 superScope.minNewElements = subScope.minNewElements
101 return true
102 } else {
103 return false
104 }
105 }
106
107 private def propagateUpperLimitDown(Scope subScope, Scope superScope) {
108 if(superScope.maxNewElements>=0 && (superScope.maxNewElements<subScope.maxNewElements || subScope.maxNewElements<0)) {
109// println('''
110// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> «(superScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name»
111// subScope.maxNewElements «subScope.maxNewElements» = superScope.maxNewElements «superScope.maxNewElements»
112// ''')
113 subScope.maxNewElements = superScope.maxNewElements
114 return true
115 } else {
116 return false
117 }
118 }
119
120 private def propagateLowerLimitUp(Scope subScope, PartialInterpretation p) {
121 if(subScope.minNewElements>p.minNewElements) {
122// println('''
123// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes
124// p.minNewElements «p.minNewElements» = subScope.minNewElements «subScope.minNewElements»
125// ''')
126 p.minNewElements = subScope.minNewElements
127 return true
128 } else {
129 return false
130 }
131 }
132
133 private def propagateUpperLimitDown(Scope subScope, PartialInterpretation p) {
134 if(p.maxNewElements>=0 && (p.maxNewElements<subScope.maxNewElements || subScope.maxNewElements<0)) {
135// println('''
136// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes
137// subScope.maxNewElements «subScope.maxNewElements» = p.maxNewElements «p.maxNewElements»
138// ''')
139 subScope.maxNewElements = p.maxNewElements
140 return true
141 } else {
142 return false
143 }
144 }
145 private def removeOne(Scope scope) {
146 if(scope.maxNewElements===0) {
147 throw new IllegalArgumentException('''Inconsistent object creation: «scope.targetTypeInterpretation»''')
148 } else if(scope.maxNewElements>0) {
149 scope.maxNewElements= scope.maxNewElements-1
150 }
151 if(scope.minNewElements>0) {
152 scope.minNewElements= scope.minNewElements-1
153 }
154 }
155}
156 \ 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..4bd46fbf
--- /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,216 @@
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 val boolean lpRelaxation
30 val double timeoutSeconds
31 val boolean silent
32 val double[] columnLowerBounds
33 val double[] columnUpperBounds
34 val double[] objective
35 val Map<Dimension, Integer> dimensionsToIndicesMap
36
37 new(Polyhedron polyhedron, boolean lpRelaxation, double timeoutSeconds, boolean silent) {
38 super(polyhedron)
39 this.lpRelaxation = lpRelaxation
40 this.timeoutSeconds = timeoutSeconds
41 this.silent = silent
42 val numDimensions = polyhedron.dimensions.size
43 columnLowerBounds = newDoubleArrayOfSize(numDimensions)
44 columnUpperBounds = newDoubleArrayOfSize(numDimensions)
45 objective = newDoubleArrayOfSize(numDimensions)
46 dimensionsToIndicesMap = ImmutableMap.copyOf(polyhedron.dimensions.indexed.toMap([value], [key]))
47 }
48
49 override doSaturate() {
50 val numDimensions = polyhedron.dimensions.size
51 for (var int j = 0; j < numDimensions; j++) {
52 val dimension = polyhedron.dimensions.get(j)
53 columnLowerBounds.set(j, dimension.lowerBound.toDouble(Double.NEGATIVE_INFINITY))
54 columnUpperBounds.set(j, dimension.upperBound.toDouble(Double.POSITIVE_INFINITY))
55 }
56 val constraints = nonTrivialConstraints
57 val numConstraints = constraints.size
58 val rowStarts = newIntArrayOfSize(numConstraints + 1)
59 val rowLowerBounds = newDoubleArrayOfSize(numConstraints)
60 val rowUpperBounds = newDoubleArrayOfSize(numConstraints)
61 val numEntries = constraints.map[coefficients.size].reduce[a, b|a + b] ?: 0
62 rowStarts.set(numConstraints, numEntries)
63 val columnIndices = newIntArrayOfSize(numEntries)
64 val entries = newDoubleArrayOfSize(numEntries)
65 val unconstrainedDimensions = new HashSet
66 for (dimension : polyhedron.dimensions) {
67 if (dimension.lowerBound === null && dimension.upperBound === null) {
68 unconstrainedDimensions += dimension
69 }
70 }
71 var int index = 0
72 for (var int i = 0; i < numConstraints; i++) {
73 rowStarts.set(i, index)
74 val constraint = constraints.get(i)
75 rowLowerBounds.set(i, constraint.lowerBound.toDouble(Double.NEGATIVE_INFINITY))
76 rowUpperBounds.set(i, constraint.upperBound.toDouble(Double.POSITIVE_INFINITY))
77 if (!dimensionsToIndicesMap.keySet.containsAll(constraint.coefficients.keySet)) {
78 throw new IllegalArgumentException("Constrains has unknown dimensions")
79 }
80 for (var int j = 0; j < numDimensions; j++) {
81 val dimension = polyhedron.dimensions.get(j)
82 val coefficient = constraint.coefficients.get(dimension)
83 if (coefficient !== null && coefficient != 0) {
84 unconstrainedDimensions -= dimension
85 columnIndices.set(index, j)
86 entries.set(index, coefficient)
87 index++
88 }
89 }
90 }
91 if (index != numEntries) {
92 throw new AssertionError("Last entry does not equal the number of entries in the constraint matrix")
93 }
94 for (expressionToSaturate : polyhedron.expressionsToSaturate) {
95 val result = saturate(expressionToSaturate, rowStarts, columnIndices, entries, rowLowerBounds,
96 rowUpperBounds, unconstrainedDimensions, constraints)
97 if (result != PolyhedronSaturationResult.SATURATED) {
98 return result
99 }
100 }
101 PolyhedronSaturationResult.SATURATED
102 }
103
104 protected def saturate(LinearBoundedExpression expressionToSaturate, int[] rowStarts, int[] columnIndices,
105 double[] entries, double[] rowLowerBounds, double[] rowUpperBounds, Set<Dimension> unconstrainedDimensions,
106 ImmutableList<LinearConstraint> constraints) {
107 val numDimensions = objective.size
108 for (var int j = 0; j < numDimensions; j++) {
109 objective.set(j, 0)
110 }
111 switch (expressionToSaturate) {
112 Dimension: {
113 // CBC will return nonsensical results or call free() with invalid arguments if
114 // it is passed a fully unconstrained (-Inf lower and +Int upper bound, no inequalities) variable
115 // in the objective function.
116 if (unconstrainedDimensions.contains(expressionToSaturate)) {
117 return PolyhedronSaturationResult.SATURATED
118 }
119 val j = getIndex(expressionToSaturate)
120 objective.set(j, 1)
121 }
122 LinearConstraint: {
123 for (pair : expressionToSaturate.coefficients.entrySet) {
124 val dimension = pair.key
125 // We also have to check for unconstrained dimensions here to avoid crashing.
126 if (unconstrainedDimensions.contains(dimension)) {
127 expressionToSaturate.lowerBound = null
128 expressionToSaturate.upperBound = null
129 return PolyhedronSaturationResult.SATURATED
130 }
131 val j = getIndex(dimension)
132 objective.set(j, pair.value)
133 }
134 }
135 default:
136 throw new IllegalArgumentException("Unknown expression: " + expressionToSaturate)
137 }
138 val minimizationResult = CbcSolver.solve(columnLowerBounds, columnUpperBounds, rowStarts, columnIndices,
139 entries, rowLowerBounds, rowUpperBounds, objective, lpRelaxation, timeoutSeconds, silent)
140 switch (minimizationResult) {
141 CbcResult.SolutionBounded: {
142 val value = Math.floor(minimizationResult.value)
143 expressionToSaturate.lowerBound = value as int
144 setBound(expressionToSaturate, constraints, value, columnLowerBounds, rowLowerBounds)
145 }
146 case CbcResult.SOLUTION_UNBOUNDED: {
147 expressionToSaturate.lowerBound = null
148 setBound(expressionToSaturate, constraints, Double.NEGATIVE_INFINITY, columnLowerBounds, rowLowerBounds)
149 }
150 case CbcResult.UNSAT:
151 return PolyhedronSaturationResult.EMPTY
152 case CbcResult.ABANDONED,
153 case CbcResult.TIMEOUT:
154 return PolyhedronSaturationResult.UNKNOWN
155 default:
156 throw new RuntimeException("Unknown CbcResult: " + minimizationResult)
157 }
158 for (var int j = 0; j < numDimensions; j++) {
159 val objectiveCoefficient = objective.get(j)
160 objective.set(j, -objectiveCoefficient)
161 }
162 val maximizationResult = CbcSolver.solve(columnLowerBounds, columnUpperBounds, rowStarts, columnIndices,
163 entries, rowLowerBounds, rowUpperBounds, objective, lpRelaxation, timeoutSeconds, silent)
164 switch (maximizationResult) {
165 CbcResult.SolutionBounded: {
166 val value = Math.ceil(-maximizationResult.value)
167 expressionToSaturate.upperBound = value as int
168 setBound(expressionToSaturate, constraints, value, columnUpperBounds, rowUpperBounds)
169 }
170 case CbcResult.SOLUTION_UNBOUNDED: {
171 expressionToSaturate.upperBound = null
172 setBound(expressionToSaturate, constraints, Double.POSITIVE_INFINITY, columnUpperBounds, rowUpperBounds)
173 }
174 case CbcResult.UNSAT:
175 throw new RuntimeException("Minimization was SAT, but maximization is UNSAT")
176 case CbcResult.ABANDONED,
177 case CbcResult.TIMEOUT:
178 return PolyhedronSaturationResult.UNKNOWN
179 default:
180 throw new RuntimeException("Unknown CbcResult: " + maximizationResult)
181 }
182 return PolyhedronSaturationResult.SATURATED
183 }
184
185 private def toDouble(Integer nullableInt, double defaultValue) {
186 if (nullableInt === null) {
187 defaultValue
188 } else {
189 nullableInt.doubleValue
190 }
191 }
192
193 private def int getIndex(Dimension dimension) {
194 val index = dimensionsToIndicesMap.get(dimension)
195 if (index === null) {
196 throw new IllegalArgumentException("Unknown dimension: " + dimension)
197 }
198 index
199 }
200
201 private def void setBound(LinearBoundedExpression expression, List<LinearConstraint> constraints, double bound,
202 double[] columnBounds, double[] rowBounds) {
203 switch (expression) {
204 Dimension: {
205 val j = getIndex(expression)
206 columnBounds.set(j, bound)
207 }
208 LinearConstraint: {
209 val i = constraints.indexOf(expression)
210 if (i >= 0) {
211 rowBounds.set(i, bound)
212 }
213 }
214 }
215 }
216}
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/cardinality/MultiplicityGoalConstraintCalculator.xtend
index e05160d0..86a59aa1 100644
--- 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/cardinality/MultiplicityGoalConstraintCalculator.xtend
@@ -1,4 +1,4 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2 2
3import org.eclipse.emf.common.notify.Notifier 3import org.eclipse.emf.common.notify.Notifier
4import org.eclipse.viatra.query.runtime.api.IQuerySpecification 4import org.eclipse.viatra.query.runtime.api.IQuerySpecification
@@ -11,36 +11,36 @@ class MultiplicityGoalConstraintCalculator {
11 val IQuerySpecification<?> querySpecification; 11 val IQuerySpecification<?> querySpecification;
12 var ViatraQueryMatcher<?> matcher; 12 var ViatraQueryMatcher<?> matcher;
13 13
14 public new(String targetRelationName, IQuerySpecification<?> querySpecification) { 14 new(String targetRelationName, IQuerySpecification<?> querySpecification) {
15 this.targetRelationName = targetRelationName 15 this.targetRelationName = targetRelationName
16 this.querySpecification = querySpecification 16 this.querySpecification = querySpecification
17 this.matcher = null 17 this.matcher = null
18 } 18 }
19 19
20 public new(MultiplicityGoalConstraintCalculator other) { 20 new(MultiplicityGoalConstraintCalculator other) {
21 this.targetRelationName = other.targetRelationName 21 this.targetRelationName = other.targetRelationName
22 this.querySpecification = other.querySpecification 22 this.querySpecification = other.querySpecification
23 this.matcher = null 23 this.matcher = null
24 } 24 }
25 25
26 def public getName() { 26 def getName() {
27 targetRelationName 27 targetRelationName
28 } 28 }
29 29
30 def public init(Notifier notifier) { 30 def init(Notifier notifier) {
31 val engine = ViatraQueryEngine.on(new EMFScope(notifier)) 31 val engine = ViatraQueryEngine.on(new EMFScope(notifier))
32 matcher = querySpecification.getMatcher(engine) 32 matcher = querySpecification.getMatcher(engine)
33 } 33 }
34 34
35 def public calculateValue() { 35 def calculateValue() {
36 var res = 0 36 var res = 0
37 val allMatches = this.matcher.allMatches 37 val allMatches = this.matcher.allMatches
38 for(match : allMatches) { 38 for(match : allMatches) {
39 //println(targetRelationName+ " missing multiplicity: "+match.get(3)) 39 //println(targetRelationName+ " missing multiplicity: "+match.get(3))
40 val missingMultiplicity = match.get(4) as Integer 40 val missingMultiplicity = match.get(2) as Integer
41 res += missingMultiplicity 41 res += missingMultiplicity
42 } 42 }
43 //println(targetRelationName+ " all missing multiplicities: "+res) 43 //println(targetRelationName+ " all missing multiplicities: "+res)
44 return res 44 return res
45 } 45 }
46} \ No newline at end of file 46}
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..7c05e818
--- /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,516 @@
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.HashMap
19import java.util.HashSet
20import java.util.List
21import java.util.Map
22import java.util.Set
23import javax.naming.OperationNotSupportedException
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 Map<Scope, LinearBoundedExpression> scopeBounds
33 val LinearBoundedExpression topLevelBounds
34 val Polyhedron polyhedron
35 val PolyhedronSaturationOperator operator
36 val Set<Relation> relevantRelations
37 List<RelationConstraintUpdater> updaters = emptyList
38
39 new(PartialInterpretation p, ModelGenerationStatistics statistics, Set<? extends Type> possibleNewDynamicTypes,
40 Map<RelationMultiplicityConstraint, UnifinishedMultiplicityQueries> unfinishedMultiplicityQueries,
41 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hasElementInContainmentQuery,
42 PolyhedronSolver solver, boolean propagateRelations) {
43 super(p, statistics)
44 val builder = new PolyhedronBuilder(p)
45 builder.buildPolyhedron(possibleNewDynamicTypes)
46 scopeBounds = builder.scopeBounds
47 topLevelBounds = builder.topLevelBounds
48 polyhedron = builder.polyhedron
49 operator = solver.createSaturationOperator(polyhedron)
50 if (propagateRelations) {
51 propagateAllScopeConstraints()
52 val maximumNumberOfNewNodes = topLevelBounds.upperBound
53 if (maximumNumberOfNewNodes === null) {
54 throw new IllegalStateException("Could not determine maximum number of new nodes, it may be unbounded")
55 }
56 if (maximumNumberOfNewNodes <= 0) {
57 throw new IllegalStateException("Maximum number of new nodes is not positive")
58 }
59 builder.buildMultiplicityConstraints(unfinishedMultiplicityQueries, hasElementInContainmentQuery,
60 maximumNumberOfNewNodes)
61 relevantRelations = builder.relevantRelations
62 updaters = builder.updaters
63 } else {
64 relevantRelations = emptySet
65 }
66 }
67
68 override void doPropagateAllScopeConstraints() {
69 resetBounds()
70 populatePolyhedronFromScope()
71// println(polyhedron)
72 val result = operator.saturate()
73// println(polyhedron)
74 if (result == PolyhedronSaturationResult.EMPTY) {
75 setScopesInvalid()
76 } else {
77 populateScopesFromPolyhedron()
78 if (result != PolyhedronSaturationResult.SATURATED) {
79 super.propagateAllScopeConstraints()
80 }
81 }
82 }
83
84 override propagateAdditionToRelation(Relation r) {
85 super.propagateAdditionToRelation(r)
86 if (relevantRelations.contains(r)) {
87 propagateAllScopeConstraints()
88 }
89 }
90
91 def resetBounds() {
92 for (dimension : polyhedron.dimensions) {
93 dimension.lowerBound = 0
94 dimension.upperBound = null
95 }
96 for (constraint : polyhedron.constraints) {
97 constraint.lowerBound = null
98 constraint.upperBound = null
99 }
100 }
101
102 private def populatePolyhedronFromScope() {
103 topLevelBounds.tightenLowerBound(partialInterpretation.minNewElements)
104 if (partialInterpretation.maxNewElements >= 0) {
105 topLevelBounds.tightenUpperBound(partialInterpretation.maxNewElements)
106 }
107 for (pair : scopeBounds.entrySet) {
108 val scope = pair.key
109 val bounds = pair.value
110 bounds.tightenLowerBound(scope.minNewElements)
111 if (scope.maxNewElements >= 0) {
112 bounds.tightenUpperBound(scope.maxNewElements)
113 }
114 }
115 for (updater : updaters) {
116 updater.update(partialInterpretation)
117 }
118 }
119
120 private def populateScopesFromPolyhedron() {
121 checkBounds(topLevelBounds)
122 if (partialInterpretation.minNewElements > topLevelBounds.lowerBound) {
123 throw new IllegalArgumentException('''Lower bound of «topLevelBounds» smaller than top-level scope: «partialInterpretation.minNewElements»''')
124 } else if (partialInterpretation.minNewElements != topLevelBounds.lowerBound) {
125 partialInterpretation.minNewElements = topLevelBounds.lowerBound
126 }
127 val topLevelUpperBound = topLevelBounds.upperBound ?: -1
128 if (partialInterpretation.maxNewElements >= 0 && topLevelUpperBound >= 0 &&
129 partialInterpretation.maxNewElements < topLevelUpperBound) {
130 throw new IllegalArgumentException('''Upper bound of «topLevelBounds» larger than top-level scope: «partialInterpretation.maxNewElements»''')
131 } else if (partialInterpretation.maxNewElements != topLevelUpperBound) {
132 partialInterpretation.maxNewElements = topLevelUpperBound
133 }
134 for (pair : scopeBounds.entrySet) {
135 val scope = pair.key
136 val bounds = pair.value
137 checkBounds(bounds)
138 if (scope.minNewElements > bounds.lowerBound) {
139 throw new IllegalArgumentException('''Lower bound of «bounds» smaller than «scope.targetTypeInterpretation» scope: «scope.minNewElements»''')
140 } else if (scope.minNewElements != bounds.lowerBound) {
141 scope.minNewElements = bounds.lowerBound
142 }
143 val upperBound = bounds.upperBound ?: -1
144 if (scope.maxNewElements >= 0 && upperBound >= 0 && scope.maxNewElements < upperBound) {
145 throw new IllegalArgumentException('''Upper bound of «bounds» larger than «scope.targetTypeInterpretation» scope: «scope.maxNewElements»''')
146 } else if (scope.maxNewElements != upperBound) {
147 scope.maxNewElements = upperBound
148 }
149 }
150 }
151
152 private def checkBounds(LinearBoundedExpression bounds) {
153 if (bounds.lowerBound === null) {
154 throw new IllegalArgumentException("Infinite lower bound: " + bounds)
155 } else if (bounds.lowerBound < 0) {
156 throw new IllegalArgumentException("Negative lower bound: " + bounds)
157 }
158 if (bounds.upperBound !== null && bounds.upperBound < 0) {
159 throw new IllegalArgumentException("Negative upper bound: " + bounds)
160 }
161 }
162
163 private def setScopesInvalid() {
164 partialInterpretation.minNewElements = Integer.MAX_VALUE
165 partialInterpretation.maxNewElements = 0
166 for (scope : partialInterpretation.scopes) {
167 scope.minNewElements = Integer.MAX_VALUE
168 scope.maxNewElements = 0
169 }
170 }
171
172 private static def <T extends IPatternMatch> getCalculatedMultiplicity(ViatraQueryMatcher<T> matcher,
173 PartialInterpretation p) {
174 val match = matcher.newEmptyMatch
175 match.set(0, p.problem)
176 match.set(1, p)
177 val iterator = matcher.streamAllMatches(match).iterator
178 if (!iterator.hasNext) {
179 return null
180 }
181 val value = iterator.next.get(2) as Integer
182 if (iterator.hasNext) {
183 throw new IllegalArgumentException("Multiplicity calculation query has more than one match")
184 }
185 value
186 }
187
188 @FinalFieldsConstructor
189 private static class PolyhedronBuilder {
190 static val INFINITY_SCALE = 10
191
192 val PartialInterpretation p
193
194 Map<Type, Dimension> instanceCounts
195 Map<Type, Map<Dimension, Integer>> subtypeDimensions
196 Map<Map<Dimension, Integer>, LinearBoundedExpression> expressionsCache
197 Map<Type, LinearBoundedExpression> typeBounds
198 int infinity
199 ViatraQueryEngine queryEngine
200 ImmutableList.Builder<RelationConstraintUpdater> updatersBuilder
201
202 Map<Scope, LinearBoundedExpression> scopeBounds
203 LinearBoundedExpression topLevelBounds
204 Polyhedron polyhedron
205 Set<Relation> relevantRelations
206 List<RelationConstraintUpdater> updaters
207
208 def buildPolyhedron(Set<? extends Type> possibleNewDynamicTypes) {
209 instanceCounts = possibleNewDynamicTypes.toInvertedMap[new Dimension(name, 0, null)]
210 val types = p.problem.types
211 expressionsCache = Maps.newHashMapWithExpectedSize(types.size)
212 subtypeDimensions = types.toInvertedMap[findSubtypeDimensions.toInvertedMap[1]]
213 typeBounds = ImmutableMap.copyOf(subtypeDimensions.mapValues[toExpression])
214 scopeBounds = buildScopeBounds
215 topLevelBounds = instanceCounts.values.toInvertedMap[1].toExpression
216 val dimensions = ImmutableList.copyOf(instanceCounts.values)
217 val expressionsToSaturate = ImmutableList.copyOf(scopeBounds.values)
218 polyhedron = new Polyhedron(dimensions, new ArrayList, expressionsToSaturate)
219 addCachedConstraintsToPolyhedron()
220 }
221
222 def buildMultiplicityConstraints(
223 Map<RelationMultiplicityConstraint, UnifinishedMultiplicityQueries> constraints,
224 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hasElementInContainmentQuery,
225 int maximumNuberOfNewNodes) {
226 infinity = maximumNuberOfNewNodes * INFINITY_SCALE
227 queryEngine = ViatraQueryEngine.on(new EMFScope(p))
228 updatersBuilder = ImmutableList.builder
229 val containmentConstraints = constraints.entrySet.filter[key.containment].groupBy[key.targetType]
230 for (pair : containmentConstraints.entrySet) {
231 buildContainmentConstraints(pair.key, pair.value)
232 }
233 buildConstainmentRootConstraints(containmentConstraints.keySet, hasElementInContainmentQuery)
234 for (pair : constraints.entrySet) {
235 val constraint = pair.key
236 if (!constraint.containment) {
237 buildNonContainmentConstraints(constraint, pair.value)
238 }
239 }
240 buildRelevantRelations(constraints.keySet)
241 updaters = updatersBuilder.build
242 addCachedConstraintsToPolyhedron()
243 }
244
245 private def buildRelevantRelations(Set<RelationMultiplicityConstraint> constraints) {
246 val builder = ImmutableSet.builder
247 for (constraint : constraints) {
248 builder.add(constraint.relation)
249 if (constraint.inverseRelation !== null) {
250 builder.add(constraint.inverseRelation)
251 }
252 }
253 relevantRelations = builder.build
254 }
255
256 private def addCachedConstraintsToPolyhedron() {
257 val constraints = new HashSet
258 constraints.addAll(expressionsCache.values.filter(LinearConstraint))
259 constraints.removeAll(polyhedron.constraints)
260 polyhedron.constraints.addAll(constraints)
261 }
262
263 private def buildContainmentConstraints(Type containedType,
264 List<Map.Entry<RelationMultiplicityConstraint, UnifinishedMultiplicityQueries>> constraints) {
265 val typeCoefficients = subtypeDimensions.get(containedType)
266 val orphansLowerBoundCoefficients = new HashMap(typeCoefficients)
267 val orphansUpperBoundCoefficients = new HashMap(typeCoefficients)
268 val unfinishedMultiplicitiesMatchersBuilder = ImmutableList.builder
269 val remainingContentsQueriesBuilder = ImmutableList.builder
270 for (pair : constraints) {
271 val constraint = pair.key
272 val containerCoefficients = subtypeDimensions.get(constraint.sourceType)
273 if (constraint.isUpperBoundFinite) {
274 orphansLowerBoundCoefficients.addCoefficients(-constraint.upperBound, containerCoefficients)
275 } else {
276 orphansLowerBoundCoefficients.addCoefficients(-infinity, containerCoefficients)
277 }
278 orphansUpperBoundCoefficients.addCoefficients(-constraint.lowerBound, containerCoefficients)
279 val queries = pair.value
280 if (constraint.constrainsUnfinished) {
281 if (queries.unfinishedMultiplicityQuery === null) {
282 throw new IllegalArgumentException(
283 "Containment constraints need unfinished multiplicity queries")
284 }
285 unfinishedMultiplicitiesMatchersBuilder.add(
286 queries.unfinishedMultiplicityQuery.getMatcher(queryEngine))
287 }
288 if (queries.remainingContentsQuery === null) {
289 throw new IllegalArgumentException("Containment constraints need remaining contents queries")
290 }
291 remainingContentsQueriesBuilder.add(queries.remainingContentsQuery.getMatcher(queryEngine))
292 }
293 val orphanLowerBound = orphansLowerBoundCoefficients.toExpression
294 val orphanUpperBound = orphansUpperBoundCoefficients.toExpression
295 val updater = new ContainmentConstraintUpdater(containedType.name, orphanLowerBound, orphanUpperBound,
296 unfinishedMultiplicitiesMatchersBuilder.build, remainingContentsQueriesBuilder.build)
297 updatersBuilder.add(updater)
298 }
299
300 private def buildConstainmentRootConstraints(Set<Type> containedTypes,
301 IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hasElementInContainmentQuery) {
302 val matcher = hasElementInContainmentQuery.getMatcher(queryEngine)
303 val rootDimensions = Sets.newHashSet(instanceCounts.values)
304 for (type : containedTypes) {
305 val containedDimensions = subtypeDimensions.get(type).keySet
306 rootDimensions.removeAll(containedDimensions)
307 }
308 for (dimension : rootDimensions) {
309 updatersBuilder.add(new ContainmentRootConstraintUpdater(dimension, matcher))
310 }
311 }
312
313 private def buildNonContainmentConstraints(RelationMultiplicityConstraint constraint,
314 UnifinishedMultiplicityQueries queries) {
315 if (constraint.constrainsRemainingInverse) {
316 if (queries.unfinishedMultiplicityQuery === null) {
317 throw new IllegalArgumentException("Reference constraints need unfinished multiplicity queries")
318 }
319 val unfinishedMultiplicityMatcher = queries.unfinishedMultiplicityQuery.getMatcher(queryEngine)
320 if (queries.remainingInverseMultiplicityQuery === null) {
321 throw new IllegalArgumentException(
322 "Reference constraints need remaining inverse multiplicity queries")
323 }
324 val remainingInverseMultiplicityMatcher = queries.remainingInverseMultiplicityQuery.getMatcher(
325 queryEngine)
326 val availableMultiplicityCoefficients = new HashMap
327 availableMultiplicityCoefficients.addCoefficients(constraint.inverseUpperBound,
328 subtypeDimensions.get(constraint.targetType))
329 availableMultiplicityCoefficients.addCoefficients(-constraint.lowerBound,
330 subtypeDimensions.get(constraint.targetType))
331 val availableMultiplicity = availableMultiplicityCoefficients.toExpression
332 updatersBuilder.add(
333 new UnfinishedMultiplicityConstraintUpdater(constraint.relation.name, availableMultiplicity,
334 unfinishedMultiplicityMatcher, remainingInverseMultiplicityMatcher))
335 }
336 if (constraint.constrainsUnrepairable) {
337 if (queries.unrepairableMultiplicityQuery === null) {
338 throw new IllegalArgumentException("Reference constraints need unrepairable multiplicity queries")
339 }
340 val unrepairableMultiplicityMatcher = queries.unrepairableMultiplicityQuery.getMatcher(queryEngine)
341 val targetTypeCardinality = typeBounds.get(constraint.targetType)
342 updatersBuilder.add(
343 new UnrepairableMultiplicityConstraintUpdater(constraint.relation.name, targetTypeCardinality,
344 unrepairableMultiplicityMatcher))
345 }
346 }
347
348 private def addCoefficients(Map<Dimension, Integer> accumulator, int scale, Map<Dimension, Integer> a) {
349 for (pair : a.entrySet) {
350 val dimension = pair.key
351 val currentValue = accumulator.get(pair.key) ?: 0
352 val newValue = currentValue + scale * pair.value
353 if (newValue == 0) {
354 accumulator.remove(dimension)
355 } else {
356 accumulator.put(dimension, newValue)
357 }
358 }
359 }
360
361 private def findSubtypeDimensions(Type type) {
362 val subtypes = new HashSet
363 val dimensions = new HashSet
364 val stack = new ArrayDeque
365 stack.addLast(type)
366 while (!stack.empty) {
367 val subtype = stack.removeLast
368 if (subtypes.add(subtype)) {
369 val dimension = instanceCounts.get(subtype)
370 if (dimension !== null) {
371 dimensions.add(dimension)
372 }
373 stack.addAll(subtype.subtypes)
374 }
375 }
376 dimensions
377 }
378
379 private def toExpression(Map<Dimension, Integer> coefficients) {
380 expressionsCache.computeIfAbsent(coefficients) [ c |
381 if (c.size == 1 && c.entrySet.head.value == 1) {
382 c.entrySet.head.key
383 } else {
384 new LinearConstraint(c, null, null)
385 }
386 ]
387 }
388
389 private def buildScopeBounds() {
390 val scopeBoundsBuilder = ImmutableMap.builder
391 for (scope : p.scopes) {
392 switch (targetTypeInterpretation : scope.targetTypeInterpretation) {
393 PartialPrimitiveInterpretation:
394 throw new OperationNotSupportedException("Primitive type scopes are not yet implemented")
395 PartialComplexTypeInterpretation: {
396 val complexType = targetTypeInterpretation.interpretationOf
397 val typeBound = typeBounds.get(complexType)
398 if (typeBound === null) {
399 if (scope.minNewElements > 0) {
400 throw new IllegalArgumentException("Found scope for " + complexType.name +
401 ", but the type cannot be instantiated")
402 }
403 } else {
404 scopeBoundsBuilder.put(scope, typeBound)
405 }
406 }
407 default:
408 throw new IllegalArgumentException("Unknown PartialTypeInterpretation: " +
409 targetTypeInterpretation)
410 }
411 }
412 scopeBoundsBuilder.build
413 }
414 }
415
416 private static interface RelationConstraintUpdater {
417 def void update(PartialInterpretation p)
418 }
419
420 @FinalFieldsConstructor
421 static class ContainmentConstraintUpdater implements RelationConstraintUpdater {
422 val String name
423 val LinearBoundedExpression orphansLowerBound
424 val LinearBoundedExpression orphansUpperBound
425 val List<ViatraQueryMatcher<? extends IPatternMatch>> unfinishedMultiplicitiesMatchers
426 val List<ViatraQueryMatcher<? extends IPatternMatch>> remainingContentsQueries
427
428 override update(PartialInterpretation p) {
429 tightenLowerBound(p)
430 tightenUpperBound(p)
431 }
432
433 private def tightenLowerBound(PartialInterpretation p) {
434 var int sum = 0
435 for (matcher : remainingContentsQueries) {
436 val value = matcher.getCalculatedMultiplicity(p)
437 if (value === null) {
438 throw new IllegalArgumentException("Remaining contents count is missing for " + name)
439 }
440 if (value == -1) {
441 // Infinite upper bound, no need to tighten.
442 return
443 }
444 sum += value
445 }
446 orphansLowerBound.tightenUpperBound(sum)
447 }
448
449 private def tightenUpperBound(PartialInterpretation p) {
450 var int sum = 0
451 for (matcher : unfinishedMultiplicitiesMatchers) {
452 val value = matcher.getCalculatedMultiplicity(p)
453 if (value === null) {
454 throw new IllegalArgumentException("Unfinished multiplicity is missing for " + name)
455 }
456 sum += value
457 }
458 orphansUpperBound.tightenLowerBound(sum)
459 }
460 }
461
462 @FinalFieldsConstructor
463 static class ContainmentRootConstraintUpdater implements RelationConstraintUpdater {
464 val LinearBoundedExpression typeCardinality
465 val ViatraQueryMatcher<? extends IPatternMatch> hasElementInContainmentMatcher
466
467 override update(PartialInterpretation p) {
468 if (hasElementInContainmentMatcher.hasMatch(p)) {
469 typeCardinality.tightenUpperBound(0)
470 } else {
471 typeCardinality.tightenUpperBound(1)
472 }
473 }
474
475 private static def <T extends IPatternMatch> hasMatch(ViatraQueryMatcher<T> matcher, PartialInterpretation p) {
476 val match = matcher.newMatch(p.problem, p)
477 matcher.countMatches(match) != 0
478 }
479 }
480
481 @FinalFieldsConstructor
482 static class UnfinishedMultiplicityConstraintUpdater implements RelationConstraintUpdater {
483 val String name
484 val LinearBoundedExpression availableMultiplicityExpression
485 val ViatraQueryMatcher<? extends IPatternMatch> unfinishedMultiplicityMatcher
486 val ViatraQueryMatcher<? extends IPatternMatch> remainingInverseMultiplicityMatcher
487
488 override update(PartialInterpretation p) {
489 val unfinishedMultiplicity = unfinishedMultiplicityMatcher.getCalculatedMultiplicity(p)
490 if (unfinishedMultiplicity === null) {
491 throw new IllegalArgumentException("Unfinished multiplicity is missing for " + name)
492 }
493 val remainingInverseMultiplicity = remainingInverseMultiplicityMatcher.getCalculatedMultiplicity(p)
494 if (remainingInverseMultiplicity === null) {
495 throw new IllegalArgumentException("Remaining inverse multiplicity is missing for " + name)
496 }
497 val int requiredMultiplicity = unfinishedMultiplicity - remainingInverseMultiplicity
498 availableMultiplicityExpression.tightenLowerBound(requiredMultiplicity)
499 }
500 }
501
502 @FinalFieldsConstructor
503 static class UnrepairableMultiplicityConstraintUpdater implements RelationConstraintUpdater {
504 val String name
505 val LinearBoundedExpression targetCardinalityExpression
506 val ViatraQueryMatcher<? extends IPatternMatch> unrepairableMultiplicityMatcher
507
508 override update(PartialInterpretation p) {
509 val value = unrepairableMultiplicityMatcher.getCalculatedMultiplicity(p)
510 if (value === null) {
511 throw new IllegalArgumentException("Unrepairable multiplicity is missing for " + name)
512 }
513 targetCardinalityExpression.tightenLowerBound(value)
514 }
515 }
516}
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..9c6cb82e
--- /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,123 @@
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.FinalFieldsConstructor
7
8interface PolyhedronSolver {
9 def PolyhedronSaturationOperator createSaturationOperator(Polyhedron polyhedron)
10}
11
12enum PolyhedronSaturationResult {
13 SATURATED,
14 EMPTY,
15 UNKNOWN
16}
17
18interface PolyhedronSaturationOperator extends AutoCloseable {
19 def Polyhedron getPolyhedron()
20
21 def PolyhedronSaturationResult saturate()
22}
23
24@FinalFieldsConstructor
25@Accessors
26class Polyhedron {
27 /**
28 * The list of dimensions (variables) for this polyhedron.
29 *
30 * This list must not be modified after the polyhedron was created.
31 * However, lower and upper bounds of the dimensions may be changed.
32 *
33 * Names of dimensions in this list are assumed to be unique.
34 */
35 val List<Dimension> dimensions
36
37 /**
38 * The list of constraints defining this polyhedron.
39 *
40 * The list and its elements may be freely modified.
41 */
42 val List<LinearConstraint> constraints
43
44 /**
45 * The list of constraints that should be saturated (tightened)
46 * when a {@link PolyhedronSaturationOperator} is invoked.
47 *
48 * This list may be freely modified.
49 *
50 * Place all dimensions and constraints here to saturate all the bounds.
51 */
52 val List<LinearBoundedExpression> expressionsToSaturate
53
54 override toString() '''
55 Dimensions:
56 «FOR dimension : dimensions»
57 «dimension»
58 «ENDFOR»
59 Constraints:
60 «FOR constraint : constraints»
61 «constraint»
62 «ENDFOR»
63 '''
64
65}
66
67@Accessors
68abstract class LinearBoundedExpression {
69 var Integer lowerBound
70 var Integer upperBound
71
72 def void tightenLowerBound(Integer tighterBound) {
73 if (lowerBound === null || (tighterBound !== null && lowerBound < tighterBound)) {
74 lowerBound = tighterBound
75 }
76 }
77
78 def void tightenUpperBound(Integer tighterBound) {
79 if (upperBound === null || (tighterBound !== null && upperBound > tighterBound)) {
80 upperBound = tighterBound
81 }
82 }
83}
84
85@Accessors
86class Dimension extends LinearBoundedExpression {
87 val String name
88
89 @FinalFieldsConstructor
90 new() {
91 }
92
93 new(String name, Integer lowerBound, Integer upperBound) {
94 this(name)
95 this.lowerBound = lowerBound
96 this.upperBound = upperBound
97 }
98
99 override toString() {
100 '''«IF lowerBound !== null»«lowerBound» <= «ENDIF»«name»«IF upperBound !== null» <= «upperBound»«ENDIF»'''
101 }
102
103}
104
105@Accessors
106class LinearConstraint extends LinearBoundedExpression {
107 val Map<Dimension, Integer> coefficients
108
109 @FinalFieldsConstructor
110 new() {
111 }
112
113 new(Map<Dimension, Integer> coefficients, Integer lowerBound, Integer upperBound) {
114 this(coefficients)
115 this.lowerBound = lowerBound
116 this.upperBound = upperBound
117 }
118
119 override toString() {
120 '''«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»'''
121 }
122
123}
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..52a390a8
--- /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,134 @@
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 constrainsUnfinished && canHaveMultipleSourcesPerTarget
48 }
49
50 def constrainsRemainingInverse() {
51 lowerBound >= 1 && !containment && inverseUpperBoundFinite
52 }
53
54 def constrainsRemainingContents() {
55 containment
56 }
57
58 def isActive() {
59 constrainsUnfinished || constrainsUnrepairable || constrainsRemainingInverse || constrainsRemainingContents
60 }
61
62 def getSourceType() {
63 getParamType(0)
64 }
65
66 def getTargetType() {
67 getParamType(1)
68 }
69
70 private def getParamType(int i) {
71 val parameters = relation.parameters
72 if (i < parameters.size) {
73 val firstParam = parameters.get(i)
74 if (firstParam instanceof ComplexTypeReference) {
75 return firstParam.referred
76 }
77 }
78 throw new IllegalArgumentException("Constraint with unknown source type")
79 }
80}
81
82class RelationConstraintCalculator {
83 def calculateRelationConstraints(LogicProblem problem) {
84 val containmentRelations = switch (problem.containmentHierarchies.size) {
85 case 0:
86 <Relation>emptySet
87 case 1:
88 ImmutableSet.copyOf(problem.containmentHierarchies.head.containmentRelations)
89 default:
90 throw new IllegalArgumentException("Only a single containment hierarchy is supported")
91 }
92 val inverseRelations = new HashMap<Relation, Relation>
93 val lowerMultiplicities = new HashMap<Relation, Integer>
94 val upperMultiplicities = new HashMap<Relation, Integer>
95 for (relation : problem.relations) {
96 lowerMultiplicities.put(relation, 0)
97 upperMultiplicities.put(relation, -1)
98 }
99 for (annotation : problem.annotations) {
100 switch (annotation) {
101 InverseRelationAssertion: {
102 inverseRelations.put(annotation.inverseA, annotation.inverseB)
103 inverseRelations.put(annotation.inverseB, annotation.inverseA)
104 }
105 LowerMultiplicityAssertion:
106 lowerMultiplicities.put(annotation.relation, annotation.lower)
107 UpperMultiplicityAssertion:
108 upperMultiplicities.put(annotation.relation, annotation.upper)
109 }
110 }
111 val multiplicityConstraintsBuilder = ImmutableList.builder()
112 for (relation : problem.relations) {
113 val containment = containmentRelations.contains(relation)
114 val lowerMultiplicity = lowerMultiplicities.get(relation)
115 val upperMultiplicity = upperMultiplicities.get(relation)
116 var container = false
117 var inverseUpperMultiplicity = -1
118 val inverseRelation = inverseRelations.get(relation)
119 if (inverseRelation !== null) {
120 inverseUpperMultiplicity = upperMultiplicities.get(relation)
121 container = containmentRelations.contains(inverseRelation)
122 }
123 val constraint = new RelationMultiplicityConstraint(relation, inverseRelation, containment, container,
124 lowerMultiplicity, upperMultiplicity, inverseUpperMultiplicity)
125 if (constraint.isActive) {
126 if (relation.parameters.size != 2) {
127 throw new IllegalArgumentException('''Relation «relation.name» has multiplicity or containment constraints, but it is not binary''')
128 }
129 multiplicityConstraintsBuilder.add(constraint)
130 }
131 }
132 new RelationConstraints(multiplicityConstraintsBuilder.build)
133 }
134}
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..0bdb202e
--- /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,109 @@
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.PartialTypeInterpratation
8import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope
9import java.util.HashMap
10import java.util.HashSet
11import java.util.Map
12import java.util.Set
13import org.eclipse.xtend.lib.annotations.Accessors
14
15class ScopePropagator {
16 @Accessors(PROTECTED_GETTER) val PartialInterpretation partialInterpretation
17 val ModelGenerationStatistics statistics
18 val Map<PartialTypeInterpratation, Scope> type2Scope
19 @Accessors(PROTECTED_GETTER) val Map<Scope, Set<Scope>> superScopes
20 @Accessors(PROTECTED_GETTER) val Map<Scope, Set<Scope>> subScopes
21
22 new(PartialInterpretation p, ModelGenerationStatistics statistics) {
23 partialInterpretation = p
24 this.statistics = statistics
25 type2Scope = new HashMap
26 for (scope : p.scopes) {
27 type2Scope.put(scope.targetTypeInterpretation, scope)
28 }
29
30 superScopes = new HashMap
31 subScopes = new HashMap
32 for (scope : p.scopes) {
33 superScopes.put(scope, new HashSet)
34 subScopes.put(scope, new HashSet)
35 }
36
37 for (scope : p.scopes) {
38 val target = scope.targetTypeInterpretation
39 if (target instanceof PartialComplexTypeInterpretation) {
40 val supertypeInterpretations = target.supertypeInterpretation
41 for (supertypeInterpretation : supertypeInterpretations) {
42 val supertypeScope = type2Scope.get(supertypeInterpretation)
43 superScopes.get(scope).add(supertypeScope)
44 subScopes.get(supertypeScope).add(scope)
45 }
46 }
47 }
48 var boolean changed
49 do {
50 changed = false
51 for (scope : p.scopes) {
52 val subScopeSet = subScopes.get(scope)
53 val superScopeSet = superScopes.get(scope)
54 for (subScope : subScopeSet) {
55 changed = changed || superScopes.get(subScope).addAll(superScopeSet)
56 }
57 for (superScope : superScopeSet) {
58 changed = changed || subScopes.get(superScope).addAll(subScopeSet)
59 }
60 }
61 } while (changed)
62 }
63
64 def propagateAllScopeConstraints() {
65 statistics.incrementScopePropagationCount()
66 doPropagateAllScopeConstraints()
67 }
68
69 protected def void doPropagateAllScopeConstraints() {
70 // Nothing to propagate.
71 }
72
73 def propagateAdditionToType(PartialTypeInterpratation t) {
74// println('''Adding to «(t as PartialComplexTypeInterpretation).interpretationOf.name»''')
75 val targetScope = type2Scope.get(t)
76 targetScope.removeOne
77 val sups = superScopes.get(targetScope)
78 sups.forEach[removeOne]
79 if (this.partialInterpretation.minNewElements > 0) {
80 this.partialInterpretation.minNewElements = this.partialInterpretation.minNewElements - 1
81 }
82 if (this.partialInterpretation.maxNewElements > 0) {
83 this.partialInterpretation.maxNewElements = this.partialInterpretation.maxNewElements - 1
84 } else if (this.partialInterpretation.maxNewElements === 0) {
85 throw new IllegalArgumentException('''Inconsistent object creation: lower node limit is 0!''')
86 }
87 propagateAllScopeConstraints
88
89// println('''Target Scope: «targetScope.minNewElements» - «targetScope.maxNewElements»''')
90// println(''' «this.partialInterpretation.minNewElements» - «this.partialInterpretation.maxNewElements»''')
91// this.partialInterpretation.scopes.forEach[println(''' «(it.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name»: «it.minNewElements»-«it.maxNewElements»''')]
92// println('''All constraints are propagated upon increasing «(t as PartialComplexTypeInterpretation).interpretationOf.name»''')
93 }
94
95 def void propagateAdditionToRelation(Relation r) {
96 // Nothing to propagate.
97 }
98
99 private def removeOne(Scope scope) {
100 if (scope.maxNewElements === 0) {
101 throw new IllegalArgumentException('''Inconsistent object creation: «scope.targetTypeInterpretation»''')
102 } else if (scope.maxNewElements > 0) {
103 scope.maxNewElements = scope.maxNewElements - 1
104 }
105 if (scope.minNewElements > 0) {
106 scope.minNewElements = scope.minNewElements - 1
107 }
108 }
109}
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..b0ed75cb
--- /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,64 @@
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 Count = new Simple("Count")
20
21 public static val BasicTypeHierarchy = new Simple("BasicTypeHierarchy")
22
23 private new() {
24 }
25
26 def boolean requiresUpperBoundIndexing()
27
28 static class Simple extends ScopePropagatorStrategy {
29 val String name
30
31 @FinalFieldsConstructor
32 private new() {
33 }
34
35 override requiresUpperBoundIndexing() {
36 false
37 }
38
39 override toString() {
40 name
41 }
42 }
43
44 @Data
45 static class Polyhedral extends ScopePropagatorStrategy {
46 public static val UNLIMITED_TIME = -1
47
48 val PolyhedralScopePropagatorConstraints constraints
49 val PolyhedralScopePropagatorSolver solver
50 val double timeoutSeconds
51
52 @FinalFieldsConstructor
53 new() {
54 }
55
56 new(PolyhedralScopePropagatorConstraints constraints, PolyhedralScopePropagatorSolver solver) {
57 this(constraints, solver, UNLIMITED_TIME)
58 }
59
60 override requiresUpperBoundIndexing() {
61 constraints == PolyhedralScopePropagatorConstraints.Relational
62 }
63 }
64}
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..be8ef00a
--- /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,77 @@
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 if (subScope.minNewElements > superScope.minNewElements) {
31 superScope.minNewElements = subScope.minNewElements
32 return true
33 } else {
34 return false
35 }
36 }
37
38 private def propagateUpperLimitDown(Scope subScope, Scope superScope) {
39 if (superScope.maxNewElements >= 0 &&
40 (superScope.maxNewElements < subScope.maxNewElements || subScope.maxNewElements < 0)) {
41// println('''
42// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> «(superScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name»
43// subScope.maxNewElements «subScope.maxNewElements» = superScope.maxNewElements «superScope.maxNewElements»
44// ''')
45 subScope.maxNewElements = superScope.maxNewElements
46 return true
47 } else {
48 return false
49 }
50 }
51
52 private def propagateLowerLimitUp(Scope subScope, PartialInterpretation p) {
53 if (subScope.minNewElements > p.minNewElements) {
54// println('''
55// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes
56// p.minNewElements «p.minNewElements» = subScope.minNewElements «subScope.minNewElements»
57// ''')
58 p.minNewElements = subScope.minNewElements
59 return true
60 } else {
61 return false
62 }
63 }
64
65 private def propagateUpperLimitDown(Scope subScope, PartialInterpretation p) {
66 if (p.maxNewElements >= 0 && (p.maxNewElements < subScope.maxNewElements || subScope.maxNewElements < 0)) {
67// println('''
68// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes
69// subScope.maxNewElements «subScope.maxNewElements» = p.maxNewElements «p.maxNewElements»
70// ''')
71 subScope.maxNewElements = p.maxNewElements
72 return true
73 } else {
74 return false
75 }
76 }
77}
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..23444956
--- /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,248 @@
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.FinalFieldsConstructor
17
18class Z3PolyhedronSolver implements PolyhedronSolver {
19 val boolean lpRelaxation
20 val double timeoutSeconds
21
22 @FinalFieldsConstructor
23 new() {
24 }
25
26 new() {
27 this(false, -1)
28 }
29
30 override createSaturationOperator(Polyhedron polyhedron) {
31 new Z3SaturationOperator(polyhedron, lpRelaxation, timeoutSeconds)
32 }
33}
34
35class Z3SaturationOperator extends AbstractPolyhedronSaturationOperator {
36 static val INFINITY_SYMBOL_NAME = "oo"
37 static val MULT_SYMBOL_NAME = "*"
38 static val TIMEOUT_SYMBOL_NAME = "timeout"
39 static val INTEGER_PRECISION = new BigDecimal(Integer.MAX_VALUE).precision
40 static val ROUND_DOWN = new MathContext(INTEGER_PRECISION, RoundingMode.FLOOR)
41 static val ROUND_UP = new MathContext(INTEGER_PRECISION, RoundingMode.CEILING)
42 // The interval isolating the number is smaller than 1/10^precision.
43 static val ALGEBRAIC_NUMBER_ROUNDING = 0
44
45 extension val Context context
46 val Symbol infinitySymbol
47 val Symbol multSymbol
48 val Map<Dimension, ArithExpr> variables
49 val int timeoutMilliseconds
50
51 new(Polyhedron polyhedron, boolean lpRelaxation, double timeoutSeconds) {
52 super(polyhedron)
53 context = new Context
54 infinitySymbol = context.mkSymbol(INFINITY_SYMBOL_NAME)
55 multSymbol = context.mkSymbol(MULT_SYMBOL_NAME)
56 variables = polyhedron.dimensions.toInvertedMap [ dimension |
57 val name = dimension.name
58 if (lpRelaxation) {
59 mkRealConst(name)
60 } else {
61 mkIntConst(name)
62 }
63 ]
64 timeoutMilliseconds = Math.ceil(timeoutSeconds * 1000) as int
65 }
66
67 override doSaturate() {
68 val status = executeSolver()
69 convertStatusToSaturationResult(status)
70 }
71
72 private def convertStatusToSaturationResult(Status status) {
73 switch (status) {
74 case SATISFIABLE:
75 PolyhedronSaturationResult.SATURATED
76 case UNSATISFIABLE:
77 PolyhedronSaturationResult.EMPTY
78 case UNKNOWN:
79 PolyhedronSaturationResult.UNKNOWN
80 default:
81 throw new IllegalArgumentException("Unknown Status: " + status)
82 }
83 }
84
85 private def executeSolver() {
86 for (expressionToSaturate : polyhedron.expressionsToSaturate) {
87 val expr = expressionToSaturate.toExpr
88 val lowerResult = saturateLowerBound(expr, expressionToSaturate)
89 if (lowerResult != Status.SATISFIABLE) {
90 return lowerResult
91 }
92 val upperResult = saturateUpperBound(expr, expressionToSaturate)
93 if (upperResult != Status.SATISFIABLE) {
94 return upperResult
95 }
96 }
97 Status.SATISFIABLE
98 }
99
100 private def saturateLowerBound(ArithExpr expr, LinearBoundedExpression expressionToSaturate) {
101 val optimize = prepareOptimize
102 val handle = optimize.MkMinimize(expr)
103 val status = optimize.Check()
104 if (status == Status.SATISFIABLE) {
105 val value = switch (resultExpr : handle.lower) {
106 IntNum:
107 resultExpr.getInt()
108 RatNum:
109 floor(resultExpr)
110 AlgebraicNum:
111 floor(resultExpr.toLower(ALGEBRAIC_NUMBER_ROUNDING))
112 default:
113 if (isNegativeInfinity(resultExpr)) {
114 null
115 } else {
116 throw new IllegalArgumentException("Integer result expected, got: " + resultExpr)
117 }
118 }
119 expressionToSaturate.lowerBound = value
120 }
121 status
122 }
123
124 private def floor(RatNum ratNum) {
125 val numerator = new BigDecimal(ratNum.numerator.bigInteger)
126 val denominator = new BigDecimal(ratNum.denominator.bigInteger)
127 numerator.divide(denominator, ROUND_DOWN).setScale(0, RoundingMode.FLOOR).intValue
128 }
129
130 private def saturateUpperBound(ArithExpr expr, LinearBoundedExpression expressionToSaturate) {
131 val optimize = prepareOptimize
132 val handle = optimize.MkMaximize(expr)
133 val status = optimize.Check()
134 if (status == Status.SATISFIABLE) {
135 val value = switch (resultExpr : handle.upper) {
136 IntNum:
137 resultExpr.getInt()
138 RatNum:
139 ceil(resultExpr)
140 AlgebraicNum:
141 ceil(resultExpr.toUpper(ALGEBRAIC_NUMBER_ROUNDING))
142 default:
143 if (isPositiveInfinity(resultExpr)) {
144 null
145 } else {
146 throw new IllegalArgumentException("Integer result expected, got: " + resultExpr)
147 }
148 }
149 expressionToSaturate.upperBound = value
150 }
151 status
152 }
153
154 private def ceil(RatNum ratNum) {
155 val numerator = new BigDecimal(ratNum.numerator.bigInteger)
156 val denominator = new BigDecimal(ratNum.denominator.bigInteger)
157 numerator.divide(denominator, ROUND_UP).setScale(0, RoundingMode.CEILING).intValue
158 }
159
160 private def isPositiveInfinity(Expr expr) {
161 expr.app && expr.getFuncDecl.name == infinitySymbol
162 }
163
164 private def isNegativeInfinity(Expr expr) {
165 // Negative infinity is represented as (* (- 1) oo)
166 if (!expr.app || expr.getFuncDecl.name != multSymbol || expr.numArgs != 2) {
167 return false
168 }
169 isPositiveInfinity(expr.args.get(1))
170 }
171
172 private def prepareOptimize() {
173 val optimize = mkOptimize()
174 if (timeoutMilliseconds >= 0) {
175 val params = mkParams()
176 // We cannot turn TIMEOUT_SYMBOL_NAME into a Symbol in the constructor,
177 // because there is no add(Symbol, int) overload.
178 params.add(TIMEOUT_SYMBOL_NAME, timeoutMilliseconds)
179 optimize.parameters = params
180 }
181 assertConstraints(optimize)
182 optimize
183 }
184
185 private def assertConstraints(Optimize it) {
186 for (pair : variables.entrySet) {
187 assertBounds(pair.value, pair.key)
188 }
189 for (constraint : nonTrivialConstraints) {
190 val expr = createLinearCombination(constraint.coefficients)
191 assertBounds(expr, constraint)
192 }
193 }
194
195 private def assertBounds(Optimize it, ArithExpr expression, LinearBoundedExpression bounds) {
196 val lowerBound = bounds.lowerBound
197 val upperBound = bounds.upperBound
198 if (lowerBound == upperBound) {
199 if (lowerBound === null) {
200 return
201 }
202 Assert(mkEq(expression, mkInt(lowerBound)))
203 } else {
204 if (lowerBound !== null) {
205 Assert(mkGe(expression, mkInt(lowerBound)))
206 }
207 if (upperBound !== null) {
208 Assert(mkLe(expression, mkInt(upperBound)))
209 }
210 }
211 }
212
213 private def toExpr(LinearBoundedExpression linearBoundedExpression) {
214 switch (linearBoundedExpression) {
215 Dimension: variables.get(linearBoundedExpression)
216 LinearConstraint: createLinearCombination(linearBoundedExpression.coefficients)
217 default: throw new IllegalArgumentException("Unknown linear bounded expression:" + linearBoundedExpression)
218 }
219 }
220
221 private def createLinearCombination(Map<Dimension, Integer> coefficients) {
222 val size = coefficients.size
223 if (size == 0) {
224 return mkInt(0)
225 }
226 val array = newArrayOfSize(size)
227 var int i = 0
228 for (pair : coefficients.entrySet) {
229 val variable = variables.get(pair.key)
230 if (variable === null) {
231 throw new IllegalArgumentException("Unknown dimension: " + pair.key.name)
232 }
233 val coefficient = pair.value
234 val term = if (coefficient == 1) {
235 variable
236 } else {
237 mkMul(mkInt(coefficient), variable)
238 }
239 array.set(i, term)
240 i++
241 }
242 mkAdd(array)
243 }
244
245 override close() throws Exception {
246 context.close()
247 }
248}
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/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..1b0db90e 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,6 +16,7 @@ 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.RelationConstraints
20import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 20import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
21import java.util.HashMap 21import java.util.HashMap
22import java.util.Map 22import java.util.Map
@@ -26,22 +26,26 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
26import org.eclipse.xtend.lib.annotations.Accessors 26import org.eclipse.xtend.lib.annotations.Accessors
27 27
28import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* 28import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
29import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy
29 30
30class PatternGenerator { 31class PatternGenerator {
31 @Accessors(PUBLIC_GETTER) val TypeIndexer typeIndexer //= new TypeIndexer(this) 32 @Accessors(PUBLIC_GETTER) val TypeIndexer typeIndexer // = new TypeIndexer(this)
32 @Accessors(PUBLIC_GETTER) val RelationDeclarationIndexer relationDeclarationIndexer = new RelationDeclarationIndexer(this) 33 @Accessors(PUBLIC_GETTER) val RelationDeclarationIndexer relationDeclarationIndexer = new RelationDeclarationIndexer(
33 @Accessors(PUBLIC_GETTER) val RelationDefinitionIndexer relationDefinitionIndexer = new RelationDefinitionIndexer(this) 34 this)
35 @Accessors(PUBLIC_GETTER) val RelationDefinitionIndexer relationDefinitionIndexer = new RelationDefinitionIndexer(
36 this)
34 @Accessors(PUBLIC_GETTER) val ContainmentIndexer containmentIndexer = new ContainmentIndexer(this) 37 @Accessors(PUBLIC_GETTER) val ContainmentIndexer containmentIndexer = new ContainmentIndexer(this)
35 @Accessors(PUBLIC_GETTER) val InvalidIndexer invalidIndexer = new InvalidIndexer(this) 38 @Accessors(PUBLIC_GETTER) val InvalidIndexer invalidIndexer = new InvalidIndexer(this)
36 @Accessors(PUBLIC_GETTER) val UnfinishedIndexer unfinishedIndexer = new UnfinishedIndexer(this) 39 @Accessors(PUBLIC_GETTER) val UnfinishedIndexer unfinishedIndexer
37 @Accessors(PUBLIC_GETTER) val TypeRefinementGenerator typeRefinementGenerator //= new RefinementGenerator(this) 40 @Accessors(PUBLIC_GETTER) val TypeRefinementGenerator typeRefinementGenerator // = new RefinementGenerator(this)
38 @Accessors(PUBLIC_GETTER) val RelationRefinementGenerator relationRefinementGenerator = new RelationRefinementGenerator(this) 41 @Accessors(PUBLIC_GETTER) val RelationRefinementGenerator relationRefinementGenerator = new RelationRefinementGenerator(
39 42 this)
40 public new(TypeInferenceMethod typeInferenceMethod) { 43
41 if(typeInferenceMethod == TypeInferenceMethod.Generic) { 44 new(TypeInferenceMethod typeInferenceMethod, ScopePropagatorStrategy scopePropagatorStrategy) {
45 if (typeInferenceMethod == TypeInferenceMethod.Generic) {
42 this.typeIndexer = new GenericTypeIndexer(this) 46 this.typeIndexer = new GenericTypeIndexer(this)
43 this.typeRefinementGenerator = new GenericTypeRefinementGenerator(this) 47 this.typeRefinementGenerator = new GenericTypeRefinementGenerator(this)
44 } else if(typeInferenceMethod == TypeInferenceMethod.PreliminaryAnalysis) { 48 } else if (typeInferenceMethod == TypeInferenceMethod.PreliminaryAnalysis) {
45 this.typeIndexer = new TypeIndexerWithPreliminaryTypeAnalysis(this) 49 this.typeIndexer = new TypeIndexerWithPreliminaryTypeAnalysis(this)
46 this.typeRefinementGenerator = new TypeRefinementWithPreliminaryTypeAnalysis(this) 50 this.typeRefinementGenerator = new TypeRefinementWithPreliminaryTypeAnalysis(this)
47 } else { 51 } else {
@@ -49,112 +53,100 @@ class PatternGenerator {
49 this.typeRefinementGenerator = null 53 this.typeRefinementGenerator = null
50 throw new IllegalArgumentException('''Unknown type indexing technique : «typeInferenceMethod.name»''') 54 throw new IllegalArgumentException('''Unknown type indexing technique : «typeInferenceMethod.name»''')
51 } 55 }
56 this.unfinishedIndexer = new UnfinishedIndexer(this, scopePropagatorStrategy.requiresUpperBoundIndexing)
52 } 57 }
53 58
54 public def requiresTypeAnalysis() { 59 def requiresTypeAnalysis() {
55 typeIndexer.requiresTypeAnalysis || typeRefinementGenerator.requiresTypeAnalysis 60 typeIndexer.requiresTypeAnalysis || typeRefinementGenerator.requiresTypeAnalysis
56 } 61 }
57 62
58 public dispatch def referRelation( 63 dispatch def CharSequence referRelation(RelationDeclaration referred, String sourceVariable, String targetVariable,
59 RelationDeclaration referred, 64 Modality modality, Map<String, PQuery> fqn2PQuery) {
60 String sourceVariable, 65 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 } 66 }
67 public dispatch def referRelation( 67
68 RelationDefinition referred, 68 dispatch def CharSequence referRelation(RelationDefinition referred, String sourceVariable, String targetVariable,
69 String sourceVariable, 69 Modality modality, Map<String, PQuery> fqn2PQuery) {
70 String targetVariable, 70 val pattern = referred.annotations.filter(TransfomedViatraQuery).head.patternFullyQualifiedName.lookup(
71 Modality modality, 71 fqn2PQuery)
72 Map<String,PQuery> fqn2PQuery) 72 return this.relationDefinitionIndexer.referPattern(pattern, #[sourceVariable, targetVariable], modality, true,
73 { 73 false)
74 val pattern = referred.annotations.filter(TransfomedViatraQuery).head.patternFullyQualifiedName.lookup(fqn2PQuery)
75 return this.relationDefinitionIndexer.referPattern(pattern,#[sourceVariable,targetVariable],modality,true,false)
76 } 74 }
77 75
78 def public referRelationByName(EReference reference, 76 def referRelationByName(EReference reference, String sourceVariable, String targetVariable, Modality modality) {
79 String sourceVariable, 77 '''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 } 78 }
86 79
87 def public CharSequence referAttributeByName(EAttribute attribute, 80 def CharSequence referAttributeByName(EAttribute attribute, String sourceVariable, String targetVariable,
88 String sourceVariable, 81 Modality modality) {
89 String targetVariable, 82 '''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 } 83 }
95 84
96 public def canonizeName(String name) { 85 def canonizeName(String name) {
97 name.split(' ').join('_') 86 name.split(' ').join('_')
98 } 87 }
99 88
100 public def lowerMultiplicities(LogicProblem problem) { 89 def wfQueries(LogicProblem problem) {
101 problem.assertions.map[annotations].flatten.filter(LowerMultiplicityAssertion).filter[!it.relation.isDerived] 90 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 } 91 }
109 public def getContainments(LogicProblem p) { 92
93 def getContainments(LogicProblem p) {
110 return p.containmentHierarchies.head.containmentRelations 94 return p.containmentHierarchies.head.containmentRelations
111 } 95 }
112 public def getInverseRelations(LogicProblem p) { 96
97 def getInverseRelations(LogicProblem p) {
113 val inverseRelations = new HashMap 98 val inverseRelations = new HashMap
114 p.annotations.filter(InverseRelationAssertion).forEach[ 99 p.annotations.filter(InverseRelationAssertion).forEach [
115 inverseRelations.put(it.inverseA,it.inverseB) 100 inverseRelations.put(it.inverseA, it.inverseB)
116 inverseRelations.put(it.inverseB,it.inverseA) 101 inverseRelations.put(it.inverseB, it.inverseA)
117 ] 102 ]
118 return inverseRelations 103 return inverseRelations
119 } 104 }
120 public def isRepresentative(Relation relation, Relation inverse) { 105
121 if(inverse == null) { 106 def isRepresentative(Relation relation, Relation inverse) {
107 if (inverse === null) {
122 return true 108 return true
123 } else { 109 } else {
124 relation.name.compareTo(inverse.name)<1 110 relation.name.compareTo(inverse.name) < 1
125 } 111 }
126 } 112 }
127 113
128 public def isDerived(Relation relation) { 114 def isDerived(Relation relation) {
129 relation.annotations.exists[it instanceof DefinedByDerivedFeature] 115 relation.annotations.exists[it instanceof DefinedByDerivedFeature]
130 } 116 }
131 public def getDerivedDefinition(RelationDeclaration relation) { 117
118 def getDerivedDefinition(RelationDeclaration relation) {
132 relation.annotations.filter(DefinedByDerivedFeature).head.query 119 relation.annotations.filter(DefinedByDerivedFeature).head.query
133 } 120 }
134 121
135 private def allTypeReferences(LogicProblem problem) { 122 private def allTypeReferences(LogicProblem problem) {
136 problem.eAllContents.filter(TypeReference).toIterable 123 problem.eAllContents.filter(TypeReference).toIterable
137 } 124 }
125
138 protected def hasBoolean(LogicProblem problem) { 126 protected def hasBoolean(LogicProblem problem) {
139 problem.allTypeReferences.exists[it instanceof BoolTypeReference] 127 problem.allTypeReferences.exists[it instanceof BoolTypeReference]
140 } 128 }
129
141 protected def hasInteger(LogicProblem problem) { 130 protected def hasInteger(LogicProblem problem) {
142 problem.allTypeReferences.exists[it instanceof IntTypeReference] 131 problem.allTypeReferences.exists[it instanceof IntTypeReference]
143 } 132 }
133
144 protected def hasReal(LogicProblem problem) { 134 protected def hasReal(LogicProblem problem) {
145 problem.allTypeReferences.exists[it instanceof RealTypeReference] 135 problem.allTypeReferences.exists[it instanceof RealTypeReference]
146 } 136 }
137
147 protected def hasString(LogicProblem problem) { 138 protected def hasString(LogicProblem problem) {
148 problem.allTypeReferences.exists[it instanceof StringTypeReference] 139 problem.allTypeReferences.exists[it instanceof StringTypeReference]
149 } 140 }
150 141
151 public def transformBaseProperties( 142 def transformBaseProperties(
152 LogicProblem problem, 143 LogicProblem problem,
153 PartialInterpretation emptySolution, 144 PartialInterpretation emptySolution,
154 Map<String,PQuery> fqn2PQuery, 145 Map<String, PQuery> fqn2PQuery,
155 TypeAnalysisResult typeAnalysisResult 146 TypeAnalysisResult typeAnalysisResult,
147 RelationConstraints constraints
156 ) { 148 ) {
157 149
158 return ''' 150 return '''
159 import epackage "http://www.bme.hu/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage" 151 import epackage "http://www.bme.hu/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage"
160 import epackage "http://www.bme.hu/mit/inf/dslreasoner/logic/model/problem" 152 import epackage "http://www.bme.hu/mit/inf/dslreasoner/logic/model/problem"
@@ -188,7 +180,7 @@ class PatternGenerator {
188 180
189 private pattern elementCloseWorld(element:DefinedElement) { 181 private pattern elementCloseWorld(element:DefinedElement) {
190 PartialInterpretation.openWorldElements(i,element); 182 PartialInterpretation.openWorldElements(i,element);
191 PartialInterpretation.maxNewElements(i,0); 183 PartialInterpretation.maxNewElements(i,0);
192 } or { 184 } or {
193 Scope.targetTypeInterpretation(scope,interpretation); 185 Scope.targetTypeInterpretation(scope,interpretation);
194 PartialTypeInterpratation.elements(interpretation,element); 186 PartialTypeInterpratation.elements(interpretation,element);
@@ -221,7 +213,7 @@ class PatternGenerator {
221 ////////// 213 //////////
222 // 1.1.1 primitive Type Indexers 214 // 1.1.1 primitive Type Indexers
223 ////////// 215 //////////
224««« pattern instanceofBoolean(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) { 216 ««« pattern instanceofBoolean(problem:LogicProblem, interpretation:PartialInterpretation, element:DefinedElement) {
225««« find interpretation(problem,interpretation); 217««« find interpretation(problem,interpretation);
226««« PartialInterpretation.booleanelements(interpretation,element); 218««« PartialInterpretation.booleanelements(interpretation,element);
227««« } 219««« }
@@ -279,7 +271,7 @@ class PatternGenerator {
279 ////////// 271 //////////
280 // 3.1 Unfinishedness Measured by Multiplicity 272 // 3.1 Unfinishedness Measured by Multiplicity
281 ////////// 273 //////////
282 «unfinishedIndexer.generateUnfinishedMultiplicityQueries(problem,fqn2PQuery)» 274 «unfinishedIndexer.generateUnfinishedMultiplicityQueries(constraints.multiplicityConstraints,fqn2PQuery)»
283 275
284 ////////// 276 //////////
285 // 3.2 Unfinishedness Measured by WF Queries 277 // 3.2 Unfinishedness Measured by WF Queries
@@ -302,6 +294,6 @@ class PatternGenerator {
302 // 4.3 Relation refinement 294 // 4.3 Relation refinement
303 ////////// 295 //////////
304 «relationRefinementGenerator.generateRefineReference(problem)» 296 «relationRefinementGenerator.generateRefineReference(problem)»
305 ''' 297 '''
306 } 298 }
307} 299}
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..eadf0ae0 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
@@ -2,16 +2,23 @@ package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns
2 2
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation 3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration 4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type 6import 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.logic.model.logicproblem.LogicProblem
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics 9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysis 10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysis
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult 11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeAnalysisResult
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod 12import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod
13import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraints
14import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationMultiplicityConstraint
15import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.util.ParseUtil 16import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.util.ParseUtil
12import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 17import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
13import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace 18import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace
19import java.util.Collection
14import java.util.Map 20import java.util.Map
21import java.util.Set
15import org.eclipse.viatra.query.runtime.api.IPatternMatch 22import org.eclipse.viatra.query.runtime.api.IPatternMatch
16import org.eclipse.viatra.query.runtime.api.IQuerySpecification 23import org.eclipse.viatra.query.runtime.api.IQuerySpecification
17import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher 24import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
@@ -19,79 +26,115 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
19import org.eclipse.xtend.lib.annotations.Data 26import org.eclipse.xtend.lib.annotations.Data
20 27
21import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* 28import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
22import java.util.Collection
23import java.util.Set
24 29
25@Data class GeneratedPatterns { 30@Data
26 public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWFQueries 31class GeneratedPatterns {
27 public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFQueries 32 public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWFQueries
28 public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedMulticiplicityQueries 33 public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFQueries
29 public Map<ObjectCreationPrecondition, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineObjectQueries 34 public Map<RelationMultiplicityConstraint, UnifinishedMultiplicityQueries> multiplicityConstraintQueries
30 public Map<? extends Type, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineTypeQueries 35 public IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> hasElementInContainmentQuery
31 public Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refinerelationQueries 36 public Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedMulticiplicityQueries
37 public Map<ObjectCreationPrecondition, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineObjectQueries
38 public Map<? extends Type, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refineTypeQueries
39 public Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> refinerelationQueries
40 public Map<RelationDefinition, ModalPatternQueries> modalRelationQueries
32 public Collection<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allQueries 41 public Collection<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allQueries
33} 42}
34 43
44@Data
45class ModalPatternQueries {
46 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> mayQuery
47 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> mustQuery
48 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> currentQuery
49}
50
51@Data
52class UnifinishedMultiplicityQueries {
53 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> unfinishedMultiplicityQuery
54 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> unrepairableMultiplicityQuery
55 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> remainingInverseMultiplicityQuery
56 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> remainingContentsQuery
57}
58
35class PatternProvider { 59class PatternProvider {
36 60
37 val TypeAnalysis typeAnalysis = new TypeAnalysis 61 val TypeAnalysis typeAnalysis = new TypeAnalysis
38 62
39 public def generateQueries( 63 def generateQueries(LogicProblem problem, PartialInterpretation emptySolution, ModelGenerationStatistics statistics,
40 LogicProblem problem, 64 Set<PQuery> existingQueries, ReasonerWorkspace workspace, TypeInferenceMethod typeInferenceMethod,
41 PartialInterpretation emptySolution, 65 ScopePropagatorStrategy scopePropagatorStrategy, RelationConstraints relationConstraints, boolean writeToFile) {
42 ModelGenerationStatistics statistics,
43 Set<PQuery> existingQueries,
44 ReasonerWorkspace workspace,
45 TypeInferenceMethod typeInferenceMethod,
46 boolean writeToFile)
47 {
48 val fqn2Query = existingQueries.toMap[it.fullyQualifiedName] 66 val fqn2Query = existingQueries.toMap[it.fullyQualifiedName]
49 val PatternGenerator patternGenerator = new PatternGenerator(typeInferenceMethod) 67 val PatternGenerator patternGenerator = new PatternGenerator(typeInferenceMethod, scopePropagatorStrategy)
50 val typeAnalysisResult = if(patternGenerator.requiresTypeAnalysis) { 68 val typeAnalysisResult = if (patternGenerator.requiresTypeAnalysis) {
51 val startTime = System.nanoTime 69 val startTime = System.nanoTime
52 val result = typeAnalysis.performTypeAnalysis(problem,emptySolution) 70 val result = typeAnalysis.performTypeAnalysis(problem, emptySolution)
53 val typeAnalysisTime = System.nanoTime - startTime 71 val typeAnalysisTime = System.nanoTime - startTime
54 statistics.PreliminaryTypeAnalisisTime = typeAnalysisTime 72 statistics.preliminaryTypeAnalisisTime = typeAnalysisTime
55 result 73 result
56 } else { 74 } else {
57 null 75 null
58 } 76 }
59 val baseIndexerFile = patternGenerator.transformBaseProperties(problem,emptySolution,fqn2Query,typeAnalysisResult) 77 val baseIndexerFile = patternGenerator.transformBaseProperties(problem, emptySolution, fqn2Query,
60 if(writeToFile) { 78 typeAnalysisResult, relationConstraints)
61 workspace.writeText('''generated3valued.vql_deactivated''',baseIndexerFile) 79 if (writeToFile) {
80 workspace.writeText('''generated3valued.vql_deactivated''', baseIndexerFile)
62 } 81 }
63 val ParseUtil parseUtil = new ParseUtil 82 val ParseUtil parseUtil = new ParseUtil
64 val generatedQueries = parseUtil.parse(baseIndexerFile) 83 val generatedQueries = parseUtil.parse(baseIndexerFile)
65 val runtimeQueries = calclulateRuntimeQueries(patternGenerator,problem,emptySolution,typeAnalysisResult,generatedQueries); 84 val runtimeQueries = calclulateRuntimeQueries(patternGenerator, problem, emptySolution, typeAnalysisResult,
85 relationConstraints, generatedQueries)
66 return runtimeQueries 86 return runtimeQueries
67 } 87 }
68 88
69 private def GeneratedPatterns calclulateRuntimeQueries( 89 private def GeneratedPatterns calclulateRuntimeQueries(
70 PatternGenerator patternGenerator, 90 PatternGenerator patternGenerator,
71 LogicProblem problem, 91 LogicProblem problem,
72 PartialInterpretation emptySolution, 92 PartialInterpretation emptySolution,
73 TypeAnalysisResult typeAnalysisResult, 93 TypeAnalysisResult typeAnalysisResult,
74 Map<String, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> queries 94 RelationConstraints relationConstraints,
95 Map<String, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> queries
75 ) { 96 ) {
76 val Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> 97 val invalidWFQueries = patternGenerator.invalidIndexer.getInvalidateByWfQueryNames(problem).mapValues [
77 invalidWFQueries = patternGenerator.invalidIndexer.getInvalidateByWfQueryNames(problem).mapValues[it.lookup(queries)] 98 it.lookup(queries)
78 val Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> 99 ]
79 unfinishedWFQueries = patternGenerator.unfinishedIndexer.getUnfinishedWFQueryNames(problem).mapValues[it.lookup(queries)] 100 val unfinishedWFQueries = patternGenerator.unfinishedIndexer.getUnfinishedWFQueryNames(problem).mapValues [
80 val Map<Relation, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> 101 it.lookup(queries)
81 unfinishedMultiplicityQueries = patternGenerator.unfinishedIndexer.getUnfinishedMultiplicityQueries(problem).mapValues[it.lookup(queries)] 102 ]
82 val Map<ObjectCreationPrecondition, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> 103 val multiplicityConstraintQueries = patternGenerator.unfinishedIndexer.getUnfinishedMultiplicityQueries(
83 refineObjectsQueries = patternGenerator.typeRefinementGenerator.getRefineObjectQueryNames(problem,emptySolution,typeAnalysisResult).mapValues[it.lookup(queries)] 104 relationConstraints.multiplicityConstraints).mapValues [
84 val Map<? extends Type, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> 105 new UnifinishedMultiplicityQueries(unfinishedMultiplicityQueryName?.lookup(queries),
85 refineTypeQueries = patternGenerator.typeRefinementGenerator.getRefineTypeQueryNames(problem,emptySolution,typeAnalysisResult).mapValues[it.lookup(queries)] 106 unrepairableMultiplicityQueryName?.lookup(queries),
86 val Map<Pair<RelationDeclaration, Relation>, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> 107 remainingInverseMultiplicityQueryName?.lookup(queries), remainingContentsQueryName?.lookup(queries))
87 refineRelationQueries = patternGenerator.relationRefinementGenerator.getRefineRelationQueries(problem).mapValues[it.lookup(queries)] 108 ]
109 val hasElementInContainmentQuery = patternGenerator.typeRefinementGenerator.hasElementInContainmentName.lookup(
110 queries)
111 val unfinishedMultiplicityQueries = multiplicityConstraintQueries.entrySet.filter [
112 value.unfinishedMultiplicityQuery !== null
113 ].toMap([key.relation], [value.unfinishedMultiplicityQuery])
114 val refineObjectsQueries = patternGenerator.typeRefinementGenerator.
115 getRefineObjectQueryNames(problem, emptySolution, typeAnalysisResult).mapValues[it.lookup(queries)]
116 val refineTypeQueries = patternGenerator.typeRefinementGenerator.getRefineTypeQueryNames(problem, emptySolution,
117 typeAnalysisResult).mapValues[it.lookup(queries)]
118 val refineRelationQueries = patternGenerator.relationRefinementGenerator.getRefineRelationQueries(problem).
119 mapValues[it.lookup(queries)]
120 val modalRelationQueries = problem.relations.filter(RelationDefinition).toMap([it], [ relationDefinition |
121 val indexer = patternGenerator.relationDefinitionIndexer
122 new ModalPatternQueries(
123 indexer.relationDefinitionName(relationDefinition, Modality.MAY).lookup(queries),
124 indexer.relationDefinitionName(relationDefinition, Modality.MUST).lookup(queries),
125 indexer.relationDefinitionName(relationDefinition, Modality.CURRENT).lookup(queries)
126 )
127 ])
88 return new GeneratedPatterns( 128 return new GeneratedPatterns(
89 invalidWFQueries, 129 invalidWFQueries,
90 unfinishedWFQueries, 130 unfinishedWFQueries,
131 multiplicityConstraintQueries,
132 hasElementInContainmentQuery,
91 unfinishedMultiplicityQueries, 133 unfinishedMultiplicityQueries,
92 refineObjectsQueries, 134 refineObjectsQueries,
93 refineTypeQueries, 135 refineTypeQueries,
94 refineRelationQueries, 136 refineRelationQueries,
137 modalRelationQueries,
95 queries.values 138 queries.values
96 ) 139 )
97 } 140 }
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..cedcec5a 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
@@ -71,7 +71,7 @@ class RelationDefinitionIndexer {
71 ] 71 ]
72 } 72 }
73 73
74 private def relationDefinitionName(RelationDefinition relation, Modality modality) 74 def String relationDefinitionName(RelationDefinition relation, Modality modality)
75 '''«modality.name.toLowerCase»InRelation_«base.canonizeName(relation.name)»''' 75 '''«modality.name.toLowerCase»InRelation_«base.canonizeName(relation.name)»'''
76 76
77 private def canonizeName(PVariable v) { 77 private def canonizeName(PVariable v) {
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..fa73c861 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
@@ -9,77 +9,71 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference
9 9
10class RelationRefinementGenerator { 10class RelationRefinementGenerator {
11 PatternGenerator base; 11 PatternGenerator base;
12
12 public new(PatternGenerator base) { 13 public new(PatternGenerator base) {
13 this.base = base 14 this.base = base
14 } 15 }
15 16
16 def CharSequence generateRefineReference(LogicProblem p) { 17 def CharSequence generateRefineReference(LogicProblem p) '''
17 return ''' 18 «FOR relationRefinement : this.getRelationRefinements(p)»
18 «FOR relationRefinement: this.getRelationRefinements(p)» 19 pattern «relationRefinementQueryName(relationRefinement.key,relationRefinement.value)»(
19 pattern «relationRefinementQueryName(relationRefinement.key,relationRefinement.value)»( 20 problem:LogicProblem, interpretation:PartialInterpretation,
20 problem:LogicProblem, interpretation:PartialInterpretation, 21 relationIterpretation:PartialRelationInterpretation«IF relationRefinement.value !== null», oppositeInterpretation:PartialRelationInterpretation«ENDIF»,
21 relationIterpretation:PartialRelationInterpretation«IF relationRefinement.value != null», oppositeInterpretation:PartialRelationInterpretation«ENDIF», 22 from: DefinedElement, to: DefinedElement)
22 from: DefinedElement, to: DefinedElement) 23 {
23 { 24 find interpretation(problem,interpretation);
24 find interpretation(problem,interpretation); 25 PartialInterpretation.partialrelationinterpretation(interpretation,relationIterpretation);
25 PartialInterpretation.partialrelationinterpretation(interpretation,relationIterpretation); 26 PartialRelationInterpretation.interpretationOf.name(relationIterpretation,"«relationRefinement.key.name»");
26 PartialRelationInterpretation.interpretationOf.name(relationIterpretation,"«relationRefinement.key.name»"); 27 «IF relationRefinement.value !== null»
27 «IF relationRefinement.value != null» 28 PartialInterpretation.partialrelationinterpretation(interpretation,oppositeInterpretation);
28 PartialInterpretation.partialrelationinterpretation(interpretation,oppositeInterpretation); 29 PartialRelationInterpretation.interpretationOf.name(oppositeInterpretation,"«relationRefinement.value.name»");
29 PartialRelationInterpretation.interpretationOf.name(oppositeInterpretation,"«relationRefinement.value.name»"); 30 «ENDIF»
30 «ENDIF» 31 find mustExist(problem, interpretation, from);
31 find mustExist(problem, interpretation, from); 32 find mustExist(problem, interpretation, to);
32 find mustExist(problem, interpretation, to); 33 «base.typeIndexer.referInstanceOfByReference(relationRefinement.key.parameters.get(0), Modality::MUST,"from")»
33 «base.typeIndexer.referInstanceOfByReference(relationRefinement.key.parameters.get(0), Modality::MUST,"from")» 34 «base.typeIndexer.referInstanceOfByReference(relationRefinement.key.parameters.get(1), Modality::MUST,"to")»
34 «base.typeIndexer.referInstanceOfByReference(relationRefinement.key.parameters.get(1), Modality::MUST,"to")» 35 «base.relationDeclarationIndexer.referRelation(relationRefinement.key,"from","to",Modality.MAY)»
35 «base.relationDeclarationIndexer.referRelation(relationRefinement.key,"from","to",Modality.MAY)» 36 neg «base.relationDeclarationIndexer.referRelation(relationRefinement.key,"from","to",Modality.MUST)»
36 neg «base.relationDeclarationIndexer.referRelation(relationRefinement.key,"from","to",Modality.MUST)» 37 }
37 }
38 «ENDFOR» 38 «ENDFOR»
39 ''' 39 '''
40 } 40
41
42 def String relationRefinementQueryName(RelationDeclaration relation, Relation inverseRelation) { 41 def String relationRefinementQueryName(RelationDeclaration relation, Relation inverseRelation) {
43 '''«IF inverseRelation != null 42 '''«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 } 43 }
48 44
49 def referRefinementQuery(RelationDeclaration relation, Relation inverseRelation, String relInterpretationName, 45 def referRefinementQuery(RelationDeclaration relation, Relation inverseRelation, String relInterpretationName,
50 String inverseInterpretationName, String sourceName, String targetName) 46 String inverseInterpretationName, String sourceName,
51 '''find «this.relationRefinementQueryName(relation,inverseRelation)»(problem, interpretation, «relInterpretationName», «IF inverseRelation != null»inverseInterpretationName, «ENDIF»«sourceName», «targetName»);''' 47 String targetName) '''find «this.relationRefinementQueryName(relation,inverseRelation)»(problem, interpretation, «relInterpretationName», «IF inverseRelation !== null»inverseInterpretationName, «ENDIF»«sourceName», «targetName»);'''
52 48
53 def getRefineRelationQueries(LogicProblem p) { 49 def getRefineRelationQueries(LogicProblem p) {
54// val containmentRelations = p.containmentHierarchies.map[containmentRelations].flatten.toSet 50// val containmentRelations = p.containmentHierarchies.map[containmentRelations].flatten.toSet
55// p.relations.filter(RelationDeclaration).filter[!containmentRelations.contains(it)].toInvertedMap['''refineRelation_«base.canonizeName(it.name)»'''] 51// p.relations.filter(RelationDeclaration).filter[!containmentRelations.contains(it)].toInvertedMap['''refineRelation_«base.canonizeName(it.name)»''']
56 /* 52 /*
57 val res = new LinkedHashMap 53 * val res = new LinkedHashMap
58 for(relation: getRelationRefinements(p)) { 54 * for(relation: getRelationRefinements(p)) {
59 if(inverseRelations.containsKey(relation)) { 55 * if(inverseRelations.containsKey(relation)) {
60 val name = '''refineRelation_«base.canonizeName(relation.name)»_and_«base.canonizeName(inverseRelations.get(relation).name)»''' 56 * val name = '''refineRelation_«base.canonizeName(relation.name)»_and_«base.canonizeName(inverseRelations.get(relation).name)»'''
61 res.put(relation -> inverseRelations.get(relation),name) 57 * res.put(relation -> inverseRelations.get(relation),name)
62 } else { 58 * } else {
63 val name = '''refineRelation_«base.canonizeName(relation.name)»''' 59 * val name = '''refineRelation_«base.canonizeName(relation.name)»'''
64 res.put(relation -> null,name) 60 * res.put(relation -> null,name)
65 } 61 * }
66 } 62 * }
67 return res*/ 63 return res*/
68 64 getRelationRefinements(p).toInvertedMap[relationRefinementQueryName(it.key, it.value)]
69 getRelationRefinements(p).toInvertedMap[relationRefinementQueryName(it.key,it.value)]
70 } 65 }
71
72 66
73 def getRelationRefinements(LogicProblem p) { 67 def getRelationRefinements(LogicProblem p) {
74 val inverses = base.getInverseRelations(p) 68 val inverses = base.getInverseRelations(p)
75 val containments = base.getContainments(p) 69 val containments = base.getContainments(p)
76 val list = new LinkedList 70 val list = new LinkedList
77 for(relation : p.relations.filter(RelationDeclaration)) { 71 for (relation : p.relations.filter(RelationDeclaration)) {
78 if(!containments.contains(relation)) { 72 if (!containments.contains(relation)) {
79 if(inverses.containsKey(relation)) { 73 if (inverses.containsKey(relation)) {
80 val inverse = inverses.get(relation) 74 val inverse = inverses.get(relation)
81 if(!containments.contains(inverse)) { 75 if (!containments.contains(inverse)) {
82 if(base.isRepresentative(relation,inverse)) { 76 if (base.isRepresentative(relation, inverse)) {
83 list += (relation -> inverse) 77 list += (relation -> inverse)
84 } 78 }
85 } 79 }
@@ -90,4 +84,4 @@ class RelationRefinementGenerator {
90 } 84 }
91 return list 85 return list
92 } 86 }
93} \ No newline at end of file 87}
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..7d687e99 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,122 @@
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}
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..15b5a047 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,198 @@
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
4import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem 3import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
5import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransformedViatraWellformednessConstraint 4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality
5import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationMultiplicityConstraint
6import java.util.LinkedHashMap
7import java.util.List
6import java.util.Map 8import java.util.Map
7import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery 9import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery
10import org.eclipse.xtend.lib.annotations.Data
8 11
9import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* 12import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
10import java.util.LinkedHashMap 13
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.Modality 14@Data
12import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference 15class UnifinishedMultiplicityQueryNames {
16 val String unfinishedMultiplicityQueryName
17 val String unrepairableMultiplicityQueryName
18 val String remainingInverseMultiplicityQueryName
19 val String remainingContentsQueryName
20}
13 21
14class UnfinishedIndexer { 22class UnfinishedIndexer {
15 val PatternGenerator base 23 val PatternGenerator base
16 24 val boolean indexUpperMultiplicities
17 new(PatternGenerator patternGenerator) { 25
26 new(PatternGenerator patternGenerator, boolean indexUpperMultiplicities) {
18 this.base = patternGenerator 27 this.base = patternGenerator
28 this.indexUpperMultiplicities = indexUpperMultiplicities
19 } 29 }
20 30
21 def generateUnfinishedWfQueries(LogicProblem problem, Map<String,PQuery> fqn2PQuery) { 31 def generateUnfinishedWfQueries(LogicProblem problem, Map<String, PQuery> fqn2PQuery) {
22 val wfQueries = base.wfQueries(problem) 32 val wfQueries = base.wfQueries(problem)
23 ''' 33 '''
24 «FOR wfQuery: wfQueries» 34 «FOR wfQuery : wfQueries»
25 pattern unfinishedBy_«base.canonizeName(wfQuery.target.name)»(problem:LogicProblem, interpretation:PartialInterpretation, 35 pattern unfinishedBy_«base.canonizeName(wfQuery.target.name)»(problem:LogicProblem, interpretation:PartialInterpretation,
26 «FOR param : wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery).parameters SEPARATOR ', '»var_«param.name»«ENDFOR») 36 «FOR param : wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery).parameters SEPARATOR ', '»var_«param.name»«ENDFOR»)
27 { 37 {
28 «base.relationDefinitionIndexer.referPattern( 38 «base.relationDefinitionIndexer.referPattern(
29 wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery), 39 wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery),
30 wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery).parameters.map['''var_«it.name»'''], 40 wfQuery.patternFullyQualifiedName.lookup(fqn2PQuery).parameters.map['''var_«it.name»'''],
31 Modality.CURRENT, 41 Modality.CURRENT,
32 true,false)» 42 true,false)»
33 } 43 }
34 «ENDFOR» 44 «ENDFOR»
35 ''' 45 '''
36 } 46 }
47
37 def getUnfinishedWFQueryNames(LogicProblem problem) { 48 def getUnfinishedWFQueryNames(LogicProblem problem) {
38 val wfQueries = base.wfQueries(problem) 49 val wfQueries = base.wfQueries(problem)
39 val map = new LinkedHashMap 50 val map = new LinkedHashMap
40 for(wfQuery : wfQueries) { 51 for (wfQuery : wfQueries) {
41 map.put(wfQuery.target,'''unfinishedBy_«base.canonizeName(wfQuery.target.name)»''') 52 map.put(wfQuery.target, '''unfinishedBy_«base.canonizeName(wfQuery.target.name)»''')
42 } 53 }
43 return map 54 return map
44 } 55 }
45 def generateUnfinishedMultiplicityQueries(LogicProblem problem, Map<String,PQuery> fqn2PQuery) { 56
46 val lowerMultiplicities = base.lowerMultiplicities(problem) 57 def generateUnfinishedMultiplicityQueries(List<RelationMultiplicityConstraint> constraints,
47 return ''' 58 Map<String, PQuery> fqn2PQuery) '''
48 «FOR lowerMultiplicity : lowerMultiplicities» 59 «FOR constraint : constraints»
49 pattern «unfinishedMultiplicityName(lowerMultiplicity)»(problem:LogicProblem, interpretation:PartialInterpretation, relationIterpretation:PartialRelationInterpretation, object:DefinedElement,missingMultiplicity) { 60 «IF constraint.constrainsUnfinished»
50 find interpretation(problem,interpretation); 61 private pattern «unfinishedMultiplicityName(constraint)»_helper(problem:LogicProblem, interpretation:PartialInterpretation, object:DefinedElement, missingMultiplicity:java Integer) {
51 PartialInterpretation.partialrelationinterpretation(interpretation,relationIterpretation); 62 find interpretation(problem,interpretation);
52 PartialRelationInterpretation.interpretationOf.name(relationIterpretation,"«lowerMultiplicity.relation.name»"); 63 find mustExist(problem,interpretation,object);
53 «base.typeIndexer.referInstanceOf(lowerMultiplicity.firstParamTypeOfRelation,Modality::MUST,"object")» 64 «base.typeIndexer.referInstanceOf(constraint.sourceType,Modality::MUST,"object")»
54 numberOfExistingReferences == count «base.referRelation(lowerMultiplicity.relation,"object","_",Modality.MUST,fqn2PQuery)» 65 numberOfExistingReferences == count «base.referRelation(constraint.relation,"object","_",Modality.MUST,fqn2PQuery)»
55 check(numberOfExistingReferences < «lowerMultiplicity.lower»); 66 check(numberOfExistingReferences < «constraint.lowerBound»);
56 missingMultiplicity == eval(«lowerMultiplicity.lower»-numberOfExistingReferences); 67 missingMultiplicity == eval(«constraint.lowerBound»-numberOfExistingReferences);
57 } 68 }
69
70 pattern «unfinishedMultiplicityName(constraint)»(problem:LogicProblem, interpretation:PartialInterpretation, missingMultiplicity:java Integer) {
71 find interpretation(problem,interpretation);
72 missingMultiplicity == sum find «unfinishedMultiplicityName(constraint)»_helper(problem, interpretation, _, #_);
73 }
74 «ENDIF»
75
76 «IF indexUpperMultiplicities»
77 «IF constraint.constrainsUnrepairable || constraint.constrainsRemainingInverse»
78 private pattern «repairMatchName(constraint)»(problem:LogicProblem, interpretation:PartialInterpretation, source:DefinedElement, target:DefinedElement) {
79 find interpretation(problem,interpretation);
80 find mustExist(problem,interpretation,source);
81 «base.typeIndexer.referInstanceOf(constraint.sourceType,Modality::MUST,"source")»
82 find mustExist(problem,interpretation,target);
83 «base.typeIndexer.referInstanceOf(constraint.targetType,Modality::MUST,"target")»
84 neg «base.referRelation(constraint.relation,"source","target",Modality.MUST,fqn2PQuery)»
85 «base.referRelation(constraint.relation,"source","target",Modality.MAY,fqn2PQuery)»
86 }
87 «ENDIF»
88
89 «IF constraint.constrainsUnrepairable»
90 private pattern «unrepairableMultiplicityName(constraint)»_helper(problem:LogicProblem, interpretation:PartialInterpretation, object:DefinedElement, unrepairableMultiplicity:java Integer) {
91 find interpretation(problem,interpretation);
92 find mustExist(problem,interpretation,object);
93 «base.typeIndexer.referInstanceOf(constraint.sourceType,Modality::MUST,"object")»
94 find «unfinishedMultiplicityName(constraint)»_helper(problem, interpretation, object, missingMultiplicity);
95 numberOfRepairMatches == count find «repairMatchName(constraint)»(problem, interpretation, object, _);
96 check(numberOfRepairMatches < missingMultiplicity);
97 unrepairableMultiplicity == eval(missingMultiplicity-numberOfRepairMatches);
98 }
99
100 private pattern «unrepairableMultiplicityName(constraint)»(problem:LogicProblem, interpretation:PartialInterpretation, unrepairableMultiplicity:java Integer) {
101 find interpretation(problem,interpretation);
102 unrepairableMultiplicity == max find «unrepairableMultiplicityName(constraint)»_helper(problem, interpretation, _, #_);
103 } or {
104 find interpretation(problem,interpretation);
105 neg find «unrepairableMultiplicityName(constraint)»_helper(problem, interpretation, _, _);
106 unrepairableMultiplicity == 0;
107 }
108 «ENDIF»
109
110 «IF constraint.constrainsRemainingInverse»
111 private pattern «remainingMultiplicityName(constraint)»_helper(problem:LogicProblem, interpretation:PartialInterpretation, object:DefinedElement, remainingMultiplicity:java Integer) {
112 find interpretation(problem,interpretation);
113 find mustExist(problem,interpretation,object);
114 «base.typeIndexer.referInstanceOf(constraint.targetType,Modality::MUST,"object")»
115 numberOfExistingReferences == count «base.referRelation(constraint.relation,"_","object",Modality.MUST,fqn2PQuery)»
116 check(numberOfExistingReferences < «constraint.inverseUpperBound»);
117 numberOfRepairMatches == count find «repairMatchName(constraint)»(problem, interpretation, _, object);
118 remainingMultiplicity == eval(Math.min(«constraint.inverseUpperBound»-numberOfExistingReferences, numberOfRepairMatches));
119 }
120
121 pattern «remainingMultiplicityName(constraint)»(problem:LogicProblem, interpretation:PartialInterpretation, remainingMultiplicity:java Integer) {
122 find interpretation(problem,interpretation);
123 remainingMultiplicity == sum find «remainingMultiplicityName(constraint)»_helper(problem, interpretation, _, #_);
124 }
125 «ENDIF»
126
127 «IF constraint.constrainsRemainingContents»
128 «IF constraint.upperBoundFinite»
129 private pattern «remainingContentsName(constraint)»_helper(problem:LogicProblem, interpretation:PartialInterpretation, object:DefinedElement, remainingMultiplicity:java Integer) {
130 find interpretation(problem,interpretation);
131 find mustExist(problem,interpretation,object);
132 «base.typeIndexer.referInstanceOf(constraint.sourceType,Modality::MUST,"object")»
133 numberOfExistingReferences == count «base.referRelation(constraint.relation,"object","_",Modality.MUST,fqn2PQuery)»
134 check(numberOfExistingReferences < «constraint.upperBound»);
135 remainingMultiplicity == eval(«constraint.upperBound»-numberOfExistingReferences);
136 }
137
138 pattern «remainingContentsName(constraint)»(problem:LogicProblem, interpretation:PartialInterpretation, remainingMultiplicity:java Integer) {
139 find interpretation(problem,interpretation);
140 remainingMultiplicity == sum find «remainingContentsName(constraint)»_helper(problem, interpretation, _, #_);
141 }
142 «ELSE»
143 pattern «remainingContentsName(constraint)»_helper(problem:LogicProblem, interpretation:PartialInterpretation) {
144 find interpretation(problem,interpretation);
145 find mustExist(problem,interpretation,object);
146 «base.typeIndexer.referInstanceOf(constraint.sourceType,Modality::MUST,"object")»
147 }
148
149 pattern «remainingContentsName(constraint)»(problem:LogicProblem, interpretation:PartialInterpretation, remainingMultiplicity:java Integer) {
150 find interpretation(problem,interpretation);
151 find «remainingContentsName(constraint)»_helper(problem, interpretation);
152 remainingMultiplicity == -1;
153 } or {
154 find interpretation(problem,interpretation);
155 neg find «remainingContentsName(constraint)»_helper(problem, interpretation);
156 remainingMultiplicity == 0;
157 }
158 «ENDIF»
159 «ENDIF»
160 «ENDIF»
58 «ENDFOR» 161 «ENDFOR»
59 ''' 162 '''
60 } 163
61 def String unfinishedMultiplicityName(LowerMultiplicityAssertion lowerMultiplicityAssertion) 164 def String unfinishedMultiplicityName(
62 '''unfinishedLowerMultiplicity_«base.canonizeName(lowerMultiplicityAssertion.relation.name)»''' 165 RelationMultiplicityConstraint constraint) '''unfinishedLowerMultiplicity_«base.canonizeName(constraint.relation.name)»'''
63 166
64 def public referUnfinishedMultiplicityQuery(LowerMultiplicityAssertion lowerMultiplicityAssertion) 167 def String unrepairableMultiplicityName(
65 '''find «unfinishedMultiplicityName(lowerMultiplicityAssertion)»(problem, interpretation ,object, missingMultiplicity);''' 168 RelationMultiplicityConstraint constraint) '''unrepairableLowerMultiplicity_«base.canonizeName(constraint.relation.name)»'''
66 169
67 def getFirstParamTypeOfRelation(LowerMultiplicityAssertion lowerMultiplicityAssertion) { 170 private def String repairMatchName(
68 val parameters = lowerMultiplicityAssertion.relation.parameters 171 RelationMultiplicityConstraint constraint) '''repair_«base.canonizeName(constraint.relation.name)»'''
69 if(parameters.size == 2) { 172
70 val firstParam = parameters.get(0) 173 def String remainingMultiplicityName(
71 if(firstParam instanceof ComplexTypeReference) { 174 RelationMultiplicityConstraint constraint) '''remainingInverseUpperMultiplicity_«base.canonizeName(constraint.relation.name)»'''
72 return firstParam.referred 175
73 } 176 def String remainingContentsName(
74 } 177 RelationMultiplicityConstraint constraint) '''remainingContents_«base.canonizeName(constraint.relation.name)»'''
75 } 178
76 179 def getUnfinishedMultiplicityQueries(List<RelationMultiplicityConstraint> constraints) {
77 def getUnfinishedMultiplicityQueries(LogicProblem problem) { 180 constraints.toInvertedMap [ constraint |
78 val lowerMultiplicities = base.lowerMultiplicities(problem) 181 new UnifinishedMultiplicityQueryNames(
79 val map = new LinkedHashMap 182 if(constraint.constrainsUnfinished) unfinishedMultiplicityName(constraint) else null,
80 for(lowerMultiplicity : lowerMultiplicities) { 183 if (indexUpperMultiplicities && constraint.constrainsUnrepairable)
81 map.put(lowerMultiplicity.relation,unfinishedMultiplicityName(lowerMultiplicity)) 184 unrepairableMultiplicityName(constraint)
82 } 185 else
83 return map 186 null,
187 if (indexUpperMultiplicities && constraint.constrainsRemainingInverse)
188 remainingMultiplicityName(constraint)
189 else
190 null,
191 if (indexUpperMultiplicities && constraint.constrainsRemainingContents)
192 remainingContentsName(constraint)
193 else
194 null
195 )
196 ]
84 } 197 }
85} 198}
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..b6fdbe06 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,6 +1,6 @@
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.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator
4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns 4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns
5import java.util.ArrayList 5import java.util.ArrayList
6 6
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..bf816de9 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
@@ -6,7 +6,7 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration 6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type 7import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics 8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator 9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns 10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ObjectCreationPrecondition 11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ObjectCreationPrecondition
12import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation 12import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
@@ -98,10 +98,12 @@ class RefinementRuleProvider {
98 val newLink2 = factory2.createBinaryElementRelationLink => [it.param1 = newElement it.param2 = container] 98 val newLink2 = factory2.createBinaryElementRelationLink => [it.param1 = newElement it.param2 = container]
99 inverseRelationInterpretation.relationlinks+=newLink2 99 inverseRelationInterpretation.relationlinks+=newLink2
100 100
101 val propagatorStartTime = System.nanoTime
102 statistics.addExecutionTime(propagatorStartTime-startTime)
103
101 // Scope propagation 104 // Scope propagation
102 scopePropagator.propagateAdditionToType(typeInterpretation) 105 scopePropagator.propagateAdditionToType(typeInterpretation)
103 106 statistics.addScopePropagationTime(System.nanoTime-propagatorStartTime)
104 statistics.addExecutionTime(System.nanoTime-startTime)
105 ] 107 ]
106 } else { 108 } else {
107 ruleBuilder.action[match | 109 ruleBuilder.action[match |
@@ -132,10 +134,12 @@ class RefinementRuleProvider {
132 val newLink = factory2.createBinaryElementRelationLink => [it.param1 = container it.param2 = newElement] 134 val newLink = factory2.createBinaryElementRelationLink => [it.param1 = container it.param2 = newElement]
133 relationInterpretation.relationlinks+=newLink 135 relationInterpretation.relationlinks+=newLink
134 136
137 val propagatorStartTime = System.nanoTime
138 statistics.addExecutionTime(propagatorStartTime-startTime)
139
135 // Scope propagation 140 // Scope propagation
136 scopePropagator.propagateAdditionToType(typeInterpretation) 141 scopePropagator.propagateAdditionToType(typeInterpretation)
137 142 statistics.addScopePropagationTime(System.nanoTime-propagatorStartTime)
138 statistics.addExecutionTime(System.nanoTime-startTime)
139 ] 143 ]
140 } 144 }
141 } else { 145 } else {
@@ -162,29 +166,31 @@ class RefinementRuleProvider {
162 typeInterpretation.elements += newElement 166 typeInterpretation.elements += newElement
163 typeInterpretation.supertypeInterpretation.forEach[it.elements += newElement] 167 typeInterpretation.supertypeInterpretation.forEach[it.elements += newElement]
164 168
169 val propagatorStartTime = System.nanoTime
170 statistics.addExecutionTime(propagatorStartTime-startTime)
171
165 // Scope propagation 172 // Scope propagation
166 scopePropagator.propagateAdditionToType(typeInterpretation) 173 scopePropagator.propagateAdditionToType(typeInterpretation)
167 174 statistics.addScopePropagationTime(System.nanoTime-propagatorStartTime)
168 statistics.addExecutionTime(System.nanoTime-startTime)
169 ] 175 ]
170 } 176 }
171 return ruleBuilder.build 177 return ruleBuilder.build
172 } 178 }
173 179
174 def createRelationRefinementRules(GeneratedPatterns patterns, ModelGenerationStatistics statistics) { 180 def createRelationRefinementRules(GeneratedPatterns patterns, ScopePropagator scopePropagator, ModelGenerationStatistics statistics) {
175 val res = new LinkedHashMap 181 val res = new LinkedHashMap
176 for(LHSEntry: patterns.refinerelationQueries.entrySet) { 182 for(LHSEntry: patterns.refinerelationQueries.entrySet) {
177 val declaration = LHSEntry.key.key 183 val declaration = LHSEntry.key.key
178 val inverseReference = LHSEntry.key.value 184 val inverseReference = LHSEntry.key.value
179 val lhs = LHSEntry.value as IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> 185 val lhs = LHSEntry.value as IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>>
180 val rule = createRelationRefinementRule(declaration,inverseReference,lhs,statistics) 186 val rule = createRelationRefinementRule(declaration,inverseReference,lhs,scopePropagator,statistics)
181 res.put(LHSEntry.key,rule) 187 res.put(LHSEntry.key,rule)
182 } 188 }
183 return res 189 return res
184 } 190 }
185 191
186 def private BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>> 192 def private BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>>
187 createRelationRefinementRule(RelationDeclaration declaration, Relation inverseRelation, IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> lhs, ModelGenerationStatistics statistics) 193 createRelationRefinementRule(RelationDeclaration declaration, Relation inverseRelation, IQuerySpecification<ViatraQueryMatcher<GenericPatternMatch>> lhs, ScopePropagator scopePropagator, ModelGenerationStatistics statistics)
188 { 194 {
189 val name = '''addRelation_«declaration.name.canonizeName»«IF inverseRelation != null»_and_«inverseRelation.name.canonizeName»«ENDIF»''' 195 val name = '''addRelation_«declaration.name.canonizeName»«IF inverseRelation != null»_and_«inverseRelation.name.canonizeName»«ENDIF»'''
190 val ruleBuilder = factory.createRule 196 val ruleBuilder = factory.createRule
@@ -201,7 +207,13 @@ class RefinementRuleProvider {
201 val trg = match.get(4) as DefinedElement 207 val trg = match.get(4) as DefinedElement
202 val link = createBinaryElementRelationLink => [it.param1 = src it.param2 = trg] 208 val link = createBinaryElementRelationLink => [it.param1 = src it.param2 = trg]
203 relationInterpretation.relationlinks += link 209 relationInterpretation.relationlinks += link
204 statistics.addExecutionTime(System.nanoTime-startTime) 210
211 val propagatorStartTime = System.nanoTime
212 statistics.addExecutionTime(propagatorStartTime-startTime)
213
214 // Scope propagation
215 scopePropagator.propagateAdditionToRelation(declaration)
216 statistics.addScopePropagationTime(System.nanoTime-propagatorStartTime)
205 ] 217 ]
206 } else { 218 } else {
207 ruleBuilder.action [ match | 219 ruleBuilder.action [ match |
@@ -217,7 +229,13 @@ class RefinementRuleProvider {
217 relationInterpretation.relationlinks += link 229 relationInterpretation.relationlinks += link
218 val inverseLink = createBinaryElementRelationLink => [it.param1 = trg it.param2 = src] 230 val inverseLink = createBinaryElementRelationLink => [it.param1 = trg it.param2 = src]
219 inverseInterpretation.relationlinks += inverseLink 231 inverseInterpretation.relationlinks += inverseLink
220 statistics.addExecutionTime(System.nanoTime-startTime) 232
233 val propagatorStartTime = System.nanoTime
234 statistics.addExecutionTime(propagatorStartTime-startTime)
235
236 // Scope propagation
237 scopePropagator.propagateAdditionToRelation(declaration)
238 statistics.addScopePropagationTime(System.nanoTime-propagatorStartTime)
221 ] 239 ]
222 } 240 }
223 241
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend
index 41482b28..c7c1ad77 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/Descriptor.xtend
@@ -4,10 +4,21 @@ import java.util.HashMap
4import java.util.Map 4import java.util.Map
5import java.util.Set 5import java.util.Set
6import org.eclipse.xtend.lib.annotations.Data 6import org.eclipse.xtend.lib.annotations.Data
7import org.eclipse.xtend2.lib.StringConcatenationClient
7 8
8@Data abstract class AbstractNodeDescriptor { 9@Data abstract class AbstractNodeDescriptor {
9 long dataHash 10 long dataHash
10 11
12 protected def StringConcatenationClient prettyPrint() {
13 '''(«dataHash»)[«class.simpleName»]'''
14 }
15
16 override toString() {
17 '''
18 «prettyPrint»
19 '''
20 }
21
11// @Pure 22// @Pure
12// @Override 23// @Override
13// override public boolean equals(Object obj) { 24// override public boolean equals(Object obj) {
@@ -24,34 +35,41 @@ import org.eclipse.xtend.lib.annotations.Data
24// } 35// }
25} 36}
26 37
27@Data class LocalNodeDescriptor extends AbstractNodeDescriptor{ 38@Data class LocalNodeDescriptor extends AbstractNodeDescriptor {
28 Set<String> types 39 Set<String> types
29 String id; 40 String id;
41
30 new(String id, Set<String> types) { 42 new(String id, Set<String> types) {
31 super(calcualteDataHash(id,types)) 43 super(calcualteDataHash(id, types))
32 this.types = types 44 this.types = types
33 this.id = id 45 this.id = id
34 } 46 }
35 47
36 def private static calcualteDataHash(String id, Set<String> types) { 48 def private static calcualteDataHash(String id, Set<String> types) {
37 val int prime = 31; 49 val int prime = 31;
38 var result = 0 50 var result = 0
39 if(id !== null) 51 if (id !== null)
40 result = id.hashCode(); 52 result = id.hashCode();
41 if(types !== null) { 53 if (types !== null) {
42 result = prime * result + types.hashCode 54 result = prime * result + types.hashCode
43 } 55 }
44 return result 56 return result
45 } 57 }
46 58
47 override hashCode() { 59 override hashCode() {
48 return this.dataHash.hashCode 60 return this.dataHash.hashCode
49 } 61 }
50 62
63 override protected prettyPrint() {
64 '''(«dataHash»)[«IF id !== null»id = "«id»"«IF types === null || !types.empty», «ENDIF»«ENDIF»«IF types === null»TYPES = null«ELSE»«FOR type : types SEPARATOR ", "»«type»«ENDFOR»«ENDIF»]'''
65 }
66
51 override toString() { 67 override toString() {
52 return class.name + this.dataHash 68 '''
69 «prettyPrint»
70 '''
53 } 71 }
54 72
55// @Pure 73// @Pure
56// @Override 74// @Override
57// override public boolean equals(Object obj) { 75// override public boolean equals(Object obj) {
@@ -66,7 +84,6 @@ import org.eclipse.xtend.lib.annotations.Data
66// return false; 84// return false;
67// return true; 85// return true;
68// } 86// }
69
70// @Pure 87// @Pure
71// override public boolean equals(Object obj) { 88// override public boolean equals(Object obj) {
72// if (this === obj) 89// if (this === obj)
@@ -97,49 +114,70 @@ import org.eclipse.xtend.lib.annotations.Data
97 String type 114 String type
98} 115}
99 116
100@Data class FurtherNodeDescriptor<NodeRep> extends AbstractNodeDescriptor{ 117@Data class FurtherNodeDescriptor<NodeRep> extends AbstractNodeDescriptor {
101 118
102 NodeRep previousRepresentation 119 NodeRep previousRepresentation
103 Map<IncomingRelation<NodeRep>,Integer> incomingEdges 120 Map<IncomingRelation<NodeRep>, Integer> incomingEdges
104 Map<OutgoingRelation<NodeRep>,Integer> outgoingEdges 121 Map<OutgoingRelation<NodeRep>, Integer> outgoingEdges
105 122
106 new( 123 new(NodeRep previousRepresentation, Map<IncomingRelation<NodeRep>, Integer> incomingEdges,
107 NodeRep previousRepresentation, 124 Map<OutgoingRelation<NodeRep>, Integer> outgoingEdges) {
108 Map<IncomingRelation<NodeRep>,Integer> incomingEdges, 125 super(calculateDataHash(previousRepresentation, incomingEdges, outgoingEdges))
109 Map<OutgoingRelation<NodeRep>,Integer> outgoingEdges) 126 this.previousRepresentation = previousRepresentation
110 { 127 this.incomingEdges = new HashMap(incomingEdges)
111 super(calculateDataHash(previousRepresentation,incomingEdges,outgoingEdges)) 128 this.outgoingEdges = new HashMap(outgoingEdges)
112 this.previousRepresentation = previousRepresentation
113 this.incomingEdges = new HashMap(incomingEdges)
114 this.outgoingEdges = new HashMap(outgoingEdges)
115 }
116
117 static def private <NodeRep> int calculateDataHash(
118 NodeRep previousRepresentation,
119 Map<IncomingRelation<NodeRep>,Integer> incomingEdges,
120 Map<OutgoingRelation<NodeRep>,Integer> outgoingEdges)
121 {
122 val int prime = 31;
123 var int result = previousRepresentation.hashCode;
124 if(incomingEdges !== null)
125 result = prime * result + incomingEdges.hashCode();
126 if(outgoingEdges !== null)
127 result = prime * result + outgoingEdges.hashCode();
128 return result;
129 }
130
131 override hashCode() {
132 return this.dataHash.hashCode
133 } 129 }
134 130
131 static def private <NodeRep> int calculateDataHash(NodeRep previousRepresentation,
132 Map<IncomingRelation<NodeRep>, Integer> incomingEdges, Map<OutgoingRelation<NodeRep>, Integer> outgoingEdges) {
133 val int prime = 31;
134 var int result = previousRepresentation.hashCode;
135 if (incomingEdges !== null)
136 result = prime * result + incomingEdges.hashCode();
137 if (outgoingEdges !== null)
138 result = prime * result + outgoingEdges.hashCode();
139 return result;
140 }
141
142 override hashCode() {
143 return this.dataHash.hashCode
144 }
145
146 override prettyPrint() {
147 '''
148 («dataHash»)[
149 PREV = «previousRepresentation?.prettyPrint»
150 «IF incomingEdges === null»
151 IN null
152 «ELSE»
153 «FOR edge : incomingEdges.entrySet»
154 IN «edge.value» «edge.key.type» = «edge.key.from.prettyPrint»
155 «ENDFOR»
156 «ENDIF»
157 «IF outgoingEdges === null»
158 OUT null
159 «ELSE»
160 «FOR edge : outgoingEdges.entrySet»
161 OUT «edge.value» «edge.key.type» = «edge.key.to.prettyPrint»
162 «ENDFOR»
163 «ENDIF»
164 ]'''
165 }
166
167 private def StringConcatenationClient prettyPrint(NodeRep rep) {
168 if (rep instanceof AbstractNodeDescriptor) {
169 rep.prettyPrint
170 } else {
171 '''«rep»'''
172 }
173 }
174
135 override toString() { 175 override toString() {
136 return class.name + dataHash 176 '''
137// return '''[«previousRepresentation»,(«FOR 177 «prettyPrint»
138// in: incomingEdges.entrySet»(«in.key.type.name»=«in.key.from»,«in.value»)«ENDFOR»),(«FOR 178 '''
139// out: outgoingEdges.entrySet»(«out.key.type.name»=«out.key.to»,«out.value»)«ENDFOR»),«FOR
140// att: attributeValues»(«att.type.name»=«att.value»)«ENDFOR»]'''
141 } 179 }
142 180
143// @Pure 181// @Pure
144// @Override 182// @Override
145// override public boolean equals(Object obj) { 183// override public boolean equals(Object obj) {
@@ -154,7 +192,6 @@ import org.eclipse.xtend.lib.annotations.Data
154// return false; 192// return false;
155// return true; 193// return true;
156// } 194// }
157
158// @Pure 195// @Pure
159// override public boolean equals(Object obj) { 196// override public boolean equals(Object obj) {
160// if (this === obj) 197// if (this === obj)
@@ -191,24 +228,23 @@ import org.eclipse.xtend.lib.annotations.Data
191// return true; 228// return true;
192// } 229// }
193} 230}
194
195/* 231/*
196@Data 232 * @Data
197class ModelDescriptor { 233 * class ModelDescriptor {
198 int dataHash 234 * int dataHash
199 int unknownElements 235 * int unknownElements
200 Map<? extends AbstractNodeDescriptor,Integer> knownElements 236 * Map<? extends AbstractNodeDescriptor,Integer> knownElements
201 237 *
202 public new(Map<? extends AbstractNodeDescriptor,Integer> knownElements, int unknownElements) { 238 * public new(Map<? extends AbstractNodeDescriptor,Integer> knownElements, int unknownElements) {
203 this.dataHash = calculateDataHash(knownElements,unknownElements) 239 * this.dataHash = calculateDataHash(knownElements,unknownElements)
204 this.unknownElements = unknownElements 240 * this.unknownElements = unknownElements
205 this.knownElements = knownElements 241 * this.knownElements = knownElements
206 } 242 * }
207 243 *
208 def private static calculateDataHash(Map<? extends AbstractNodeDescriptor,Integer> knownElements, int unknownElements) 244 * def private static calculateDataHash(Map<? extends AbstractNodeDescriptor,Integer> knownElements, int unknownElements)
209 { 245 * {
210 val int prime = 31; 246 * val int prime = 31;
211 return knownElements.hashCode * prime + unknownElements.hashCode 247 * return knownElements.hashCode * prime + unknownElements.hashCode
212 } 248 * }
213} 249 * }
214*/ \ No newline at end of file 250 */
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend
new file mode 100644
index 00000000..efc89803
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/NeighbourhoodOptions.xtend
@@ -0,0 +1,22 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood
2
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration
5import java.util.Set
6import org.eclipse.xtend.lib.annotations.Data
7
8@Data
9class NeighbourhoodOptions {
10 public static val FixPointRage = -1
11 public static val GraphWidthRange = -2
12 public static val FullParallels = Integer.MAX_VALUE
13 public static val MaxNumbers = Integer.MAX_VALUE
14
15 public static val DEFAULT = new NeighbourhoodOptions(GraphWidthRange, FullParallels, MaxNumbers, null, null)
16
17 val int range
18 val int parallels
19 val int maxNumber
20 val Set<TypeDeclaration> relevantTypes
21 val Set<RelationDeclaration> relevantRelations
22}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend
index d1bf0348..a0382e8e 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2NeighbourhoodRepresentation.xtend
@@ -4,32 +4,34 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration 4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration 5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration
6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink 6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BinaryElementRelationLink
7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 8import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation
10import java.util.ArrayList
8import java.util.HashMap 11import java.util.HashMap
9import java.util.HashSet 12import java.util.HashSet
10import java.util.LinkedList
11import java.util.List 13import java.util.List
12import java.util.Map 14import java.util.Map
13import java.util.Set 15import java.util.Set
14 16
15import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* 17import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
16import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation
17import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
18 18
19abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresentation,NodeRepresentation> { 19abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresentation, NodeRepresentation> {
20 private val boolean deepRepresentation 20 val boolean deepRepresentation
21 private val boolean mergeSimilarNeighbourhood 21 val boolean mergeSimilarNeighbourhood
22 22
23 protected new(boolean deeprepresentation, boolean mergeSimilarNeighbourhood) { 23 protected new(boolean deeprepresentation, boolean mergeSimilarNeighbourhood) {
24 this.deepRepresentation = deeprepresentation 24 this.deepRepresentation = deeprepresentation
25 this.mergeSimilarNeighbourhood = mergeSimilarNeighbourhood 25 this.mergeSimilarNeighbourhood = mergeSimilarNeighbourhood
26 } 26 }
27 27
28 public static val FixPointRage = -1 28 public static val FixPointRage = NeighbourhoodOptions.FixPointRage
29 public static val GraphWidthRange = -2 29 public static val GraphWidthRange = NeighbourhoodOptions.GraphWidthRange
30 public static val FullParallels = Integer.MAX_VALUE 30 public static val FullParallels = NeighbourhoodOptions.FullParallels
31 public static val MaxNumbers = Integer.MAX_VALUE 31 public static val MaxNumbers = NeighbourhoodOptions.MaxNumbers
32 32
33 static val FOCUSED_ELEMENT_NAME = "<<THIS>>"
34
33 /** 35 /**
34 * Creates a neighbourhood representation with traces 36 * Creates a neighbourhood representation with traces
35 * @param model The model to be represented. 37 * @param model The model to be represented.
@@ -37,10 +39,15 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta
37 * @param parallels The maximal number of parallel references to be differentiated. 39 * @param parallels The maximal number of parallel references to be differentiated.
38 * @param maxNumber The maximal number of elements in a equivalence class that chan be differentiated. 40 * @param maxNumber The maximal number of elements in a equivalence class that chan be differentiated.
39 */ 41 */
40 def public createRepresentation(PartialInterpretation model, int range, int parallels, int maxNumber) { 42 def createRepresentation(PartialInterpretation model, int range, int parallels, int maxNumber) {
41 return createRepresentation(model,range,parallels,maxNumber,null,null) 43 return createRepresentation(model, range, parallels, maxNumber, null, null)
44 }
45
46 def createRepresentation(PartialInterpretation model, NeighbourhoodOptions options) {
47 createRepresentation(model, options.range, options.parallels, options.maxNumber, options.relevantTypes,
48 options.relevantRelations)
42 } 49 }
43 50
44 /** 51 /**
45 * Creates a neighbourhood representation with traces 52 * Creates a neighbourhood representation with traces
46 * @param model The model to be represented. 53 * @param model The model to be represented.
@@ -48,45 +55,50 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta
48 * @param parallels The maximal number of parallel references to be differentiated. 55 * @param parallels The maximal number of parallel references to be differentiated.
49 * @param maxNumber The maximal number of elements in a equivalence class that chan be differentiated. 56 * @param maxNumber The maximal number of elements in a equivalence class that chan be differentiated.
50 */ 57 */
51 def public createRepresentation( 58 def createRepresentation(PartialInterpretation model, int range, int parallels, int maxNumber,
52 PartialInterpretation model, 59 Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations) {
53 int range, int parallels, int maxNumber, 60 createRepresentationWithFocus(model, range, parallels, maxNumber, relevantTypes, relevantRelations, null)
54 Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations) 61 }
55 { 62
63 def createRepresentationWithFocus(PartialInterpretation model, NeighbourhoodOptions options,
64 DefinedElement focusedElement) {
65 createRepresentationWithFocus(model, options.range, options.parallels, options.maxNumber, options.relevantTypes,
66 options.relevantRelations, focusedElement)
67 }
68
69 def createRepresentationWithFocus(PartialInterpretation model, int range, int parallels, int maxNumber,
70 Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations, DefinedElement focusedElement) {
56 val Map<DefinedElement, Set<String>> types = new HashMap 71 val Map<DefinedElement, Set<String>> types = new HashMap
57 fillTypes(model,types,relevantTypes) 72 fillTypes(model, types, relevantTypes)
58 val Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations = new HashMap; 73 val Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations = new HashMap;
59 val Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations = new HashMap; 74 val Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations = new HashMap;
60 fillReferences(model,IncomingRelations,OutgoingRelations,relevantRelations) 75 fillReferences(model, IncomingRelations, OutgoingRelations, relevantRelations)
61 76
62 val res = doRecursiveNeighbourCalculation(model,types,IncomingRelations,OutgoingRelations,range,parallels,maxNumber); 77 val res = doRecursiveNeighbourCalculation(model, types, IncomingRelations, OutgoingRelations, range, parallels,
63 78 maxNumber, focusedElement);
79
64 return res; 80 return res;
65 } 81 }
66 82
67 def private isRelevant(TypeDeclaration t, Set<TypeDeclaration> relevantTypes) { 83 def private isRelevant(TypeDeclaration t, Set<TypeDeclaration> relevantTypes) {
68 if(relevantTypes === null) { 84 if (relevantTypes === null) {
69 return true 85 return true
70 } else { 86 } else {
71 return relevantTypes.contains(t) 87 return relevantTypes.contains(t)
72 } 88 }
73 } 89 }
90
74 def private isRelevant(RelationDeclaration r, Set<RelationDeclaration> relevantRelations) { 91 def private isRelevant(RelationDeclaration r, Set<RelationDeclaration> relevantRelations) {
75 if(relevantRelations === null) { 92 if (relevantRelations === null) {
76 return true 93 return true
77 } else { 94 } else {
78 return relevantRelations.contains(r) 95 return relevantRelations.contains(r)
79 } 96 }
80 } 97 }
81 /**
82 * Gets the largest
83 */
84/**
85 98
99 /**
86 * Gets the minimal neighbourhood size such that every reachable node appears in the shape of every other at least once. 100 * Gets the minimal neighbourhood size such that every reachable node appears in the shape of every other at least once.
87
88 */ 101 */
89
90 def private getWidth(Map<DefinedElement, Set<String>> types, 102 def private getWidth(Map<DefinedElement, Set<String>> types,
91 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, 103 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations,
92 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations) { 104 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations) {
@@ -99,6 +111,7 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta
99 reachable.put(element, new HashSet) 111 reachable.put(element, new HashSet)
100 newReachable.put(element, set) 112 newReachable.put(element, set)
101 } 113 }
114
102 var int width = 0 115 var int width = 0
103 var boolean newAdded 116 var boolean newAdded
104 do { 117 do {
@@ -122,7 +135,6 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta
122 } while (newAdded) 135 } while (newAdded)
123 return width 136 return width
124 } 137 }
125
126 /** 138 /**
127 * Creates a neighbourhood representation with traces 139 * Creates a neighbourhood representation with traces
128 * @param model The model to be represented. 140 * @param model The model to be represented.
@@ -131,68 +143,71 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta
131 * @param range The range of the neighbourhood. 143 * @param range The range of the neighbourhood.
132 * @param parallels The maximal number of parallel references to be differentiated. 144 * @param parallels The maximal number of parallel references to be differentiated.
133 */ 145 */
134 def private NeighbourhoodWithTraces<ModelRepresentation,NodeRepresentation> doRecursiveNeighbourCalculation( 146 def private NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> doRecursiveNeighbourCalculation(
135 PartialInterpretation model, 147 PartialInterpretation model, Map<DefinedElement, Set<String>> types,
136 Map<DefinedElement, Set<String>> types,
137 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, 148 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations,
138 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, 149 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, int range, int parallels,
139 int range, int parallels, int maxNumber) 150 int maxNumber, DefinedElement focusedElement) {
140 { 151 if (range == 0) {
141 if(range == 0){ 152 val r = calculateLocalNodeDescriptors(model, types, maxNumber, focusedElement)
142 val r = calculateLocalNodeDescriptors(model,types,maxNumber) 153 val res = this.createLocalRepresentation(r.value, r.key)
143 val res = this.createLocalRepresentation(r.value,r.key) 154 if (res.modelRepresentation === null) {
144 if(res.modelRepresentation === null) {
145 throw new IllegalArgumentException('''Model representation is null''') 155 throw new IllegalArgumentException('''Model representation is null''')
146 } else if(res.nodeRepresentations === null || res.nodeRepresentations.empty) { 156 } else if (res.nodeRepresentations === null || res.nodeRepresentations.empty) {
147 throw new IllegalArgumentException('''No node representation''') 157 throw new IllegalArgumentException('''No node representation''')
148 } else if(res.previousRepresentation !== null) { 158 } else if (res.previousRepresentation !== null) {
149 throw new IllegalArgumentException('''The previous representation of the first neighbourhood have to be null''') 159 throw new IllegalArgumentException('''The previous representation of the first neighbourhood have to be null''')
150 } else return res 160 } else
151 } else if(range > 0) { 161 return res
152 val previous = doRecursiveNeighbourCalculation(model,types,IncomingRelations,OutgoingRelations,range-1,parallels,maxNumber) 162 } else if (range > 0) {
153 val r = calculateFurtherNodeDescriptors(model,previous,IncomingRelations,OutgoingRelations,parallels,maxNumber) 163 val previous = doRecursiveNeighbourCalculation(model, types, IncomingRelations, OutgoingRelations,
154 //println('''Level «range» finished.''') 164 range - 1, parallels, maxNumber, focusedElement)
155 val res = createFurtherRepresentation(r.key,r.value,previous,deepRepresentation) 165 val r = calculateFurtherNodeDescriptors(model, previous, IncomingRelations, OutgoingRelations, parallels,
156 if(res.modelRepresentation === null) { 166 maxNumber)
167 // println('''Level «range» finished.''')
168 val res = createFurtherRepresentation(r.key, r.value, previous, deepRepresentation)
169 if (res.modelRepresentation === null) {
157 throw new IllegalArgumentException('''Model representation is null''') 170 throw new IllegalArgumentException('''Model representation is null''')
158 } else if(res.nodeRepresentations === null || res.nodeRepresentations.empty) { 171 } else if (res.nodeRepresentations === null || res.nodeRepresentations.empty) {
159 throw new IllegalArgumentException('''No node representation''') 172 throw new IllegalArgumentException('''No node representation''')
160 } else if(res.previousRepresentation === null && deepRepresentation) { 173 } else if (res.previousRepresentation === null && deepRepresentation) {
161 throw new IllegalArgumentException('''Need previous representations''') 174 throw new IllegalArgumentException('''Need previous representations''')
162 } else return res 175 } else
176 return res
163 } else if (range == FixPointRage) { 177 } else if (range == FixPointRage) {
164 return refineUntilFixpoint(model,types,IncomingRelations,OutgoingRelations,parallels,maxNumber) 178 return refineUntilFixpoint(model, types, IncomingRelations, OutgoingRelations, parallels, maxNumber,
179 focusedElement)
165 } else if (range == GraphWidthRange) { 180 } else if (range == GraphWidthRange) {
166 val width = this.getWidth(types,IncomingRelations,OutgoingRelations) 181 val width = this.getWidth(types, IncomingRelations, OutgoingRelations)
167 //println(width) 182 // println(width)
168 return doRecursiveNeighbourCalculation(model,types,IncomingRelations,OutgoingRelations,width,parallels,maxNumber) 183 return doRecursiveNeighbourCalculation(model, types, IncomingRelations, OutgoingRelations, width, parallels,
184 maxNumber, focusedElement)
169 } 185 }
170 } 186 }
171 187
172 def private refineUntilFixpoint( 188 def private refineUntilFixpoint(PartialInterpretation model, Map<DefinedElement, Set<String>> types,
173 PartialInterpretation model,
174 Map<DefinedElement, Set<String>> types,
175 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, 189 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations,
176 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, 190 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, int parallels, int maxNumbers,
177 int parallels, int maxNumbers) 191 DefinedElement focusedElement) {
178 {
179 var lastRange = 0 192 var lastRange = 0
180 val last = calculateLocalNodeDescriptors(model,types,maxNumbers) 193 val last = calculateLocalNodeDescriptors(model, types, maxNumbers, focusedElement)
181 var lastRepresentation = this.createLocalRepresentation(last.value,last.key) 194 var lastRepresentation = this.createLocalRepresentation(last.value, last.key)
182 //println('''Level 0 finished.''') 195 // println('''Level 0 finished.''')
183 var boolean hasRefined 196 var boolean hasRefined
184 do { 197 do {
185 val nextRange = lastRange+1 198 val nextRange = lastRange + 1
186 val next = calculateFurtherNodeDescriptors(model,lastRepresentation,IncomingRelations,OutgoingRelations,parallels,maxNumbers) 199 val next = calculateFurtherNodeDescriptors(model, lastRepresentation, IncomingRelations, OutgoingRelations,
187 val nextRepresentation = createFurtherRepresentation(next.key,next.value,lastRepresentation,deepRepresentation) 200 parallels, maxNumbers)
188 201 val nextRepresentation = createFurtherRepresentation(next.key, next.value, lastRepresentation,
189 val previousNumberOfTypes =lastRepresentation.nodeRepresentations.values.toSet.size 202 deepRepresentation)
203
204 val previousNumberOfTypes = lastRepresentation.nodeRepresentations.values.toSet.size
190 val nextNumberOfTypes = nextRepresentation.nodeRepresentations.values.toSet.size 205 val nextNumberOfTypes = nextRepresentation.nodeRepresentations.values.toSet.size
191 hasRefined = nextNumberOfTypes > previousNumberOfTypes 206 hasRefined = nextNumberOfTypes > previousNumberOfTypes
192 207
193 lastRange = nextRange 208 lastRange = nextRange
194 lastRepresentation = nextRepresentation 209 lastRepresentation = nextRepresentation
195 210
196// if(hasRefined) { 211// if(hasRefined) {
197// println('''Level «nextRange» is calculated, number of types is refined: «previousNumberOfTypes» -> «nextNumberOfTypes»''') 212// println('''Level «nextRange» is calculated, number of types is refined: «previousNumberOfTypes» -> «nextNumberOfTypes»''')
198// } else { 213// } else {
@@ -201,211 +216,219 @@ abstract class PartialInterpretation2NeighbourhoodRepresentation<ModelRepresenta
201 } while (hasRefined) 216 } while (hasRefined)
202 return lastRepresentation 217 return lastRepresentation
203 } 218 }
204 219
205 def private getElements(PartialInterpretation model) { 220 def private getElements(PartialInterpretation model) {
206 return 221 return model.problem.elements + model.newElements + model.openWorldElements
207 model.problem.elements +
208 model.newElements +
209 model.openWorldElements
210 } 222 }
211 223
212 def private fillTypes(PartialInterpretation model, Map<DefinedElement, Set<String>> node2Type, Set<TypeDeclaration> relevantTypes) { 224 def private fillTypes(PartialInterpretation model, Map<DefinedElement, Set<String>> node2Type,
213 for(element : model.elements) { 225 Set<TypeDeclaration> relevantTypes) {
226 for (element : model.elements) {
214 node2Type.put(element, new HashSet) 227 node2Type.put(element, new HashSet)
215 } 228 }
216 229
217// for(typeDefinition : model.problem.types.filter(TypeDefinition)) { 230// for(typeDefinition : model.problem.types.filter(TypeDefinition)) {
218// // Dont need 231// // Dont need
219// } 232// }
220 for(typeInterpretation : model.partialtypeinterpratation) { 233 for (typeInterpretation : model.partialtypeinterpratation) {
221 if(typeInterpretation instanceof PartialPrimitiveInterpretation) { 234 if (typeInterpretation instanceof PartialPrimitiveInterpretation) {
222 235 } else if (typeInterpretation instanceof PartialComplexTypeInterpretation) {
223 } else if(typeInterpretation instanceof PartialComplexTypeInterpretation) {
224 val type = typeInterpretation.interpretationOf 236 val type = typeInterpretation.interpretationOf
225 if(type.isRelevant(relevantTypes)) { 237 if (type.isRelevant(relevantTypes)) {
226 for(element : typeInterpretation.elements) { 238 for (element : typeInterpretation.elements) {
227 element.lookup(node2Type).add(type.name) 239 element.lookup(node2Type).add(type.name)
228 } 240 }
229 } 241 }
230 } 242 }
231 } 243 }
232 } 244 }
233 245
234 /** 246 /**
235 * Indexes the references 247 * Indexes the references
236 */ 248 */
237 def private fillReferences(PartialInterpretation model, 249 def private fillReferences(PartialInterpretation model,
238 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, 250 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations,
239 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, 251 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations,
240 Set<RelationDeclaration> relevantRelations) 252 Set<RelationDeclaration> relevantRelations) {
241 { 253 for (object : model.elements) {
242 for(object : model.elements) { 254 IncomingRelations.put(object, new ArrayList)
243 IncomingRelations.put(object,new LinkedList) 255 OutgoingRelations.put(object, new ArrayList)
244 OutgoingRelations.put(object,new LinkedList)
245 } 256 }
246 for(relationInterpretation : model.partialrelationinterpretation) { 257 for (relationInterpretation : model.partialrelationinterpretation) {
247 val type = relationInterpretation.interpretationOf 258 val type = relationInterpretation.interpretationOf
248 if(type.isRelevant(relevantRelations)) { 259 if (type.isRelevant(relevantRelations)) {
249 for(link : relationInterpretation.relationlinks) { 260 for (link : relationInterpretation.relationlinks) {
250 if(link instanceof BinaryElementRelationLink) { 261 if (link instanceof BinaryElementRelationLink) {
251 OutgoingRelations.get(link.param1) += new OutgoingRelation(link.param2,type.name) 262 OutgoingRelations.get(link.param1) += new OutgoingRelation(link.param2, type.name)
252 IncomingRelations.get(link.param2) += new IncomingRelation(link.param1,type.name) 263 IncomingRelations.get(link.param2) += new IncomingRelation(link.param1, type.name)
253 } else throw new UnsupportedOperationException 264 } else
265 throw new UnsupportedOperationException
254 } 266 }
255 } 267 }
256 } 268 }
257 } 269 }
258 270
259 /** 271 /**
260 * Creates a local representation of the objects (aka zero range neighbourhood) 272 * Creates a local representation of the objects (aka zero range neighbourhood)
261 */ 273 */
262 def abstract protected NeighbourhoodWithTraces<ModelRepresentation,NodeRepresentation> createLocalRepresentation( 274 def abstract protected NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> createLocalRepresentation(
263 Map<DefinedElement, LocalNodeDescriptor> node2Representation, 275 Map<DefinedElement, LocalNodeDescriptor> node2Representation,
264 Map<LocalNodeDescriptor, Integer> representation2Amount 276 Map<LocalNodeDescriptor, Integer> representation2Amount
265 ) 277 )
266 278
267 /** 279 /**
268 * Creates a 280 * Creates a
269 */ 281 */
270 def abstract protected NeighbourhoodWithTraces<ModelRepresentation,NodeRepresentation> createFurtherRepresentation( 282 def abstract protected NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> createFurtherRepresentation(
271 Map<FurtherNodeDescriptor<NodeRepresentation>, Integer> nodeDescriptors, 283 Map<FurtherNodeDescriptor<NodeRepresentation>, Integer> nodeDescriptors,
272 Map<DefinedElement, FurtherNodeDescriptor<NodeRepresentation>> node2Representation, 284 Map<DefinedElement, FurtherNodeDescriptor<NodeRepresentation>> node2Representation,
273 NeighbourhoodWithTraces<ModelRepresentation,NodeRepresentation> previous, 285 NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> previous,
274 boolean deepRepresentation 286 boolean deepRepresentation
275 ) 287 )
276 288
277 def private addOne(int original, int max) { 289 def private addOne(int original, int max) {
278 if(original == Integer.MAX_VALUE) return Integer.MAX_VALUE 290 if(original == Integer.MAX_VALUE) return Integer.MAX_VALUE
279 if(original +1 > max) return Integer.MAX_VALUE 291 if(original + 1 > max) return Integer.MAX_VALUE else return original + 1
280 else return original+1
281 } 292 }
282 293
283 private def calculateIncomingEdges(Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, 294 private def calculateIncomingEdges(Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations,
284 DefinedElement object, Map<DefinedElement, ? extends NodeRepresentation> previousNodeRepresentations, int parallel) 295 DefinedElement object, Map<DefinedElement, ? extends NodeRepresentation> previousNodeRepresentations,
285 { 296 int parallel) {
286 val Map<IncomingRelation<NodeRepresentation>, Integer> res = new HashMap 297 val Map<IncomingRelation<NodeRepresentation>, Integer> res = new HashMap
287 for (incomingConcreteEdge : IncomingRelations.get(object)) { 298 for (incomingConcreteEdge : IncomingRelations.get(object)) {
288 val IncomingRelation<NodeRepresentation> e = new IncomingRelation( 299 val IncomingRelation<NodeRepresentation> e = new IncomingRelation(
289 previousNodeRepresentations.get(incomingConcreteEdge.from), incomingConcreteEdge.type) 300 previousNodeRepresentations.get(incomingConcreteEdge.from), incomingConcreteEdge.type)
290 if (res.containsKey(e)) { 301 if (res.containsKey(e)) {
291 res.put(e, addOne(res.get(e),parallel)) 302 res.put(e, addOne(res.get(e), parallel))
292 } else { 303 } else {
293 res.put(e, 1) 304 res.put(e, 1)
294 } 305 }
295 } 306 }
296 return res 307 return res
297 } 308 }
298 309
299 private def calcuateOutgoingEdges(Map<DefinedElement,List<OutgoingRelation<DefinedElement>>> OutgoingRelations, 310 private def calcuateOutgoingEdges(Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations,
300 DefinedElement object, Map<DefinedElement, ? extends NodeRepresentation> previousNodeRepresentations, int parallel) 311 DefinedElement object, Map<DefinedElement, ? extends NodeRepresentation> previousNodeRepresentations,
301 { 312 int parallel) {
302 val Map<OutgoingRelation<NodeRepresentation>,Integer> res= new HashMap 313 val Map<OutgoingRelation<NodeRepresentation>, Integer> res = new HashMap
303 for(outgoingConcreteEdge : OutgoingRelations.get(object)) { 314 for (outgoingConcreteEdge : OutgoingRelations.get(object)) {
304 val OutgoingRelation<NodeRepresentation> e = 315 val OutgoingRelation<NodeRepresentation> e = new OutgoingRelation(
305 new OutgoingRelation( 316 previousNodeRepresentations.get(outgoingConcreteEdge.to), outgoingConcreteEdge.type)
306 previousNodeRepresentations.get(outgoingConcreteEdge.to), 317 if (res.containsKey(e)) {
307 outgoingConcreteEdge.type) 318 res.put(e, addOne(res.get(e), parallel))
308 if(res.containsKey(e)) {
309 res.put(e,addOne(res.get(e),parallel))
310 } else { 319 } else {
311 res.put(e,1) 320 res.put(e, 1)
312 } 321 }
313 } 322 }
314 return res; 323 return res;
315 } 324 }
316 325
317 /*def private <KEY,VALUE> void addOrCreate_Set(Map<KEY,Set<VALUE>> map, KEY key, VALUE value) { 326 /*def private <KEY,VALUE> void addOrCreate_Set(Map<KEY,Set<VALUE>> map, KEY key, VALUE value) {
318 var Set<VALUE> s; 327 * var Set<VALUE> s;
319 if(map.containsKey(key)) { 328 * if(map.containsKey(key)) {
320 s = map.get(key); 329 * s = map.get(key);
321 } else { 330 * } else {
322 s = new HashSet 331 * s = new HashSet
323 map.put(key,s) 332 * map.put(key,s)
324 } 333 * }
325 s.add(value) 334 * s.add(value)
326 }*/ 335 }*/
327 336 private def calculateFurtherNodeDescriptors(PartialInterpretation model,
328
329 private def calculateFurtherNodeDescriptors(
330 PartialInterpretation model,
331 NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> previous, 337 NeighbourhoodWithTraces<ModelRepresentation, NodeRepresentation> previous,
332 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations, 338 Map<DefinedElement, List<IncomingRelation<DefinedElement>>> IncomingRelations,
333 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, 339 Map<DefinedElement, List<OutgoingRelation<DefinedElement>>> OutgoingRelations, int parallels, int maxNumber) {
334 int parallels, int maxNumber)
335 {
336 val previousNodeRepresentations = previous.nodeRepresentations 340 val previousNodeRepresentations = previous.nodeRepresentations
337 val node2Representation = new HashMap<DefinedElement,FurtherNodeDescriptor<NodeRepresentation>> 341 val node2Representation = new HashMap<DefinedElement, FurtherNodeDescriptor<NodeRepresentation>>
338 val Map<FurtherNodeDescriptor<NodeRepresentation>,Integer> descriptor2Number = 342 val Map<FurtherNodeDescriptor<NodeRepresentation>, Integer> descriptor2Number = if (this.
339 if(this.mergeSimilarNeighbourhood){ new HashMap } else { null } 343 mergeSimilarNeighbourhood) {
340 val Map<FurtherNodeDescriptor<NodeRepresentation>,FurtherNodeDescriptor<NodeRepresentation>> uniqueDescription = 344 new HashMap
341 if(this.mergeSimilarNeighbourhood){ new HashMap } else { null } 345 } else {
342 346 null
343 for(object: model.elements) { 347 }
344 val incomingEdges = this.calculateIncomingEdges(IncomingRelations, object, previousNodeRepresentations,parallels) 348 val Map<FurtherNodeDescriptor<NodeRepresentation>, FurtherNodeDescriptor<NodeRepresentation>> uniqueDescription = if (this.
345 val outgoingEdges = this.calcuateOutgoingEdges(OutgoingRelations,object, previousNodeRepresentations,parallels) 349 mergeSimilarNeighbourhood) {
346 350 new HashMap
351 } else {
352 null
353 }
354
355 for (object : model.elements) {
356 val incomingEdges = this.calculateIncomingEdges(IncomingRelations, object, previousNodeRepresentations,
357 parallels)
358 val outgoingEdges = this.calcuateOutgoingEdges(OutgoingRelations, object, previousNodeRepresentations,
359 parallels)
360
347 val previousType = previousNodeRepresentations.get(object) 361 val previousType = previousNodeRepresentations.get(object)
348 362
349 if(previousType === null) { 363 if (previousType === null) {
350 println("Error in state coder") 364 println("Error in state coder")
351 } 365 }
352 366
353 val nodeDescriptor = new FurtherNodeDescriptor( 367 val nodeDescriptor = new FurtherNodeDescriptor(previousType, incomingEdges, outgoingEdges)
354 previousType, 368
355 incomingEdges, 369 if (this.mergeSimilarNeighbourhood) {
356 outgoingEdges) 370 if (descriptor2Number.containsKey(nodeDescriptor)) {
357
358 if(this.mergeSimilarNeighbourhood) {
359 if(descriptor2Number.containsKey(nodeDescriptor)) {
360 descriptor2Number.put( 371 descriptor2Number.put(
361 nodeDescriptor, 372 nodeDescriptor,
362 addOne(descriptor2Number.get(nodeDescriptor),maxNumber) 373 addOne(descriptor2Number.get(nodeDescriptor), maxNumber)
363 ) 374 )
364 node2Representation.put(object,uniqueDescription.get(nodeDescriptor)) 375 node2Representation.put(object, uniqueDescription.get(nodeDescriptor))
365 } else { 376 } else {
366 descriptor2Number.put(nodeDescriptor,if(1>maxNumber){Integer.MAX_VALUE}else{1}) 377 descriptor2Number.put(nodeDescriptor, if (1 > maxNumber) {
367 uniqueDescription.put(nodeDescriptor,nodeDescriptor) 378 Integer.MAX_VALUE
368 node2Representation.put(object,nodeDescriptor) 379 } else {
380 1
381 })
382 uniqueDescription.put(nodeDescriptor, nodeDescriptor)
383 node2Representation.put(object, nodeDescriptor)
369 } 384 }
370 } else { 385 } else {
371 node2Representation.put(object,nodeDescriptor) 386 node2Representation.put(object, nodeDescriptor)
372 } 387 }
373 } 388 }
374 389
375 return descriptor2Number -> node2Representation 390 return descriptor2Number -> node2Representation
376 } 391 }
377 392
378 private def calculateLocalNodeDescriptors( 393 private def calculateLocalNodeDescriptors(PartialInterpretation model, Map<DefinedElement, Set<String>> types,
379 PartialInterpretation model, 394 int maxNumber, DefinedElement focusedElement) {
380 Map<DefinedElement, Set<String>> types,
381 int maxNumber)
382 {
383 val Map<DefinedElement, LocalNodeDescriptor> node2Representation = new HashMap 395 val Map<DefinedElement, LocalNodeDescriptor> node2Representation = new HashMap
384 val Map<LocalNodeDescriptor, Integer> representation2Amount = 396 val Map<LocalNodeDescriptor, Integer> representation2Amount = if (mergeSimilarNeighbourhood) {
385 if(mergeSimilarNeighbourhood){ new HashMap } else { null } 397 new HashMap
386 val Map<LocalNodeDescriptor, LocalNodeDescriptor> uniqueRepresentation = 398 } else {
387 if(this.mergeSimilarNeighbourhood){ new HashMap } else { null } 399 null
388 400 }
389 for(element : model.elements) { 401 val Map<LocalNodeDescriptor, LocalNodeDescriptor> uniqueRepresentation = if (this.mergeSimilarNeighbourhood) {
390 var newDescriptor = new LocalNodeDescriptor(element.name,element.lookup(types)) 402 new HashMap
391 if(this.mergeSimilarNeighbourhood){ 403 } else {
392 if(uniqueRepresentation.containsKey(newDescriptor)) { 404 null
405 }
406
407 for (element : model.elements) {
408 val name = if(element == focusedElement) FOCUSED_ELEMENT_NAME else element.name
409 var newDescriptor = new LocalNodeDescriptor(name, element.lookup(types))
410 if (this.mergeSimilarNeighbourhood) {
411 if (uniqueRepresentation.containsKey(newDescriptor)) {
393 newDescriptor = newDescriptor.lookup(uniqueRepresentation) 412 newDescriptor = newDescriptor.lookup(uniqueRepresentation)
394 node2Representation.put(element,newDescriptor) 413 node2Representation.put(element, newDescriptor)
395 representation2Amount.put( 414 representation2Amount.put(
396 newDescriptor, 415 newDescriptor,
397 addOne(newDescriptor.lookup(representation2Amount),maxNumber) 416 addOne(newDescriptor.lookup(representation2Amount), maxNumber)
398 ) 417 )
399 } else { 418 } else {
400 uniqueRepresentation.put(newDescriptor,newDescriptor) 419 uniqueRepresentation.put(newDescriptor, newDescriptor)
401 node2Representation.put(element,newDescriptor) 420 node2Representation.put(element, newDescriptor)
402 representation2Amount.put(newDescriptor, if(1>maxNumber){Integer.MAX_VALUE}else{1}) 421 representation2Amount.put(newDescriptor, if (1 > maxNumber) {
422 Integer.MAX_VALUE
423 } else {
424 1
425 })
403 } 426 }
404 } else { 427 } else {
405 node2Representation.put(element,newDescriptor) 428 node2Representation.put(element, newDescriptor)
406 } 429 }
407 } 430 }
408 431
409 return representation2Amount -> node2Representation 432 return representation2Amount -> node2Representation
410 } 433 }
411} \ No newline at end of file 434}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend
new file mode 100644
index 00000000..c10457b0
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/neighbourhood/PartialInterpretation2PairwiseNeighbourhoodRepresentation.xtend
@@ -0,0 +1,68 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood
2
3import com.google.common.collect.Maps
4import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
6import java.util.HashMap
7import java.util.Map
8import org.eclipse.xtend.lib.annotations.Data
9import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
10
11@Data
12class PairwiseNeighbourhoodRepresentation<BasicNodeRepresentation> {
13 val Map<?, Integer> modelRepresentation
14 val Map<DefinedElement, BasicNodeRepresentation> basicNodeRepresentations
15 val Map<DefinedElement, ? extends Map<DefinedElement, ? extends BasicNodeRepresentation>> pairwiseNodeRepresentations
16
17 def getBasicRepresentation(DefinedElement a) {
18 basicNodeRepresentations.get(a)
19 }
20
21 def getPairwiseRepresentation(DefinedElement a, DefinedElement b) {
22 pairwiseNodeRepresentations.get(a).get(b)
23 }
24}
25
26@FinalFieldsConstructor
27class PartialInterpretation2PairwiseNeighbourhoodRepresentation<BasicNodeRepresentation> {
28 val PartialInterpretation2NeighbourhoodRepresentation<? extends Map<? extends BasicNodeRepresentation, Integer>, BasicNodeRepresentation> basicNeighbourhoodRepresenter
29
30 def createRepresentation(PartialInterpretation model, NeighbourhoodOptions options) {
31 val basicRepresentation = basicNeighbourhoodRepresenter.createRepresentation(model, options)
32 val basicModelRepresentation = basicRepresentation.modelRepresentation
33 val basicNodeRepresentations = basicRepresentation.nodeRepresentations
34 val pairwiseNodeRepresentations = Maps.newHashMapWithExpectedSize(basicNodeRepresentations.size)
35 val modelRepresentation = new HashMap<Object, Integer>
36 for (nodeWithBasicRepresentation : basicNodeRepresentations.entrySet) {
37 val node = nodeWithBasicRepresentation.key
38 val basicNodeRepresentation = nodeWithBasicRepresentation.value
39 val count = basicModelRepresentation.get(basicNodeRepresentation)
40 if (count == 1) {
41 pairwiseNodeRepresentations.put(node, basicNodeRepresentations)
42 modelRepresentation.put(basicNodeRepresentation, count)
43 } else {
44 val neighbourhoodRepresentation = basicNeighbourhoodRepresenter.
45 createRepresentationWithFocus(model, options, node)
46 pairwiseNodeRepresentations.put(node, neighbourhoodRepresentation.nodeRepresentations)
47 modelRepresentation.compute(neighbourhoodRepresentation.modelRepresentation) [ key, value |
48 if (value === null) {
49 if (1 > options.maxNumber) {
50 Integer.MAX_VALUE
51 } else {
52 1
53 }
54 } else {
55 addOne(value, options.maxNumber)
56 }
57 ]
58 }
59 }
60 new PairwiseNeighbourhoodRepresentation(modelRepresentation, basicNodeRepresentations,
61 pairwiseNodeRepresentations)
62 }
63
64 def private addOne(int original, int max) {
65 if(original == Integer.MAX_VALUE) return Integer.MAX_VALUE
66 if(original + 1 > max) return Integer.MAX_VALUE else return original + 1
67 }
68}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend
new file mode 100644
index 00000000..089880b1
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/AbstractNeighborhoodBasedStateCoderFactory.xtend
@@ -0,0 +1,137 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder
2
3import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodOptions
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.PartialRelationInterpretation
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage
10import java.util.LinkedList
11import java.util.List
12import org.eclipse.emf.common.notify.Notifier
13import org.eclipse.emf.ecore.EClass
14import org.eclipse.emf.ecore.EObject
15import org.eclipse.emf.ecore.EStructuralFeature
16import org.eclipse.viatra.dse.statecode.IStateCoder
17import org.eclipse.viatra.dse.statecode.IStateCoderFactory
18import org.eclipse.viatra.query.runtime.api.IPatternMatch
19import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine
20import org.eclipse.viatra.query.runtime.base.api.FeatureListener
21import org.eclipse.viatra.query.runtime.base.api.IndexingLevel
22import org.eclipse.viatra.query.runtime.base.api.InstanceListener
23import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper
24import org.eclipse.viatra.query.runtime.emf.EMFScope
25import org.eclipse.xtend.lib.annotations.Accessors
26
27abstract class AbstractNeighbourhoodBasedStateCoderFactory implements IStateCoderFactory {
28 val List<AbstractNeighbourhoodBasedPartialInterpretationStateCoder> statecoders = new LinkedList
29
30 val NeighbourhoodOptions options
31
32 protected new() {
33 this(NeighbourhoodOptions.DEFAULT)
34 }
35
36 protected new(NeighbourhoodOptions options) {
37 this.options = options
38 }
39
40 synchronized override createStateCoder() {
41 val res = doCreateStateCoder(options)
42 statecoders += res
43 return res
44 }
45
46 protected def AbstractNeighbourhoodBasedPartialInterpretationStateCoder doCreateStateCoder(
47 NeighbourhoodOptions options)
48
49 def getSumStatecoderRuntime() {
50 statecoders.map[statecoderRuntime].reduce[p1, p2|p1 + p2]
51 }
52}
53
54abstract class AbstractNeighbourhoodBasedPartialInterpretationStateCoder implements IStateCoder {
55 val NeighbourhoodOptions options
56
57 var PartialInterpretation target
58
59 protected new(NeighbourhoodOptions options) {
60 this.options = options
61 }
62
63 @Accessors(PUBLIC_GETTER) var long statecoderRuntime = 0
64
65 synchronized private def refreshStateCodes() {
66 if (refreshNeeded) {
67 val startTime = System.nanoTime
68 doRefreshStateCodes(target, options)
69 statecoderRuntime += (System.nanoTime - startTime)
70 }
71 }
72
73 protected def boolean isRefreshNeeded()
74
75 protected def void doRefreshStateCodes(PartialInterpretation target, NeighbourhoodOptions options)
76
77 synchronized override createActivationCode(IPatternMatch match) {
78 refreshStateCodes
79 val startTime = System.nanoTime
80 val code = doCreateActivationCode(match)
81 statecoderRuntime += (System.nanoTime - startTime)
82 code
83 }
84
85 protected def Object doCreateActivationCode(IPatternMatch match)
86
87 synchronized override createStateCode() {
88 refreshStateCodes
89 doCreateStateCode
90 }
91
92 protected def Object doCreateStateCode()
93
94 override init(Notifier notifier) {
95 this.target = notifier as PartialInterpretation
96 val queryEngine = ViatraQueryEngine.on(new EMFScope(notifier))
97 val baseIndex = queryEngine.getBaseIndex() as EMFBaseIndexWrapper
98 val navigationHelper = baseIndex.getNavigationHelper();
99
100 val classes = PartialinterpretationPackage.eINSTANCE.EClassifiers.filter(EClass).toSet
101 val features = classes.map[it.EAllStructuralFeatures].flatten.toSet
102 navigationHelper.registerObservedTypes(classes, null, features, IndexingLevel.FULL);
103
104 navigationHelper.addFeatureListener(features, new FeatureListener() {
105 override void featureInserted(EObject host, EStructuralFeature feature, Object value) { invalidate }
106
107 override void featureDeleted(EObject host, EStructuralFeature feature, Object value) { invalidate }
108 })
109 navigationHelper.addInstanceListener(classes, new InstanceListener() {
110 override void instanceInserted(EClass clazz, EObject instance) { invalidate }
111
112 override void instanceDeleted(EClass clazz, EObject instance) { invalidate }
113 })
114 }
115
116 synchronized def invalidate() {
117 doInvalidate
118 }
119
120 protected def void doInvalidate()
121
122 def protected getFallbackCode(Object o) {
123 switch (o) {
124 PartialInterpretation,
125 LogicProblem:
126 null
127 PartialRelationInterpretation:
128 o.interpretationOf.name
129 PartialPrimitiveInterpretation:
130 o.class.simpleName.hashCode
131 PartialComplexTypeInterpretation:
132 o.interpretationOf.name.hashCode
133 default:
134 throw new UnsupportedOperationException('''Unsupported type: «o.class.simpleName»''')
135 }
136 }
137}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend
index f55a501a..c7b8ee37 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/IdentifierBasedStateCoderFactory.xtend
@@ -62,13 +62,13 @@ class IdentifierBasedStateCode {
62 int numberOfNewElement 62 int numberOfNewElement
63 SortedSet<RelationStatecoder> relationStatecoders 63 SortedSet<RelationStatecoder> relationStatecoders
64 64
65 private static val comparator = new Comparator<RelationStatecoder>() { 65 static val comparator = new Comparator<RelationStatecoder>() {
66 override compare(RelationStatecoder o1, RelationStatecoder o2) { 66 override compare(RelationStatecoder o1, RelationStatecoder o2) {
67 o1.relationName.compareTo(o2.relationName) 67 o1.relationName.compareTo(o2.relationName)
68 } 68 }
69 } 69 }
70 70
71 public new(int numberOfNewElements) { 71 new(int numberOfNewElements) {
72 this.numberOfNewElement = numberOfNewElements 72 this.numberOfNewElement = numberOfNewElements
73 this.relationStatecoders = new TreeSet(comparator) 73 this.relationStatecoders = new TreeSet(comparator)
74 } 74 }
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend
index a86bcd1f..4ff39999 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/NeighbourhoodBasedStateCoderFactory.xtend
@@ -1,223 +1,86 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder 1package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder
2 2
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement
3import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor 4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodOptions
4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice 6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage
7import java.util.ArrayList 8import java.util.ArrayList
8import java.util.LinkedList
9import java.util.List
10import java.util.Map 9import java.util.Map
11import org.eclipse.emf.common.notify.Notifier
12import org.eclipse.emf.ecore.EClass
13import org.eclipse.emf.ecore.EObject
14import org.eclipse.emf.ecore.EStructuralFeature
15import org.eclipse.viatra.dse.statecode.IStateCoder
16import org.eclipse.viatra.dse.statecode.IStateCoderFactory
17import org.eclipse.viatra.query.runtime.api.IPatternMatch 10import org.eclipse.viatra.query.runtime.api.IPatternMatch
18import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine 11
19import org.eclipse.viatra.query.runtime.base.api.FeatureListener 12class NeighbourhoodBasedStateCoderFactory extends AbstractNeighbourhoodBasedStateCoderFactory {
20import org.eclipse.viatra.query.runtime.base.api.IndexingLevel 13 new() {
21import org.eclipse.viatra.query.runtime.base.api.InstanceListener
22import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper
23import org.eclipse.viatra.query.runtime.emf.EMFScope
24import org.eclipse.xtend.lib.annotations.Accessors
25import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement
26import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
27import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation
28import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRelationInterpretation
29import java.util.Set
30import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration
31import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
32import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2NeighbourhoodRepresentation
33import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
34import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialPrimitiveInterpretation
35
36class NeighbourhoodBasedStateCoderFactory implements IStateCoderFactory {
37 val List<NeighbourhoodBasedPartialInterpretationStateCoder> statecoders = new LinkedList
38
39 val int range
40 val int parallels
41 val int maxNumber
42 val Set<TypeDeclaration> relevantTypes
43 val Set<RelationDeclaration> relevantRelations
44
45 public new() {
46 this.range = PartialInterpretation2NeighbourhoodRepresentation::GraphWidthRange
47 this.parallels = PartialInterpretation2NeighbourhoodRepresentation::FullParallels
48 this.maxNumber = PartialInterpretation2NeighbourhoodRepresentation::MaxNumbers
49 this.relevantTypes = null
50 this.relevantRelations = null
51 } 14 }
52 15
53 public new(int range, int parallels, int maxNumber, Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations) { 16 new(NeighbourhoodOptions options) {
54 this.range = range 17 super(options)
55 this.parallels = parallels 18 }
56 this.maxNumber = maxNumber 19
57 this.relevantTypes = relevantTypes 20 override protected doCreateStateCoder(NeighbourhoodOptions options) {
58 this.relevantRelations = relevantRelations 21 new NeighbourhoodBasedPartialInterpretationStateCoder(options)
59 } 22 }
60 23
61 synchronized override createStateCoder() {
62 val res = new NeighbourhoodBasedPartialInterpretationStateCoder(statecoders.size,
63 range,parallels,maxNumber,relevantTypes,relevantRelations)
64 statecoders += res
65 return res
66 }
67 def getSumStatecoderRuntime() {
68 statecoders.map[statecoderRuntime].reduce[p1, p2|p1+p2]
69 }
70} 24}
71 25
72class NeighbourhoodBasedPartialInterpretationStateCoder implements IStateCoder{ 26class NeighbourhoodBasedPartialInterpretationStateCoder extends AbstractNeighbourhoodBasedPartialInterpretationStateCoder {
73 val int id; 27 val calculator = new PartialInterpretation2ImmutableTypeLattice
74 val int range 28
75 val int parallels 29 var Map<DefinedElement, ? extends AbstractNodeDescriptor> nodeRepresentations = null
76 val int maxNumber 30 var Map<? extends AbstractNodeDescriptor, Integer> modelRepresentation = null
77 val Set<TypeDeclaration> relevantTypes 31
78 val Set<RelationDeclaration> relevantRelations 32 new(NeighbourhoodOptions options) {
79 33 super(options)
80 val calculator =
81 new PartialInterpretation2ImmutableTypeLattice
82 var PartialInterpretation target
83
84 private var Map<DefinedElement, ? extends AbstractNodeDescriptor> nodeRepresentations = null
85 private var Map<? extends AbstractNodeDescriptor, Integer> modelRepresentation = null
86
87 /*public new(int id) {
88 this.id = id
89 this.range = PartialInterpretation2NeighbourhoodRepresentation::FixPointRage
90 this.parallels = PartialInterpretation2NeighbourhoodRepresentation::FullParallels
91 this.maxNumber = maxNumber = PartialInterpretation2NeighbourhoodRepresentation::MaxNumbers
92 this.relevantTypes = relevantTypes
93 this.relevantRelations = relevantRelations
94 }*/
95
96 public new(int id, int range, int parallels, int maxNumber, Set<TypeDeclaration> relevantTypes, Set<RelationDeclaration> relevantRelations) {
97 this.id = id
98 this.range = range
99 this.parallels = parallels
100 this.maxNumber = maxNumber
101 this.relevantTypes = relevantTypes
102 this.relevantRelations = relevantRelations
103 } 34 }
104 35
105 @Accessors(PUBLIC_GETTER) var long statecoderRuntime = 0 36 override protected isRefreshNeeded() {
106 37 nodeRepresentations === null || modelRepresentation === null
107// val range = -1 38 }
108// val par = Integer.MAX_VALUE 39
109 //val deeprepresentation = false 40 override doRefreshStateCodes(PartialInterpretation target, NeighbourhoodOptions options) {
110 41 val code = calculator.createRepresentation(target, options)
111 ///////// 42 modelRepresentation = code.modelRepresentation
112 // Caching version 43 nodeRepresentations = code.nodeRepresentations
113 ///////// 44 }
114 synchronized private def refreshStateCodes() { 45
115 if(this.nodeRepresentations === null || this.modelRepresentation === null) { 46 override doCreateActivationCode(IPatternMatch match) {
116 val startTime = System.nanoTime 47 val size = match.specification.parameters.size
117 //relevantObjects.forEach[println(it)] 48 val res = new ArrayList(size)
118 val code = calculator.createRepresentation(target,range,parallels,maxNumber,relevantTypes,relevantRelations) 49 var int index = 0
119 this.modelRepresentation = code.modelRepresentation 50 var int equivalenceHash = 0
120 this.nodeRepresentations = code.nodeRepresentations 51 val prime = 31
121 statecoderRuntime += (System.nanoTime - startTime) 52
122 } 53 while (index < size) {
123 } 54 res.add(getCode(match.get(index)))
124 synchronized override createActivationCode(IPatternMatch match) { 55 index++
125 refreshStateCodes 56 for (var i = 0; i < index; i++) {
126 57 val number = if (match.get(index) === match.get(i)) {
127 val startTime = System.nanoTime 58 1
128 val size = match.specification.parameters.size 59 } else {
129 val res = new ArrayList(size) 60 0
130 var int index = 0 61 }
131 var int equivalenceHash = 0 62 equivalenceHash = prime * equivalenceHash + number
132 val prime = 31
133
134 while(index < size) {
135 res.add(getCode(match.get(index)))
136 index++
137 for(var i = 0; i<index; i++) {
138 val number = if(match.get(index) === match.get(i)){1}else{0}
139 equivalenceHash = prime * equivalenceHash + number
140 }
141 }
142
143 statecoderRuntime += (System.nanoTime - startTime)
144 return match.specification.fullyQualifiedName->(res->equivalenceHash).hashCode
145 }
146
147
148 def private getCode(Object o) {
149 if(o instanceof DefinedElement) {
150 this.nodeRepresentations.get(o)
151 } else if(o instanceof PartialInterpretation || o instanceof LogicProblem) {
152 return null
153 } else if(o instanceof PartialRelationInterpretation) {
154 return o.interpretationOf.name
155 } else if(o instanceof PartialTypeInterpratation) {
156 if(o instanceof PartialPrimitiveInterpretation) {
157 o.class.simpleName.hashCode
158 } else if (o instanceof PartialComplexTypeInterpretation){
159 return o.interpretationOf.name.hashCode
160 } else {
161 throw new UnsupportedOperationException('''Unsupported type: «o.class.simpleName»''')
162 } 63 }
163 } else {
164 throw new UnsupportedOperationException('''Unsupported type: «o.class.simpleName»''')
165 } 64 }
166 } 65
167 66 match.specification.fullyQualifiedName -> (res -> equivalenceHash).hashCode
168 synchronized override createStateCode() { 67 }
169 refreshStateCodes 68
170 return this.modelRepresentation.hashCode 69 def private getCode(Object o) {
171 } 70 switch (o) {
172 ///////// 71 DefinedElement:
173 // Caching version 72 nodeRepresentations.get(o)
174 ///////// 73 default:
175 74 getFallbackCode(o)
176 ///////// 75 }
177 // Recalculating version 76 }
178 ///////// 77
179// synchronized override createActivationCode(IPatternMatch match) { 78 override doCreateStateCode() {
180// val nodes = calculator.createRepresentation(getRelevantObjects().toList,range,par).nodeRepresentations 79 modelRepresentation.hashCode
181// val res = match.toArray.map[objectInMatch | 80 }
182// nodes.get(objectInMatch) 81
183// ] 82 override doInvalidate() {
184// return res 83 nodeRepresentations = null
185// } 84 modelRepresentation = null
186//
187// override createStateCode() {
188// return this.calculator.createRepresentation(getRelevantObjects().toList,range,par).modelRepresentation
189// }
190 /////////
191 // Recalculating version
192 /////////
193
194 override init(Notifier notifier) {
195 this.target = notifier as PartialInterpretation
196 val queryEngine = ViatraQueryEngine.on(new EMFScope(notifier))
197 val baseIndex = queryEngine.getBaseIndex() as EMFBaseIndexWrapper
198 val navigationHelper = baseIndex.getNavigationHelper();
199
200 val classes = PartialinterpretationPackage.eINSTANCE.EClassifiers.filter(EClass).toSet
201 val features = classes.map[it.EAllStructuralFeatures].flatten.toSet
202 navigationHelper.registerObservedTypes(
203 classes,
204 null,
205 features,
206 IndexingLevel.FULL);
207
208
209 navigationHelper.addFeatureListener(features, new FeatureListener() {
210 override public void featureInserted(EObject host, EStructuralFeature feature, Object value) { invalidate }
211 override public void featureDeleted(EObject host, EStructuralFeature feature, Object value) { invalidate }
212 });
213 navigationHelper.addInstanceListener(classes, new InstanceListener() {
214 override public void instanceInserted(EClass clazz, EObject instance) { invalidate }
215 override public void instanceDeleted(EClass clazz, EObject instance) { invalidate }
216 });
217 }
218
219 synchronized def public invalidate() {
220 this.nodeRepresentations = null
221 this.modelRepresentation = null
222 } 85 }
223} 86}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend
new file mode 100644
index 00000000..84e798f2
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage/src/hu/bme/mit/inf/dslreasoner/viatrasolver/partialinterpretationlanguage/statecoder/PairwiseNeighbourhoodBasedStateCoderFactory.xtend
@@ -0,0 +1,75 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder
2
3import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.DefinedElement
4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodOptions
6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PairwiseNeighbourhoodRepresentation
7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice
8import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2PairwiseNeighbourhoodRepresentation
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
10import java.util.ArrayList
11import org.eclipse.viatra.query.runtime.api.IPatternMatch
12
13class PairwiseNeighbourhoodBasedStateCoderFactory extends AbstractNeighbourhoodBasedStateCoderFactory {
14 new() {
15 }
16
17 new(NeighbourhoodOptions options) {
18 super(options)
19 }
20
21 override protected doCreateStateCoder(NeighbourhoodOptions options) {
22 new PairwiseNeighbourhoodBasedPartialInterpretationStateCoder(options)
23 }
24}
25
26class PairwiseNeighbourhoodBasedPartialInterpretationStateCoder extends AbstractNeighbourhoodBasedPartialInterpretationStateCoder {
27 val calculator = new PartialInterpretation2PairwiseNeighbourhoodRepresentation(
28 new PartialInterpretation2ImmutableTypeLattice)
29 var PairwiseNeighbourhoodRepresentation<? extends AbstractNodeDescriptor> representation
30
31 new(NeighbourhoodOptions options) {
32 super(options)
33 }
34
35 override protected isRefreshNeeded() {
36 representation === null
37 }
38
39 override protected doRefreshStateCodes(PartialInterpretation target, NeighbourhoodOptions options) {
40 representation = calculator.createRepresentation(target, options)
41 }
42
43 override protected doCreateActivationCode(IPatternMatch match) {
44 val size = match.specification.parameters.size
45 val res = new ArrayList(size * size)
46 for (var int i = 0; i < size; i++) {
47 val a = match.get(i)
48 for (var int j = 0; j < size; j++) {
49 val b = match.get(j)
50 res.add(getPairwiseRepresentation(a, b))
51 }
52 }
53 match.specification.fullyQualifiedName -> res.hashCode
54 }
55
56 private def getPairwiseRepresentation(Object a, Object b) {
57 if (b instanceof DefinedElement) {
58 if (a instanceof DefinedElement) {
59 representation.getPairwiseRepresentation(a, b)
60 } else {
61 representation.getBasicRepresentation(b)
62 }
63 } else {
64 getFallbackCode(b)
65 }
66 }
67
68 override protected doCreateStateCode() {
69 representation.modelRepresentation.hashCode
70 }
71
72 override protected doInvalidate() {
73 representation = null
74 }
75}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/META-INF/MANIFEST.MF b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/META-INF/MANIFEST.MF
index 2a271acf..4ad61ccb 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/META-INF/MANIFEST.MF
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/META-INF/MANIFEST.MF
@@ -3,7 +3,8 @@ Bundle-ManifestVersion: 2
3Bundle-Name: Reasoner 3Bundle-Name: Reasoner
4Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner 4Bundle-SymbolicName: hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner
5Bundle-Version: 1.0.0.qualifier 5Bundle-Version: 1.0.0.qualifier
6Export-Package: hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner 6Export-Package: hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner,
7 hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization
7Require-Bundle: hu.bme.mit.inf.dslreasoner.ecore2logic;bundle-version="1.0.0", 8Require-Bundle: hu.bme.mit.inf.dslreasoner.ecore2logic;bundle-version="1.0.0",
8 hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0", 9 hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0",
9 hu.bme.mit.inf.dslreasoner.viatra2logic;bundle-version="1.0.0", 10 hu.bme.mit.inf.dslreasoner.viatra2logic;bundle-version="1.0.0",
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend
index 6639e5f3..1abde0a8 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend
@@ -1,5 +1,7 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner 1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner
2 2
3import com.google.common.collect.ImmutableList
4import com.google.common.collect.Lists
3import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel 5import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel
4import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasoner 6import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasoner
5import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasonerException 7import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasonerException
@@ -10,19 +12,25 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage
10import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicresultFactory 12import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicresultFactory
11import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult 13import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult
12import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethodProvider 14import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethodProvider
13import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator
14import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.PartialInterpretationInitialiser 15import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.PartialInterpretationInitialiser
15import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 16import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
16import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage 17import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage
18import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.AbstractNeighbourhoodBasedStateCoderFactory
17import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.IdentifierBasedStateCoderFactory 19import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.IdentifierBasedStateCoderFactory
18import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedStateCoderFactory 20import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.PairwiseNeighbourhoodBasedStateCoderFactory
19import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.BestFirstStrategyForModelGeneration 21import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.BestFirstStrategyForModelGeneration
22import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.DiversityChecker
23import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.InconsistentScopeGlobalConstraint
24import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.LoggerSolutionFoundHandler
20import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ModelGenerationCompositeObjective 25import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ModelGenerationCompositeObjective
21import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PartialModelAsLogicInterpretation 26import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PartialModelAsLogicInterpretation
22import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ScopeObjective 27import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ScopeObjective
28import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.SurelyViolatedObjectiveGlobalConstraint
23import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.UnfinishedMultiplicityObjective 29import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.UnfinishedMultiplicityObjective
24import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.UnfinishedWFObjective 30import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ViatraReasonerSolutionSaver
25import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.WF2ObjectiveConverter 31import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.WF2ObjectiveConverter
32import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ThreeValuedCostElement
33import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ThreeValuedCostObjective
26import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace 34import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace
27import java.util.List 35import java.util.List
28import java.util.Map 36import java.util.Map
@@ -31,185 +39,247 @@ import org.eclipse.viatra.dse.api.DesignSpaceExplorer
31import org.eclipse.viatra.dse.api.DesignSpaceExplorer.DseLoggingLevel 39import org.eclipse.viatra.dse.api.DesignSpaceExplorer.DseLoggingLevel
32import org.eclipse.viatra.dse.solutionstore.SolutionStore 40import org.eclipse.viatra.dse.solutionstore.SolutionStore
33import org.eclipse.viatra.dse.statecode.IStateCoderFactory 41import org.eclipse.viatra.dse.statecode.IStateCoderFactory
34import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.SolutionStoreWithDiversityDescriptor 42import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedStateCoderFactory
35import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.DiversityGranularity
36 43
37class ViatraReasoner extends LogicReasoner{ 44class ViatraReasoner extends LogicReasoner {
38 val PartialInterpretationInitialiser initialiser = new PartialInterpretationInitialiser() 45 val PartialInterpretationInitialiser initialiser = new PartialInterpretationInitialiser()
39 val ModelGenerationMethodProvider modelGenerationMethodProvider = new ModelGenerationMethodProvider 46 val ModelGenerationMethodProvider modelGenerationMethodProvider = new ModelGenerationMethodProvider
40 val extension LogicresultFactory factory = LogicresultFactory.eINSTANCE 47 val extension LogicresultFactory factory = LogicresultFactory.eINSTANCE
41 val WF2ObjectiveConverter wf2ObjectiveConverter = new WF2ObjectiveConverter 48 val WF2ObjectiveConverter wf2ObjectiveConverter = new WF2ObjectiveConverter
42 49
43 50 override solve(LogicProblem problem, LogicSolverConfiguration configuration,
44 override solve(LogicProblem problem, LogicSolverConfiguration configuration, ReasonerWorkspace workspace) throws LogicReasonerException { 51 ReasonerWorkspace workspace) throws LogicReasonerException {
45 val viatraConfig = configuration.asConfig 52 val viatraConfig = configuration.asConfig
46 53
47 if(viatraConfig.debugCongiguration.logging) { 54 if (viatraConfig.documentationLevel == DocumentationLevel.FULL) {
48 DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.VERBOSE_FULL) 55 DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.VERBOSE_FULL)
49 } else { 56 } else {
50 DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.WARN) 57 DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.WARN)
51 } 58 }
52 59
53 val DesignSpaceExplorer dse = new DesignSpaceExplorer(); 60 val DesignSpaceExplorer dse = new DesignSpaceExplorer();
54 61
55 dse.addMetaModelPackage(LogiclanguagePackage.eINSTANCE) 62 dse.addMetaModelPackage(LogiclanguagePackage.eINSTANCE)
56 dse.addMetaModelPackage(LogicproblemPackage.eINSTANCE) 63 dse.addMetaModelPackage(LogicproblemPackage.eINSTANCE)
57 dse.addMetaModelPackage(PartialinterpretationPackage.eINSTANCE) 64 dse.addMetaModelPackage(PartialinterpretationPackage.eINSTANCE)
58 65
59 val transformationStartTime = System.nanoTime 66 val transformationStartTime = System.nanoTime
60 67
61 68 val emptySolution = initialiser.initialisePartialInterpretation(problem, viatraConfig.typeScopes).output
62 69 if ((viatraConfig.documentationLevel == DocumentationLevel::FULL ||
63 val emptySolution = initialiser.initialisePartialInterpretation(problem,viatraConfig.typeScopes).output 70 viatraConfig.documentationLevel == DocumentationLevel::NORMAL) && workspace !== null) {
64 if((viatraConfig.documentationLevel == DocumentationLevel::FULL || viatraConfig.documentationLevel == DocumentationLevel::NORMAL) && workspace !== null) { 71 workspace.writeModel(emptySolution, "init.partialmodel")
65 workspace.writeModel(emptySolution,"init.partialmodel") 72 }
66 }
67 emptySolution.problemConainer = problem 73 emptySolution.problemConainer = problem
68 74
69 val ScopePropagator scopePropagator = new ScopePropagator(emptySolution)
70 scopePropagator.propagateAllScopeConstraints
71
72 val method = modelGenerationMethodProvider.createModelGenerationMethod( 75 val method = modelGenerationMethodProvider.createModelGenerationMethod(
73 problem, 76 problem,
74 emptySolution, 77 emptySolution,
75 workspace, 78 workspace,
76 viatraConfig.nameNewElements, 79 viatraConfig.nameNewElements,
77 viatraConfig.typeInferenceMethod, 80 viatraConfig.typeInferenceMethod,
78 scopePropagator, 81 viatraConfig.scopePropagatorStrategy,
79 viatraConfig.documentationLevel 82 viatraConfig.documentationLevel
80 ) 83 )
81 84
82 dse.addObjective(new ModelGenerationCompositeObjective( 85 dse.addObjective(new ModelGenerationCompositeObjective(
83 new ScopeObjective, 86 new ScopeObjective,
84 method.unfinishedMultiplicities.map[new UnfinishedMultiplicityObjective(it)], 87 method.unfinishedMultiplicities.map[new UnfinishedMultiplicityObjective(it)],
85 new UnfinishedWFObjective(method.unfinishedWF) 88 wf2ObjectiveConverter.createCompletenessObjective(method.unfinishedWF)
86 )) 89 ))
87 90
88 dse.addGlobalConstraint(wf2ObjectiveConverter.createInvalidationObjective(method.invalidWF)) 91 val extremalObjectives = Lists.newArrayListWithExpectedSize(viatraConfig.costObjectives.size)
89 for(additionalConstraint : viatraConfig.searchSpaceConstraints.additionalGlobalConstraints) { 92 for (entry : viatraConfig.costObjectives.indexed) {
93 val objectiveName = '''costObjective«entry.key»'''
94 val objectiveConfig = entry.value
95 val elementsBuilder = ImmutableList.builder
96 for (elementConfig : objectiveConfig.elements) {
97 val relationName = elementConfig.patternQualifiedName
98 val modalQueries = method.modalRelationQueries.get(relationName)
99 if (modalQueries === null) {
100 throw new IllegalArgumentException("Unknown relation: " + relationName)
101 }
102 elementsBuilder.add(new ThreeValuedCostElement(
103 modalQueries.currentQuery,
104 modalQueries.mayQuery,
105 modalQueries.mustQuery,
106 elementConfig.weight
107 ))
108 }
109 val costElements = elementsBuilder.build
110 val costObjective = new ThreeValuedCostObjective(objectiveName, costElements, objectiveConfig.kind,
111 objectiveConfig.threshold, 3)
112 dse.addObjective(costObjective)
113 if (objectiveConfig.findExtremum) {
114 extremalObjectives += costObjective
115 }
116 }
117
118 val numberOfRequiredSolutions = configuration.solutionScope.numberOfRequiredSolutions
119 val solutionStore = if (extremalObjectives.empty) {
120 new SolutionStore(numberOfRequiredSolutions)
121 } else {
122 new SolutionStore()
123 }
124 solutionStore.registerSolutionFoundHandler(new LoggerSolutionFoundHandler(viatraConfig))
125 val diversityChecker = DiversityChecker.of(viatraConfig.diversityRequirement)
126 val solutionSaver = new ViatraReasonerSolutionSaver(newArrayList(extremalObjectives), numberOfRequiredSolutions,
127 diversityChecker)
128 val solutionCopier = solutionSaver.solutionCopier
129 solutionStore.withSolutionSaver(solutionSaver)
130 dse.solutionStore = solutionStore
131
132 dse.addGlobalConstraint(wf2ObjectiveConverter.createInvalidationGlobalConstraint(method.invalidWF))
133 dse.addGlobalConstraint(new SurelyViolatedObjectiveGlobalConstraint(solutionSaver))
134 dse.addGlobalConstraint(new InconsistentScopeGlobalConstraint)
135 for (additionalConstraint : viatraConfig.searchSpaceConstraints.additionalGlobalConstraints) {
90 dse.addGlobalConstraint(additionalConstraint.apply(method)) 136 dse.addGlobalConstraint(additionalConstraint.apply(method))
91 } 137 }
92 138
93 dse.setInitialModel(emptySolution,false) 139 dse.setInitialModel(emptySolution, false)
94 140
95 val IStateCoderFactory statecoder = if(viatraConfig.stateCoderStrategy == StateCoderStrategy.Neighbourhood) { 141 val IStateCoderFactory statecoder = switch (viatraConfig.stateCoderStrategy) {
96 new NeighbourhoodBasedStateCoderFactory 142 case Neighbourhood:
97 } else { 143 new NeighbourhoodBasedStateCoderFactory
98 new IdentifierBasedStateCoderFactory 144 case PairwiseNeighbourhood:
145 new PairwiseNeighbourhoodBasedStateCoderFactory
146 default:
147 new IdentifierBasedStateCoderFactory
99 } 148 }
100 dse.stateCoderFactory = statecoder 149 dse.stateCoderFactory = statecoder
101 150
102 dse.maxNumberOfThreads = 1 151 dse.maxNumberOfThreads = 1
103 152
104 val solutionStore = new SolutionStore(configuration.solutionScope.numberOfRequiredSolution) 153 for (rule : method.relationRefinementRules) {
105 dse.solutionStore = solutionStore
106
107 for(rule : method.relationRefinementRules) {
108 dse.addTransformationRule(rule) 154 dse.addTransformationRule(rule)
109 } 155 }
110 for(rule : method.objectRefinementRules) { 156 for (rule : method.objectRefinementRules) {
111 dse.addTransformationRule(rule) 157 dse.addTransformationRule(rule)
112 } 158 }
113 159
114 val strategy = new BestFirstStrategyForModelGeneration(workspace,viatraConfig,method) 160 val strategy = new BestFirstStrategyForModelGeneration(workspace, viatraConfig, method)
115 viatraConfig.progressMonitor.workedForwardTransformation 161 viatraConfig.progressMonitor.workedForwardTransformation
116 162
117 val transformationTime = System.nanoTime - transformationStartTime 163 val transformationTime = System.nanoTime - transformationStartTime
118 val solverStartTime = System.nanoTime 164 val solverStartTime = System.nanoTime
119 165
120 var boolean stoppedByTimeout 166 var boolean stoppedByTimeout
121 var boolean stoppedByException 167 try {
122 try{ 168 stoppedByTimeout = dse.startExplorationWithTimeout(strategy, configuration.runtimeLimit * 1000);
123 stoppedByTimeout = dse.startExplorationWithTimeout(strategy,configuration.runtimeLimit*1000);
124 stoppedByException = false
125 } catch (NullPointerException npe) { 169 } catch (NullPointerException npe) {
126 stoppedByTimeout = false 170 stoppedByTimeout = false
127 stoppedByException = true
128 } 171 }
129 val solverTime = System.nanoTime - solverStartTime 172 val solverTime = System.nanoTime - solverStartTime
130 viatraConfig.progressMonitor.workedSearchFinished 173 viatraConfig.progressMonitor.workedSearchFinished
131 174
132 //additionalMatches = strategy.solutionStoreWithCopy.additionalMatches 175 // additionalMatches = strategy.solutionStoreWithCopy.additionalMatches
133 val statistics = createStatistics => [ 176 val statistics = createStatistics => [
134 //it.solverTime = viatraConfig.runtimeLimit 177 // it.solverTime = viatraConfig.runtimeLimit
135 it.solverTime = (solverTime/1000000) as int 178 it.solverTime = (solverTime / 1000000) as int
136 it.transformationTime = (transformationTime/1000000) as int 179 it.transformationTime = (transformationTime / 1000000) as int
137 for(x : 0..<strategy.solutionStoreWithCopy.allRuntimes.size) { 180 for (pair : solutionCopier.getAllCopierRuntimes(true).indexed) {
138 it.entries += createIntStatisticEntry => [ 181 it.entries += createIntStatisticEntry => [
139 it.name = '''_Solution«x»FoundAt''' 182 it.name = '''_Solution«pair.key»FoundAt'''
140 it.value = (strategy.solutionStoreWithCopy.allRuntimes.get(x)/1000000) as int 183 it.value = (pair.value / 1000000) as int
141 ] 184 ]
142 } 185 }
143 it.entries += createIntStatisticEntry => [ 186 it.entries += createIntStatisticEntry => [
144 it.name = "TransformationExecutionTime" it.value = (method.statistics.transformationExecutionTime/1000000) as int 187 it.name = "TransformationExecutionTime"
188 it.value = (method.statistics.transformationExecutionTime / 1000000) as int
145 ] 189 ]
146 it.entries += createIntStatisticEntry => [ 190 it.entries += createIntStatisticEntry => [
147 it.name = "TypeAnalysisTime" it.value = (method.statistics.PreliminaryTypeAnalisisTime/1000000) as int 191 it.name = "ScopePropagationTime"
192 it.value = (method.statistics.scopePropagationTime / 1000000) as int
148 ] 193 ]
149 it.entries += createIntStatisticEntry => [ 194 it.entries += createIntStatisticEntry => [
150 it.name = "StateCoderTime" it.value = (statecoder.runtime/1000000) as int 195 it.name = "TypeAnalysisTime"
196 it.value = (method.statistics.preliminaryTypeAnalisisTime / 1000000) as int
151 ] 197 ]
152 it.entries += createIntStatisticEntry => [ 198 it.entries += createIntStatisticEntry => [
153 it.name = "StateCoderFailCount" it.value = strategy.numberOfStatecoderFail 199 it.name = "StateCoderTime"
200 it.value = (statecoder.runtime / 1000000) as int
154 ] 201 ]
155 it.entries += createIntStatisticEntry => [ 202 it.entries += createIntStatisticEntry => [
156 it.name = "SolutionCopyTime" it.value = (strategy.solutionStoreWithCopy.sumRuntime/1000000) as int 203 it.name = "StateCoderFailCount"
204 it.value = strategy.numberOfStatecoderFail
157 ] 205 ]
158 if(strategy.solutionStoreWithDiversityDescriptor.isActive) { 206 it.entries += createIntStatisticEntry => [
207 it.name = "SolutionCopyTime"
208 it.value = (solutionCopier.getTotalCopierRuntime / 1000000) as int
209 ]
210 it.entries += createIntStatisticEntry => [
211 it.name = "States"
212 it.value = dse.numberOfStates as int
213 ]
214 it.entries += createIntStatisticEntry => [
215 it.name = "Decisions"
216 it.value = method.statistics.decisionsTried
217 ]
218 it.entries += createIntStatisticEntry => [
219 it.name = "ScopePropagations"
220 it.value = method.statistics.scopePropagatorInvocations
221 ]
222 if (diversityChecker.isActive) {
159 it.entries += createIntStatisticEntry => [ 223 it.entries += createIntStatisticEntry => [
160 it.name = "SolutionDiversityCheckTime" it.value = (strategy.solutionStoreWithDiversityDescriptor.sumRuntime/1000000) as int 224 it.name = "SolutionDiversityCheckTime"
225 it.value = (diversityChecker.totalRuntime / 1000000) as int
161 ] 226 ]
162 it.entries += createRealStatisticEntry => [ 227 it.entries += createRealStatisticEntry => [
163 it.name = "SolutionDiversitySuccessRate" it.value = strategy.solutionStoreWithDiversityDescriptor.successRate 228 it.name = "SolutionDiversitySuccessRate"
229 it.value = diversityChecker.successRate
164 ] 230 ]
165 } 231 }
166 ] 232 ]
167 233
168 viatraConfig.progressMonitor.workedBackwardTransformationFinished 234 viatraConfig.progressMonitor.workedBackwardTransformationFinished
169 235
170 if(stoppedByTimeout) { 236 if (stoppedByTimeout) {
171 return createInsuficientResourcesResult=>[ 237 return createInsuficientResourcesResult => [
172 it.problem = problem 238 it.problem = problem
173 it.resourceName="time" 239 it.resourceName = "time"
174 it.representation += strategy.solutionStoreWithCopy.solutions 240 it.representation += solutionCopier.getPartialInterpretations(true)
175 it.statistics = statistics 241 it.statistics = statistics
176 ] 242 ]
177 } else { 243 } else {
178 if(solutionStore.solutions.empty) { 244 if (solutionStore.solutions.empty) {
179 return createInconsistencyResult => [ 245 return createInconsistencyResult => [
180 it.problem = problem 246 it.problem = problem
181 it.representation += strategy.solutionStoreWithCopy.solutions 247 it.representation += solutionCopier.getPartialInterpretations(true)
182 it.statistics = statistics 248 it.statistics = statistics
183 ] 249 ]
184 } else { 250 } else {
185 return createModelResult => [ 251 return createModelResult => [
186 it.problem = problem 252 it.problem = problem
187 it.trace = strategy.solutionStoreWithCopy.copyTraces 253 it.trace = solutionCopier.getTraces(true)
188 it.representation += strategy.solutionStoreWithCopy.solutions 254 it.representation += solutionCopier.getPartialInterpretations(true)
189 it.statistics = statistics 255 it.statistics = statistics
190 ] 256 ]
191 } 257 }
192 } 258 }
193 } 259 }
194 260
195 private def dispatch long runtime(NeighbourhoodBasedStateCoderFactory sc) { 261 private def dispatch long runtime(AbstractNeighbourhoodBasedStateCoderFactory sc) {
196 sc.sumStatecoderRuntime 262 sc.sumStatecoderRuntime
197 } 263 }
198 264
199 private def dispatch long runtime(IdentifierBasedStateCoderFactory sc) { 265 private def dispatch long runtime(IdentifierBasedStateCoderFactory sc) {
200 sc.sumStatecoderRuntime 266 sc.sumStatecoderRuntime
201 } 267 }
202 268
203 override getInterpretations(ModelResult modelResult) { 269 override getInterpretations(ModelResult modelResult) {
204 val indexes = 0..<modelResult.representation.size 270 val indexes = 0 ..< modelResult.representation.size
205 val traces = modelResult.trace as List<Map<EObject, EObject>>; 271 val traces = modelResult.trace as List<Map<EObject, EObject>>;
206 val res = indexes.map[i | new PartialModelAsLogicInterpretation(modelResult.representation.get(i) as PartialInterpretation,traces.get(i))].toList 272 val res = indexes.map [ i |
273 new PartialModelAsLogicInterpretation(modelResult.representation.get(i) as PartialInterpretation,
274 traces.get(i))
275 ].toList
207 return res 276 return res
208 } 277 }
209 278
210 private def ViatraReasonerConfiguration asConfig(LogicSolverConfiguration configuration) { 279 private def ViatraReasonerConfiguration asConfig(LogicSolverConfiguration configuration) {
211 if(configuration instanceof ViatraReasonerConfiguration) { 280 if (configuration instanceof ViatraReasonerConfiguration) {
212 return configuration 281 return configuration
213 } else throw new IllegalArgumentException('''Wrong configuration. Expected: «ViatraReasonerConfiguration.name», but got: «configuration.class.name»"''') 282 } else
283 throw new IllegalArgumentException('''Wrong configuration. Expected: «ViatraReasonerConfiguration.name», but got: «configuration.class.name»"''')
214 } 284 }
215} 285}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend
index c4d7e231..a5f42a5f 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend
@@ -6,19 +6,27 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration
6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration 6import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod 7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod 8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorConstraints
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorSolver
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser 12import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser
13import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind
14import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold
10import java.util.LinkedList 15import java.util.LinkedList
11import java.util.List 16import java.util.List
12import java.util.Set 17import java.util.Set
13import org.eclipse.xtext.xbase.lib.Functions.Function1 18import org.eclipse.xtext.xbase.lib.Functions.Function1
14 19
15public enum StateCoderStrategy { 20enum StateCoderStrategy {
16 Neighbourhood, NeighbourhoodWithEquivalence, IDBased, DefinedByDiversity 21 Neighbourhood,
22 PairwiseNeighbourhood,
23 NeighbourhoodWithEquivalence,
24 IDBased,
25 DefinedByDiversity
17} 26}
18 27
19class ViatraReasonerConfiguration extends LogicSolverConfiguration{ 28class ViatraReasonerConfiguration extends LogicSolverConfiguration {
20 //public var Iterable<PQuery> existingQueries 29 // public var Iterable<PQuery> existingQueries
21
22 public var nameNewElements = false 30 public var nameNewElements = false
23 public var StateCoderStrategy stateCoderStrategy = StateCoderStrategy.Neighbourhood 31 public var StateCoderStrategy stateCoderStrategy = StateCoderStrategy.Neighbourhood
24 public var TypeInferenceMethod typeInferenceMethod = TypeInferenceMethod.PreliminaryAnalysis 32 public var TypeInferenceMethod typeInferenceMethod = TypeInferenceMethod.PreliminaryAnalysis
@@ -26,7 +34,7 @@ class ViatraReasonerConfiguration extends LogicSolverConfiguration{
26 * Once per 1/randomBacktrackChance the search selects a random state. 34 * Once per 1/randomBacktrackChance the search selects a random state.
27 */ 35 */
28 public var int randomBacktrackChance = 20; 36 public var int randomBacktrackChance = 20;
29 37
30 /** 38 /**
31 * Describes the required diversity between the solutions. 39 * Describes the required diversity between the solutions.
32 * Null means that the solutions have to have different state codes only. 40 * Null means that the solutions have to have different state codes only.
@@ -40,14 +48,19 @@ class ViatraReasonerConfiguration extends LogicSolverConfiguration{
40 /** 48 /**
41 * Configuration for debugging support. 49 * Configuration for debugging support.
42 */ 50 */
43 public var DebugConfiguration debugCongiguration = new DebugConfiguration 51 public var DebugConfiguration debugConfiguration = new DebugConfiguration
44 /** 52 /**
45 * Configuration for cutting search space. 53 * Configuration for cutting search space.
46 */ 54 */
47 public var SearchSpaceConstraint searchSpaceConstraints = new SearchSpaceConstraint 55 public var SearchSpaceConstraint searchSpaceConstraints = new SearchSpaceConstraint
56
57 public var ScopePropagatorStrategy scopePropagatorStrategy = new ScopePropagatorStrategy.Polyhedral(
58 PolyhedralScopePropagatorConstraints.Relational, PolyhedralScopePropagatorSolver.Clp)
59
60 public var List<CostObjectiveConfiguration> costObjectives = newArrayList
48} 61}
49 62
50public class DiversityDescriptor { 63class DiversityDescriptor {
51 public var ensureDiversity = false 64 public var ensureDiversity = false
52 public static val FixPointRange = -1 65 public static val FixPointRange = -1
53 public var int range = FixPointRange 66 public var int range = FixPointRange
@@ -57,20 +70,31 @@ public class DiversityDescriptor {
57 public var Set<RelationDeclaration> relevantRelations = null 70 public var Set<RelationDeclaration> relevantRelations = null
58} 71}
59 72
60public class DebugConfiguration { 73class DebugConfiguration {
61 public var logging = false 74 public var PartialInterpretationVisualiser partialInterpretatioVisualiser = null
62 public var PartialInterpretationVisualiser partialInterpretatioVisualiser = null;
63 public var partalInterpretationVisualisationFrequency = 1 75 public var partalInterpretationVisualisationFrequency = 1
64} 76}
65 77
66public class InternalConsistencyCheckerConfiguration { 78class InternalConsistencyCheckerConfiguration {
67 public var LogicReasoner internalIncosnsitencyDetector = null 79 public var LogicReasoner internalIncosnsitencyDetector = null
68 public var LogicSolverConfiguration internalInconsistencDetectorConfiguration = null 80 public var LogicSolverConfiguration internalInconsistencDetectorConfiguration = null
69 public var incternalConsistencyCheckingFrequency = 1 81 public var incternalConsistencyCheckingFrequency = 1
70} 82}
71 83
72public class SearchSpaceConstraint { 84class SearchSpaceConstraint {
73 public static val UNLIMITED_MAXDEPTH = Integer.MAX_VALUE 85 public static val UNLIMITED_MAXDEPTH = Integer.MAX_VALUE
74 public var int maxDepth = UNLIMITED_MAXDEPTH 86 public var int maxDepth = UNLIMITED_MAXDEPTH
75 public var List<Function1<ModelGenerationMethod, ModelGenerationMethodBasedGlobalConstraint>> additionalGlobalConstraints = new LinkedList 87 public var List<Function1<ModelGenerationMethod, ModelGenerationMethodBasedGlobalConstraint>> additionalGlobalConstraints = new LinkedList
76} \ No newline at end of file 88}
89
90class CostObjectiveConfiguration {
91 public var List<CostObjectiveElementConfiguration> elements = newArrayList
92 public var ObjectiveKind kind
93 public var ObjectiveThreshold threshold
94 public var boolean findExtremum
95}
96
97class CostObjectiveElementConfiguration {
98 public var String patternQualifiedName
99 public var int weight
100}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java
index 60f46033..5af7fc69 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java
@@ -21,6 +21,7 @@ import java.util.PriorityQueue;
21import java.util.Random; 21import java.util.Random;
22 22
23import org.apache.log4j.Logger; 23import org.apache.log4j.Logger;
24import org.eclipse.emf.ecore.EObject;
24import org.eclipse.emf.ecore.util.EcoreUtil; 25import org.eclipse.emf.ecore.util.EcoreUtil;
25import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; 26import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy;
26import org.eclipse.viatra.dse.base.ThreadContext; 27import org.eclipse.viatra.dse.base.ThreadContext;
@@ -75,8 +76,6 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
75 // Running 76 // Running
76 private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; 77 private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore;
77 private SolutionStore solutionStore; 78 private SolutionStore solutionStore;
78 private SolutionStoreWithCopy solutionStoreWithCopy;
79 private SolutionStoreWithDiversityDescriptor solutionStoreWithDiversityDescriptor;
80 private volatile boolean isInterrupted = false; 79 private volatile boolean isInterrupted = false;
81 private ModelResult modelResultByInternalSolver = null; 80 private ModelResult modelResultByInternalSolver = null;
82 private Random random = new Random(); 81 private Random random = new Random();
@@ -95,14 +94,9 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
95 this.workspace = workspace; 94 this.workspace = workspace;
96 this.configuration = configuration; 95 this.configuration = configuration;
97 this.method = method; 96 this.method = method;
97 //logger.setLevel(Level.DEBUG);
98 } 98 }
99 99
100 public SolutionStoreWithCopy getSolutionStoreWithCopy() {
101 return solutionStoreWithCopy;
102 }
103 public SolutionStoreWithDiversityDescriptor getSolutionStoreWithDiversityDescriptor() {
104 return solutionStoreWithDiversityDescriptor;
105 }
106 public int getNumberOfStatecoderFail() { 100 public int getNumberOfStatecoderFail() {
107 return numberOfStatecoderFail; 101 return numberOfStatecoderFail;
108 } 102 }
@@ -121,9 +115,6 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
121 matchers.add(matcher); 115 matchers.add(matcher);
122 } 116 }
123 117
124 this.solutionStoreWithCopy = new SolutionStoreWithCopy();
125 this.solutionStoreWithDiversityDescriptor = new SolutionStoreWithDiversityDescriptor(configuration.diversityRequirement);
126
127 final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); 118 final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper();
128 this.comparator = new Comparator<TrajectoryWithFitness>() { 119 this.comparator = new Comparator<TrajectoryWithFitness>() {
129 @Override 120 @Override
@@ -146,13 +137,13 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
146 return; 137 return;
147 } 138 }
148 139
149 final Fitness firstFittness = context.calculateFitness(); 140 final Fitness firstfitness = context.calculateFitness();
150 checkForSolution(firstFittness); 141 solutionStore.newSolution(context);
151 142
152 final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); 143 final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper();
153 final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); 144 final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]);
154 TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness); 145 TrajectoryWithFitness currentTrajectoryWithfitness = new TrajectoryWithFitness(firstTrajectory, firstfitness);
155 trajectoiresToExplore.add(currentTrajectoryWithFittness); 146 trajectoiresToExplore.add(currentTrajectoryWithfitness);
156 147
157 //if(configuration) 148 //if(configuration)
158 visualiseCurrentState(); 149 visualiseCurrentState();
@@ -167,22 +158,22 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
167 158
168 mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) { 159 mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) {
169 160
170 if (currentTrajectoryWithFittness == null) { 161 if (currentTrajectoryWithfitness == null) {
171 if (trajectoiresToExplore.isEmpty()) { 162 if (trajectoiresToExplore.isEmpty()) {
172 logger.debug("State space is fully traversed."); 163 logger.debug("State space is fully traversed.");
173 return; 164 return;
174 } else { 165 } else {
175 currentTrajectoryWithFittness = selectState(); 166 currentTrajectoryWithfitness = selectState();
176 if (logger.isDebugEnabled()) { 167 if (logger.isDebugEnabled()) {
177 logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray())); 168 logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray()));
178 logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness); 169 logger.debug("New trajectory is chosen: " + currentTrajectoryWithfitness);
179 } 170 }
180 context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory); 171 context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithfitness.trajectory);
181 } 172 }
182 } 173 }
183 174
184// visualiseCurrentState(); 175// visualiseCurrentState();
185// boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); 176// boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithfitness);
186// if(consistencyCheckResult == true) { 177// if(consistencyCheckResult == true) {
187// continue mainLoop; 178// continue mainLoop;
188// } 179// }
@@ -194,10 +185,11 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
194 final Object nextActivation = iterator.next(); 185 final Object nextActivation = iterator.next();
195// if (!iterator.hasNext()) { 186// if (!iterator.hasNext()) {
196// logger.debug("Last untraversed activation of the state."); 187// logger.debug("Last untraversed activation of the state.");
197// trajectoiresToExplore.remove(currentTrajectoryWithFittness); 188// trajectoiresToExplore.remove(currentTrajectoryWithfitness);
198// } 189// }
199 logger.debug("Executing new activation: " + nextActivation); 190 logger.debug("Executing new activation: " + nextActivation);
200 context.executeAcitvationId(nextActivation); 191 context.executeAcitvationId(nextActivation);
192 method.getStatistics().incrementDecisionCount();
201 193
202 visualiseCurrentState(); 194 visualiseCurrentState();
203// for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { 195// for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) {
@@ -209,7 +201,7 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
209// System.out.println("---------"); 201// System.out.println("---------");
210// } 202// }
211 203
212 boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); 204 boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithfitness);
213 if(consistencyCheckResult == true) { continue mainLoop; } 205 if(consistencyCheckResult == true) { continue mainLoop; }
214 206
215 if (context.isCurrentStateAlreadyTraversed()) { 207 if (context.isCurrentStateAlreadyTraversed()) {
@@ -220,38 +212,38 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
220 context.backtrack(); 212 context.backtrack();
221 } else { 213 } else {
222 final Fitness nextFitness = context.calculateFitness(); 214 final Fitness nextFitness = context.calculateFitness();
223 checkForSolution(nextFitness); 215 solutionStore.newSolution(context);
224 if (context.getDepth() > configuration.searchSpaceConstraints.maxDepth) { 216 if (context.getDepth() > configuration.searchSpaceConstraints.maxDepth) {
225 logger.debug("Reached max depth."); 217 logger.debug("Reached max depth.");
226 context.backtrack(); 218 context.backtrack();
227 continue; 219 continue;
228 } 220 }
229 221
230 TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness( 222 TrajectoryWithFitness nextTrajectoryWithfitness = new TrajectoryWithFitness(
231 context.getTrajectory().toArray(), nextFitness); 223 context.getTrajectory().toArray(), nextFitness);
232 trajectoiresToExplore.add(nextTrajectoryWithFittness); 224 trajectoiresToExplore.add(nextTrajectoryWithfitness);
233 225
234 int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFittness.fitness, 226 int compare = objectiveComparatorHelper.compare(currentTrajectoryWithfitness.fitness,
235 nextTrajectoryWithFittness.fitness); 227 nextTrajectoryWithfitness.fitness);
236 if (compare < 0) { 228 if (compare < 0) {
237 logger.debug("Better fitness, moving on: " + nextFitness); 229 logger.debug("Better fitness, moving on: " + nextFitness);
238 currentTrajectoryWithFittness = nextTrajectoryWithFittness; 230 currentTrajectoryWithfitness = nextTrajectoryWithfitness;
239 continue mainLoop; 231 continue mainLoop;
240 } else if (compare == 0) { 232 } else if (compare == 0) {
241 logger.debug("Equally good fitness, moving on: " + nextFitness); 233 logger.debug("Equally good fitness, moving on: " + nextFitness);
242 currentTrajectoryWithFittness = nextTrajectoryWithFittness; 234 currentTrajectoryWithfitness = nextTrajectoryWithfitness;
243 continue mainLoop; 235 continue mainLoop;
244 } else { 236 } else {
245 logger.debug("Worse fitness."); 237 logger.debug("Worse fitness.");
246 currentTrajectoryWithFittness = null; 238 currentTrajectoryWithfitness = null;
247 continue mainLoop; 239 continue mainLoop;
248 } 240 }
249 } 241 }
250 } 242 }
251 243
252 logger.debug("State is fully traversed."); 244 logger.debug("State is fully traversed.");
253 trajectoiresToExplore.remove(currentTrajectoryWithFittness); 245 trajectoiresToExplore.remove(currentTrajectoryWithfitness);
254 currentTrajectoryWithFittness = null; 246 currentTrajectoryWithfitness = null;
255 247
256 } 248 }
257 logger.info("Interrupted."); 249 logger.info("Interrupted.");
@@ -263,25 +255,13 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
263 activationIds = new ArrayList<Object>(context.getUntraversedActivationIds()); 255 activationIds = new ArrayList<Object>(context.getUntraversedActivationIds());
264 Collections.shuffle(activationIds); 256 Collections.shuffle(activationIds);
265 } catch (NullPointerException e) { 257 } catch (NullPointerException e) {
258 logger.warn("Unexpected state code: " + context.getDesignSpaceManager().getCurrentState());
266 numberOfStatecoderFail++; 259 numberOfStatecoderFail++;
267 activationIds = Collections.emptyList(); 260 activationIds = Collections.emptyList();
268 } 261 }
269 return activationIds; 262 return activationIds;
270 } 263 }
271 264
272 private void checkForSolution(final Fitness fittness) {
273 if (fittness.isSatisifiesHardObjectives()) {
274 if (solutionStoreWithDiversityDescriptor.isDifferent(context)) {
275 solutionStoreWithCopy.newSolution(context);
276 solutionStoreWithDiversityDescriptor.newSolution(context);
277 solutionStore.newSolution(context);
278 configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolution);
279
280 logger.debug("Found a solution.");
281 }
282 }
283 }
284
285 @Override 265 @Override
286 public void interruptStrategy() { 266 public void interruptStrategy() {
287 isInterrupted = true; 267 isInterrupted = true;
@@ -311,13 +291,16 @@ public class BestFirstStrategyForModelGeneration implements IStrategy {
311 } 291 }
312 292
313 public void visualiseCurrentState() { 293 public void visualiseCurrentState() {
314 PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugCongiguration.partialInterpretatioVisualiser; 294 PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugConfiguration.partialInterpretatioVisualiser;
315 if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) { 295 if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) {
316 PartialInterpretation p = (PartialInterpretation) (context.getModel()); 296 PartialInterpretation p = (PartialInterpretation) (context.getModel());
317 int id = ++numberOfPrintedModel; 297 int id = ++numberOfPrintedModel;
318 if (id % configuration.debugCongiguration.partalInterpretationVisualisationFrequency == 0) { 298 if (id % configuration.debugConfiguration.partalInterpretationVisualisationFrequency == 0) {
319 PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); 299 PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p);
320 visualisation.writeToFile(workspace, String.format("state%09d.png", id)); 300 logger.debug("Visualizing state: " + id + " (" + context.getDesignSpaceManager().getCurrentState() + ")");
301 String name = String.format("state%09d", id);
302 visualisation.writeToFile(workspace, name + ".png");
303 workspace.writeModel((EObject) context.getModel(), name + ".xmi");
321 } 304 }
322 } 305 }
323 } 306 }
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend
new file mode 100644
index 00000000..fb1b2066
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend
@@ -0,0 +1,184 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import com.google.common.collect.HashMultiset
4import com.google.common.collect.ImmutableSet
5import com.google.common.collect.Multiset
6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor
7import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodWithTraces
8import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
10import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.DiversityDescriptor
11import java.util.Collection
12import java.util.HashSet
13import java.util.Map
14import java.util.Set
15import org.eclipse.viatra.dse.base.ThreadContext
16import org.eclipse.xtend.lib.annotations.Accessors
17
18interface DiversityChecker {
19 public static val NO_DIVERSITY_CHECKER = new DiversityChecker {
20 override isActive() {
21 false
22 }
23
24 override getTotalRuntime() {
25 0
26 }
27
28 override getSuccessRate() {
29 1.0
30 }
31
32 override newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) {
33 true
34 }
35 }
36
37 def boolean isActive()
38
39 def long getTotalRuntime()
40
41 def double getSuccessRate()
42
43 def boolean newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds)
44
45 static def of(DiversityDescriptor descriptor) {
46 if (descriptor.ensureDiversity) {
47 new NodewiseDiversityChecker(descriptor)
48 } else {
49 NO_DIVERSITY_CHECKER
50 }
51 }
52}
53
54abstract class AbstractDiversityChecker implements DiversityChecker {
55 val DiversityDescriptor descriptor
56 val PartialInterpretation2ImmutableTypeLattice solutionCoder = new PartialInterpretation2ImmutableTypeLattice
57
58 @Accessors(PUBLIC_GETTER) var long totalRuntime = 0
59 var int allCheckCount = 0
60 var int successfulCheckCount = 0
61
62 protected new(DiversityDescriptor descriptor) {
63 if (!descriptor.ensureDiversity) {
64 throw new IllegalArgumentException(
65 "Diversity description should enforce diversity or NO_DIVERSITY_CHECKER should be used instead.")
66 }
67 this.descriptor = descriptor
68 }
69
70 override isActive() {
71 true
72 }
73
74 override getTotalRuntime() {
75 throw new UnsupportedOperationException("TODO: auto-generated method stub")
76 }
77
78 override getSuccessRate() {
79 (allCheckCount as double) / (successfulCheckCount as double)
80 }
81
82 override newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) {
83 val start = System.nanoTime
84 val model = threadContext.model as PartialInterpretation
85 val representation = solutionCoder.createRepresentation(model, descriptor.range, descriptor.parallels,
86 descriptor.maxNumber, descriptor.relevantTypes, descriptor.relevantRelations)
87 val isDifferent = internalNewSolution(representation, solutionId, dominatedSolutionIds)
88 totalRuntime += System.nanoTime - start
89 allCheckCount++
90 if (isDifferent) {
91 successfulCheckCount++
92 }
93 isDifferent
94 }
95
96 protected abstract def boolean internalNewSolution(
97 NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation,
98 Object solutionId, Collection<Object> dominatedSolutionIds)
99}
100
101class NodewiseDiversityChecker extends AbstractDiversityChecker {
102 var Multiset<Integer> nodeCodes = HashMultiset.create
103 val Map<Object, Set<Integer>> tracedNodeCodes = newHashMap
104
105 new(DiversityDescriptor descriptor) {
106 super(descriptor)
107 }
108
109 override protected internalNewSolution(
110 NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation,
111 Object solutionId, Collection<Object> dominatedSolutionIds) {
112 val nodeCodesInSolution = ImmutableSet.copyOf(representation.modelRepresentation.keySet.map[hashCode])
113 val remainingNodeCodes = if (dominatedSolutionIds.empty) {
114 nodeCodes
115 } else {
116 getRemainingNodeCodes(dominatedSolutionIds)
117 }
118 val hasNewCode = nodeCodesInSolution.exists[!remainingNodeCodes.contains(it)]
119 if (hasNewCode) {
120 nodeCodes = remainingNodeCodes
121 nodeCodes.addAll(nodeCodesInSolution)
122 for (dominatedSolutionId : dominatedSolutionIds) {
123 tracedNodeCodes.remove(dominatedSolutionId)
124 }
125 tracedNodeCodes.put(solutionId, nodeCodesInSolution)
126 }
127 hasNewCode
128 }
129
130 private def getRemainingNodeCodes(Collection<Object> dominatedSolutionIds) {
131 // TODO Optimize multiset operations.
132 val copyOfNodeCodes = HashMultiset.create(nodeCodes)
133 for (dominatedSolutionId : dominatedSolutionIds) {
134 val dominatedModelCode = tracedNodeCodes.get(dominatedSolutionId)
135 if (dominatedModelCode === null) {
136 throw new IllegalArgumentException("Unknown dominated solution: " + dominatedSolutionId)
137 }
138 copyOfNodeCodes.removeAll(dominatedModelCode)
139 }
140 copyOfNodeCodes
141 }
142}
143
144class GraphwiseDiversityChecker extends AbstractDiversityChecker {
145 var Set<Integer> modelCodes = newHashSet
146 val Map<Object, Integer> tracedModelCodes = newHashMap
147
148 new(DiversityDescriptor descriptor) {
149 super(descriptor)
150 }
151
152 override protected internalNewSolution(
153 NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation,
154 Object solutionId, Collection<Object> dominatedSolutionIds) {
155 val modelCodeOfSolution = representation.modelRepresentation.hashCode
156 val remainingModelCodes = if (dominatedSolutionIds.empty) {
157 modelCodes
158 } else {
159 getRemainingModelCodes(dominatedSolutionIds)
160 }
161 val isNewCode = !remainingModelCodes.contains(modelCodeOfSolution)
162 if (isNewCode) {
163 modelCodes = remainingModelCodes
164 modelCodes += modelCodeOfSolution
165 for (dominatedSolutionId : dominatedSolutionIds) {
166 tracedModelCodes.remove(dominatedSolutionId)
167 }
168 tracedModelCodes.put(solutionId, modelCodeOfSolution)
169 }
170 isNewCode
171 }
172
173 private def getRemainingModelCodes(Collection<Object> dominatedSolutionIds) {
174 val copyOfModelCodes = new HashSet(modelCodes)
175 for (dominatedSolutionId : dominatedSolutionIds) {
176 val dominatedModelCode = tracedModelCodes.get(dominatedSolutionId)
177 if (dominatedModelCode === null) {
178 throw new IllegalArgumentException("Unknown dominated solution: " + dominatedSolutionId)
179 }
180 copyOfModelCodes -= dominatedModelCode
181 }
182 copyOfModelCodes
183 }
184}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend
new file mode 100644
index 00000000..3c2e3319
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend
@@ -0,0 +1,66 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.IThreeValuedObjective
4import org.eclipse.viatra.dse.base.ThreadContext
5import org.eclipse.viatra.dse.objectives.Comparators
6import org.eclipse.viatra.dse.objectives.Fitness
7import org.eclipse.viatra.dse.objectives.IObjective
8
9final class DseUtils {
10 private new() {
11 throw new IllegalStateException("This is a static utility class and should not be instantiated directly.")
12 }
13
14 static def calculateFitness(ThreadContext it, (IObjective)=>Double getFitness) {
15 val result = new Fitness
16 var boolean satisifiesHardObjectives = true
17 for (objective : objectives) {
18 val fitness = getFitness.apply(objective)
19 result.put(objective.name, fitness)
20 if (objective.isHardObjective() && !objective.satisifiesHardObjective(fitness)) {
21 satisifiesHardObjectives = false
22 }
23 }
24 result.satisifiesHardObjectives = satisifiesHardObjectives
25 result
26 }
27
28 static def caclulateBestPossibleFitness(ThreadContext threadContext) {
29 threadContext.calculateFitness [ objective |
30 if (objective instanceof IThreeValuedObjective) {
31 objective.getBestPossibleFitness(threadContext)
32 } else {
33 switch (objective.comparator) {
34 case Comparators.LOWER_IS_BETTER:
35 Double.NEGATIVE_INFINITY
36 case Comparators.HIGHER_IS_BETTER:
37 Double.POSITIVE_INFINITY
38 case Comparators.DIFFERENCE_TO_ZERO_IS_BETTER:
39 0.0
40 default:
41 throw new IllegalArgumentException("Unknown comparator for non-three-valued objective: " +
42 objective.name)
43 }
44 }
45 ]
46 }
47
48 static def caclulateWorstPossibleFitness(ThreadContext threadContext) {
49 threadContext.calculateFitness [ objective |
50 if (objective instanceof IThreeValuedObjective) {
51 objective.getWorstPossibleFitness(threadContext)
52 } else {
53 switch (objective.comparator) {
54 case Comparators.LOWER_IS_BETTER,
55 case Comparators.DIFFERENCE_TO_ZERO_IS_BETTER:
56 Double.POSITIVE_INFINITY
57 case Comparators.HIGHER_IS_BETTER:
58 Double.NEGATIVE_INFINITY
59 default:
60 throw new IllegalArgumentException("Unknown comparator for non-three-valued objective: " +
61 objective.name)
62 }
63 }
64 ]
65 }
66}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend
new file mode 100644
index 00000000..2e039ca2
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend
@@ -0,0 +1,25 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import org.eclipse.viatra.dse.objectives.IGlobalConstraint
4import org.eclipse.viatra.dse.base.ThreadContext
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
6
7class InconsistentScopeGlobalConstraint implements IGlobalConstraint {
8
9 override init(ThreadContext context) {
10 // Nothing to initialize.
11 }
12
13 override createNew() {
14 this
15 }
16
17 override getName() {
18 class.name
19 }
20
21 override checkGlobalConstraint(ThreadContext context) {
22 val partialModel = context.model as PartialInterpretation
23 partialModel.minNewElements <= partialModel.maxNewElements || partialModel.maxNewElements < 0
24 }
25}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend
new file mode 100644
index 00000000..39ef5f9a
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend
@@ -0,0 +1,24 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration
4import org.apache.log4j.Logger
5import org.eclipse.viatra.dse.api.SolutionTrajectory
6import org.eclipse.viatra.dse.base.ThreadContext
7import org.eclipse.viatra.dse.solutionstore.ISolutionFoundHandler
8import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
9
10@FinalFieldsConstructor
11class LoggerSolutionFoundHandler implements ISolutionFoundHandler {
12 val ViatraReasonerConfiguration configuration
13
14 val logger = Logger.getLogger(SolutionCopier)
15
16 override solutionFound(ThreadContext context, SolutionTrajectory trajectory) {
17 configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolutions)
18 logger.debug("Found a solution.")
19 }
20
21 override solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) {
22 // We are not interested in invalid solutions, ignore.
23 }
24}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend
index 2489c751..9a33753c 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend
@@ -1,11 +1,13 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse 1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2 2
3import com.google.common.collect.ImmutableList
4import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.IThreeValuedObjective
3import java.util.Comparator 5import java.util.Comparator
4import java.util.List 6import java.util.List
5import org.eclipse.viatra.dse.base.ThreadContext 7import org.eclipse.viatra.dse.base.ThreadContext
6import org.eclipse.viatra.dse.objectives.Comparators 8import org.eclipse.viatra.dse.objectives.Comparators
7import org.eclipse.viatra.dse.objectives.IObjective 9import org.eclipse.viatra.dse.objectives.IObjective
8import org.eclipse.viatra.dse.objectives.impl.BaseObjective 10import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
9 11
10//class ViatraReasonerNumbers { 12//class ViatraReasonerNumbers {
11// public static val scopePriority = 2 13// public static val scopePriority = 2
@@ -22,64 +24,66 @@ import org.eclipse.viatra.dse.objectives.impl.BaseObjective
22// public static val compositePriority = 2 24// public static val compositePriority = 2
23//} 25//}
24 26
25class ModelGenerationCompositeObjective implements IObjective{ 27@FinalFieldsConstructor
26 val ScopeObjective scopeObjective 28class ModelGenerationCompositeObjective implements IThreeValuedObjective {
27 val List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives 29 val IObjective scopeObjective
28 val UnfinishedWFObjective unfinishedWFObjective 30 val List<IObjective> unfinishedMultiplicityObjectives
29 31 val IObjective unfinishedWFObjective
30 public new( 32
31 ScopeObjective scopeObjective,
32 List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives,
33 UnfinishedWFObjective unfinishedWFObjective)
34 {
35 this.scopeObjective = scopeObjective
36 this.unfinishedMultiplicityObjectives = unfinishedMultiplicityObjectives
37 this.unfinishedWFObjective = unfinishedWFObjective
38 }
39
40 override init(ThreadContext context) { 33 override init(ThreadContext context) {
41 this.scopeObjective.init(context) 34 this.scopeObjective.init(context)
42 this.unfinishedMultiplicityObjectives.forEach[it.init(context)] 35 this.unfinishedMultiplicityObjectives.forEach[it.init(context)]
43 this.unfinishedWFObjective.init(context) 36 this.unfinishedWFObjective.init(context)
44 } 37 }
45 38
46 override createNew() { 39 override createNew() {
47 return new ModelGenerationCompositeObjective( 40 return new ModelGenerationCompositeObjective(
48 this.scopeObjective, this.unfinishedMultiplicityObjectives, this.unfinishedWFObjective) 41 scopeObjective.createNew,
42 ImmutableList.copyOf(unfinishedMultiplicityObjectives.map[createNew]),
43 unfinishedWFObjective.createNew
44 )
49 } 45 }
50 46
51 override getComparator() { Comparators.LOWER_IS_BETTER } 47 override getComparator() { Comparators.LOWER_IS_BETTER }
48
52 override getFitness(ThreadContext context) { 49 override getFitness(ThreadContext context) {
53 var sum = 0.0 50 var sum = 0.0
54 val scopeFitnes = scopeObjective.getFitness(context) 51 val scopeFitnes = scopeObjective.getFitness(context)
55 //val unfinishedMultiplicitiesFitneses = unfinishedMultiplicityObjectives.map[x|x.getFitness(context)] 52 // val unfinishedMultiplicitiesFitneses = unfinishedMultiplicityObjectives.map[x|x.getFitness(context)]
56 val unfinishedWFsFitness = unfinishedWFObjective.getFitness(context) 53 val unfinishedWFsFitness = unfinishedWFObjective.getFitness(context)
57 54
58 sum+=scopeFitnes 55 sum += scopeFitnes
59 var multiplicity = 0.0 56 var multiplicity = 0.0
60 for(multiplicityObjective : unfinishedMultiplicityObjectives) { 57 for (multiplicityObjective : unfinishedMultiplicityObjectives) {
61 multiplicity+=multiplicityObjective.getFitness(context)//*0.5 58 multiplicity += multiplicityObjective.getFitness(context) // *0.5
62 } 59 }
63 sum+=multiplicity 60 sum += multiplicity
64 sum += unfinishedWFsFitness//*0.5 61 sum += unfinishedWFsFitness // *0.5
65 62 // println('''Sum=«sum»|Scope=«scopeFitnes»|Multiplicity=«multiplicity»|WFs=«unfinishedWFsFitness»''')
66 //println('''Sum=«sum»|Scope=«scopeFitnes»|Multiplicity=«multiplicity»|WFs=«unfinishedWFsFitness»''')
67
68 return sum 63 return sum
69 } 64 }
70 65
71 override getLevel() { 2 } 66 override getWorstPossibleFitness(ThreadContext threadContext) {
72 override getName() { "CompositeUnfinishednessObjective"} 67 Double.POSITIVE_INFINITY
68 }
73 69
70 override getBestPossibleFitness(ThreadContext threadContext) {
71 0.0
72 }
73
74 override getLevel() { 2 }
75
76 override getName() { "CompositeUnfinishednessObjective" }
77
74 override isHardObjective() { true } 78 override isHardObjective() { true }
79
75 override satisifiesHardObjective(Double fitness) { fitness <= 0.001 } 80 override satisifiesHardObjective(Double fitness) { fitness <= 0.001 }
76 81
77
78 override setComparator(Comparator<Double> comparator) { 82 override setComparator(Comparator<Double> comparator) {
79 throw new UnsupportedOperationException("TODO: auto-generated method stub") 83 throw new UnsupportedOperationException("Model generation objective comparator cannot be set.")
80 } 84 }
85
81 override setLevel(int level) { 86 override setLevel(int level) {
82 throw new UnsupportedOperationException("TODO: auto-generated method stub") 87 throw new UnsupportedOperationException("Model generation objective level cannot be set.")
83 } 88 }
84 89}
85} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend
new file mode 100644
index 00000000..d036257d
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend
@@ -0,0 +1,74 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import com.google.common.collect.ImmutableList
4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
5import java.util.LinkedHashMap
6import java.util.List
7import java.util.Map
8import org.eclipse.emf.ecore.EObject
9import org.eclipse.emf.ecore.util.EcoreUtil
10import org.eclipse.viatra.dse.base.ThreadContext
11import org.eclipse.xtend.lib.annotations.Accessors
12import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
13
14@FinalFieldsConstructor
15class CopiedSolution {
16 @Accessors val PartialInterpretation partialInterpretations
17 @Accessors val Map<EObject, EObject> trace
18 @Accessors val long copierRuntime
19 @Accessors var boolean current = true
20}
21
22class SolutionCopier {
23 val copiedSolutions = new LinkedHashMap<Object, CopiedSolution>
24
25 long startTime = System.nanoTime
26 @Accessors(PUBLIC_GETTER) long totalCopierRuntime = 0
27
28 def void copySolution(ThreadContext context, Object solutionId) {
29 val existingCopy = copiedSolutions.get(solutionId)
30 if (existingCopy === null) {
31 val copyStart = System.nanoTime
32 val solution = context.model as PartialInterpretation
33 val copier = new EcoreUtil.Copier
34 val copiedPartialInterpretation = copier.copy(solution) as PartialInterpretation
35 copier.copyReferences
36 totalCopierRuntime += System.nanoTime - copyStart
37 val copierRuntime = System.nanoTime - startTime
38 val copiedSolution = new CopiedSolution(copiedPartialInterpretation, copier, copierRuntime)
39 copiedSolutions.put(solutionId, copiedSolution)
40 } else {
41 existingCopy.current = true
42 }
43 }
44
45 def void markAsObsolete(Object solutionId) {
46 val copiedSolution = copiedSolutions.get(solutionId)
47 if (copiedSolution === null) {
48 throw new IllegalStateException("No solution to mark as obsolete for state code: " + solutionId)
49 }
50 copiedSolution.current = false
51 }
52
53 def List<PartialInterpretation> getPartialInterpretations(boolean currentOnly) {
54 getListOfCopiedSolutions(currentOnly).map[partialInterpretations]
55 }
56
57 def List<Map<EObject, EObject>> getTraces(boolean currentOnly) {
58 getListOfCopiedSolutions(currentOnly).map[trace]
59 }
60
61 def List<Long> getAllCopierRuntimes(boolean currentOnly) {
62 getListOfCopiedSolutions(currentOnly).map[copierRuntime]
63 }
64
65 def List<CopiedSolution> getListOfCopiedSolutions(boolean currentOnly) {
66 val values = copiedSolutions.values
67 val filteredSolutions = if (currentOnly) {
68 values.filter[current]
69 } else {
70 values
71 }
72 ImmutableList.copyOf(filteredSolutions)
73 }
74}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend
deleted file mode 100644
index a8b7301e..00000000
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend
+++ /dev/null
@@ -1,52 +0,0 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import java.util.List
4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
5import java.util.LinkedList
6import org.eclipse.emf.ecore.EObject
7import java.util.Map
8import org.eclipse.emf.ecore.util.EcoreUtil
9import org.eclipse.viatra.dse.base.ThreadContext
10import java.util.TreeMap
11import java.util.SortedMap
12
13class SolutionStoreWithCopy {
14
15 long runtime = 0
16 List<PartialInterpretation> solutions = new LinkedList
17 //public List<SortedMap<String,Integer>> additionalMatches = new LinkedList
18 List<Map<EObject,EObject>> copyTraces = new LinkedList
19
20 long sartTime = System.nanoTime
21 List<Long> solutionTimes = new LinkedList
22
23 /*def newSolution(ThreadContext context, SortedMap<String,Integer> additonalMatch) {
24 additionalMatches+= additonalMatch
25 newSolution(context)
26 }*/
27
28 def newSolution(ThreadContext context) {
29 //print(System.nanoTime-initTime + ";")
30 val copyStart = System.nanoTime
31 val solution = context.model as PartialInterpretation
32 val copier = new EcoreUtil.Copier
33 val solutionCopy = copier.copy(solution) as PartialInterpretation
34 copier.copyReferences
35 solutions.add(solutionCopy)
36 copyTraces.add(copier)
37 runtime += System.nanoTime - copyStart
38 solutionTimes.add(System.nanoTime-sartTime)
39 }
40 def getSumRuntime() {
41 return runtime
42 }
43 def getAllRuntimes() {
44 return solutionTimes
45 }
46 def getSolutions() {
47 solutions
48 }
49 def getCopyTraces() {
50 return copyTraces
51 }
52} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend
deleted file mode 100644
index 1e7f18a8..00000000
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend
+++ /dev/null
@@ -1,120 +0,0 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice
4import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
5import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.DiversityDescriptor
6import java.util.LinkedList
7import java.util.List
8import org.eclipse.viatra.dse.base.ThreadContext
9import java.util.HashSet
10import java.util.Set
11
12enum DiversityGranularity {
13 Nodewise, Graphwise
14}
15
16class SolutionStoreWithDiversityDescriptor {
17 val DiversityDescriptor descriptor
18 DiversityGranularity granularity
19 val PartialInterpretation2ImmutableTypeLattice solutionCoder = new PartialInterpretation2ImmutableTypeLattice
20 val Set<Integer> solutionCodeList = new HashSet
21
22 var long runtime
23 var int allCheck
24 var int successfulCheck
25
26 new(DiversityDescriptor descriptor) {
27 if(descriptor.ensureDiversity) {
28 this.descriptor = descriptor
29 this.granularity = DiversityGranularity::Nodewise
30 } else {
31 this.descriptor = null
32 this.granularity = DiversityGranularity::Nodewise
33 }
34 }
35
36 def public isActive() {
37 descriptor!==null
38 }
39
40 def getSumRuntime() {
41 return runtime
42 }
43 def getSuccessRate() {
44 return successfulCheck as double / allCheck
45 }
46
47 def isDifferent(ThreadContext context) {
48 if(active) {
49 val start = System.nanoTime
50 val model = context.model as PartialInterpretation
51 var boolean isDifferent
52 if(this.granularity == DiversityGranularity::Graphwise) {
53 val code = solutionCoder.createRepresentation(model,
54 descriptor.range,
55 descriptor.parallels,
56 descriptor.maxNumber,
57 descriptor.relevantTypes,
58 descriptor.relevantRelations).modelRepresentation.hashCode
59
60 isDifferent = !solutionCodeList.contains(code)
61 } else if(this.granularity == DiversityGranularity::Nodewise){
62 val codes = solutionCoder.createRepresentation(model,
63 descriptor.range,
64 descriptor.parallels,
65 descriptor.maxNumber,
66 descriptor.relevantTypes,
67 descriptor.relevantRelations).modelRepresentation.keySet.map[hashCode].toList
68 val differentCodes = codes.filter[!solutionCodeList.contains(it)]
69 //println(differentCodes.size)
70
71 isDifferent = differentCodes.size>=1
72 } else {
73 throw new UnsupportedOperationException('''Unsupported diversity type: «this.granularity»''')
74 }
75
76 runtime += System.nanoTime - start
77 allCheck++
78 if(isDifferent) { successfulCheck++ }
79 return isDifferent
80 } else {
81 allCheck++
82 successfulCheck++
83 return true
84 }
85 }
86
87 def canBeDifferent(ThreadContext context) {
88 return true
89 }
90
91 def newSolution(ThreadContext context) {
92 if(active) {
93 val start = System.nanoTime
94 val model = context.model as PartialInterpretation
95 if(this.granularity == DiversityGranularity::Graphwise) {
96 val code = solutionCoder.createRepresentation(model,
97 descriptor.range,
98 descriptor.parallels,
99 descriptor.maxNumber,
100 descriptor.relevantTypes,
101 descriptor.relevantRelations).modelRepresentation.hashCode
102
103 solutionCodeList += code.hashCode
104 } else if(this.granularity == DiversityGranularity::Nodewise){
105 val codes = solutionCoder.createRepresentation(model,
106 descriptor.range,
107 descriptor.parallels,
108 descriptor.maxNumber,
109 descriptor.relevantTypes,
110 descriptor.relevantRelations).modelRepresentation.keySet.map[hashCode].toList
111
112 solutionCodeList += codes.map[it.hashCode]
113 } else {
114 throw new UnsupportedOperationException('''Unsupported diversity type: «this.granularity»''')
115 }
116
117 runtime += System.nanoTime - start
118 }
119 }
120} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend
new file mode 100644
index 00000000..8ed3e912
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend
@@ -0,0 +1,27 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import org.eclipse.viatra.dse.base.ThreadContext
4import org.eclipse.viatra.dse.objectives.IGlobalConstraint
5import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
6
7@FinalFieldsConstructor
8class SurelyViolatedObjectiveGlobalConstraint implements IGlobalConstraint {
9 val ViatraReasonerSolutionSaver solutionSaver
10
11 override init(ThreadContext context) {
12 // Nothing to initialize.
13 }
14
15 override createNew() {
16 this
17 }
18
19 override getName() {
20 class.name
21 }
22
23 override checkGlobalConstraint(ThreadContext context) {
24 val bestFitness = DseUtils.caclulateBestPossibleFitness(context)
25 bestFitness.satisifiesHardObjectives && solutionSaver.fitnessMayBeSaved(bestFitness)
26 }
27}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend
index aad9a448..9f0c642f 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend
@@ -1,15 +1,15 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse 1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2 2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.MultiplicityGoalConstraintCalculator 3import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator
4import java.util.Comparator 4import java.util.Comparator
5import org.eclipse.viatra.dse.base.ThreadContext 5import org.eclipse.viatra.dse.base.ThreadContext
6import org.eclipse.viatra.dse.objectives.IObjective
7import org.eclipse.viatra.dse.objectives.Comparators 6import org.eclipse.viatra.dse.objectives.Comparators
7import org.eclipse.viatra.dse.objectives.IObjective
8 8
9class UnfinishedMultiplicityObjective implements IObjective { 9class UnfinishedMultiplicityObjective implements IObjective {
10 val MultiplicityGoalConstraintCalculator unfinishedMultiplicity; 10 val MultiplicityGoalConstraintCalculator unfinishedMultiplicity;
11 11
12 public new(MultiplicityGoalConstraintCalculator unfinishedMultiplicity) { 12 new(MultiplicityGoalConstraintCalculator unfinishedMultiplicity) {
13 this.unfinishedMultiplicity = unfinishedMultiplicity 13 this.unfinishedMultiplicity = unfinishedMultiplicity
14 } 14 }
15 15
@@ -29,9 +29,9 @@ class UnfinishedMultiplicityObjective implements IObjective {
29 override satisifiesHardObjective(Double fitness) { return fitness <=0.01 } 29 override satisifiesHardObjective(Double fitness) { return fitness <=0.01 }
30 30
31 override setComparator(Comparator<Double> comparator) { 31 override setComparator(Comparator<Double> comparator) {
32 throw new UnsupportedOperationException("TODO: auto-generated method stub") 32 throw new UnsupportedOperationException
33 } 33 }
34 override setLevel(int level) { 34 override setLevel(int level) {
35 throw new UnsupportedOperationException("TODO: auto-generated method stub") 35 throw new UnsupportedOperationException
36 } 36 }
37} \ No newline at end of file 37}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend
index e0111cf6..bf34aeeb 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend
@@ -1,23 +1,21 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse 1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2 2
3import org.eclipse.viatra.dse.objectives.IObjective 3import java.util.ArrayList
4import org.eclipse.viatra.query.runtime.api.IPatternMatch
5import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
6import org.eclipse.viatra.query.runtime.api.IQuerySpecification
7import java.util.Collection 4import java.util.Collection
8import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine 5import java.util.Comparator
9import org.eclipse.viatra.query.runtime.emf.EMFScope
10import org.eclipse.viatra.dse.base.ThreadContext
11import java.util.List 6import java.util.List
7import org.eclipse.viatra.dse.base.ThreadContext
12import org.eclipse.viatra.dse.objectives.Comparators 8import org.eclipse.viatra.dse.objectives.Comparators
13import java.util.ArrayList 9import org.eclipse.viatra.dse.objectives.IObjective
14import java.util.Comparator 10import org.eclipse.viatra.query.runtime.api.IPatternMatch
11import org.eclipse.viatra.query.runtime.api.IQuerySpecification
12import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
15 13
16class UnfinishedWFObjective implements IObjective { 14class UnfinishedWFObjective implements IObjective {
17 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs 15 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs
18 val List<ViatraQueryMatcher<?>> matchers 16 val List<ViatraQueryMatcher<?>> matchers
19 17
20 public new(Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs) { 18 new(Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs) {
21 this.unfinishedWFs = unfinishedWFs 19 this.unfinishedWFs = unfinishedWFs
22 matchers = new ArrayList(unfinishedWFs.size) 20 matchers = new ArrayList(unfinishedWFs.size)
23 } 21 }
@@ -48,9 +46,9 @@ class UnfinishedWFObjective implements IObjective {
48 override satisifiesHardObjective(Double fitness) { return fitness <=0.01 } 46 override satisifiesHardObjective(Double fitness) { return fitness <=0.01 }
49 47
50 override setComparator(Comparator<Double> comparator) { 48 override setComparator(Comparator<Double> comparator) {
51 throw new UnsupportedOperationException("TODO: auto-generated method stub") 49 throw new UnsupportedOperationException()
52 } 50 }
53 override setLevel(int level) { 51 override setLevel(int level) {
54 throw new UnsupportedOperationException("TODO: auto-generated method stub") 52 throw new UnsupportedOperationException()
55 } 53 }
56} \ No newline at end of file 54} \ No newline at end of file
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend
new file mode 100644
index 00000000..6bffeb59
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend
@@ -0,0 +1,137 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2
3import java.util.HashMap
4import java.util.Map
5import org.eclipse.viatra.dse.api.DSEException
6import org.eclipse.viatra.dse.api.Solution
7import org.eclipse.viatra.dse.api.SolutionTrajectory
8import org.eclipse.viatra.dse.base.ThreadContext
9import org.eclipse.viatra.dse.objectives.Fitness
10import org.eclipse.viatra.dse.objectives.IObjective
11import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper
12import org.eclipse.viatra.dse.solutionstore.SolutionStore.ISolutionSaver
13import org.eclipse.xtend.lib.annotations.Accessors
14
15/**
16 * Based on {@link SolutionStore.BestSolutionSaver}.
17 */
18class ViatraReasonerSolutionSaver implements ISolutionSaver {
19 @Accessors val solutionCopier = new SolutionCopier
20 @Accessors val DiversityChecker diversityChecker
21 val boolean hasExtremalObjectives
22 val int numberOfRequiredSolutions
23 val ObjectiveComparatorHelper comparatorHelper
24 val Map<SolutionTrajectory, Fitness> trajectories = new HashMap
25
26 @Accessors(PUBLIC_SETTER) var Map<Object, Solution> solutionsCollection
27
28 new(IObjective[][] leveledExtremalObjectives, int numberOfRequiredSolutions, DiversityChecker diversityChecker) {
29 this.diversityChecker = diversityChecker
30 comparatorHelper = new ObjectiveComparatorHelper(leveledExtremalObjectives)
31 hasExtremalObjectives = leveledExtremalObjectives.exists[!empty]
32 this.numberOfRequiredSolutions = numberOfRequiredSolutions
33 }
34
35 override saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) {
36 if (hasExtremalObjectives) {
37 saveBestSolutionOnly(context, id, solutionTrajectory)
38 } else {
39 saveAnyDiverseSolution(context, id, solutionTrajectory)
40 }
41 }
42
43 private def saveBestSolutionOnly(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) {
44 val fitness = context.lastFitness
45 if (!fitness.satisifiesHardObjectives) {
46 return false
47 }
48 val dominatedTrajectories = newArrayList
49 for (entry : trajectories.entrySet) {
50 val isLastFitnessBetter = comparatorHelper.compare(fitness, entry.value)
51 if (isLastFitnessBetter < 0) {
52 // Found a trajectory that dominates the current one, no need to save
53 return false
54 }
55 if (isLastFitnessBetter > 0) {
56 dominatedTrajectories += entry.key
57 }
58 }
59 if (dominatedTrajectories.size == 0 && !needsMoreSolutionsWithSameFitness) {
60 return false
61 }
62 if (!diversityChecker.newSolution(context, id, dominatedTrajectories.map[solution.stateCode])) {
63 return false
64 }
65 // We must save the new trajectory before removing dominated trajectories
66 // to avoid removing the current solution when it is reachable only via dominated trajectories.
67 val solutionSaved = basicSaveSolution(context, id, solutionTrajectory, fitness)
68 for (dominatedTrajectory : dominatedTrajectories) {
69 trajectories -= dominatedTrajectory
70 val dominatedSolution = dominatedTrajectory.solution
71 if (!dominatedSolution.trajectories.remove(dominatedTrajectory)) {
72 throw new DSEException(
73 "Dominated solution is not reachable from dominated trajectory. This should never happen!")
74 }
75 if (dominatedSolution.trajectories.empty) {
76 val dominatedSolutionId = dominatedSolution.stateCode
77 solutionCopier.markAsObsolete(dominatedSolutionId)
78 solutionsCollection -= dominatedSolutionId
79 }
80 }
81 solutionSaved
82 }
83
84 private def saveAnyDiverseSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) {
85 val fitness = context.lastFitness
86 if (!fitness.satisifiesHardObjectives) {
87 return false
88 }
89 if (!diversityChecker.newSolution(context, id, emptyList)) {
90 return false
91 }
92 basicSaveSolution(context, id, solutionTrajectory, fitness)
93 }
94
95 private def basicSaveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory, Fitness fitness) {
96 var boolean solutionSaved = false
97 var dseSolution = solutionsCollection.get(id)
98 if (dseSolution === null) {
99 solutionCopier.copySolution(context, id)
100 dseSolution = new Solution(id, solutionTrajectory)
101 solutionsCollection.put(id, dseSolution)
102 solutionSaved = true
103 } else {
104 solutionSaved = dseSolution.trajectories.add(solutionTrajectory)
105 }
106 if (solutionSaved) {
107 solutionTrajectory.solution = dseSolution
108 trajectories.put(solutionTrajectory, fitness)
109 }
110 solutionSaved
111 }
112
113 def fitnessMayBeSaved(Fitness fitness) {
114 if (!hasExtremalObjectives) {
115 return true
116 }
117 var boolean mayDominate
118 for (existingFitness : trajectories.values) {
119 val isNewFitnessBetter = comparatorHelper.compare(fitness, existingFitness)
120 if (isNewFitnessBetter < 0) {
121 return false
122 }
123 if (isNewFitnessBetter > 0) {
124 mayDominate = true
125 }
126 }
127 mayDominate || needsMoreSolutionsWithSameFitness
128 }
129
130 private def boolean needsMoreSolutionsWithSameFitness() {
131 if (solutionsCollection === null) {
132 // The solutions collection will only be initialized upon saving the first solution.
133 return true
134 }
135 solutionsCollection.size < numberOfRequiredSolutions
136 }
137}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend
index 5a528a9e..63d78220 100644
--- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend
@@ -1,5 +1,6 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse 1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse
2 2
3import com.google.common.collect.ImmutableList
3import java.util.ArrayList 4import java.util.ArrayList
4import java.util.Collection 5import java.util.Collection
5import org.eclipse.viatra.dse.objectives.Comparators 6import org.eclipse.viatra.dse.objectives.Comparators
@@ -12,25 +13,35 @@ import org.eclipse.viatra.query.runtime.api.IQuerySpecification
12import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher 13import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
13 14
14class WF2ObjectiveConverter { 15class WF2ObjectiveConverter {
15 16 static val UNFINISHED_WFS_NAME = "unfinishedWFs"
17 static val INVALIDATED_WFS_NAME = "invalidatedWFs"
18
16 def createCompletenessObjective( 19 def createCompletenessObjective(
17 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF) 20 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF) {
18 { 21 // createConstraintObjective(UNFINISHED_WFS_NAME, unfinishedWF)
19 val res = new ConstraintsObjective('''unfinishedWFs''', 22 new UnfinishedWFObjective(unfinishedWF)
20 unfinishedWF.map[ 23 }
21 new QueryConstraint(it.fullyQualifiedName,it,2.0) 24
22 ].toList 25 def createInvalidationObjective(
26 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidatedByWF) {
27 createConstraintObjective(INVALIDATED_WFS_NAME, invalidatedByWF)
28 }
29
30 def IGlobalConstraint createInvalidationGlobalConstraint(
31 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidatedByWF) {
32 new ModelQueriesGlobalConstraint(INVALIDATED_WFS_NAME, new ArrayList(invalidatedByWF))
33 }
34
35 private def createConstraintObjective(String name,
36 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> queries) {
37 val res = new ConstraintsObjective(
38 name,
39 ImmutableList.copyOf(queries.map [
40 new QueryConstraint(it.fullyQualifiedName, it, 1.0)
41 ])
23 ) 42 )
24 res.withComparator(Comparators.LOWER_IS_BETTER) 43 res.withComparator(Comparators.LOWER_IS_BETTER)
25 res.level = 2 44 res.level = 2
26 return res 45 res
27 }
28
29 def IGlobalConstraint createInvalidationObjective(
30 Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidatedByWF)
31 {
32 return new ModelQueriesGlobalConstraint('''invalidatedWFs''',
33 new ArrayList(invalidatedByWF)
34 )
35 } 46 }
36} \ No newline at end of file 47}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend
new file mode 100644
index 00000000..cd911ab5
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend
@@ -0,0 +1,35 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization
2
3import org.eclipse.viatra.dse.base.ThreadContext
4
5abstract class AbstractThreeValuedObjective extends DirectionalThresholdObjective implements IThreeValuedObjective {
6 protected new(String name, ObjectiveKind kind, ObjectiveThreshold threshold, int level) {
7 super(name, kind, threshold, level)
8 }
9
10 abstract def double getLowestPossibleFitness(ThreadContext threadContext)
11
12 abstract def double getHighestPossibleFitness(ThreadContext threadContext)
13
14 override getWorstPossibleFitness(ThreadContext threadContext) {
15 switch (kind) {
16 case LOWER_IS_BETTER:
17 getHighestPossibleFitness(threadContext)
18 case HIGHER_IS_BETTER:
19 getLowestPossibleFitness(threadContext)
20 default:
21 throw new IllegalStateException("Unknown three valued objective kind: " + kind)
22 }
23 }
24
25 override getBestPossibleFitness(ThreadContext threadContext) {
26 switch (kind) {
27 case LOWER_IS_BETTER:
28 getLowestPossibleFitness(threadContext)
29 case HIGHER_IS_BETTER:
30 getHighestPossibleFitness(threadContext)
31 default:
32 throw new IllegalStateException("Unknown three valued objective kind: " + kind)
33 }
34 }
35}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend
new file mode 100644
index 00000000..0aa442f5
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend
@@ -0,0 +1,62 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization
2
3import com.google.common.collect.ImmutableList
4import java.util.Collection
5import org.eclipse.viatra.dse.base.ThreadContext
6
7class CompositeDirectionalThresholdObjective extends DirectionalThresholdObjective {
8 val Collection<DirectionalThresholdObjective> objectives
9
10 new(String name, Collection<DirectionalThresholdObjective> objectives) {
11 this(name, objectives, getKind(objectives), getThreshold(objectives), getLevel(objectives))
12 }
13
14 new(String name, DirectionalThresholdObjective... objectives) {
15 this(name, objectives as Collection<DirectionalThresholdObjective>)
16 }
17
18 protected new(String name, Iterable<DirectionalThresholdObjective> objectives, ObjectiveKind kind,
19 ObjectiveThreshold threshold, int level) {
20 super(name, kind, threshold, level)
21 this.objectives = ImmutableList.copyOf(objectives)
22 }
23
24 override createNew() {
25 new CompositeDirectionalThresholdObjective(name, objectives.map[createNew as DirectionalThresholdObjective],
26 kind, threshold, level)
27 }
28
29 override init(ThreadContext context) {
30 for (objective : objectives) {
31 objective.init(context)
32 }
33 }
34
35 override protected getRawFitness(ThreadContext context) {
36 var double fitness = 0
37 for (objective : objectives) {
38 fitness += objective.getFitness(context)
39 }
40 fitness
41 }
42
43 private static def getKind(Collection<DirectionalThresholdObjective> objectives) {
44 val kinds = objectives.map[kind].toSet
45 if (kinds.size != 1) {
46 throw new IllegalArgumentException("Passed objectives must have the same kind")
47 }
48 kinds.head
49 }
50
51 private static def getThreshold(Collection<DirectionalThresholdObjective> objectives) {
52 objectives.map[threshold].reduce[a, b|a.merge(b)]
53 }
54
55 private static def int getLevel(Collection<DirectionalThresholdObjective> objectives) {
56 val levels = objectives.map[level].toSet
57 if (levels.size != 1) {
58 throw new IllegalArgumentException("Passed objectives must have the same level")
59 }
60 levels.head
61 }
62}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend
new file mode 100644
index 00000000..376e3d1a
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend
@@ -0,0 +1,164 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization
2
3import java.util.Comparator
4import org.eclipse.viatra.dse.base.ThreadContext
5import org.eclipse.viatra.dse.objectives.IObjective
6import org.eclipse.xtend.lib.annotations.Accessors
7import org.eclipse.xtend.lib.annotations.Data
8import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
9
10abstract class ObjectiveThreshold {
11 public static val NO_THRESHOLD = new ObjectiveThreshold {
12 override isHard() {
13 false
14 }
15
16 override satisfiesThreshold(double cost, Comparator<Double> comparator) {
17 true
18 }
19
20 override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) {
21 cost
22 }
23
24 override ObjectiveThreshold merge(ObjectiveThreshold other) {
25 if (other == NO_THRESHOLD) {
26 NO_THRESHOLD
27 } else {
28 throw new IllegalArgumentException("Merged thresholds must have the same type")
29 }
30 }
31 }
32
33 private new() {
34 }
35
36 def boolean isHard() {
37 true
38 }
39
40 def boolean satisfiesThreshold(double cost, ObjectiveKind kind) {
41 satisfiesThreshold(cost, kind.comparator)
42 }
43
44 def boolean satisfiesThreshold(double cost, Comparator<Double> comparator)
45
46 def double postProcessCost(double cost, ObjectiveKind kind) {
47 if (satisfiesThreshold(cost, kind)) {
48 postProcessSatisfactoryCost(cost, kind)
49 } else {
50 cost
51 }
52 }
53
54 protected def double postProcessSatisfactoryCost(double cost, ObjectiveKind kind)
55
56 def ObjectiveThreshold merge(ObjectiveThreshold other)
57
58 @Data
59 static class Exclusive extends ObjectiveThreshold {
60 static val EPSILON = 0.1
61
62 val double threshold
63 val boolean clampToThreshold
64
65 @FinalFieldsConstructor
66 new() {
67 }
68
69 new(double threshold) {
70 this(threshold, true)
71 }
72
73 override satisfiesThreshold(double cost, Comparator<Double> comparator) {
74 comparator.compare(threshold, cost) < 0
75 }
76
77 override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) {
78 if (clampToThreshold) {
79 threshold + Math.signum(kind.satisfiedValue) * EPSILON
80 } else {
81 cost
82 }
83 }
84
85 override ObjectiveThreshold merge(ObjectiveThreshold other) {
86 if (other instanceof Exclusive) {
87 new Exclusive(threshold + other.threshold)
88 } else {
89 throw new IllegalArgumentException("Merged thresholds must have the same type")
90 }
91 }
92 }
93
94 @Data
95 static class Inclusive extends ObjectiveThreshold {
96 val double threshold
97 val boolean clampToThreshold
98
99 @FinalFieldsConstructor
100 new() {
101 }
102
103 new(double threshold) {
104 this(threshold, true)
105 }
106
107 override satisfiesThreshold(double cost, Comparator<Double> comparator) {
108 comparator.compare(threshold, cost) <= 0
109 }
110
111 override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) {
112 if (clampToThreshold) {
113 threshold
114 } else {
115 cost
116 }
117 }
118
119 override ObjectiveThreshold merge(ObjectiveThreshold other) {
120 if (other instanceof Inclusive) {
121 new Inclusive(threshold + other.threshold)
122 } else {
123 throw new IllegalArgumentException("Merged thresholds must have the same type")
124 }
125 }
126 }
127}
128
129abstract class DirectionalThresholdObjective implements IObjective {
130 @Accessors val String name
131 @Accessors ObjectiveKind kind
132 @Accessors ObjectiveThreshold threshold
133 @Accessors int level
134
135 protected new(String name, ObjectiveKind kind, ObjectiveThreshold threshold, int level) {
136 this.name = name
137 this.kind = kind
138 this.threshold = threshold
139 this.level = level
140 }
141
142 override isHardObjective() {
143 threshold.hard
144 }
145
146 override satisifiesHardObjective(Double fitness) {
147 threshold.satisfiesThreshold(fitness, comparator)
148 }
149
150 override getComparator() {
151 kind.comparator
152 }
153
154 override setComparator(Comparator<Double> comparator) {
155 kind = ObjectiveKind.fromComparator(comparator)
156 }
157
158 override getFitness(ThreadContext context) {
159 val fitness = getRawFitness(context)
160 threshold.postProcessCost(fitness, kind)
161 }
162
163 protected def double getRawFitness(ThreadContext context)
164}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend
new file mode 100644
index 00000000..4a870a3e
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend
@@ -0,0 +1,10 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization
2
3import org.eclipse.viatra.dse.base.ThreadContext
4import org.eclipse.viatra.dse.objectives.IObjective
5
6interface IThreeValuedObjective extends IObjective {
7 def Double getWorstPossibleFitness(ThreadContext threadContext)
8
9 def Double getBestPossibleFitness(ThreadContext threadContext)
10}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend
new file mode 100644
index 00000000..a0c6a2c1
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend
@@ -0,0 +1,52 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization
2
3import com.google.common.collect.ImmutableList
4import java.util.Collection
5import org.eclipse.viatra.dse.base.ThreadContext
6import org.eclipse.viatra.query.runtime.api.IPatternMatch
7import org.eclipse.viatra.query.runtime.api.IQuerySpecification
8import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
9import org.eclipse.xtend.lib.annotations.Data
10
11@Data
12class MatchCostElement {
13 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification
14 val double weight
15}
16
17class MatchCostObjective extends DirectionalThresholdObjective {
18 val Collection<MatchCostElement> costElements
19 Collection<CostElementMatcher> matchers
20
21 new(String name, Collection<MatchCostElement> costElements, ObjectiveKind kind, ObjectiveThreshold threshold,
22 int level) {
23 super(name, kind, threshold, level)
24 this.costElements = costElements
25 }
26
27 override createNew() {
28 new MatchCostObjective(name, costElements, kind, threshold, level)
29 }
30
31 override init(ThreadContext context) {
32 val queryEngine = context.queryEngine
33 matchers = ImmutableList.copyOf(costElements.map [
34 val matcher = querySpecification.getMatcher(queryEngine)
35 new CostElementMatcher(matcher, weight)
36 ])
37 }
38
39 override protected getRawFitness(ThreadContext context) {
40 var double cost = 0
41 for (it : matchers) {
42 cost += weight * matcher.countMatches
43 }
44 cost
45 }
46
47 @Data
48 private static class CostElementMatcher {
49 val ViatraQueryMatcher<? extends IPatternMatch> matcher
50 val double weight
51 }
52}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java
new file mode 100644
index 00000000..cbbaaafd
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java
@@ -0,0 +1,60 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization;
2
3import java.util.Comparator;
4
5import org.eclipse.viatra.dse.objectives.Comparators;
6
7public enum ObjectiveKind {
8 LOWER_IS_BETTER {
9
10 @Override
11 public Comparator<Double> getComparator() {
12 return Comparators.LOWER_IS_BETTER;
13 }
14
15 @Override
16 public double getInvalidValue() {
17 return Double.POSITIVE_INFINITY;
18 }
19
20 @Override
21 public double getSatisfiedValue() {
22 return Double.NEGATIVE_INFINITY;
23 }
24
25 },
26 HIGHER_IS_BETTER {
27
28 @Override
29 public Comparator<Double> getComparator() {
30 return Comparators.HIGHER_IS_BETTER;
31 }
32
33 @Override
34 public double getInvalidValue() {
35 return Double.NEGATIVE_INFINITY;
36 }
37
38 @Override
39 public double getSatisfiedValue() {
40 return Double.POSITIVE_INFINITY;
41 }
42
43 };
44
45 public abstract Comparator<Double> getComparator();
46
47 public abstract double getInvalidValue();
48
49 public abstract double getSatisfiedValue();
50
51 public static ObjectiveKind fromComparator(Comparator<Double> comparator) {
52 if (Comparators.LOWER_IS_BETTER.equals(comparator)) {
53 return ObjectiveKind.LOWER_IS_BETTER;
54 } else if (Comparators.HIGHER_IS_BETTER.equals(comparator)) {
55 return ObjectiveKind.HIGHER_IS_BETTER;
56 } else {
57 throw new IllegalStateException("Only LOWER_IS_BETTER and HIGHER_IS_BETTER comparators are supported.");
58 }
59 }
60}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend
new file mode 100644
index 00000000..d355f5be
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend
@@ -0,0 +1,48 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization
2
3import org.eclipse.viatra.dse.base.ThreadContext
4import org.eclipse.viatra.query.runtime.api.IPatternMatch
5import org.eclipse.viatra.query.runtime.api.IQuerySpecification
6import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
7
8class QueryBasedObjective extends DirectionalThresholdObjective {
9 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification
10 ViatraQueryMatcher<? extends IPatternMatch> matcher
11
12 new(IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification,
13 ObjectiveKind kind, ObjectiveThreshold threshold, int level) {
14 super(querySpecification.simpleName + " objective", kind, threshold, level)
15 if (querySpecification.parameters.size != 1) {
16 throw new IllegalArgumentException("Objective query must have a single parameter")
17 }
18 this.querySpecification = querySpecification
19 }
20
21 override createNew() {
22 new QueryBasedObjective(querySpecification, kind, threshold, level)
23 }
24
25 override init(ThreadContext context) {
26 matcher = querySpecification.getMatcher(context.queryEngine)
27 }
28
29 override protected getRawFitness(ThreadContext context) {
30 val iterator = matcher.allMatches.iterator
31 if (!iterator.hasNext) {
32 return invalidValue
33 }
34 val value = iterator.next.get(0)
35 if (iterator.hasNext) {
36 throw new IllegalStateException("Multiple matches for objective query")
37 }
38 if (value instanceof Number) {
39 value.doubleValue
40 } else {
41 throw new IllegalStateException("Objective value is not an instance of Number")
42 }
43 }
44
45 private def getInvalidValue() {
46 kind.invalidValue
47 }
48}
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend
new file mode 100644
index 00000000..0a6fd55b
--- /dev/null
+++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend
@@ -0,0 +1,85 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization
2
3import com.google.common.collect.ImmutableList
4import java.util.Collection
5import org.eclipse.viatra.dse.base.ThreadContext
6import org.eclipse.viatra.query.runtime.api.IPatternMatch
7import org.eclipse.viatra.query.runtime.api.IQuerySpecification
8import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
9import org.eclipse.xtend.lib.annotations.Data
10
11@Data
12class ThreeValuedCostElement {
13 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> currentMatchQuery
14 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> mayMatchQuery
15 val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> mustMatchQuery
16 val int weight
17}
18
19class ThreeValuedCostObjective extends AbstractThreeValuedObjective {
20 val Collection<ThreeValuedCostElement> costElements
21 Collection<CostElementMatchers> matchers
22
23 new(String name, Collection<ThreeValuedCostElement> costElements, ObjectiveKind kind, ObjectiveThreshold threshold,
24 int level) {
25 super(name, kind, threshold, level)
26 this.costElements = costElements
27 }
28
29 override createNew() {
30 new ThreeValuedCostObjective(name, costElements, kind, threshold, level)
31 }
32
33 override init(ThreadContext context) {
34 val queryEngine = context.queryEngine
35 matchers = ImmutableList.copyOf(costElements.map [ element |
36 new CostElementMatchers(
37 queryEngine.getMatcher(element.currentMatchQuery),
38 queryEngine.getMatcher(element.mayMatchQuery),
39 queryEngine.getMatcher(element.mustMatchQuery),
40 element.weight
41 )
42 ])
43 }
44
45 override getRawFitness(ThreadContext context) {
46 var int cost = 0
47 for (matcher : matchers) {
48 cost += matcher.weight * matcher.currentMatcher.countMatches
49 }
50 cost as double
51 }
52
53 override getLowestPossibleFitness(ThreadContext threadContext) {
54 var int cost = 0
55 for (matcher : matchers) {
56 if (matcher.weight >= 0) {
57 cost += matcher.weight * matcher.mustMatcher.countMatches
58 } else if (matcher.mayMatcher.countMatches > 0) {
59 // TODO Count may matches.
60 return Double.NEGATIVE_INFINITY
61 }
62 }
63 cost as double
64 }
65
66 override getHighestPossibleFitness(ThreadContext threadContext) {
67 var int cost = 0
68 for (matcher : matchers) {
69 if (matcher.weight <= 0) {
70 cost += matcher.weight * matcher.mustMatcher.countMatches
71 } else if (matcher.mayMatcher.countMatches > 0) {
72 return Double.POSITIVE_INFINITY
73 }
74 }
75 cost as double
76 }
77
78 @Data
79 private static class CostElementMatchers {
80 val ViatraQueryMatcher<? extends IPatternMatch> currentMatcher
81 val ViatraQueryMatcher<? extends IPatternMatch> mayMatcher
82 val ViatraQueryMatcher<? extends IPatternMatch> mustMatcher
83 val int weight
84 }
85}