aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kris7topher@gmail.com>2019-07-14 00:56:19 +0200
committerLibravatar Kristóf Marussy <kris7topher@gmail.com>2019-07-14 00:56:19 +0200
commitfc505b6b171a2d54c3bad6078031b028b55131d3 (patch)
tree8eaa033e053e21ca60bd7f958055cc46e93b7cba
parentTry fix statecode bug (diff)
downloadVIATRA-Generator-fc505b6b171a2d54c3bad6078031b028b55131d3.tar.gz
VIATRA-Generator-fc505b6b171a2d54c3bad6078031b028b55131d3.tar.zst
VIATRA-Generator-fc505b6b171a2d54c3bad6078031b028b55131d3.zip
Polyhedron abstraction with Z3 for cardinality propagation
-rw-r--r--Solvers/SMT-Solver/com.microsoft.z3/.classpath15
-rw-r--r--Solvers/SMT-Solver/com.microsoft.z3/.gitignore1
-rw-r--r--Solvers/SMT-Solver/com.microsoft.z3/.project28
-rw-r--r--Solvers/SMT-Solver/com.microsoft.z3/META-INF/MANIFEST.MF22
-rw-r--r--Solvers/SMT-Solver/com.microsoft.z3/build.properties3
-rw-r--r--Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.dllbin0 -> 13731840 bytes
-rwxr-xr-xSolvers/SMT-Solver/com.microsoft.z3/lib/libz3.dylibbin0 -> 20880828 bytes
-rwxr-xr-xSolvers/SMT-Solver/com.microsoft.z3/lib/libz3.sobin0 -> 23841920 bytes
-rw-r--r--Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.dllbin0 -> 97280 bytes
-rwxr-xr-xSolvers/SMT-Solver/com.microsoft.z3/lib/libz3java.dylibbin0 -> 165680 bytes
-rwxr-xr-xSolvers/SMT-Solver/com.microsoft.z3/lib/libz3java.sobin0 -> 270824 bytes
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/META-INF/MANIFEST.MF4
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ModelGenerationMethodProvider.xtend24
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronScopePropagator.xtend153
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/PolyhedronSolver.xtend115
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/ScopePropagator.xtend (renamed from Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/ScopePropagator.xtend)121
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/cardinality/Z3PolyhedronSolver.xtend206
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/rules/RefinementRuleProvider.xtend2
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend7
-rw-r--r--Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend3
-rw-r--r--Tests/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests/META-INF/MANIFEST.MF2
-rw-r--r--Tests/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/tests/cardinality/Z3PolyhedronSolverTest.xtend199
22 files changed, 833 insertions, 72 deletions
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/.classpath b/Solvers/SMT-Solver/com.microsoft.z3/.classpath
new file mode 100644
index 00000000..ffdc022a
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/.classpath
@@ -0,0 +1,15 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<classpath>
3 <classpathentry exported="true" kind="lib" path="com.microsoft.z3.jar">
4 <attributes>
5 <attribute name="org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY" value="com.microsoft.z3/lib"/>
6 </attributes>
7 </classpathentry>
8 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
9 <attributes>
10 <attribute name="module" value="true"/>
11 </attributes>
12 </classpathentry>
13 <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
14 <classpathentry kind="output" path="bin"/>
15</classpath>
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/.gitignore b/Solvers/SMT-Solver/com.microsoft.z3/.gitignore
new file mode 100644
index 00000000..ae3c1726
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/.gitignore
@@ -0,0 +1 @@
/bin/
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/.project b/Solvers/SMT-Solver/com.microsoft.z3/.project
new file mode 100644
index 00000000..ec5bbc58
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/.project
@@ -0,0 +1,28 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<projectDescription>
3 <name>com.microsoft.z3</name>
4 <comment></comment>
5 <projects>
6 </projects>
7 <buildSpec>
8 <buildCommand>
9 <name>org.eclipse.jdt.core.javabuilder</name>
10 <arguments>
11 </arguments>
12 </buildCommand>
13 <buildCommand>
14 <name>org.eclipse.pde.ManifestBuilder</name>
15 <arguments>
16 </arguments>
17 </buildCommand>
18 <buildCommand>
19 <name>org.eclipse.pde.SchemaBuilder</name>
20 <arguments>
21 </arguments>
22 </buildCommand>
23 </buildSpec>
24 <natures>
25 <nature>org.eclipse.pde.PluginNature</nature>
26 <nature>org.eclipse.jdt.core.javanature</nature>
27 </natures>
28</projectDescription>
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/META-INF/MANIFEST.MF b/Solvers/SMT-Solver/com.microsoft.z3/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..01faa2ad
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
1Manifest-Version: 1.0
2Bundle-ManifestVersion: 2
3Bundle-Name: Z3
4Bundle-SymbolicName: com.microsoft.z3
5Bundle-Version: 4.8.5.qualifier
6Bundle-Vendor: Microsoft
7Automatic-Module-Name: com.microsoft.z3
8Bundle-ClassPath: com.microsoft.z3.jar
9Bundle-NativeCode: lib/libz3.so;
10 lib/libz3java.so;
11 osname=Linux;
12 processor=x86_64;
13 lib/libz3.dylib;
14 lib/libz3java.dylib;
15 osname=MacOSX;
16 processor=x86_64,
17 lib/libz3.dll;
18 lib/libz3java.dll;
19 osname=win32;
20 processor=x86_64
21Export-Package: com.microsoft.z3,
22 com.microsoft.z3.enumerations
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/build.properties b/Solvers/SMT-Solver/com.microsoft.z3/build.properties
new file mode 100644
index 00000000..87f4e73f
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/build.properties
@@ -0,0 +1,3 @@
1bin.includes = META-INF/,\
2 lib/,\
3 com.microsoft.z3.jar
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.dll b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.dll
new file mode 100644
index 00000000..0b518988
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.dll
Binary files differ
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.dylib b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.dylib
new file mode 100755
index 00000000..7884a0e7
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.dylib
Binary files differ
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.so b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.so
new file mode 100755
index 00000000..5beffe36
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3.so
Binary files differ
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.dll b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.dll
new file mode 100644
index 00000000..5e8dbc9b
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.dll
Binary files differ
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.dylib b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.dylib
new file mode 100755
index 00000000..2d9116ac
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.dylib
Binary files differ
diff --git a/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.so b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.so
new file mode 100755
index 00000000..e2d2618d
--- /dev/null
+++ b/Solvers/SMT-Solver/com.microsoft.z3/lib/libz3java.so
Binary files differ
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 b2ee3981..37495e50 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,7 @@ 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,
7 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval, 8 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval,
8 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.aggregators, 9 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.interval.aggregators,
9 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns, 10 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns,
@@ -22,7 +23,8 @@ Require-Bundle: hu.bme.mit.inf.dslreasoner.logic.model;bundle-version="1.0.0",
22 com.google.inject;bundle-version="3.0.0", 23 com.google.inject;bundle-version="3.0.0",
23 org.eclipse.xtext;bundle-version="2.10.0", 24 org.eclipse.xtext;bundle-version="2.10.0",
24 org.eclipse.viatra.transformation.runtime.emf;bundle-version="1.5.0", 25 org.eclipse.viatra.transformation.runtime.emf;bundle-version="1.5.0",
25 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"
26Bundle-RequiredExecutionEnvironment: JavaSE-1.8 28Bundle-RequiredExecutionEnvironment: JavaSE-1.8
27Import-Package: org.apache.log4j 29Import-Package: org.apache.log4j
28Automatic-Module-Name: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery 30Automatic-Module-Name: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery
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 b6918294..0040dbcd 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
@@ -4,6 +4,11 @@ import com.google.common.collect.ImmutableMap
4import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel 4import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel
5import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem 5import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem
6import 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.PolyhedronScopePropagator
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy
10import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Z3PolyhedronSolver
11import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries 12import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider 13import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider
9import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider 14import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider
@@ -63,7 +68,7 @@ class ModelGenerationMethodProvider {
63 ReasonerWorkspace workspace, 68 ReasonerWorkspace workspace,
64 boolean nameNewElements, 69 boolean nameNewElements,
65 TypeInferenceMethod typeInferenceMethod, 70 TypeInferenceMethod typeInferenceMethod,
66 ScopePropagator scopePropagator, 71 ScopePropagatorStrategy scopePropagatorStrategy,
67 DocumentationLevel debugLevel 72 DocumentationLevel debugLevel
68 ) { 73 ) {
69 val statistics = new ModelGenerationStatistics 74 val statistics = new ModelGenerationStatistics
@@ -74,6 +79,8 @@ class ModelGenerationMethodProvider {
74 79
75 val queries = patternProvider.generateQueries(logicProblem, emptySolution, statistics, existingQueries, 80 val queries = patternProvider.generateQueries(logicProblem, emptySolution, statistics, existingQueries,
76 workspace, typeInferenceMethod, writeFiles) 81 workspace, typeInferenceMethod, writeFiles)
82 val scopePropagator = createScopePropagator(scopePropagatorStrategy, emptySolution, queries)
83 scopePropagator.propagateAllScopeConstraints
77 val // LinkedHashMap<Pair<Relation, ? extends Type>, BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>>> 84 val // LinkedHashMap<Pair<Relation, ? extends Type>, BatchTransformationRule<GenericPatternMatch, ViatraQueryMatcher<GenericPatternMatch>>>
78 objectRefinementRules = refinementRuleProvider.createObjectRefinementRules(queries, scopePropagator, 85 objectRefinementRules = refinementRuleProvider.createObjectRefinementRules(queries, scopePropagator,
79 nameNewElements, statistics) 86 nameNewElements, statistics)
@@ -104,4 +111,19 @@ class ModelGenerationMethodProvider {
104 queries.allQueries 111 queries.allQueries
105 ) 112 )
106 } 113 }
114
115 private def createScopePropagator(ScopePropagatorStrategy scopePropagatorStrategy,
116 PartialInterpretation emptySolution, GeneratedPatterns queries) {
117 switch (scopePropagatorStrategy) {
118 case BasicTypeHierarchy:
119 new ScopePropagator(emptySolution)
120 case PolyhedralTypeHierarchy: {
121 val types = queries.refineObjectQueries.keySet.map[newType].toSet
122 val solver = new Z3PolyhedronSolver
123 new PolyhedronScopePropagator(emptySolution, types, solver)
124 }
125 default:
126 throw new IllegalArgumentException("Unknown scope propagator strategy: " + scopePropagatorStrategy)
127 }
128 }
107} 129}
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..8f210ffb
--- /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,153 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.google.common.collect.ImmutableList
4import com.google.common.collect.ImmutableMap
5import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type
6import 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.PartialPrimitiveInterpretation
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope
10import java.util.ArrayDeque
11import java.util.HashMap
12import java.util.HashSet
13import java.util.Map
14import java.util.Set
15
16class PolyhedronScopePropagator extends ScopePropagator {
17 val Map<Scope, LinearBoundedExpression> scopeBounds
18 val LinearConstraint topLevelBounds
19 val PolyhedronSaturationOperator operator
20
21 new(PartialInterpretation p, Set<? extends Type> possibleNewDynamicTypes, PolyhedronSolver solver) {
22 super(p)
23 val instanceCounts = possibleNewDynamicTypes.toInvertedMap[new Dimension(name, 0, null)]
24 val primitiveDimensions = new HashMap
25 val constraintsBuilder = ImmutableList.builder
26 val scopeBoundsBuilder = ImmutableMap.builder
27 // Dimensions for instantiable types were created according to the type analysis,
28 // but for any possible primitive types, we create them on demand,
29 // as there is no Type directly associated with a PartialPrimitiveInterpretation.
30 for (scope : p.scopes) {
31 switch (targetTypeInterpretation : scope.targetTypeInterpretation) {
32 PartialPrimitiveInterpretation: {
33 val dimension = primitiveDimensions.computeIfAbsent(targetTypeInterpretation) [ interpretation |
34 new Dimension(interpretation.eClass.name, 0, null)
35 ]
36 scopeBoundsBuilder.put(scope, dimension)
37 }
38 PartialComplexTypeInterpretation: {
39 val complexType = targetTypeInterpretation.interpretationOf
40 val dimensions = findSubtypeDimensions(complexType, instanceCounts)
41 switch (dimensions.size) {
42 case 0:
43 if (scope.minNewElements > 0) {
44 throw new IllegalArgumentException("Found scope for " + complexType.name +
45 ", but the type cannot be instantiated")
46 }
47 case 1:
48 scopeBoundsBuilder.put(scope, dimensions.head)
49 default: {
50 val constraint = new LinearConstraint(dimensions.toInvertedMap[1], null, null)
51 constraintsBuilder.add(constraint)
52 scopeBoundsBuilder.put(scope, constraint)
53 }
54 }
55 }
56 default:
57 throw new IllegalArgumentException("Unknown PartialTypeInterpretation: " + targetTypeInterpretation)
58 }
59 }
60 val allDimensions = ImmutableList.builder.addAll(instanceCounts.values).addAll(primitiveDimensions.values).build
61 scopeBounds = scopeBoundsBuilder.build
62 topLevelBounds = new LinearConstraint(allDimensions.toInvertedMap[1], null, null)
63 constraintsBuilder.add(topLevelBounds)
64 val expressionsToSaturate = ImmutableList.builder.addAll(scopeBounds.values).add(topLevelBounds).build
65 val polyhedron = new Polyhedron(allDimensions, constraintsBuilder.build, expressionsToSaturate)
66 operator = solver.createSaturationOperator(polyhedron)
67 }
68
69 private def findSubtypeDimensions(Type type, Map<Type, Dimension> instanceCounts) {
70 val subtypes = new HashSet
71 val dimensions = new HashSet
72 val stack = new ArrayDeque
73 stack.addLast(type)
74 while (!stack.empty) {
75 val subtype = stack.removeLast
76 if (subtypes.add(subtype)) {
77 val dimension = instanceCounts.get(subtype)
78 if (dimension !== null) {
79 dimensions.add(dimension)
80 }
81 stack.addAll(subtype.subtypes)
82 }
83 }
84 dimensions
85 }
86
87 override void propagateAllScopeConstraints() {
88 populatePolyhedronFromScope()
89 val result = operator.saturate()
90 if (result == PolyhedronSaturationResult.EMPTY) {
91 throw new IllegalStateException("Scope bounds cannot be satisfied")
92 } else {
93 populateScopesFromPolyhedron()
94 if (result != PolyhedronSaturationResult.SATURATED) {
95 super.propagateAllScopeConstraints()
96 }
97 }
98 }
99
100 private def populatePolyhedronFromScope() {
101 topLevelBounds.lowerBound = partialInterpretation.minNewElements
102 if (partialInterpretation.maxNewElements >= 0) {
103 topLevelBounds.upperBound = partialInterpretation.maxNewElements
104 }
105 for (pair : scopeBounds.entrySet) {
106 val scope = pair.key
107 val bounds = pair.value
108 bounds.lowerBound = scope.minNewElements
109 if (scope.maxNewElements >= 0) {
110 bounds.upperBound = scope.maxNewElements
111 }
112 }
113 }
114
115 private def populateScopesFromPolyhedron() {
116 checkFiniteBounds(topLevelBounds)
117 if (partialInterpretation.minNewElements > topLevelBounds.lowerBound) {
118 throw new IllegalArgumentException('''Lower bound of «topLevelBounds» smaller than top-level scope: «partialInterpretation.minNewElements»''')
119 } else if (partialInterpretation.minNewElements != topLevelBounds.lowerBound) {
120 partialInterpretation.minNewElements = topLevelBounds.lowerBound
121 }
122 if (partialInterpretation.maxNewElements >= 0 &&
123 partialInterpretation.maxNewElements < topLevelBounds.upperBound) {
124 throw new IllegalArgumentException('''Upper bound of «topLevelBounds» larger than top-level scope: «partialInterpretation.maxNewElements»''')
125 } else if (partialInterpretation.maxNewElements != topLevelBounds.upperBound) {
126 partialInterpretation.maxNewElements = topLevelBounds.upperBound
127 }
128 for (pair : scopeBounds.entrySet) {
129 val scope = pair.key
130 val bounds = pair.value
131 checkFiniteBounds(bounds)
132 if (scope.minNewElements > bounds.lowerBound) {
133 throw new IllegalArgumentException('''Lower bound of «bounds» smaller than «scope.targetTypeInterpretation» scope: «scope.minNewElements»''')
134 } else if (scope.minNewElements != bounds.lowerBound) {
135 scope.minNewElements = bounds.lowerBound
136 }
137 if (scope.maxNewElements >= 0 && scope.maxNewElements < bounds.upperBound) {
138 throw new IllegalArgumentException('''Upper bound of «bounds» larger than «scope.targetTypeInterpretation» scope: «scope.maxNewElements»''')
139 } else if (scope.maxNewElements != bounds.upperBound) {
140 scope.maxNewElements = bounds.upperBound
141 }
142 }
143 }
144
145 private def checkFiniteBounds(LinearBoundedExpression bounds) {
146 if (bounds.lowerBound === null) {
147 throw new IllegalArgumentException("Infinite lower bound: " + bounds)
148 }
149 if (bounds.upperBound === null) {
150 throw new IllegalArgumentException("Infinite upper bound: " + bounds)
151 }
152 }
153}
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..08bf25b9
--- /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,115 @@
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««« Saturate:
64««« «FOR expression : expressionsToSaturate»
65««« «IF expression instanceof Dimension»dimension«ELSEIF expression instanceof LinearConstraint»constraint«ELSE»unknown«ENDIF» «expression»
66««« «ENDFOR»
67 '''
68
69}
70
71@Accessors
72abstract class LinearBoundedExpression {
73 var Integer lowerBound
74 var Integer upperBound
75}
76
77@Accessors
78class Dimension extends LinearBoundedExpression {
79 val String name
80
81 @FinalFieldsConstructor
82 new() {
83 }
84
85 new(String name, Integer lowerBound, Integer upperBound) {
86 this(name)
87 this.lowerBound = lowerBound
88 this.upperBound = upperBound
89 }
90
91 override toString() {
92 '''«IF lowerBound !== null»«lowerBound» <= «ENDIF»«name»«IF upperBound !== null» <= «upperBound»«ENDIF»'''
93 }
94
95}
96
97@Accessors
98class LinearConstraint extends LinearBoundedExpression {
99 val Map<Dimension, Integer> coefficients
100
101 @FinalFieldsConstructor
102 new() {
103 }
104
105 new(Map<Dimension, Integer> coefficients, Integer lowerBound, Integer upperBound) {
106 this(coefficients)
107 this.lowerBound = lowerBound
108 this.upperBound = upperBound
109 }
110
111 override toString() {
112 '''«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»'''
113 }
114
115}
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/cardinality/ScopePropagator.xtend
index 38633c07..c8fb3409 100644
--- 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/cardinality/ScopePropagator.xtend
@@ -1,40 +1,46 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra 1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2 2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
3import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 4import 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.PartialTypeInterpratation
5import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope 6import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope
6import java.util.HashMap 7import java.util.HashMap
8import java.util.HashSet
7import java.util.Map 9import java.util.Map
8import java.util.Set 10import java.util.Set
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation 11import org.eclipse.xtend.lib.annotations.Accessors
10import java.util.HashSet 12
13enum ScopePropagatorStrategy {
14 BasicTypeHierarchy,
15 PolyhedralTypeHierarchy
16}
11 17
12class ScopePropagator { 18class ScopePropagator {
13 PartialInterpretation partialInterpretation 19 @Accessors(PROTECTED_GETTER) PartialInterpretation partialInterpretation
14 Map<PartialTypeInterpratation,Scope> type2Scope 20 Map<PartialTypeInterpratation, Scope> type2Scope
15 21
16 val Map<Scope, Set<Scope>> superScopes 22 val Map<Scope, Set<Scope>> superScopes
17 val Map<Scope, Set<Scope>> subScopes 23 val Map<Scope, Set<Scope>> subScopes
18 24
19 public new(PartialInterpretation p) { 25 new(PartialInterpretation p) {
20 partialInterpretation = p 26 partialInterpretation = p
21 type2Scope = new HashMap 27 type2Scope = new HashMap
22 for(scope : p.scopes) { 28 for (scope : p.scopes) {
23 type2Scope.put(scope.targetTypeInterpretation,scope) 29 type2Scope.put(scope.targetTypeInterpretation, scope)
24 } 30 }
25 31
26 superScopes = new HashMap 32 superScopes = new HashMap
27 subScopes = new HashMap 33 subScopes = new HashMap
28 for(scope : p.scopes) { 34 for (scope : p.scopes) {
29 superScopes.put(scope,new HashSet) 35 superScopes.put(scope, new HashSet)
30 subScopes.put(scope,new HashSet) 36 subScopes.put(scope, new HashSet)
31 } 37 }
32 38
33 for(scope : p.scopes) { 39 for (scope : p.scopes) {
34 val target = scope.targetTypeInterpretation 40 val target = scope.targetTypeInterpretation
35 if(target instanceof PartialComplexTypeInterpretation) { 41 if (target instanceof PartialComplexTypeInterpretation) {
36 val supertypeInterpretations = target.supertypeInterpretation 42 val supertypeInterpretations = target.supertypeInterpretation
37 for(supertypeInterpretation : supertypeInterpretations) { 43 for (supertypeInterpretation : supertypeInterpretations) {
38 val supertypeScope = type2Scope.get(supertypeInterpretation) 44 val supertypeScope = type2Scope.get(supertypeInterpretation)
39 superScopes.get(scope).add(supertypeScope) 45 superScopes.get(scope).add(supertypeScope)
40 subScopes.get(supertypeScope).add(scope) 46 subScopes.get(supertypeScope).add(scope)
@@ -42,70 +48,57 @@ class ScopePropagator {
42 } 48 }
43 } 49 }
44 } 50 }
45 51
46 def public propagateAllScopeConstraints() { 52 def propagateAllScopeConstraints() {
47 var boolean hadChanged 53 var boolean hadChanged
48 do{ 54 do {
49 hadChanged = false 55 hadChanged = false
50 for(superScopeEntry : superScopes.entrySet) { 56 for (superScopeEntry : superScopes.entrySet) {
51 val sub = superScopeEntry.key 57 val sub = superScopeEntry.key
52 hadChanged = propagateLowerLimitUp(sub,partialInterpretation) || hadChanged 58 hadChanged = propagateLowerLimitUp(sub, partialInterpretation) || hadChanged
53 hadChanged = propagateUpperLimitDown(sub,partialInterpretation) || hadChanged 59 hadChanged = propagateUpperLimitDown(sub, partialInterpretation) || hadChanged
54 for(sup: superScopeEntry.value) { 60 for (sup : superScopeEntry.value) {
55 hadChanged = propagateLowerLimitUp(sub,sup) || hadChanged 61 hadChanged = propagateLowerLimitUp(sub, sup) || hadChanged
56 hadChanged = propagateUpperLimitDown(sub,sup) || hadChanged 62 hadChanged = propagateUpperLimitDown(sub, sup) || hadChanged
57 } 63 }
58 } 64 }
59 } while(hadChanged) 65 } while (hadChanged)
60// println('''All constraints are propagated.''')
61 } 66 }
62 67
63 def public propagateAdditionToType(PartialTypeInterpratation t) { 68 def propagateAdditionToType(PartialTypeInterpratation t) {
64// println('''Adding to «(t as PartialComplexTypeInterpretation).interpretationOf.name»''') 69// println('''Adding to «(t as PartialComplexTypeInterpretation).interpretationOf.name»''')
65 val targetScope = type2Scope.get(t) 70 val targetScope = type2Scope.get(t)
66 targetScope.removeOne 71 targetScope.removeOne
67 val sups = superScopes.get(targetScope) 72 val sups = superScopes.get(targetScope)
68 sups.forEach[removeOne] 73 sups.forEach[removeOne]
69 if(this.partialInterpretation.minNewElements > 0) { 74 if (this.partialInterpretation.minNewElements > 0) {
70 this.partialInterpretation.minNewElements = this.partialInterpretation.minNewElements-1 75 this.partialInterpretation.minNewElements = this.partialInterpretation.minNewElements - 1
71 } 76 }
72 if(this.partialInterpretation.maxNewElements > 0) { 77 if (this.partialInterpretation.maxNewElements > 0) {
73 this.partialInterpretation.maxNewElements = this.partialInterpretation.maxNewElements-1 78 this.partialInterpretation.maxNewElements = this.partialInterpretation.maxNewElements - 1
74 } else if(this.partialInterpretation.maxNewElements === 0) { 79 } else if (this.partialInterpretation.maxNewElements === 0) {
75 throw new IllegalArgumentException('''Inconsistent object creation: lower node limit is 0!''') 80 throw new IllegalArgumentException('''Inconsistent object creation: lower node limit is 0!''')
76 } 81 }
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 82 propagateAllScopeConstraints
87 83
88// println('''Target Scope: «targetScope.minNewElements» - «targetScope.maxNewElements»''') 84// println('''Target Scope: «targetScope.minNewElements» - «targetScope.maxNewElements»''')
89// println(''' «this.partialInterpretation.minNewElements» - «this.partialInterpretation.maxNewElements»''') 85// println(''' «this.partialInterpretation.minNewElements» - «this.partialInterpretation.maxNewElements»''')
90// this.partialInterpretation.scopes.forEach[println(''' «(it.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name»: «it.minNewElements»-«it.maxNewElements»''')] 86// 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»''') 87// println('''All constraints are propagated upon increasing «(t as PartialComplexTypeInterpretation).interpretationOf.name»''')
92 } 88 }
93 89
94 private def propagateLowerLimitUp(Scope subScope, Scope superScope) { 90 private def propagateLowerLimitUp(Scope subScope, Scope superScope) {
95 if(subScope.minNewElements>superScope.minNewElements) { 91 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 92 superScope.minNewElements = subScope.minNewElements
101 return true 93 return true
102 } else { 94 } else {
103 return false 95 return false
104 } 96 }
105 } 97 }
106 98
107 private def propagateUpperLimitDown(Scope subScope, Scope superScope) { 99 private def propagateUpperLimitDown(Scope subScope, Scope superScope) {
108 if(superScope.maxNewElements>=0 && (superScope.maxNewElements<subScope.maxNewElements || subScope.maxNewElements<0)) { 100 if (superScope.maxNewElements >= 0 &&
101 (superScope.maxNewElements < subScope.maxNewElements || subScope.maxNewElements < 0)) {
109// println(''' 102// println('''
110// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> «(superScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» 103// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> «(superScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name»
111// subScope.maxNewElements «subScope.maxNewElements» = superScope.maxNewElements «superScope.maxNewElements» 104// subScope.maxNewElements «subScope.maxNewElements» = superScope.maxNewElements «superScope.maxNewElements»
@@ -116,9 +109,9 @@ class ScopePropagator {
116 return false 109 return false
117 } 110 }
118 } 111 }
119 112
120 private def propagateLowerLimitUp(Scope subScope, PartialInterpretation p) { 113 private def propagateLowerLimitUp(Scope subScope, PartialInterpretation p) {
121 if(subScope.minNewElements>p.minNewElements) { 114 if (subScope.minNewElements > p.minNewElements) {
122// println(''' 115// println('''
123// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes 116// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes
124// p.minNewElements «p.minNewElements» = subScope.minNewElements «subScope.minNewElements» 117// p.minNewElements «p.minNewElements» = subScope.minNewElements «subScope.minNewElements»
@@ -129,9 +122,9 @@ class ScopePropagator {
129 return false 122 return false
130 } 123 }
131 } 124 }
132 125
133 private def propagateUpperLimitDown(Scope subScope, PartialInterpretation p) { 126 private def propagateUpperLimitDown(Scope subScope, PartialInterpretation p) {
134 if(p.maxNewElements>=0 && (p.maxNewElements<subScope.maxNewElements || subScope.maxNewElements<0)) { 127 if (p.maxNewElements >= 0 && (p.maxNewElements < subScope.maxNewElements || subScope.maxNewElements < 0)) {
135// println(''' 128// println('''
136// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes 129// «(subScope.targetTypeInterpretation as PartialComplexTypeInterpretation).interpretationOf.name» -> nodes
137// subScope.maxNewElements «subScope.maxNewElements» = p.maxNewElements «p.maxNewElements» 130// subScope.maxNewElements «subScope.maxNewElements» = p.maxNewElements «p.maxNewElements»
@@ -142,15 +135,15 @@ class ScopePropagator {
142 return false 135 return false
143 } 136 }
144 } 137 }
138
145 private def removeOne(Scope scope) { 139 private def removeOne(Scope scope) {
146 if(scope.maxNewElements===0) { 140 if (scope.maxNewElements === 0) {
147 throw new IllegalArgumentException('''Inconsistent object creation: «scope.targetTypeInterpretation»''') 141 throw new IllegalArgumentException('''Inconsistent object creation: «scope.targetTypeInterpretation»''')
148 } else if(scope.maxNewElements>0) { 142 } else if (scope.maxNewElements > 0) {
149 scope.maxNewElements= scope.maxNewElements-1 143 scope.maxNewElements = scope.maxNewElements - 1
150 } 144 }
151 if(scope.minNewElements>0) { 145 if (scope.minNewElements > 0) {
152 scope.minNewElements= scope.minNewElements-1 146 scope.minNewElements = scope.minNewElements - 1
153 } 147 }
154 } 148 }
155} 149}
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/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..f1a84f2d
--- /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,206 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality
2
3import com.microsoft.z3.ArithExpr
4import com.microsoft.z3.Context
5import com.microsoft.z3.Expr
6import com.microsoft.z3.IntNum
7import com.microsoft.z3.Optimize
8import com.microsoft.z3.Status
9import com.microsoft.z3.Symbol
10import java.util.Map
11import org.eclipse.xtend.lib.annotations.Accessors
12import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
13
14class Z3PolyhedronSolver implements PolyhedronSolver {
15 val boolean lpRelaxation
16
17 @FinalFieldsConstructor
18 new() {
19 }
20
21 new() {
22 this(true)
23 }
24
25 override createSaturationOperator(Polyhedron polyhedron) {
26 new Z3SaturationOperator(polyhedron, lpRelaxation)
27 }
28}
29
30class Z3SaturationOperator implements PolyhedronSaturationOperator {
31 static val INFINITY_SYMBOL_NAME = "oo"
32 static val MULT_SYMBOL_NAME = "*"
33
34 extension val Context context
35 val Symbol infinitySymbol
36 val Symbol multSymbol
37 @Accessors val Polyhedron polyhedron
38 val Map<Dimension, ArithExpr> variables
39
40 new(Polyhedron polyhedron, boolean lpRelaxation) {
41 context = new Context
42 infinitySymbol = context.mkSymbol(INFINITY_SYMBOL_NAME)
43 multSymbol = context.mkSymbol(MULT_SYMBOL_NAME)
44 this.polyhedron = polyhedron
45 variables = polyhedron.dimensions.toInvertedMap [ dimension |
46 val name = dimension.name
47 if (lpRelaxation) {
48 mkRealConst(name)
49 } else {
50 mkIntConst(name)
51 }
52 ]
53 }
54
55 override saturate() {
56 val status = doSaturate()
57 convertStatusToSaturationResult(status)
58 }
59
60 private def convertStatusToSaturationResult(Status status) {
61 switch (status) {
62 case SATISFIABLE:
63 PolyhedronSaturationResult.SATURATED
64 case UNSATISFIABLE:
65 PolyhedronSaturationResult.EMPTY
66 case UNKNOWN:
67 PolyhedronSaturationResult.UNKNOWN
68 default:
69 throw new IllegalArgumentException("Unknown Status: " + status)
70 }
71 }
72
73 private def doSaturate() {
74 for (expressionToSaturate : polyhedron.expressionsToSaturate) {
75 val expr = expressionToSaturate.toExpr
76 val lowerResult = saturateLowerBound(expr, expressionToSaturate)
77 if (lowerResult != Status.SATISFIABLE) {
78 return lowerResult
79 }
80 val upperResult = saturateUpperBound(expr, expressionToSaturate)
81 if (upperResult != Status.SATISFIABLE) {
82 return upperResult
83 }
84 }
85 Status.SATISFIABLE
86 }
87
88 private def saturateLowerBound(ArithExpr expr, LinearBoundedExpression expressionToSaturate) {
89 val optimize = prepareOptimize
90 val handle = optimize.MkMinimize(expr)
91 val status = optimize.Check()
92 if (status == Status.SATISFIABLE) {
93 val value = switch (resultExpr : handle.lower) {
94 IntNum:
95 resultExpr.getInt()
96 default:
97 if (isNegativeInfinity(resultExpr)) {
98 null
99 } else {
100 throw new IllegalArgumentException("Integer result expected, got: " + resultExpr)
101 }
102 }
103 expressionToSaturate.lowerBound = value
104 }
105 status
106 }
107
108 private def saturateUpperBound(ArithExpr expr, LinearBoundedExpression expressionToSaturate) {
109 val optimize = prepareOptimize
110 val handle = optimize.MkMaximize(expr)
111 val status = optimize.Check()
112 if (status == Status.SATISFIABLE) {
113 val value = switch (resultExpr : handle.upper) {
114 IntNum:
115 resultExpr.getInt()
116 default:
117 if (isPositiveInfinity(resultExpr)) {
118 null
119 } else {
120 throw new IllegalArgumentException("Integer result expected, got: " + resultExpr)
121 }
122 }
123 expressionToSaturate.upperBound = value
124 }
125 status
126 }
127
128 private def isPositiveInfinity(Expr expr) {
129 expr.app && expr.getFuncDecl.name == infinitySymbol
130 }
131
132 private def isNegativeInfinity(Expr expr) {
133 // Negative infinity is represented as (* (- 1) oo)
134 if (!expr.app || expr.getFuncDecl.name != multSymbol || expr.numArgs != 2) {
135 return false
136 }
137 isPositiveInfinity(expr.args.get(1))
138 }
139
140 private def prepareOptimize() {
141 val optimize = mkOptimize()
142 assertConstraints(optimize)
143 optimize
144 }
145
146 private def assertConstraints(Optimize it) {
147 for (pair : variables.entrySet) {
148 assertBounds(pair.value, pair.key)
149 }
150 for (constraint : polyhedron.constraints) {
151 val expr = createLinearCombination(constraint.coefficients)
152 assertBounds(expr, constraint)
153 }
154 }
155
156 private def assertBounds(Optimize it, ArithExpr expression, LinearBoundedExpression bounds) {
157 val lowerBound = bounds.lowerBound
158 val upperBound = bounds.upperBound
159 if (lowerBound == upperBound) {
160 if (lowerBound === null) {
161 return
162 }
163 Assert(mkEq(expression, mkInt(lowerBound)))
164 } else {
165 if (lowerBound !== null) {
166 Assert(mkGe(expression, mkInt(lowerBound)))
167 }
168 if (upperBound !== null) {
169 Assert(mkLe(expression, mkInt(upperBound)))
170 }
171 }
172 }
173
174 private def toExpr(LinearBoundedExpression linearBoundedExpression) {
175 switch (linearBoundedExpression) {
176 Dimension: variables.get(linearBoundedExpression)
177 LinearConstraint: createLinearCombination(linearBoundedExpression.coefficients)
178 default: throw new IllegalArgumentException("Unknown linear bounded expression:" + linearBoundedExpression)
179 }
180 }
181
182 private def createLinearCombination(Map<Dimension, Integer> coefficients) {
183 val size = coefficients.size
184 val array = newArrayOfSize(size)
185 var int i = 0
186 for (pair : coefficients.entrySet) {
187 val variable = variables.get(pair.key)
188 if (variable === null) {
189 throw new IllegalArgumentException("Unknown dimension: " + pair.key.name)
190 }
191 val coefficient = pair.value
192 val term = if (coefficient == 1) {
193 variable
194 } else {
195 mkMul(mkInt(coefficient), variable)
196 }
197 array.set(i, term)
198 i++
199 }
200 mkAdd(array)
201 }
202
203 override close() throws Exception {
204 context.close()
205 }
206}
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..5fefa551 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
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 701eb054..101f0a3e 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
@@ -12,7 +12,7 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage
12import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicresultFactory 12import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicresultFactory
13import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult 13import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult
14import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethodProvider 14import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethodProvider
15import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator 15import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator
16import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.PartialInterpretationInitialiser 16import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.PartialInterpretationInitialiser
17import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation 17import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
18import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage 18import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage
@@ -71,16 +71,13 @@ class ViatraReasoner extends LogicReasoner {
71 } 71 }
72 emptySolution.problemConainer = problem 72 emptySolution.problemConainer = problem
73 73
74 val ScopePropagator scopePropagator = new ScopePropagator(emptySolution)
75 scopePropagator.propagateAllScopeConstraints
76
77 val method = modelGenerationMethodProvider.createModelGenerationMethod( 74 val method = modelGenerationMethodProvider.createModelGenerationMethod(
78 problem, 75 problem,
79 emptySolution, 76 emptySolution,
80 workspace, 77 workspace,
81 viatraConfig.nameNewElements, 78 viatraConfig.nameNewElements,
82 viatraConfig.typeInferenceMethod, 79 viatraConfig.typeInferenceMethod,
83 scopePropagator, 80 viatraConfig.scopePropagatorStrategy,
84 viatraConfig.documentationLevel 81 viatraConfig.documentationLevel
85 ) 82 )
86 83
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 99decdd9..7a3a2d67 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,6 +6,7 @@ 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.ScopePropagatorStrategy
9import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser 10import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser
10import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind 11import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind
11import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold 12import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold
@@ -49,6 +50,8 @@ class ViatraReasonerConfiguration extends LogicSolverConfiguration {
49 * Configuration for cutting search space. 50 * Configuration for cutting search space.
50 */ 51 */
51 public var SearchSpaceConstraint searchSpaceConstraints = new SearchSpaceConstraint 52 public var SearchSpaceConstraint searchSpaceConstraints = new SearchSpaceConstraint
53
54 public var ScopePropagatorStrategy scopePropagatorStrategy = ScopePropagatorStrategy.PolyhedralTypeHierarchy
52 55
53 public var List<CostObjectiveConfiguration> costObjectives = newArrayList 56 public var List<CostObjectiveConfiguration> costObjectives = newArrayList
54} 57}
diff --git a/Tests/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests/META-INF/MANIFEST.MF b/Tests/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests/META-INF/MANIFEST.MF
index 76c113c1..43e40319 100644
--- a/Tests/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests/META-INF/MANIFEST.MF
+++ b/Tests/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests/META-INF/MANIFEST.MF
@@ -11,3 +11,5 @@ Require-Bundle: com.google.guava,
11 org.eclipse.xtend.lib, 11 org.eclipse.xtend.lib,
12 org.eclipse.xtend.lib.macro, 12 org.eclipse.xtend.lib.macro,
13 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery 13 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatraquery
14Export-Package: hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests.cardinality,
15 hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests.interval
diff --git a/Tests/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/tests/cardinality/Z3PolyhedronSolverTest.xtend b/Tests/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/tests/cardinality/Z3PolyhedronSolverTest.xtend
new file mode 100644
index 00000000..2d159752
--- /dev/null
+++ b/Tests/hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests/src/hu/bme/mit/inf/dslreasoner/viatrasolver/logic2viatra/tests/cardinality/Z3PolyhedronSolverTest.xtend
@@ -0,0 +1,199 @@
1package hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.tests.cardinality
2
3import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Dimension
4import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearConstraint
5import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Polyhedron
6import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronSaturationOperator
7import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronSaturationResult
8import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Z3PolyhedronSolver
9import org.junit.After
10import org.junit.Before
11import org.junit.Test
12
13import static org.junit.Assert.*
14
15class Z3PolyhedronSolverTest {
16 var Z3PolyhedronSolver solver
17 var PolyhedronSaturationOperator operator
18
19 @Before
20 def void setUp() {
21 solver = new Z3PolyhedronSolver(false)
22 }
23
24 @After
25 def void tearDown() {
26 destroyOperatorIfExists()
27 }
28
29 @Test
30 def void singleDimensionTest() {
31 val x = new Dimension("x", 0, 1)
32 createSaturationOperator(new Polyhedron(#[x], #[], #[x]))
33
34 val result = saturate()
35
36 assertEquals(PolyhedronSaturationResult.SATURATED, result)
37 assertEquals(0, x.lowerBound)
38 assertEquals(1, x.upperBound)
39 }
40
41 @Test
42 def void singleDimensionNegativeValueTest() {
43 val x = new Dimension("x", -2, -1)
44 createSaturationOperator(new Polyhedron(#[x], #[], #[x]))
45
46 val result = saturate()
47
48 assertEquals(PolyhedronSaturationResult.SATURATED, result)
49 assertEquals(-2, x.lowerBound)
50 assertEquals(-1, x.upperBound)
51 }
52
53 @Test
54 def void singleDimensionConstraintTest() {
55 val x = new Dimension("x", null, null)
56 val constraint = new LinearConstraint(#{x -> 2}, 0, 2)
57 createSaturationOperator(new Polyhedron(#[x], #[constraint], #[x]))
58
59 val result = saturate()
60
61 assertEquals(PolyhedronSaturationResult.SATURATED, result)
62 assertEquals(0, x.lowerBound)
63 assertEquals(1, x.upperBound)
64 }
65
66 @Test
67 def void singleDimensionConstraintUnitCoefficientTest() {
68 val x = new Dimension("x", null, null)
69 val constraint = new LinearConstraint(#{x -> 1}, 1, 3)
70 createSaturationOperator(new Polyhedron(#[x], #[constraint], #[x]))
71
72 val result = saturate()
73
74 assertEquals(PolyhedronSaturationResult.SATURATED, result)
75 assertEquals(1, x.lowerBound)
76 assertEquals(3, x.upperBound)
77 }
78
79 @Test
80 def void singleDimensionConstraintIntegerTest() {
81 val x = new Dimension("x", null, null)
82 val constraint = new LinearConstraint(#{x -> 2}, 0, 3)
83 createSaturationOperator(new Polyhedron(#[x], #[constraint], #[x]))
84
85 val result = saturate()
86
87 assertEquals(PolyhedronSaturationResult.SATURATED, result)
88 assertEquals(0, x.lowerBound)
89 assertEquals(1, x.upperBound)
90 }
91
92 @Test
93 def void singleDimensionUnboundedFromAboveTest() {
94 val x = new Dimension("x", 0, null)
95 createSaturationOperator(new Polyhedron(#[x], #[], #[x]))
96
97 val result = saturate()
98
99 assertEquals(PolyhedronSaturationResult.SATURATED, result)
100 assertEquals(0, x.lowerBound)
101 assertEquals(null, x.upperBound)
102 }
103
104 @Test
105 def void singleDimensionUnboundedFromBelowTest() {
106 val x = new Dimension("x", null, 0)
107 createSaturationOperator(new Polyhedron(#[x], #[], #[x]))
108
109 val result = saturate()
110
111 assertEquals(PolyhedronSaturationResult.SATURATED, result)
112 assertEquals(null, x.lowerBound)
113 assertEquals(0, x.upperBound)
114 }
115
116 @Test
117 def void singleDimensionUnsatisfiableTest() {
118 val x = new Dimension("x", 0, 1)
119 val constraint = new LinearConstraint(#{x -> 2}, -2, -1)
120 createSaturationOperator(new Polyhedron(#[x], #[constraint], #[x]))
121
122 val result = saturate()
123
124 assertEquals(PolyhedronSaturationResult.EMPTY, result)
125 }
126
127 @Test
128 def void equalityConstraintTest() {
129 val x = new Dimension("x", null, null)
130 val y = new Dimension("y", 1, 2)
131 val constraint = new LinearConstraint(#{x -> 2, y -> 2}, 6, 6)
132 createSaturationOperator(new Polyhedron(#[x, y], #[constraint], #[x]))
133
134 val result = saturate()
135
136 assertEquals(PolyhedronSaturationResult.SATURATED, result)
137 assertEquals(1, x.lowerBound)
138 assertEquals(2, x.upperBound)
139 }
140
141 @Test
142 def void saturateConstraintTest() {
143 val x = new Dimension("x", 0, 2)
144 val y = new Dimension("y", 1, 2)
145 val constraint = new LinearConstraint(#{x -> 2, y -> 1}, 0, 8)
146 createSaturationOperator(new Polyhedron(#[x, y], #[constraint], #[constraint]))
147
148 val result = saturate()
149
150 assertEquals(PolyhedronSaturationResult.SATURATED, result)
151 assertEquals(1, constraint.lowerBound)
152 assertEquals(6, constraint.upperBound)
153 }
154
155 @Test(expected=IllegalArgumentException)
156 def void unknownVariableTest() {
157 val x = new Dimension("x", 0, 1)
158 val y = new Dimension("y", 0, 1)
159 val constraint = new LinearConstraint(#{y -> 2}, 0, 2)
160 createSaturationOperator(new Polyhedron(#[x], #[constraint], #[x]))
161
162 saturate()
163 }
164
165 @Test
166 def void unsatisfiableMultipleInheritanceTest() {
167 val x = new Dimension("x", 0, 1)
168 val y = new Dimension("y", 0, 1)
169 val z = new Dimension("z", 0, 1)
170 createSaturationOperator(new Polyhedron(
171 #[x, y, z],
172 #[
173 new LinearConstraint(#{x -> 1, y -> 1}, 1, 1),
174 new LinearConstraint(#{x -> 1, z -> 1}, 1, 1),
175 new LinearConstraint(#{y -> 1, z -> 1}, 1, 1)
176 ],
177 #[x, y, z]
178 ))
179
180 val result = saturate()
181
182 assertEquals(PolyhedronSaturationResult.EMPTY, result)
183 }
184
185 private def createSaturationOperator(Polyhedron polyhedron) {
186 destroyOperatorIfExists()
187 operator = solver.createSaturationOperator(polyhedron)
188 }
189
190 private def destroyOperatorIfExists() {
191 if (operator !== null) {
192 operator.close
193 }
194 }
195
196 private def saturate() {
197 operator.saturate
198 }
199}