diff options
Diffstat (limited to 'Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner')
39 files changed, 3418 insertions, 914 deletions
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodBasedGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodBasedGlobalConstraint.xtend index 28cf986d..691e0645 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodBasedGlobalConstraint.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodBasedGlobalConstraint.xtend | |||
@@ -1,11 +1,10 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner |
2 | 2 | ||
3 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint | 3 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint |
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod | 4 | |
5 | 5 | abstract class ModelGenerationMethodBasedGlobalConstraint implements IGlobalConstraint { | |
6 | abstract class ModelGenerationMethodBasedGlobalConstraint implements IGlobalConstraint { | 6 | val protected ModelGenerationMethod method |
7 | val protected ModelGenerationMethod method | 7 | new(ModelGenerationMethod method) { |
8 | new(ModelGenerationMethod method) { | 8 | this.method = method |
9 | this.method = method | 9 | } |
10 | } | 10 | } |
11 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodProvider.xtend new file mode 100644 index 00000000..25137eba --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ModelGenerationMethodProvider.xtend | |||
@@ -0,0 +1,201 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner | ||
2 | |||
3 | import com.google.common.collect.ImmutableMap | ||
4 | import com.google.common.collect.ImmutableSet | ||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
7 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationStatistics | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.CachingSimplePolyhedronScopePropagatorStrategy | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.CbcPolyhedronSolver | ||
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator | ||
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronExtensionOperator | ||
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronScopePropagator | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.RelationConstraintCalculator | ||
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagator | ||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.TypeHierarchyScopePropagator | ||
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Z3PolyhedronSolver | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.GeneratedPatterns | ||
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternProvider | ||
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.GoalConstraintProvider | ||
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.rules.RefinementRuleProvider | ||
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.DiversityChecker | ||
27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ViatraReasonerSolutionSaver | ||
28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ThreeValuedCostObjectiveProvider | ||
29 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace | ||
30 | import java.util.Collection | ||
31 | import java.util.List | ||
32 | import java.util.Map | ||
33 | import java.util.Set | ||
34 | import org.eclipse.viatra.dse.objectives.IObjective | ||
35 | import org.eclipse.viatra.query.runtime.api.GenericQueryGroup | ||
36 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
37 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
38 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
39 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
40 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
41 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
42 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | ||
43 | import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule | ||
44 | import org.eclipse.xtend.lib.annotations.Data | ||
45 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ExtendedPolyhedronScopePropagatorStrategy | ||
46 | |||
47 | @Data class ModelGenerationMethod { | ||
48 | ModelGenerationStatistics statistics | ||
49 | |||
50 | Collection<? extends BatchTransformationRule<?, ?>> objectRefinementRules | ||
51 | Collection<? extends BatchTransformationRule<?, ?>> relationRefinementRules | ||
52 | |||
53 | List<MultiplicityGoalConstraintCalculator> unfinishedMultiplicities | ||
54 | |||
55 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF | ||
56 | |||
57 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidWF | ||
58 | |||
59 | Map<PConstraint, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> mustUnitPropagationPreconditions | ||
60 | Map<PConstraint, IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> currentUnitPropagationPreconditions | ||
61 | |||
62 | Map<String, ModalPatternQueries> modalRelationQueries | ||
63 | |||
64 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> allPatterns | ||
65 | |||
66 | Collection<IObjective> costObjectives | ||
67 | boolean optimizationProblem | ||
68 | ViatraReasonerSolutionSaver solutionSaver | ||
69 | } | ||
70 | |||
71 | class ModelGenerationMethodProvider { | ||
72 | val PatternProvider patternProvider = new PatternProvider | ||
73 | val RefinementRuleProvider refinementRuleProvider = new RefinementRuleProvider | ||
74 | val GoalConstraintProvider goalConstraintProvider = new GoalConstraintProvider | ||
75 | val relationConstraintCalculator = new RelationConstraintCalculator | ||
76 | |||
77 | def ModelGenerationMethod createModelGenerationMethod( | ||
78 | LogicProblem logicProblem, | ||
79 | PartialInterpretation emptySolution, | ||
80 | ReasonerWorkspace workspace, | ||
81 | ViatraReasonerConfiguration config | ||
82 | ) { | ||
83 | val statistics = new ModelGenerationStatistics | ||
84 | val debugLevel = config.documentationLevel | ||
85 | val writeFiles = (debugLevel === DocumentationLevel.NORMAL || debugLevel === DocumentationLevel.FULL) | ||
86 | |||
87 | val Set<PQuery> existingQueries = logicProblem.relations.map[annotations].flatten.filter(TransfomedViatraQuery). | ||
88 | map[it.patternPQuery as PQuery].toSet | ||
89 | |||
90 | val relationConstraints = relationConstraintCalculator.calculateRelationConstraints(logicProblem) | ||
91 | val queries = patternProvider.generateQueries(logicProblem, emptySolution, statistics, existingQueries, | ||
92 | workspace, config.typeInferenceMethod, config.scopePropagatorStrategy, relationConstraints, config.hints, | ||
93 | config.unitPropagationPatternGenerators, writeFiles) | ||
94 | |||
95 | val unfinishedMultiplicities = goalConstraintProvider.getUnfinishedMultiplicityQueries(logicProblem, queries, | ||
96 | config.calculateObjectCreationCosts) | ||
97 | val unfinishedWF = queries.getUnfinishedWFQueries.values | ||
98 | val modalRelationQueriesBuilder = ImmutableMap.builder | ||
99 | for (entry : queries.modalRelationQueries.entrySet) { | ||
100 | val annotation = entry.key.annotations.filter(TransfomedViatraQuery).head | ||
101 | if (annotation !== null) { | ||
102 | modalRelationQueriesBuilder.put(annotation.patternFullyQualifiedName, entry.value) | ||
103 | } | ||
104 | } | ||
105 | val modalRelationQueries = modalRelationQueriesBuilder.build | ||
106 | val invalidWF = queries.getInvalidWFQueries.values | ||
107 | val mustUnitPropagationPreconditions = queries.getMustUnitPropagationPreconditionPatterns | ||
108 | val currentUnitPropagationPreconditions = queries.getCurrentUnitPropagationPreconditionPatterns | ||
109 | val queriesToPrepare = ImmutableSet.builder.addAll(queries.refineObjectQueries.values).addAll( | ||
110 | queries.refineTypeQueries.values).addAll(queries.refineRelationQueries.values).addAll( | ||
111 | queries.mustRelationPropagationQueries.values).addAll(queries.multiplicityConstraintQueries.values.flatMap [ | ||
112 | allQueries | ||
113 | ]).addAll(queries.unfinishedWFQueries.values).addAll(queries.invalidWFQueries.values).addAll( | ||
114 | queries.mustUnitPropagationPreconditionPatterns.values).addAll( | ||
115 | queries.currentUnitPropagationPreconditionPatterns.values).add(queries.hasElementInContainmentQuery).build | ||
116 | val queryEngine = ViatraQueryEngine.on(new EMFScope(emptySolution)) | ||
117 | GenericQueryGroup.of(queriesToPrepare).prepare(queryEngine) | ||
118 | |||
119 | val objectiveProvider = new ThreeValuedCostObjectiveProvider(queryEngine, emptySolution, modalRelationQueries) | ||
120 | val transformedObjectives = objectiveProvider.getCostObjectives(config.costObjectives) | ||
121 | |||
122 | val solutionSaver = new ViatraReasonerSolutionSaver(transformedObjectives.leveledExtremalObjectives, | ||
123 | config.solutionScope.numberOfRequiredSolutions, DiversityChecker.of(config.diversityRequirement)) | ||
124 | |||
125 | val allHints = ImmutableSet.builder | ||
126 | allHints.addAll(config.hints) | ||
127 | for (hint : transformedObjectives.hints) { | ||
128 | hint.boundsProvider = solutionSaver | ||
129 | allHints.add(hint) | ||
130 | } | ||
131 | |||
132 | val scopePropagator = createScopePropagator(config.scopePropagatorStrategy, emptySolution, allHints.build, | ||
133 | transformedObjectives.extensionOperators, queries, statistics) | ||
134 | scopePropagator.propagateAllScopeConstraints | ||
135 | val unitRulePropagator = refinementRuleProvider.createUnitPrulePropagator(logicProblem, emptySolution, queries, | ||
136 | scopePropagator, statistics) | ||
137 | val objectRefinementRules = refinementRuleProvider.createObjectRefinementRules(logicProblem, emptySolution, | ||
138 | queries, unitRulePropagator, config.nameNewElements, statistics) | ||
139 | val relationRefinementRules = refinementRuleProvider.createRelationRefinementRules(queries, unitRulePropagator, | ||
140 | statistics) | ||
141 | |||
142 | return new ModelGenerationMethod( | ||
143 | statistics, | ||
144 | objectRefinementRules.values, | ||
145 | relationRefinementRules.values, | ||
146 | unfinishedMultiplicities, | ||
147 | unfinishedWF, | ||
148 | invalidWF, | ||
149 | mustUnitPropagationPreconditions, | ||
150 | currentUnitPropagationPreconditions, | ||
151 | modalRelationQueries, | ||
152 | queries.allQueries, | ||
153 | transformedObjectives.objectives, | ||
154 | transformedObjectives.optimizationProblem, | ||
155 | solutionSaver | ||
156 | ) | ||
157 | } | ||
158 | |||
159 | private def createScopePropagator(ScopePropagatorStrategy scopePropagatorStrategy, | ||
160 | PartialInterpretation emptySolution, Collection<LinearTypeConstraintHint> hints, | ||
161 | Collection<PolyhedronExtensionOperator> extensionOperators, GeneratedPatterns queries, | ||
162 | ModelGenerationStatistics statistics) { | ||
163 | if (!hints.empty && !(scopePropagatorStrategy instanceof ScopePropagatorStrategy.Polyhedral)) { | ||
164 | throw new IllegalArgumentException("Only the Polyhedral scope propagator strategy can use hints.") | ||
165 | } | ||
166 | switch (scopePropagatorStrategy) { | ||
167 | case ScopePropagatorStrategy.None, | ||
168 | case ScopePropagatorStrategy.Basic: | ||
169 | new ScopePropagator(emptySolution, statistics) | ||
170 | case ScopePropagatorStrategy.BasicTypeHierarchy: | ||
171 | new TypeHierarchyScopePropagator(emptySolution, statistics) | ||
172 | ScopePropagatorStrategy.Polyhedral: { | ||
173 | val types = queries.refineObjectQueries.keySet.map[newType].toSet | ||
174 | val allPatternsByName = queries.allQueries.toMap[fullyQualifiedName] | ||
175 | val solver = switch (scopePropagatorStrategy.solver) { | ||
176 | case Z3Integer: | ||
177 | new Z3PolyhedronSolver(false, scopePropagatorStrategy.timeoutSeconds) | ||
178 | case Z3Real: | ||
179 | new Z3PolyhedronSolver(true, scopePropagatorStrategy.timeoutSeconds) | ||
180 | case Cbc: | ||
181 | new CbcPolyhedronSolver(false, scopePropagatorStrategy.timeoutSeconds, true) | ||
182 | case Clp: | ||
183 | new CbcPolyhedronSolver(true, scopePropagatorStrategy.timeoutSeconds, true) | ||
184 | default: | ||
185 | throw new IllegalArgumentException("Unknown polyhedron solver: " + | ||
186 | scopePropagatorStrategy.solver) | ||
187 | } | ||
188 | val strategy = if (extensionOperators.empty) { | ||
189 | new CachingSimplePolyhedronScopePropagatorStrategy(solver, statistics) | ||
190 | } else { | ||
191 | new ExtendedPolyhedronScopePropagatorStrategy(solver, extensionOperators, statistics) | ||
192 | } | ||
193 | new PolyhedronScopePropagator(emptySolution, statistics, types, queries.multiplicityConstraintQueries, | ||
194 | queries.hasElementInContainmentQuery, allPatternsByName, hints, strategy, | ||
195 | scopePropagatorStrategy.requiresUpperBoundIndexing, scopePropagatorStrategy.updateHeuristic) | ||
196 | } | ||
197 | default: | ||
198 | throw new IllegalArgumentException("Unknown scope propagator strategy: " + scopePropagatorStrategy) | ||
199 | } | ||
200 | } | ||
201 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend index 4331420d..4d2fd741 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasoner.xtend | |||
@@ -10,20 +10,28 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | |||
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage | 10 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage |
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicresultFactory | 11 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicresultFactory |
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult | 12 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult |
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethodProvider | ||
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator | 13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ScopePropagator |
14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.PartialInterpretationInitialiser | 15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.PartialInterpretationInitialiser |
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage | 17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage |
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.AbstractNeighbourhoodBasedStateCoderFactory | ||
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.IdentifierBasedStateCoderFactory | 19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.IdentifierBasedStateCoderFactory |
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedStateCoderFactory | 20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedHashStateCoderFactory |
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.PairwiseNeighbourhoodBasedStateCoderFactory | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.BasicScopeGlobalConstraint | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.HillClimbingOnRealisticMetricStrategyForModelGeneration | 23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.HillClimbingOnRealisticMetricStrategyForModelGeneration |
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.InconsistentScopeGlobalConstraint | ||
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.LoggerSolutionFoundHandler | ||
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ModelGenerationCompositeObjective | 26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ModelGenerationCompositeObjective |
27 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.NumericSolver | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PartialModelAsLogicInterpretation | 28 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PartialModelAsLogicInterpretation |
29 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.PunishSizeObjective | ||
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ScopeObjective | 30 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.ScopeObjective |
31 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.SurelyViolatedObjectiveGlobalConstraint | ||
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.UnfinishedMultiplicityObjective | 32 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.UnfinishedMultiplicityObjective |
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.UnfinishedWFObjective | ||
26 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.WF2ObjectiveConverter | 33 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse.WF2ObjectiveConverter |
34 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind | ||
27 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace | 35 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace |
28 | import java.util.List | 36 | import java.util.List |
29 | import java.util.Map | 37 | import java.util.Map |
@@ -34,193 +42,320 @@ import org.eclipse.viatra.dse.api.DesignSpaceExplorer.DseLoggingLevel | |||
34 | import org.eclipse.viatra.dse.solutionstore.SolutionStore | 42 | import org.eclipse.viatra.dse.solutionstore.SolutionStore |
35 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory | 43 | import org.eclipse.viatra.dse.statecode.IStateCoderFactory |
36 | 44 | ||
37 | class ViatraReasoner extends LogicReasoner{ | 45 | class ViatraReasoner extends LogicReasoner { |
38 | val PartialInterpretationInitialiser initialiser = new PartialInterpretationInitialiser() | 46 | val PartialInterpretationInitialiser initialiser = new PartialInterpretationInitialiser() |
39 | val ModelGenerationMethodProvider modelGenerationMethodProvider = new ModelGenerationMethodProvider | 47 | val ModelGenerationMethodProvider modelGenerationMethodProvider = new ModelGenerationMethodProvider |
40 | val extension LogicresultFactory factory = LogicresultFactory.eINSTANCE | 48 | val extension LogicresultFactory factory = LogicresultFactory.eINSTANCE |
41 | val WF2ObjectiveConverter wf2ObjectiveConverter = new WF2ObjectiveConverter | 49 | val WF2ObjectiveConverter wf2ObjectiveConverter = new WF2ObjectiveConverter |
42 | 50 | ||
43 | 51 | override solve(LogicProblem problem, LogicSolverConfiguration configuration, | |
44 | override solve(LogicProblem problem, LogicSolverConfiguration configuration, ReasonerWorkspace workspace) throws LogicReasonerException { | 52 | ReasonerWorkspace workspace) throws LogicReasonerException { |
45 | val viatraConfig = configuration.asConfig | 53 | val viatraConfig = configuration.asConfig |
46 | 54 | ||
47 | if(viatraConfig.debugCongiguration.logging) { | 55 | if (viatraConfig.documentationLevel == DocumentationLevel.FULL) { |
48 | DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.VERBOSE_FULL) | 56 | DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.VERBOSE_FULL) |
49 | } else { | 57 | } else { |
50 | DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.WARN) | 58 | DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.WARN) |
51 | } | 59 | } |
52 | 60 | ||
53 | val DesignSpaceExplorer dse = new DesignSpaceExplorer(); | 61 | val DesignSpaceExplorer dse = new DesignSpaceExplorer(); |
54 | 62 | ||
55 | dse.addMetaModelPackage(LogiclanguagePackage.eINSTANCE) | 63 | dse.addMetaModelPackage(LogiclanguagePackage.eINSTANCE) |
56 | dse.addMetaModelPackage(LogicproblemPackage.eINSTANCE) | 64 | dse.addMetaModelPackage(LogicproblemPackage.eINSTANCE) |
57 | dse.addMetaModelPackage(PartialinterpretationPackage.eINSTANCE) | 65 | dse.addMetaModelPackage(PartialinterpretationPackage.eINSTANCE) |
58 | 66 | ||
59 | val transformationStartTime = System.nanoTime | 67 | val transformationStartTime = System.nanoTime |
60 | 68 | val emptySolution = initialiser.initialisePartialInterpretation(problem, viatraConfig.typeScopes).output | |
61 | 69 | if ((viatraConfig.documentationLevel == DocumentationLevel::FULL || | |
62 | 70 | viatraConfig.documentationLevel == DocumentationLevel::NORMAL) && workspace !== null) { | |
63 | val emptySolution = initialiser.initialisePartialInterpretation(problem,viatraConfig.typeScopes).output | 71 | workspace.writeModel(emptySolution, "init.partialmodel") |
64 | 72 | } | |
65 | if((viatraConfig.documentationLevel == DocumentationLevel::FULL || viatraConfig.documentationLevel == DocumentationLevel::NORMAL) && workspace !== null) { | 73 | |
66 | workspace.writeModel(emptySolution,"init.partialmodel") | ||
67 | } | ||
68 | emptySolution.problemConainer = problem | 74 | emptySolution.problemConainer = problem |
69 | val emptySolutionCopy = EcoreUtil.copy(emptySolution) | 75 | val emptySolutionCopy = EcoreUtil.copy(emptySolution) |
76 | |||
70 | val ScopePropagator scopePropagator = new ScopePropagator(emptySolution) | 77 | val ScopePropagator scopePropagator = new ScopePropagator(emptySolution) |
71 | scopePropagator.propagateAllScopeConstraints | 78 | scopePropagator.propagateAllScopeConstraints |
72 | 79 | ||
80 | var BasicScopeGlobalConstraint basicScopeGlobalConstraint = null | ||
81 | if (viatraConfig.scopePropagatorStrategy == ScopePropagatorStrategy.None) { | ||
82 | basicScopeGlobalConstraint = new BasicScopeGlobalConstraint(emptySolution) | ||
83 | emptySolution.scopes.clear | ||
84 | } | ||
85 | |||
73 | val method = modelGenerationMethodProvider.createModelGenerationMethod( | 86 | val method = modelGenerationMethodProvider.createModelGenerationMethod( |
74 | problem, | 87 | problem, |
75 | emptySolution, | 88 | emptySolution, |
76 | workspace, | 89 | workspace, |
77 | viatraConfig.nameNewElements, | 90 | viatraConfig |
78 | viatraConfig.typeInferenceMethod, | ||
79 | scopePropagator, | ||
80 | viatraConfig.documentationLevel | ||
81 | ) | 91 | ) |
82 | 92 | ||
83 | dse.addObjective(new ModelGenerationCompositeObjective( | 93 | val compositeObjective = new ModelGenerationCompositeObjective( |
84 | new ScopeObjective, | 94 | basicScopeGlobalConstraint ?: new ScopeObjective, |
85 | method.unfinishedMultiplicities.map[new UnfinishedMultiplicityObjective(it)], | 95 | method.unfinishedMultiplicities.map[new UnfinishedMultiplicityObjective(it)], |
86 | new UnfinishedWFObjective(method.unfinishedWF), | 96 | wf2ObjectiveConverter.createCompletenessObjective(method.unfinishedWF), |
87 | viatraConfig.isWFOptional | 97 | viatraConfig |
88 | )) | 98 | ) |
99 | dse.addObjective(compositeObjective) | ||
100 | if (viatraConfig.punishSize != PunishSizeStrategy.NONE) { | ||
101 | val punishSizeStrategy = switch (viatraConfig.punishSize) { | ||
102 | case SMALLER_IS_BETTER: ObjectiveKind.LOWER_IS_BETTER | ||
103 | case LARGER_IS_BETTER: ObjectiveKind.HIGHER_IS_BETTER | ||
104 | default: throw new IllegalArgumentException("Unknown PunishSizeStrategy: " + viatraConfig.punishSize) | ||
105 | } | ||
106 | val punishObjective = new PunishSizeObjective(punishSizeStrategy, compositeObjective.level + 1) | ||
107 | dse.addObjective(punishObjective) | ||
108 | } | ||
89 | 109 | ||
90 | dse.addGlobalConstraint(wf2ObjectiveConverter.createInvalidationObjective(method.invalidWF)) | 110 | for (costObjective : method.costObjectives) { |
91 | for(additionalConstraint : viatraConfig.searchSpaceConstraints.additionalGlobalConstraints) { | 111 | dse.addObjective(costObjective) |
112 | } | ||
113 | val numberOfRequiredSolutions = configuration.solutionScope.numberOfRequiredSolutions | ||
114 | val solutionStore = if (method.optimizationProblem) { | ||
115 | new SolutionStore() | ||
116 | } else { | ||
117 | new SolutionStore(numberOfRequiredSolutions) | ||
118 | } | ||
119 | solutionStore.registerSolutionFoundHandler(new LoggerSolutionFoundHandler(viatraConfig)) | ||
120 | val numericSolver = new NumericSolver(method, viatraConfig.runIntermediateNumericalConsistencyChecks, false) | ||
121 | val solutionSaver = method.solutionSaver | ||
122 | solutionSaver.numericSolver = numericSolver | ||
123 | val solutionCopier = solutionSaver.solutionCopier | ||
124 | val diversityChecker = solutionSaver.diversityChecker | ||
125 | solutionStore.withSolutionSaver(solutionSaver) | ||
126 | dse.solutionStore = solutionStore | ||
127 | |||
128 | dse.addGlobalConstraint(wf2ObjectiveConverter.createInvalidationGlobalConstraint(method.invalidWF)) | ||
129 | dse.addGlobalConstraint(new SurelyViolatedObjectiveGlobalConstraint(solutionSaver)) | ||
130 | dse.addGlobalConstraint(new InconsistentScopeGlobalConstraint) | ||
131 | if (basicScopeGlobalConstraint !== null) { | ||
132 | dse.addGlobalConstraint(basicScopeGlobalConstraint) | ||
133 | } | ||
134 | for (additionalConstraint : viatraConfig.searchSpaceConstraints.additionalGlobalConstraints) { | ||
92 | dse.addGlobalConstraint(additionalConstraint.apply(method)) | 135 | dse.addGlobalConstraint(additionalConstraint.apply(method)) |
93 | } | 136 | } |
94 | 137 | ||
95 | dse.setInitialModel(emptySolution,false) | 138 | dse.setInitialModel(emptySolution, false) |
96 | 139 | ||
97 | val IStateCoderFactory statecoder = if(viatraConfig.stateCoderStrategy == StateCoderStrategy.Neighbourhood) { | 140 | val IStateCoderFactory statecoder = switch (viatraConfig.stateCoderStrategy) { |
98 | new NeighbourhoodBasedStateCoderFactory | 141 | case Neighbourhood: |
99 | } else { | 142 | new NeighbourhoodBasedHashStateCoderFactory |
100 | new IdentifierBasedStateCoderFactory | 143 | case PairwiseNeighbourhood: |
144 | new PairwiseNeighbourhoodBasedStateCoderFactory | ||
145 | default: | ||
146 | new IdentifierBasedStateCoderFactory | ||
101 | } | 147 | } |
102 | dse.stateCoderFactory = statecoder | 148 | dse.stateCoderFactory = statecoder |
103 | 149 | ||
104 | dse.maxNumberOfThreads = 1 | 150 | dse.maxNumberOfThreads = 1 |
105 | 151 | ||
106 | val solutionStore = new SolutionStore(configuration.solutionScope.numberOfRequiredSolution) | 152 | for (rule : method.relationRefinementRules) { |
107 | dse.solutionStore = solutionStore | ||
108 | |||
109 | for(rule : method.relationRefinementRules) { | ||
110 | dse.addTransformationRule(rule) | 153 | dse.addTransformationRule(rule) |
111 | } | 154 | } |
112 | for(rule : method.objectRefinementRules) { | 155 | for (rule : method.objectRefinementRules) { |
113 | dse.addTransformationRule(rule) | 156 | dse.addTransformationRule(rule) |
114 | } | 157 | } |
115 | 158 | ||
116 | val strategy = new HillClimbingOnRealisticMetricStrategyForModelGeneration(workspace,viatraConfig,method) | 159 | val strategy = new HillClimbingOnRealisticMetricStrategyForModelGeneration(workspace,viatraConfig,method) |
117 | viatraConfig.progressMonitor.workedForwardTransformation | 160 | viatraConfig.progressMonitor.workedForwardTransformation |
118 | 161 | val transformationFinished = System.nanoTime | |
119 | val transformationTime = System.nanoTime - transformationStartTime | 162 | val transformationTime = transformationFinished - transformationStartTime |
120 | val solverStartTime = System.nanoTime | 163 | val solverStartTime = System.nanoTime |
121 | 164 | ||
122 | var boolean stoppedByTimeout | 165 | var boolean stoppedByTimeout |
123 | var boolean stoppedByException | 166 | try { |
124 | try{ | 167 | stoppedByTimeout = dse.startExplorationWithTimeout(strategy, configuration.runtimeLimit * 1000); |
125 | stoppedByTimeout = dse.startExplorationWithTimeout(strategy,configuration.runtimeLimit*1000); | ||
126 | stoppedByException = false | ||
127 | } catch (NullPointerException npe) { | 168 | } catch (NullPointerException npe) { |
128 | stoppedByTimeout = false | 169 | stoppedByTimeout = false |
129 | stoppedByException = true | ||
130 | } | 170 | } |
131 | val solverTime = System.nanoTime - solverStartTime | 171 | val solverTime = System.nanoTime - solverStartTime |
132 | viatraConfig.progressMonitor.workedSearchFinished | 172 | viatraConfig.progressMonitor.workedSearchFinished |
133 | 173 | ||
134 | //find trajectory to each solution | 174 | // additionalMatches = strategy.solutionStoreWithCopy.additionalMatches |
135 | if(viatraConfig.documentationLevel == DocumentationLevel.NONE){ | ||
136 | PartialInterpretationMetric.initPaths(); | ||
137 | //PartialInterpretationMetric.outputTrajectories(emptySolutionCopy, dse.solutions.toList()); | ||
138 | } | ||
139 | |||
140 | //additionalMatches = strategy.solutionStoreWithCopy.additionalMatches | ||
141 | val statistics = createStatistics => [ | 175 | val statistics = createStatistics => [ |
142 | //it.solverTime = viatraConfig.runtimeLimit | 176 | // it.solverTime = viatraConfig.runtimeLimit |
143 | it.solverTime = (solverTime/1000000) as int | 177 | it.solverTime = (solverTime / 1000000) as int |
144 | it.transformationTime = (transformationTime/1000000) as int | 178 | it.transformationTime = (transformationTime / 1000000) as int |
145 | for(x : 0..<strategy.solutionStoreWithCopy.allRuntimes.size) { | 179 | for (pair : solutionCopier.getAllCopierRuntimes(true).indexed) { |
146 | it.entries += createIntStatisticEntry => [ | 180 | it.entries += createIntStatisticEntry => [ |
147 | it.name = '''_Solution«x»FoundAt''' | 181 | it.name = '''Solution«pair.key»FoundAt''' |
148 | it.value = (strategy.solutionStoreWithCopy.allRuntimes.get(x)/1000000) as int | 182 | it.value = (pair.value / 1000000) as int |
149 | ] | 183 | ] |
150 | } | 184 | } |
185 | for (x : 0 ..< strategy.times.size) { | ||
186 | it.entries += createStringStatisticEntry => [ | ||
187 | it.name = '''Solution«x+1»DetailedStatistics''' | ||
188 | it.value = strategy.times.get(x) | ||
189 | ] | ||
190 | } | ||
191 | it.entries += createIntStatisticEntry => [ | ||
192 | it.name = "ExplorationInitializationTime" | ||
193 | it.value = ((strategy.explorationStarted - transformationFinished) / 1000000) as int | ||
194 | ] | ||
195 | it.entries += createIntStatisticEntry => [ | ||
196 | it.name = "TransformationExecutionTime" | ||
197 | it.value = (method.statistics.transformationExecutionTime / 1000000) as int | ||
198 | ] | ||
199 | it.entries += createIntStatisticEntry => [ | ||
200 | it.name = "ScopePropagationTime" | ||
201 | it.value = (method.statistics.scopePropagationTime / 1000000) as int | ||
202 | ] | ||
203 | it.entries += createIntStatisticEntry => [ | ||
204 | it.name = "MustRelationPropagationTime" | ||
205 | it.value = (method.statistics.mustRelationPropagationTime / 1000000) as int | ||
206 | ] | ||
207 | it.entries += createIntStatisticEntry => [ | ||
208 | it.name = "TypeAnalysisTime" | ||
209 | it.value = (method.statistics.preliminaryTypeAnalisisTime / 1000000) as int | ||
210 | ] | ||
211 | it.entries += createIntStatisticEntry => [ | ||
212 | it.name = "StateCoderTime" | ||
213 | it.value = (statecoder.runtime / 1000000) as int | ||
214 | ] | ||
215 | it.entries += createIntStatisticEntry => [ | ||
216 | it.name = "StateCoderFailCount" | ||
217 | it.value = strategy.numberOfStatecoderFail | ||
218 | ] | ||
151 | it.entries += createIntStatisticEntry => [ | 219 | it.entries += createIntStatisticEntry => [ |
152 | it.name = "TransformationExecutionTime" it.value = (method.statistics.transformationExecutionTime/1000000) as int | 220 | it.name = "SolutionCopyTime" |
221 | it.value = (solutionCopier.getTotalCopierRuntime / 1000000) as int | ||
153 | ] | 222 | ] |
154 | it.entries += createIntStatisticEntry => [ | 223 | it.entries += createIntStatisticEntry => [ |
155 | it.name = "TypeAnalysisTime" it.value = (method.statistics.PreliminaryTypeAnalisisTime/1000000) as int | 224 | it.name = "States" |
225 | it.value = dse.numberOfStates as int | ||
226 | ] | ||
227 | it.entries += createIntStatisticEntry => [ | ||
228 | it.name = "ForwardTime" | ||
229 | it.value = (strategy.forwardTime / 1000000) as int | ||
230 | ] | ||
231 | it.entries += createIntStatisticEntry => [ | ||
232 | it.name = "BacktrackingTime" | ||
233 | it.value = (strategy.backtrackingTime / 1000000) as int | ||
234 | ] | ||
235 | it.entries += createIntStatisticEntry => [ | ||
236 | it.name = "GlobalConstraintEvaluationTime" | ||
237 | it.value = (strategy.globalConstraintEvaluationTime / 1000000) as int | ||
238 | ] | ||
239 | it.entries += createIntStatisticEntry => [ | ||
240 | it.name = "FitnessCalculationTime" | ||
241 | it.value = (strategy.fitnessCalculationTime / 1000000) as int | ||
242 | ] | ||
243 | it.entries += createIntStatisticEntry => [ | ||
244 | it.name = "SolutionCopyTime" | ||
245 | it.value = (solutionSaver.totalCopierRuntime / 1000000) as int | ||
246 | ] | ||
247 | it.entries += createIntStatisticEntry => [ | ||
248 | it.name = "ActivationSelectionTime" | ||
249 | it.value = (strategy.activationSelector.runtime / 1000000) as int | ||
250 | ] | ||
251 | it.entries += createIntStatisticEntry => [ | ||
252 | it.name = "Decisions" | ||
253 | it.value = method.statistics.decisionsTried | ||
156 | ] | 254 | ] |
157 | it.entries += createIntStatisticEntry =>[ | 255 | it.entries += createIntStatisticEntry =>[ |
158 | it.name = "MetricCalculationTime" it.value = (method.statistics.metricCalculationTime/1000000) as int | 256 | it.name = "MetricCalculationTime" it.value = (method.statistics.metricCalculationTime/1000000) as int |
159 | ] | 257 | ] |
160 | it.entries += createIntStatisticEntry => [ | 258 | it.entries += createIntStatisticEntry => [ |
161 | it.name = "StateCoderTime" it.value = (statecoder.runtime/1000000) as int | 259 | it.name = "Transformations" |
260 | it.value = method.statistics.transformationInvocations | ||
162 | ] | 261 | ] |
163 | it.entries += createIntStatisticEntry => [ | 262 | it.entries += createIntStatisticEntry => [ |
164 | it.name = "StateCoderFailCount" it.value = strategy.numberOfStatecoderFail | 263 | it.name = "ScopePropagations" |
264 | it.value = method.statistics.scopePropagatorInvocations | ||
165 | ] | 265 | ] |
166 | it.entries += createIntStatisticEntry => [ | 266 | it.entries += createIntStatisticEntry => [ |
167 | it.name = "SolutionCopyTime" it.value = (strategy.solutionStoreWithCopy.sumRuntime/1000000) as int | 267 | it.name = "ScopePropagationsSolverCalls" |
268 | it.value = method.statistics.scopePropagatorSolverInvocations | ||
168 | ] | 269 | ] |
169 | if(strategy.solutionStoreWithDiversityDescriptor.isActive) { | 270 | // it.entries += createIntStatisticEntry => [ |
271 | // it.name = "NumericalSolverSumTime" | ||
272 | // it.value = (strategy.numericSolver.runtime / 1000000) as int | ||
273 | // ] | ||
274 | // it.entries += createIntStatisticEntry => [ | ||
275 | // it.name = "NumericalSolverProblemFormingTime" | ||
276 | // it.value = (strategy.numericSolver.solverFormingProblem / 1000000) as int | ||
277 | // ] | ||
278 | // it.entries += createIntStatisticEntry => [ | ||
279 | // it.name = "NumericalSolverSolvingTime" | ||
280 | // it.value = (strategy.numericSolver.solverSolvingProblem / 1000000) as int | ||
281 | // ] | ||
282 | // it.entries += createIntStatisticEntry => [ | ||
283 | // it.name = "NumericalSolverInterpretingSolution" | ||
284 | // it.value = (strategy.numericSolver.solverSolution / 1000000) as int | ||
285 | // ] | ||
286 | // it.entries += createIntStatisticEntry => [ | ||
287 | // it.name = "NumericalSolverCachingTime" | ||
288 | // it.value = (strategy.numericSolver.cachingTime / 1000000) as int | ||
289 | // ] | ||
290 | // it.entries += createIntStatisticEntry => [ | ||
291 | // it.name = "NumericalSolverCallNumber" | ||
292 | // it.value = strategy.numericSolver.numberOfSolverCalls | ||
293 | // ] | ||
294 | // it.entries += createIntStatisticEntry => [ | ||
295 | // it.name = "NumericalSolverCachedAnswerNumber" | ||
296 | // it.value = strategy.numericSolver.numberOfCachedSolverCalls | ||
297 | // ] | ||
298 | if (diversityChecker.active) { | ||
170 | it.entries += createIntStatisticEntry => [ | 299 | it.entries += createIntStatisticEntry => [ |
171 | it.name = "SolutionDiversityCheckTime" it.value = (strategy.solutionStoreWithDiversityDescriptor.sumRuntime/1000000) as int | 300 | it.name = "SolutionDiversityCheckTime" |
301 | it.value = (diversityChecker.totalRuntime / 1000000) as int | ||
172 | ] | 302 | ] |
173 | it.entries += createRealStatisticEntry => [ | 303 | it.entries += createRealStatisticEntry => [ |
174 | it.name = "SolutionDiversitySuccessRate" it.value = strategy.solutionStoreWithDiversityDescriptor.successRate | 304 | it.name = "SolutionDiversitySuccessRate" |
305 | it.value = diversityChecker.successRate | ||
175 | ] | 306 | ] |
176 | } | 307 | } |
177 | ] | 308 | ] |
178 | 309 | ||
179 | viatraConfig.progressMonitor.workedBackwardTransformationFinished | 310 | viatraConfig.progressMonitor.workedBackwardTransformationFinished |
180 | 311 | ||
181 | if(stoppedByTimeout) { | 312 | if (stoppedByTimeout) { |
182 | return createInsuficientResourcesResult=>[ | 313 | return createInsuficientResourcesResult => [ |
183 | it.problem = problem | 314 | it.problem = problem |
184 | it.resourceName="time" | 315 | it.resourceName = "time" |
185 | it.representation += strategy.solutionStoreWithCopy.solutions | 316 | it.representation += solutionCopier.getPartialInterpretations(true) |
186 | it.statistics = statistics | 317 | it.statistics = statistics |
187 | ] | 318 | ] |
188 | } else { | 319 | } else { |
189 | if(solutionStore.solutions.empty) { | 320 | if (solutionStore.solutions.empty) { |
190 | return createInconsistencyResult => [ | 321 | return createInconsistencyResult => [ |
191 | it.problem = problem | 322 | it.problem = problem |
192 | it.representation += strategy.solutionStoreWithCopy.solutions | 323 | it.representation += solutionCopier.getPartialInterpretations(true) |
193 | it.statistics = statistics | 324 | it.statistics = statistics |
194 | ] | 325 | ] |
195 | } else { | 326 | } else { |
196 | return createModelResult => [ | 327 | return createModelResult => [ |
197 | it.problem = problem | 328 | it.problem = problem |
198 | it.trace = strategy.solutionStoreWithCopy.copyTraces | 329 | it.trace = solutionCopier.getTraces(true) |
199 | it.representation += strategy.solutionStoreWithCopy.solutions | 330 | it.representation += solutionCopier.getPartialInterpretations(true) |
200 | it.statistics = statistics | 331 | it.statistics = statistics |
201 | ] | 332 | ] |
202 | } | 333 | } |
203 | } | 334 | } |
204 | } | 335 | } |
205 | 336 | ||
206 | private def dispatch long runtime(NeighbourhoodBasedStateCoderFactory sc) { | 337 | private def dispatch long runtime(AbstractNeighbourhoodBasedStateCoderFactory sc) { |
207 | sc.sumStatecoderRuntime | 338 | sc.sumStatecoderRuntime |
208 | } | 339 | } |
209 | 340 | ||
210 | private def dispatch long runtime(IdentifierBasedStateCoderFactory sc) { | 341 | private def dispatch long runtime(IdentifierBasedStateCoderFactory sc) { |
211 | sc.sumStatecoderRuntime | 342 | sc.sumStatecoderRuntime |
212 | } | 343 | } |
213 | 344 | ||
214 | override getInterpretations(ModelResult modelResult) { | 345 | override getInterpretations(ModelResult modelResult) { |
215 | val indexes = 0..<modelResult.representation.size | 346 | val indexes = 0 ..< modelResult.representation.size |
216 | val traces = modelResult.trace as List<Map<EObject, EObject>>; | 347 | val traces = modelResult.trace as List<Map<EObject, EObject>>; |
217 | val res = indexes.map[i | new PartialModelAsLogicInterpretation(modelResult.representation.get(i) as PartialInterpretation,traces.get(i))].toList | 348 | val res = indexes.map [ i | |
349 | new PartialModelAsLogicInterpretation(modelResult.representation.get(i) as PartialInterpretation, | ||
350 | traces.get(i)) | ||
351 | ].toList | ||
218 | return res | 352 | return res |
219 | } | 353 | } |
220 | 354 | ||
221 | private def ViatraReasonerConfiguration asConfig(LogicSolverConfiguration configuration) { | 355 | private def ViatraReasonerConfiguration asConfig(LogicSolverConfiguration configuration) { |
222 | if(configuration instanceof ViatraReasonerConfiguration) { | 356 | if (configuration instanceof ViatraReasonerConfiguration) { |
223 | return configuration | 357 | return configuration |
224 | } else throw new IllegalArgumentException('''Wrong configuration. Expected: «ViatraReasonerConfiguration.name», but got: «configuration.class.name»"''') | 358 | } else |
359 | throw new IllegalArgumentException('''Wrong configuration. Expected: «ViatraReasonerConfiguration.name», but got: «configuration.class.name»"''') | ||
225 | } | 360 | } |
226 | } | 361 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend index 10734859..628844de 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/ViatraReasonerConfiguration.xtend | |||
@@ -5,21 +5,37 @@ import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasoner | |||
5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicSolverConfiguration | 5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicSolverConfiguration |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDeclaration |
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration | 7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration |
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod | 8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.TypeInferenceMethod |
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorConstraints | ||
11 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedralScopePropagatorSolver | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ScopePropagatorStrategy | ||
13 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.UnitPropagationPatternGenerator | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser | 14 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser |
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.CostObjectiveHint | ||
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind | ||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold | ||
11 | import java.util.LinkedList | 18 | import java.util.LinkedList |
12 | import java.util.List | 19 | import java.util.List |
13 | import java.util.Set | 20 | import java.util.Set |
14 | import org.eclipse.xtext.xbase.lib.Functions.Function1 | 21 | import org.eclipse.xtext.xbase.lib.Functions.Function1 |
15 | 22 | ||
16 | public enum StateCoderStrategy { | 23 | enum StateCoderStrategy { |
17 | Neighbourhood, NeighbourhoodWithEquivalence, IDBased, DefinedByDiversity | 24 | Neighbourhood, |
25 | PairwiseNeighbourhood, | ||
26 | NeighbourhoodWithEquivalence, | ||
27 | IDBased, | ||
28 | DefinedByDiversity | ||
18 | } | 29 | } |
19 | 30 | ||
20 | class ViatraReasonerConfiguration extends LogicSolverConfiguration{ | 31 | enum PunishSizeStrategy { |
21 | //public var Iterable<PQuery> existingQueries | 32 | NONE, |
22 | 33 | SMALLER_IS_BETTER, | |
34 | LARGER_IS_BETTER | ||
35 | } | ||
36 | |||
37 | class ViatraReasonerConfiguration extends LogicSolverConfiguration { | ||
38 | // public var Iterable<PQuery> existingQueries | ||
23 | public var nameNewElements = false | 39 | public var nameNewElements = false |
24 | public var StateCoderStrategy stateCoderStrategy = StateCoderStrategy.Neighbourhood | 40 | public var StateCoderStrategy stateCoderStrategy = StateCoderStrategy.Neighbourhood |
25 | public var TypeInferenceMethod typeInferenceMethod = TypeInferenceMethod.PreliminaryAnalysis | 41 | public var TypeInferenceMethod typeInferenceMethod = TypeInferenceMethod.PreliminaryAnalysis |
@@ -27,7 +43,7 @@ class ViatraReasonerConfiguration extends LogicSolverConfiguration{ | |||
27 | * Once per 1/randomBacktrackChance the search selects a random state. | 43 | * Once per 1/randomBacktrackChance the search selects a random state. |
28 | */ | 44 | */ |
29 | public var int randomBacktrackChance = 20; | 45 | public var int randomBacktrackChance = 20; |
30 | 46 | ||
31 | /** | 47 | /** |
32 | * Describes the required diversity between the solutions. | 48 | * Describes the required diversity between the solutions. |
33 | * Null means that the solutions have to have different state codes only. | 49 | * Null means that the solutions have to have different state codes only. |
@@ -41,22 +57,40 @@ class ViatraReasonerConfiguration extends LogicSolverConfiguration{ | |||
41 | /** | 57 | /** |
42 | * Configuration for debugging support. | 58 | * Configuration for debugging support. |
43 | */ | 59 | */ |
44 | public var DebugConfiguration debugCongiguration = new DebugConfiguration | 60 | public var DebugConfiguration debugConfiguration = new DebugConfiguration |
45 | /** | 61 | /** |
46 | * Configuration for cutting search space. | 62 | * Configuration for cutting search space. |
47 | */ | 63 | */ |
48 | public var SearchSpaceConstraint searchSpaceConstraints = new SearchSpaceConstraint | 64 | public var SearchSpaceConstraint searchSpaceConstraints = new SearchSpaceConstraint |
49 | 65 | ||
50 | public var RealisticGuidance realisticGuidance = RealisticGuidance.Composite; | 66 | public var runIntermediateNumericalConsistencyChecks = true |
67 | |||
68 | public var punishSize = PunishSizeStrategy.NONE | ||
69 | public var scopeWeight = 1 | ||
70 | public var conaintmentWeight = 2 | ||
71 | public var nonContainmentWeight = 1 | ||
72 | public var unfinishedWFWeight = 1 | ||
73 | public var calculateObjectCreationCosts = false | ||
74 | |||
75 | public var RealisticGuidance realisticGuidance = RealisticGuidance.Composite; | ||
51 | 76 | ||
52 | public var isWFOptional = false; | 77 | public var isWFOptional = false; |
53 | 78 | ||
54 | public var allowMustViolations = false; | 79 | public var allowMustViolations = false; |
55 | 80 | ||
56 | public var String domain = ''; | 81 | public var String domain = ''; |
82 | public var ScopePropagatorStrategy scopePropagatorStrategy = new ScopePropagatorStrategy.Polyhedral( | ||
83 | PolyhedralScopePropagatorConstraints.Relational, PolyhedralScopePropagatorSolver.Clp) | ||
84 | // public var ScopePropagatorStrategy scopePropagatorStrategy = ScopePropagatorStrategy.BasicTypeHierarchy | ||
85 | |||
86 | public var List<LinearTypeConstraintHint> hints = newArrayList | ||
87 | |||
88 | public var List<CostObjectiveConfiguration> costObjectives = newArrayList | ||
89 | |||
90 | public var List<UnitPropagationPatternGenerator> unitPropagationPatternGenerators = newArrayList | ||
57 | } | 91 | } |
58 | 92 | ||
59 | public class DiversityDescriptor { | 93 | class DiversityDescriptor { |
60 | public var ensureDiversity = false | 94 | public var ensureDiversity = false |
61 | public static val FixPointRange = -1 | 95 | public static val FixPointRange = -1 |
62 | public var int range = FixPointRange | 96 | public var int range = FixPointRange |
@@ -66,6 +100,23 @@ public class DiversityDescriptor { | |||
66 | public var Set<RelationDeclaration> relevantRelations = null | 100 | public var Set<RelationDeclaration> relevantRelations = null |
67 | } | 101 | } |
68 | 102 | ||
103 | class DebugConfiguration { | ||
104 | public var PartialInterpretationVisualiser partialInterpretatioVisualiser = null | ||
105 | public var partalInterpretationVisualisationFrequency = 1 | ||
106 | } | ||
107 | |||
108 | class InternalConsistencyCheckerConfiguration { | ||
109 | public var LogicReasoner internalIncosnsitencyDetector = null | ||
110 | public var LogicSolverConfiguration internalInconsistencDetectorConfiguration = null | ||
111 | public var incternalConsistencyCheckingFrequency = 1 | ||
112 | } | ||
113 | |||
114 | class SearchSpaceConstraint { | ||
115 | public static val UNLIMITED_MAXDEPTH = Integer.MAX_VALUE | ||
116 | public var int maxDepth = UNLIMITED_MAXDEPTH | ||
117 | public var List<Function1<ModelGenerationMethod, ModelGenerationMethodBasedGlobalConstraint>> additionalGlobalConstraints = new LinkedList | ||
118 | } | ||
119 | |||
69 | public enum RealisticGuidance{ | 120 | public enum RealisticGuidance{ |
70 | MPC, | 121 | MPC, |
71 | NodeActivity, | 122 | NodeActivity, |
@@ -75,21 +126,16 @@ public enum RealisticGuidance{ | |||
75 | Composite_Without_Violations, | 126 | Composite_Without_Violations, |
76 | Violations | 127 | Violations |
77 | } | 128 | } |
78 | 129 | class CostObjectiveConfiguration { | |
79 | public class DebugConfiguration { | 130 | public var List<CostObjectiveElementConfiguration> elements = newArrayList |
80 | public var logging = false | 131 | public var ObjectiveKind kind |
81 | public var PartialInterpretationVisualiser partialInterpretatioVisualiser = null; | 132 | public var ObjectiveThreshold threshold |
82 | public var partalInterpretationVisualisationFrequency = 1 | 133 | public var boolean findExtremum |
134 | public var CostObjectiveHint hint | ||
83 | } | 135 | } |
84 | 136 | ||
85 | public class InternalConsistencyCheckerConfiguration { | 137 | class CostObjectiveElementConfiguration { |
86 | public var LogicReasoner internalIncosnsitencyDetector = null | 138 | public var String patternQualifiedName |
87 | public var LogicSolverConfiguration internalInconsistencDetectorConfiguration = null | 139 | public var int weight |
88 | public var incternalConsistencyCheckingFrequency = 1 | ||
89 | } | 140 | } |
90 | 141 | ||
91 | public class SearchSpaceConstraint { | ||
92 | public static val UNLIMITED_MAXDEPTH = Integer.MAX_VALUE | ||
93 | public var int maxDepth = UNLIMITED_MAXDEPTH | ||
94 | public var List<Function1<ModelGenerationMethod, ModelGenerationMethodBasedGlobalConstraint>> additionalGlobalConstraints = new LinkedList | ||
95 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ActivationSelector.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ActivationSelector.xtend new file mode 100644 index 00000000..65f9814c --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ActivationSelector.xtend | |||
@@ -0,0 +1,24 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import java.util.ArrayList | ||
4 | import java.util.Collection | ||
5 | import java.util.Random | ||
6 | |||
7 | abstract class ActivationSelector { | ||
8 | long runtime = 0 | ||
9 | protected val Random r | ||
10 | new(Random r) { | ||
11 | this.r = r | ||
12 | } | ||
13 | |||
14 | def randomizeActivationIDs(Collection<Object> activationIDs) { | ||
15 | val startTime = System.nanoTime | ||
16 | val res = internalRandomizationOfActivationIDs(activationIDs) | ||
17 | runtime+= System.nanoTime-startTime | ||
18 | return res | ||
19 | } | ||
20 | def protected ArrayList<Object> internalRandomizationOfActivationIDs(Collection<Object> activationIDs); | ||
21 | def getRuntime(){ | ||
22 | return runtime | ||
23 | } | ||
24 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BalancedActivationSelector.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BalancedActivationSelector.xtend new file mode 100644 index 00000000..2df9957b --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BalancedActivationSelector.xtend | |||
@@ -0,0 +1,51 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import java.util.Collection | ||
4 | import java.util.HashMap | ||
5 | import java.util.Map | ||
6 | import java.util.List | ||
7 | import java.util.Random | ||
8 | import java.util.ArrayList | ||
9 | import java.util.LinkedList | ||
10 | import java.util.Collections | ||
11 | |||
12 | class BalancedActivationSelector extends ActivationSelector{ | ||
13 | val Random r = new Random | ||
14 | |||
15 | new(Random r) { | ||
16 | super(r) | ||
17 | } | ||
18 | |||
19 | override protected internalRandomizationOfActivationIDs(Collection<Object> activationIDs) { | ||
20 | val Map<String,List<Object>> urns = new HashMap | ||
21 | val res = new ArrayList(activationIDs.size) | ||
22 | for(activationID : activationIDs) { | ||
23 | val pair = activationID as Pair<String,? extends Object> | ||
24 | val name = pair.key | ||
25 | val selectedUrn = urns.get(name) | ||
26 | if(selectedUrn!==null) { | ||
27 | selectedUrn.add(activationID) | ||
28 | } else { | ||
29 | val collection = new LinkedList | ||
30 | collection.add(activationID) | ||
31 | urns.put(name,collection) | ||
32 | } | ||
33 | } | ||
34 | |||
35 | for(list:urns.values) { | ||
36 | Collections.shuffle(list,r) | ||
37 | } | ||
38 | |||
39 | while(!urns.empty) { | ||
40 | val randomEntry = urns.entrySet.get(r.nextInt(urns.size)) | ||
41 | val list = randomEntry.value | ||
42 | val removedLast = list.remove(list.size-1) | ||
43 | res.add(removedLast) | ||
44 | if(list.empty) { | ||
45 | urns.remove(randomEntry.key) | ||
46 | } | ||
47 | } | ||
48 | return res | ||
49 | } | ||
50 | |||
51 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BasicScopeGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BasicScopeGlobalConstraint.xtend new file mode 100644 index 00000000..67f447ed --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BasicScopeGlobalConstraint.xtend | |||
@@ -0,0 +1,103 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialTypeInterpratation | ||
6 | import java.util.Comparator | ||
7 | import java.util.List | ||
8 | import org.eclipse.viatra.dse.base.ThreadContext | ||
9 | import org.eclipse.viatra.dse.objectives.Comparators | ||
10 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint | ||
11 | import org.eclipse.viatra.dse.objectives.IObjective | ||
12 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
13 | |||
14 | class BasicScopeGlobalConstraint implements IGlobalConstraint, IObjective { | ||
15 | val PartialInterpretation p | ||
16 | val List<ScopeAssertion> assertions | ||
17 | |||
18 | new(PartialInterpretation p) { | ||
19 | this.p = p | ||
20 | assertions = ImmutableList.copyOf(p.scopes.map [ | ||
21 | val currentSize = targetTypeInterpretation.elements.size | ||
22 | val minElements = minNewElements + currentSize | ||
23 | val maxElements = if (maxNewElements < 0) { | ||
24 | -1 | ||
25 | } else { | ||
26 | maxNewElements + currentSize | ||
27 | } | ||
28 | new ScopeAssertion(minElements, maxElements, targetTypeInterpretation) | ||
29 | ]) | ||
30 | } | ||
31 | |||
32 | override init(ThreadContext context) { | ||
33 | if (context.model != p) { | ||
34 | throw new IllegalArgumentException( | ||
35 | "Partial model must be passed to the constructor of BasicScopeGlobalConstraint") | ||
36 | } | ||
37 | } | ||
38 | |||
39 | override checkGlobalConstraint(ThreadContext context) { | ||
40 | assertions.forall[upperBoundSatisfied] | ||
41 | } | ||
42 | |||
43 | override getFitness(ThreadContext context) { | ||
44 | var double fitness = p.minNewElements | ||
45 | for (assertion : assertions) { | ||
46 | if (!assertion.lowerBoundSatisfied) { | ||
47 | fitness += 1 | ||
48 | } | ||
49 | } | ||
50 | fitness | ||
51 | } | ||
52 | |||
53 | override satisifiesHardObjective(Double fitness) { | ||
54 | fitness <= 0.01 | ||
55 | } | ||
56 | |||
57 | override BasicScopeGlobalConstraint createNew() { | ||
58 | this | ||
59 | } | ||
60 | |||
61 | override getName() { | ||
62 | class.name | ||
63 | } | ||
64 | |||
65 | override getComparator() { | ||
66 | Comparators.LOWER_IS_BETTER | ||
67 | } | ||
68 | |||
69 | override getLevel() { | ||
70 | 2 | ||
71 | } | ||
72 | |||
73 | override isHardObjective() { | ||
74 | true | ||
75 | } | ||
76 | |||
77 | override setComparator(Comparator<Double> comparator) { | ||
78 | throw new UnsupportedOperationException | ||
79 | } | ||
80 | |||
81 | override setLevel(int level) { | ||
82 | throw new UnsupportedOperationException | ||
83 | } | ||
84 | |||
85 | @FinalFieldsConstructor | ||
86 | private static class ScopeAssertion { | ||
87 | val int lowerBound | ||
88 | val int upperBound | ||
89 | val PartialTypeInterpratation typeDefinitions | ||
90 | |||
91 | private def getCount() { | ||
92 | typeDefinitions.elements.size | ||
93 | } | ||
94 | |||
95 | private def isLowerBoundSatisfied() { | ||
96 | count >= lowerBound | ||
97 | } | ||
98 | |||
99 | private def isUpperBoundSatisfied() { | ||
100 | upperBound < 0 || count <= upperBound | ||
101 | } | ||
102 | } | ||
103 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java index d9a1e54c..2940d12d 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/BestFirstStrategyForModelGeneration.java | |||
@@ -9,9 +9,7 @@ | |||
9 | *******************************************************************************/ | 9 | *******************************************************************************/ |
10 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse; | 10 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse; |
11 | 11 | ||
12 | import java.util.ArrayList; | ||
13 | import java.util.Arrays; | 12 | import java.util.Arrays; |
14 | import java.util.Collection; | ||
15 | import java.util.Collections; | 13 | import java.util.Collections; |
16 | import java.util.Comparator; | 14 | import java.util.Comparator; |
17 | import java.util.Iterator; | 15 | import java.util.Iterator; |
@@ -22,17 +20,16 @@ import java.util.Random; | |||
22 | 20 | ||
23 | import org.apache.log4j.Level; | 21 | import org.apache.log4j.Level; |
24 | import org.apache.log4j.Logger; | 22 | import org.apache.log4j.Logger; |
23 | import org.eclipse.emf.ecore.EObject; | ||
25 | import org.eclipse.emf.ecore.util.EcoreUtil; | 24 | import org.eclipse.emf.ecore.util.EcoreUtil; |
25 | import org.eclipse.viatra.dse.api.SolutionTrajectory; | ||
26 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | 26 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; |
27 | import org.eclipse.viatra.dse.base.ThreadContext; | 27 | import org.eclipse.viatra.dse.base.ThreadContext; |
28 | import org.eclipse.viatra.dse.objectives.Fitness; | 28 | import org.eclipse.viatra.dse.objectives.Fitness; |
29 | import org.eclipse.viatra.dse.objectives.IObjective; | 29 | import org.eclipse.viatra.dse.objectives.IObjective; |
30 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; | 30 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper; |
31 | import org.eclipse.viatra.dse.solutionstore.ISolutionFoundHandler; | ||
31 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; | 32 | import org.eclipse.viatra.dse.solutionstore.SolutionStore; |
32 | import org.eclipse.viatra.query.runtime.api.IPatternMatch; | ||
33 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | ||
34 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine; | ||
35 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher; | ||
36 | 33 | ||
37 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel; | 34 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel; |
38 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasoner; | 35 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicReasoner; |
@@ -40,11 +37,11 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem; | |||
40 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.InconsistencyResult; | 37 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.InconsistencyResult; |
41 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicResult; | 38 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicResult; |
42 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult; | 39 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult; |
43 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod; | ||
44 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.PartialInterpretation2Logic; | 40 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.PartialInterpretation2Logic; |
45 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation; | 41 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation; |
46 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualisation; | 42 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualisation; |
47 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser; | 43 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser; |
44 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ModelGenerationMethod; | ||
48 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration; | 45 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration; |
49 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace; | 46 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace; |
50 | 47 | ||
@@ -77,54 +74,72 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
77 | // Running | 74 | // Running |
78 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; | 75 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; |
79 | private SolutionStore solutionStore; | 76 | private SolutionStore solutionStore; |
80 | private SolutionStoreWithCopy solutionStoreWithCopy; | ||
81 | private SolutionStoreWithDiversityDescriptor solutionStoreWithDiversityDescriptor; | ||
82 | private volatile boolean isInterrupted = false; | 77 | private volatile boolean isInterrupted = false; |
83 | private ModelResult modelResultByInternalSolver = null; | 78 | private ModelResult modelResultByInternalSolver = null; |
84 | private Random random = new Random(); | 79 | private Random random = new Random(); |
85 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> matchers; | 80 | // private Collection<ViatraQueryMatcher<? extends IPatternMatch>> matchers; |
86 | 81 | public ActivationSelector activationSelector = new EvenActivationSelector(random); | |
82 | public ViatraReasonerSolutionSaver solutionSaver; | ||
83 | public NumericSolver numericSolver; | ||
87 | // Statistics | 84 | // Statistics |
88 | private int numberOfStatecoderFail = 0; | 85 | private int numberOfStatecoderFail = 0; |
89 | private int numberOfPrintedModel = 0; | 86 | private int numberOfPrintedModel = 0; |
90 | private int numberOfSolverCalls = 0; | 87 | private int numberOfSolverCalls = 0; |
88 | public long globalConstraintEvaluationTime = 0; | ||
89 | public long fitnessCalculationTime = 0; | ||
90 | |||
91 | public long explorationStarted = 0; | ||
91 | 92 | ||
92 | public BestFirstStrategyForModelGeneration( | 93 | public BestFirstStrategyForModelGeneration( |
93 | ReasonerWorkspace workspace, | 94 | ReasonerWorkspace workspace, |
94 | ViatraReasonerConfiguration configuration, | 95 | ViatraReasonerConfiguration configuration, |
95 | ModelGenerationMethod method) | 96 | ModelGenerationMethod method, |
96 | { | 97 | ViatraReasonerSolutionSaver solutionSaver, |
98 | NumericSolver numericSolver) { | ||
97 | this.workspace = workspace; | 99 | this.workspace = workspace; |
98 | this.configuration = configuration; | 100 | this.configuration = configuration; |
99 | this.method = method; | 101 | this.method = method; |
102 | this.solutionSaver = solutionSaver; | ||
103 | this.numericSolver = numericSolver; | ||
104 | // logger.setLevel(Level.DEBUG); | ||
100 | } | 105 | } |
101 | 106 | ||
102 | public SolutionStoreWithCopy getSolutionStoreWithCopy() { | ||
103 | return solutionStoreWithCopy; | ||
104 | } | ||
105 | public SolutionStoreWithDiversityDescriptor getSolutionStoreWithDiversityDescriptor() { | ||
106 | return solutionStoreWithDiversityDescriptor; | ||
107 | } | ||
108 | public int getNumberOfStatecoderFail() { | 107 | public int getNumberOfStatecoderFail() { |
109 | return numberOfStatecoderFail; | 108 | return numberOfStatecoderFail; |
110 | } | 109 | } |
110 | public long getForwardTime() { | ||
111 | return context.getDesignSpaceManager().getForwardTime(); | ||
112 | } | ||
113 | public long getBacktrackingTime() { | ||
114 | return context.getDesignSpaceManager().getBacktrackingTime(); | ||
115 | } | ||
111 | 116 | ||
112 | @Override | 117 | @Override |
113 | public void initStrategy(ThreadContext context) { | 118 | public void initStrategy(ThreadContext context) { |
114 | this.context = context; | 119 | this.context = context; |
115 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | 120 | this.solutionStore = context.getGlobalContext().getSolutionStore(); |
116 | ViatraQueryEngine engine = context.getQueryEngine(); | 121 | solutionStore.registerSolutionFoundHandler(new ISolutionFoundHandler() { |
117 | // // TODO: visualisation | 122 | |
118 | matchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | 123 | @Override |
119 | for(IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> p : this.method.getAllPatterns()) { | 124 | public void solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { |
120 | //System.out.println(p.getSimpleName()); | 125 | // Ignore. |
121 | ViatraQueryMatcher<? extends IPatternMatch> matcher = p.getMatcher(engine); | 126 | } |
122 | matchers.add(matcher); | 127 | |
123 | } | 128 | @Override |
129 | public void solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
130 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolutions); | ||
131 | saveTimes(); | ||
132 | logger.debug("Found a solution."); | ||
133 | } | ||
134 | }); | ||
135 | numericSolver.init(context); | ||
124 | 136 | ||
125 | this.solutionStoreWithCopy = new SolutionStoreWithCopy(); | 137 | // ViatraQueryEngine engine = context.getQueryEngine(); |
126 | this.solutionStoreWithDiversityDescriptor = new SolutionStoreWithDiversityDescriptor(configuration.diversityRequirement); | 138 | // matchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); |
127 | 139 | // for(IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> p : this.method.getAllPatterns()) { | |
140 | // ViatraQueryMatcher<? extends IPatternMatch> matcher = p.getMatcher(engine); | ||
141 | // } | ||
142 | // | ||
128 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 143 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
129 | this.comparator = new Comparator<TrajectoryWithFitness>() { | 144 | this.comparator = new Comparator<TrajectoryWithFitness>() { |
130 | @Override | 145 | @Override |
@@ -138,23 +153,26 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
138 | 153 | ||
139 | @Override | 154 | @Override |
140 | public void explore() { | 155 | public void explore() { |
141 | if (!context.checkGlobalConstraints()) { | 156 | this.explorationStarted=System.nanoTime(); |
157 | if (!checkGlobalConstraints()) { | ||
142 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | 158 | logger.info("Global contraint is not satisifed in the first state. Terminate."); |
143 | return; | 159 | return; |
160 | } else if(!numericSolver.maySatisfiable()) { | ||
161 | logger.info("Numeric contraints are not satisifed in the first state. Terminate."); | ||
162 | return; | ||
144 | } | 163 | } |
145 | if (configuration.searchSpaceConstraints.maxDepth == 0) { | 164 | if (configuration.searchSpaceConstraints.maxDepth == 0) { |
146 | logger.info("Maximal depth is reached in the initial solution. Terminate."); | 165 | logger.info("Maximal depth is reached in the initial solution. Terminate."); |
147 | return; | 166 | return; |
148 | } | 167 | } |
149 | 168 | ||
150 | final Fitness firstFittness = context.calculateFitness(); | 169 | final Fitness firstFitness = calculateFitness(); |
151 | checkForSolution(firstFittness); | 170 | checkForSolution(firstFitness); |
152 | 171 | ||
153 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 172 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
154 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); | 173 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); |
155 | TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness); | 174 | TrajectoryWithFitness currentTrajectoryWithFitness = new TrajectoryWithFitness(firstTrajectory, firstFitness); |
156 | trajectoiresToExplore.add(currentTrajectoryWithFittness); | 175 | trajectoiresToExplore.add(currentTrajectoryWithFitness); |
157 | |||
158 | //if(configuration) | 176 | //if(configuration) |
159 | visualiseCurrentState(); | 177 | visualiseCurrentState(); |
160 | // for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { | 178 | // for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { |
@@ -168,22 +186,22 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
168 | 186 | ||
169 | mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) { | 187 | mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) { |
170 | 188 | ||
171 | if (currentTrajectoryWithFittness == null) { | 189 | if (currentTrajectoryWithFitness == null) { |
172 | if (trajectoiresToExplore.isEmpty()) { | 190 | if (trajectoiresToExplore.isEmpty()) { |
173 | logger.debug("State space is fully traversed."); | 191 | logger.debug("State space is fully traversed."); |
174 | return; | 192 | return; |
175 | } else { | 193 | } else { |
176 | currentTrajectoryWithFittness = selectState(); | 194 | currentTrajectoryWithFitness = selectState(); |
177 | if (logger.isDebugEnabled()) { | 195 | if (logger.isDebugEnabled()) { |
178 | logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray())); | 196 | logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray())); |
179 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness); | 197 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFitness); |
180 | } | 198 | } |
181 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory); | 199 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFitness.trajectory); |
182 | } | 200 | } |
183 | } | 201 | } |
184 | 202 | ||
185 | // visualiseCurrentState(); | 203 | // visualiseCurrentState(); |
186 | // boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); | 204 | // boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithfitness); |
187 | // if(consistencyCheckResult == true) { | 205 | // if(consistencyCheckResult == true) { |
188 | // continue mainLoop; | 206 | // continue mainLoop; |
189 | // } | 207 | // } |
@@ -193,32 +211,30 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
193 | 211 | ||
194 | while (!isInterrupted && !configuration.progressMonitor.isCancelled() && iterator.hasNext()) { | 212 | while (!isInterrupted && !configuration.progressMonitor.isCancelled() && iterator.hasNext()) { |
195 | final Object nextActivation = iterator.next(); | 213 | final Object nextActivation = iterator.next(); |
196 | // if (!iterator.hasNext()) { | ||
197 | // logger.debug("Last untraversed activation of the state."); | ||
198 | // trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
199 | // } | ||
200 | logger.debug("Executing new activation: " + nextActivation); | 214 | logger.debug("Executing new activation: " + nextActivation); |
201 | context.executeAcitvationId(nextActivation); | 215 | context.executeAcitvationId(nextActivation); |
216 | method.getStatistics().incrementDecisionCount(); | ||
202 | 217 | ||
203 | visualiseCurrentState(); | 218 | visualiseCurrentState(); |
204 | // for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { | 219 | // for(ViatraQueryMatcher<? extends IPatternMatch> matcher : matchers) { |
205 | // System.out.println(matcher.getPatternName()); | 220 | // int c = matcher.countMatches(); |
206 | // System.out.println("---------"); | 221 | // if(c>=1) { |
207 | // for(IPatternMatch m : matcher.getAllMatches()) { | 222 | // System.out.println(c+ " " +matcher.getPatternName()); |
208 | // System.out.println(m); | 223 | // } |
209 | // } | ||
210 | // System.out.println("---------"); | ||
211 | // } | 224 | // } |
212 | 225 | ||
213 | boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); | 226 | boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFitness); |
214 | if(consistencyCheckResult == true) { continue mainLoop; } | 227 | if(consistencyCheckResult == true) { continue mainLoop; } |
215 | 228 | ||
216 | if (context.isCurrentStateAlreadyTraversed()) { | 229 | if (context.isCurrentStateAlreadyTraversed()) { |
217 | logger.info("The new state is already visited."); | 230 | logger.info("The new state is already visited."); |
218 | context.backtrack(); | 231 | context.backtrack(); |
219 | } else if (!context.checkGlobalConstraints()) { | 232 | } else if (!checkGlobalConstraints()) { |
220 | logger.debug("Global contraint is not satisifed."); | 233 | logger.debug("Global contraint is not satisifed."); |
221 | context.backtrack(); | 234 | context.backtrack(); |
235 | } else if (!numericSolver.maySatisfiable()) { | ||
236 | logger.debug("Numeric constraints are not satisifed."); | ||
237 | context.backtrack(); | ||
222 | } else { | 238 | } else { |
223 | final Fitness nextFitness = context.calculateFitness(); | 239 | final Fitness nextFitness = context.calculateFitness(); |
224 | checkForSolution(nextFitness); | 240 | checkForSolution(nextFitness); |
@@ -228,59 +244,89 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
228 | continue; | 244 | continue; |
229 | } | 245 | } |
230 | 246 | ||
231 | TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness( | 247 | TrajectoryWithFitness nextTrajectoryWithfitness = new TrajectoryWithFitness( |
232 | context.getTrajectory().toArray(), nextFitness); | 248 | context.getTrajectory().toArray(), nextFitness); |
233 | trajectoiresToExplore.add(nextTrajectoryWithFittness); | 249 | trajectoiresToExplore.add(nextTrajectoryWithfitness); |
234 | 250 | ||
235 | int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFittness.fitness, | 251 | int compare = objectiveComparatorHelper.compare(currentTrajectoryWithFitness.fitness, |
236 | nextTrajectoryWithFittness.fitness); | 252 | nextTrajectoryWithfitness.fitness); |
237 | if (compare < 0) { | 253 | if (compare < 0) { |
238 | logger.debug("Better fitness, moving on: " + nextFitness); | 254 | logger.debug("Better fitness, moving on: " + nextFitness); |
239 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | 255 | currentTrajectoryWithFitness = nextTrajectoryWithfitness; |
240 | continue mainLoop; | 256 | continue mainLoop; |
241 | } else if (compare == 0) { | 257 | } else if (compare == 0) { |
242 | logger.debug("Equally good fitness, moving on: " + nextFitness); | 258 | logger.debug("Equally good fitness, moving on: " + nextFitness); |
243 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | 259 | currentTrajectoryWithFitness = nextTrajectoryWithfitness; |
244 | continue mainLoop; | 260 | continue mainLoop; |
245 | } else { | 261 | } else { |
246 | logger.debug("Worse fitness."); | 262 | logger.debug("Worse fitness."); |
247 | currentTrajectoryWithFittness = null; | 263 | currentTrajectoryWithFitness = null; |
248 | continue mainLoop; | 264 | continue mainLoop; |
249 | } | 265 | } |
250 | } | 266 | } |
251 | } | 267 | } |
252 | 268 | ||
253 | logger.debug("State is fully traversed."); | 269 | logger.debug("State is fully traversed."); |
254 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | 270 | trajectoiresToExplore.remove(currentTrajectoryWithFitness); |
255 | currentTrajectoryWithFittness = null; | 271 | currentTrajectoryWithFitness = null; |
256 | 272 | ||
257 | } | 273 | } |
258 | logger.info("Interrupted."); | 274 | logger.info("Interrupted."); |
259 | } | 275 | } |
260 | 276 | ||
277 | private boolean checkGlobalConstraints() { | ||
278 | long start = System.nanoTime(); | ||
279 | boolean result = context.checkGlobalConstraints(); | ||
280 | globalConstraintEvaluationTime += System.nanoTime() - start; | ||
281 | return result; | ||
282 | } | ||
283 | |||
284 | private Fitness calculateFitness() { | ||
285 | long start = System.nanoTime(); | ||
286 | Fitness fitness = context.calculateFitness(); | ||
287 | fitnessCalculationTime += System.nanoTime() - start; | ||
288 | return fitness; | ||
289 | } | ||
290 | |||
261 | private List<Object> selectActivation() { | 291 | private List<Object> selectActivation() { |
262 | List<Object> activationIds; | 292 | List<Object> activationIds; |
263 | try { | 293 | try { |
264 | activationIds = new ArrayList<Object>(context.getUntraversedActivationIds()); | 294 | activationIds = this.activationSelector.randomizeActivationIDs(context.getUntraversedActivationIds()); |
265 | Collections.shuffle(activationIds); | ||
266 | } catch (NullPointerException e) { | 295 | } catch (NullPointerException e) { |
296 | // logger.warn("Unexpected state code: " + context.getDesignSpaceManager().getCurrentState()); | ||
267 | numberOfStatecoderFail++; | 297 | numberOfStatecoderFail++; |
268 | activationIds = Collections.emptyList(); | 298 | activationIds = Collections.emptyList(); |
269 | } | 299 | } |
270 | return activationIds; | 300 | return activationIds; |
271 | } | 301 | } |
272 | 302 | ||
273 | private void checkForSolution(final Fitness fittness) { | 303 | private void checkForSolution(final Fitness fitness) { |
274 | if (fittness.isSatisifiesHardObjectives()) { | 304 | solutionStore.newSolution(context); |
275 | if (solutionStoreWithDiversityDescriptor.isDifferent(context)) { | 305 | } |
276 | solutionStoreWithCopy.newSolution(context); | 306 | |
277 | solutionStoreWithDiversityDescriptor.newSolution(context); | 307 | public List<String> times = new LinkedList<String>(); |
278 | solutionStore.newSolution(context); | 308 | private void saveTimes() { |
279 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolution); | 309 | long forwardTime = context.getDesignSpaceManager().getForwardTime()/1000000; |
280 | 310 | long backtrackingTime = context.getDesignSpaceManager().getBacktrackingTime()/1000000; | |
281 | logger.debug("Found a solution."); | 311 | long activationSelection = this.activationSelector.getRuntime()/1000000; |
282 | } | 312 | long solutionCopierTime = this.solutionSaver.getTotalCopierRuntime()/1000000; |
283 | } | 313 | long numericalSolverSumTime = this.numericSolver.getRuntime()/1000000; |
314 | long numericalSolverProblemForming = this.numericSolver.getSolverSolvingProblem()/1000000; | ||
315 | long numericalSolverSolving = this.numericSolver.getSolverSolvingProblem()/1000000; | ||
316 | long numericalSolverInterpreting = this.numericSolver.getSolverSolution()/1000000; | ||
317 | this.times.add( | ||
318 | "(TransformationExecutionTime"+method.getStatistics().transformationExecutionTime/1000000+ | ||
319 | "|ForwardTime:"+forwardTime+ | ||
320 | "|Backtrackingtime:"+backtrackingTime+ | ||
321 | "|GlobalConstraintEvaluationTime:"+(globalConstraintEvaluationTime/1000000)+ | ||
322 | "|FitnessCalculationTime:"+(fitnessCalculationTime/1000000)+ | ||
323 | "|ActivationSelectionTime:"+activationSelection+ | ||
324 | "|SolutionCopyTime:"+solutionCopierTime+ | ||
325 | "|NumericalSolverSumTime:"+numericalSolverSumTime+ | ||
326 | "|NumericalSolverProblemFormingTime:"+numericalSolverProblemForming+ | ||
327 | "|NumericalSolverSolvingTime:"+numericalSolverSolving+ | ||
328 | "|NumericalSolverInterpretingSolution:"+numericalSolverInterpreting+")"); | ||
329 | |||
284 | } | 330 | } |
285 | 331 | ||
286 | @Override | 332 | @Override |
@@ -309,7 +355,7 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
309 | } else { | 355 | } else { |
310 | return trajectoiresToExplore.element(); | 356 | return trajectoiresToExplore.element(); |
311 | } | 357 | } |
312 | } | 358 | } |
313 | 359 | ||
314 | // private void logCurrentStateMetric() { | 360 | // private void logCurrentStateMetric() { |
315 | // if(this.configuration.documentationLevel != DocumentationLevel.NONE || workspace == null) { | 361 | // if(this.configuration.documentationLevel != DocumentationLevel.NONE || workspace == null) { |
@@ -322,13 +368,16 @@ public class BestFirstStrategyForModelGeneration implements IStrategy { | |||
322 | 368 | ||
323 | 369 | ||
324 | public void visualiseCurrentState() { | 370 | public void visualiseCurrentState() { |
325 | PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugCongiguration.partialInterpretatioVisualiser; | 371 | PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugConfiguration.partialInterpretatioVisualiser; |
326 | if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) { | 372 | if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) { |
327 | PartialInterpretation p = (PartialInterpretation) (context.getModel()); | 373 | PartialInterpretation p = (PartialInterpretation) (context.getModel()); |
328 | int id = ++numberOfPrintedModel; | 374 | int id = ++numberOfPrintedModel; |
329 | if (id % configuration.debugCongiguration.partalInterpretationVisualisationFrequency == 0) { | 375 | if (id % configuration.debugConfiguration.partalInterpretationVisualisationFrequency == 0) { |
330 | PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); | 376 | PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); |
331 | visualisation.writeToFile(workspace, String.format("state%09d.png", id)); | 377 | logger.debug("Visualizing state: " + id + " (" + context.getDesignSpaceManager().getCurrentState() + ")"); |
378 | String name = String.format("state%09d", id); | ||
379 | visualisation.writeToFile(workspace, name + ".png"); | ||
380 | workspace.writeModel((EObject) context.getModel(), name + ".xmi"); | ||
332 | } | 381 | } |
333 | } | 382 | } |
334 | } | 383 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend new file mode 100644 index 00000000..fb1b2066 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DiversityChecker.xtend | |||
@@ -0,0 +1,184 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import com.google.common.collect.HashMultiset | ||
4 | import com.google.common.collect.ImmutableSet | ||
5 | import com.google.common.collect.Multiset | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.AbstractNodeDescriptor | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.NeighbourhoodWithTraces | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.DiversityDescriptor | ||
11 | import java.util.Collection | ||
12 | import java.util.HashSet | ||
13 | import java.util.Map | ||
14 | import java.util.Set | ||
15 | import org.eclipse.viatra.dse.base.ThreadContext | ||
16 | import org.eclipse.xtend.lib.annotations.Accessors | ||
17 | |||
18 | interface DiversityChecker { | ||
19 | public static val NO_DIVERSITY_CHECKER = new DiversityChecker { | ||
20 | override isActive() { | ||
21 | false | ||
22 | } | ||
23 | |||
24 | override getTotalRuntime() { | ||
25 | 0 | ||
26 | } | ||
27 | |||
28 | override getSuccessRate() { | ||
29 | 1.0 | ||
30 | } | ||
31 | |||
32 | override newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
33 | true | ||
34 | } | ||
35 | } | ||
36 | |||
37 | def boolean isActive() | ||
38 | |||
39 | def long getTotalRuntime() | ||
40 | |||
41 | def double getSuccessRate() | ||
42 | |||
43 | def boolean newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) | ||
44 | |||
45 | static def of(DiversityDescriptor descriptor) { | ||
46 | if (descriptor.ensureDiversity) { | ||
47 | new NodewiseDiversityChecker(descriptor) | ||
48 | } else { | ||
49 | NO_DIVERSITY_CHECKER | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | abstract class AbstractDiversityChecker implements DiversityChecker { | ||
55 | val DiversityDescriptor descriptor | ||
56 | val PartialInterpretation2ImmutableTypeLattice solutionCoder = new PartialInterpretation2ImmutableTypeLattice | ||
57 | |||
58 | @Accessors(PUBLIC_GETTER) var long totalRuntime = 0 | ||
59 | var int allCheckCount = 0 | ||
60 | var int successfulCheckCount = 0 | ||
61 | |||
62 | protected new(DiversityDescriptor descriptor) { | ||
63 | if (!descriptor.ensureDiversity) { | ||
64 | throw new IllegalArgumentException( | ||
65 | "Diversity description should enforce diversity or NO_DIVERSITY_CHECKER should be used instead.") | ||
66 | } | ||
67 | this.descriptor = descriptor | ||
68 | } | ||
69 | |||
70 | override isActive() { | ||
71 | true | ||
72 | } | ||
73 | |||
74 | override getTotalRuntime() { | ||
75 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | ||
76 | } | ||
77 | |||
78 | override getSuccessRate() { | ||
79 | (allCheckCount as double) / (successfulCheckCount as double) | ||
80 | } | ||
81 | |||
82 | override newSolution(ThreadContext threadContext, Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
83 | val start = System.nanoTime | ||
84 | val model = threadContext.model as PartialInterpretation | ||
85 | val representation = solutionCoder.createRepresentation(model, descriptor.range, descriptor.parallels, | ||
86 | descriptor.maxNumber, descriptor.relevantTypes, descriptor.relevantRelations) | ||
87 | val isDifferent = internalNewSolution(representation, solutionId, dominatedSolutionIds) | ||
88 | totalRuntime += System.nanoTime - start | ||
89 | allCheckCount++ | ||
90 | if (isDifferent) { | ||
91 | successfulCheckCount++ | ||
92 | } | ||
93 | isDifferent | ||
94 | } | ||
95 | |||
96 | protected abstract def boolean internalNewSolution( | ||
97 | NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation, | ||
98 | Object solutionId, Collection<Object> dominatedSolutionIds) | ||
99 | } | ||
100 | |||
101 | class NodewiseDiversityChecker extends AbstractDiversityChecker { | ||
102 | var Multiset<Integer> nodeCodes = HashMultiset.create | ||
103 | val Map<Object, Set<Integer>> tracedNodeCodes = newHashMap | ||
104 | |||
105 | new(DiversityDescriptor descriptor) { | ||
106 | super(descriptor) | ||
107 | } | ||
108 | |||
109 | override protected internalNewSolution( | ||
110 | NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation, | ||
111 | Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
112 | val nodeCodesInSolution = ImmutableSet.copyOf(representation.modelRepresentation.keySet.map[hashCode]) | ||
113 | val remainingNodeCodes = if (dominatedSolutionIds.empty) { | ||
114 | nodeCodes | ||
115 | } else { | ||
116 | getRemainingNodeCodes(dominatedSolutionIds) | ||
117 | } | ||
118 | val hasNewCode = nodeCodesInSolution.exists[!remainingNodeCodes.contains(it)] | ||
119 | if (hasNewCode) { | ||
120 | nodeCodes = remainingNodeCodes | ||
121 | nodeCodes.addAll(nodeCodesInSolution) | ||
122 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
123 | tracedNodeCodes.remove(dominatedSolutionId) | ||
124 | } | ||
125 | tracedNodeCodes.put(solutionId, nodeCodesInSolution) | ||
126 | } | ||
127 | hasNewCode | ||
128 | } | ||
129 | |||
130 | private def getRemainingNodeCodes(Collection<Object> dominatedSolutionIds) { | ||
131 | // TODO Optimize multiset operations. | ||
132 | val copyOfNodeCodes = HashMultiset.create(nodeCodes) | ||
133 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
134 | val dominatedModelCode = tracedNodeCodes.get(dominatedSolutionId) | ||
135 | if (dominatedModelCode === null) { | ||
136 | throw new IllegalArgumentException("Unknown dominated solution: " + dominatedSolutionId) | ||
137 | } | ||
138 | copyOfNodeCodes.removeAll(dominatedModelCode) | ||
139 | } | ||
140 | copyOfNodeCodes | ||
141 | } | ||
142 | } | ||
143 | |||
144 | class GraphwiseDiversityChecker extends AbstractDiversityChecker { | ||
145 | var Set<Integer> modelCodes = newHashSet | ||
146 | val Map<Object, Integer> tracedModelCodes = newHashMap | ||
147 | |||
148 | new(DiversityDescriptor descriptor) { | ||
149 | super(descriptor) | ||
150 | } | ||
151 | |||
152 | override protected internalNewSolution( | ||
153 | NeighbourhoodWithTraces<Map<? extends AbstractNodeDescriptor, Integer>, AbstractNodeDescriptor> representation, | ||
154 | Object solutionId, Collection<Object> dominatedSolutionIds) { | ||
155 | val modelCodeOfSolution = representation.modelRepresentation.hashCode | ||
156 | val remainingModelCodes = if (dominatedSolutionIds.empty) { | ||
157 | modelCodes | ||
158 | } else { | ||
159 | getRemainingModelCodes(dominatedSolutionIds) | ||
160 | } | ||
161 | val isNewCode = !remainingModelCodes.contains(modelCodeOfSolution) | ||
162 | if (isNewCode) { | ||
163 | modelCodes = remainingModelCodes | ||
164 | modelCodes += modelCodeOfSolution | ||
165 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
166 | tracedModelCodes.remove(dominatedSolutionId) | ||
167 | } | ||
168 | tracedModelCodes.put(solutionId, modelCodeOfSolution) | ||
169 | } | ||
170 | isNewCode | ||
171 | } | ||
172 | |||
173 | private def getRemainingModelCodes(Collection<Object> dominatedSolutionIds) { | ||
174 | val copyOfModelCodes = new HashSet(modelCodes) | ||
175 | for (dominatedSolutionId : dominatedSolutionIds) { | ||
176 | val dominatedModelCode = tracedModelCodes.get(dominatedSolutionId) | ||
177 | if (dominatedModelCode === null) { | ||
178 | throw new IllegalArgumentException("Unknown dominated solution: " + dominatedSolutionId) | ||
179 | } | ||
180 | copyOfModelCodes -= dominatedModelCode | ||
181 | } | ||
182 | copyOfModelCodes | ||
183 | } | ||
184 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend new file mode 100644 index 00000000..3c2e3319 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/DseUtils.xtend | |||
@@ -0,0 +1,66 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.IThreeValuedObjective | ||
4 | import org.eclipse.viatra.dse.base.ThreadContext | ||
5 | import org.eclipse.viatra.dse.objectives.Comparators | ||
6 | import org.eclipse.viatra.dse.objectives.Fitness | ||
7 | import org.eclipse.viatra.dse.objectives.IObjective | ||
8 | |||
9 | final class DseUtils { | ||
10 | private new() { | ||
11 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly.") | ||
12 | } | ||
13 | |||
14 | static def calculateFitness(ThreadContext it, (IObjective)=>Double getFitness) { | ||
15 | val result = new Fitness | ||
16 | var boolean satisifiesHardObjectives = true | ||
17 | for (objective : objectives) { | ||
18 | val fitness = getFitness.apply(objective) | ||
19 | result.put(objective.name, fitness) | ||
20 | if (objective.isHardObjective() && !objective.satisifiesHardObjective(fitness)) { | ||
21 | satisifiesHardObjectives = false | ||
22 | } | ||
23 | } | ||
24 | result.satisifiesHardObjectives = satisifiesHardObjectives | ||
25 | result | ||
26 | } | ||
27 | |||
28 | static def caclulateBestPossibleFitness(ThreadContext threadContext) { | ||
29 | threadContext.calculateFitness [ objective | | ||
30 | if (objective instanceof IThreeValuedObjective) { | ||
31 | objective.getBestPossibleFitness(threadContext) | ||
32 | } else { | ||
33 | switch (objective.comparator) { | ||
34 | case Comparators.LOWER_IS_BETTER: | ||
35 | Double.NEGATIVE_INFINITY | ||
36 | case Comparators.HIGHER_IS_BETTER: | ||
37 | Double.POSITIVE_INFINITY | ||
38 | case Comparators.DIFFERENCE_TO_ZERO_IS_BETTER: | ||
39 | 0.0 | ||
40 | default: | ||
41 | throw new IllegalArgumentException("Unknown comparator for non-three-valued objective: " + | ||
42 | objective.name) | ||
43 | } | ||
44 | } | ||
45 | ] | ||
46 | } | ||
47 | |||
48 | static def caclulateWorstPossibleFitness(ThreadContext threadContext) { | ||
49 | threadContext.calculateFitness [ objective | | ||
50 | if (objective instanceof IThreeValuedObjective) { | ||
51 | objective.getWorstPossibleFitness(threadContext) | ||
52 | } else { | ||
53 | switch (objective.comparator) { | ||
54 | case Comparators.LOWER_IS_BETTER, | ||
55 | case Comparators.DIFFERENCE_TO_ZERO_IS_BETTER: | ||
56 | Double.POSITIVE_INFINITY | ||
57 | case Comparators.HIGHER_IS_BETTER: | ||
58 | Double.NEGATIVE_INFINITY | ||
59 | default: | ||
60 | throw new IllegalArgumentException("Unknown comparator for non-three-valued objective: " + | ||
61 | objective.name) | ||
62 | } | ||
63 | } | ||
64 | ] | ||
65 | } | ||
66 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/EvenActivationSelector.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/EvenActivationSelector.xtend new file mode 100644 index 00000000..82a5f32d --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/EvenActivationSelector.xtend | |||
@@ -0,0 +1,20 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import java.util.Random | ||
4 | import java.util.Collection | ||
5 | import java.util.Collections | ||
6 | import java.util.ArrayList | ||
7 | |||
8 | class EvenActivationSelector extends ActivationSelector { | ||
9 | |||
10 | new(Random r) { | ||
11 | super(r) | ||
12 | } | ||
13 | |||
14 | override protected internalRandomizationOfActivationIDs(Collection<Object> activationIDs) { | ||
15 | val toShuffle = new ArrayList<Object>(activationIDs); | ||
16 | Collections.shuffle(toShuffle); | ||
17 | return toShuffle | ||
18 | } | ||
19 | |||
20 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/HillClimbingOnRealisticMetricStrategyForModelGeneration.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/HillClimbingOnRealisticMetricStrategyForModelGeneration.java index eb7df089..d9f84b36 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/HillClimbingOnRealisticMetricStrategyForModelGeneration.java +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/HillClimbingOnRealisticMetricStrategyForModelGeneration.java | |||
@@ -16,6 +16,7 @@ import java.util.Random; | |||
16 | import java.util.Set; | 16 | import java.util.Set; |
17 | 17 | ||
18 | import org.apache.log4j.Logger; | 18 | import org.apache.log4j.Logger; |
19 | import org.eclipse.emf.ecore.EObject; | ||
19 | import org.eclipse.emf.ecore.util.EcoreUtil; | 20 | import org.eclipse.emf.ecore.util.EcoreUtil; |
20 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; | 21 | import org.eclipse.viatra.dse.api.strategy.interfaces.IStrategy; |
21 | import org.eclipse.viatra.dse.base.ThreadContext; | 22 | import org.eclipse.viatra.dse.base.ThreadContext; |
@@ -35,480 +36,540 @@ import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem; | |||
35 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.InconsistencyResult; | 36 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.InconsistencyResult; |
36 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicResult; | 37 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.LogicResult; |
37 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult; | 38 | import hu.bme.mit.inf.dslreasoner.logic.model.logicresult.ModelResult; |
38 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.ModelGenerationMethod; | ||
39 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.PartialInterpretation2Logic; | 39 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretation2logic.PartialInterpretation2Logic; |
40 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation; | 40 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation; |
41 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.statecoder.NeighbourhoodBasedPartialInterpretationStateCoder; | ||
41 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualisation; | 42 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualisation; |
42 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser; | 43 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.visualisation.PartialInterpretationVisualiser; |
44 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ModelGenerationMethod; | ||
43 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.RealisticGuidance; | 45 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.RealisticGuidance; |
44 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration; | 46 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration; |
45 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace; | 47 | import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace; |
46 | 48 | ||
47 | public class HillClimbingOnRealisticMetricStrategyForModelGeneration implements IStrategy { | 49 | public class HillClimbingOnRealisticMetricStrategyForModelGeneration implements IStrategy { |
48 | // Services and Configuration | 50 | // Services and Configuration |
49 | private ThreadContext context; | 51 | private ThreadContext context; |
50 | private ReasonerWorkspace workspace; | 52 | private ReasonerWorkspace workspace; |
51 | private ViatraReasonerConfiguration configuration; | 53 | private ViatraReasonerConfiguration configuration; |
52 | private ModelGenerationMethod method; | 54 | private ModelGenerationMethod method; |
53 | private PartialInterpretation2Logic partialInterpretation2Logic = new PartialInterpretation2Logic(); | 55 | private PartialInterpretation2Logic partialInterpretation2Logic = new PartialInterpretation2Logic(); |
54 | private Comparator<TrajectoryWithFitness> comparator; | 56 | private Comparator<TrajectoryWithFitness> comparator; |
55 | private Logger logger = Logger.getLogger(IStrategy.class); | 57 | private Logger logger = Logger.getLogger(IStrategy.class); |
58 | public NumericSolver numericSolver = null; | ||
59 | |||
60 | // Running | ||
61 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; | ||
62 | private SolutionStore solutionStore; | ||
63 | private SolutionStoreWithCopy solutionStoreWithCopy; | ||
64 | private SolutionStoreWithDiversityDescriptor solutionStoreWithDiversityDescriptor; | ||
65 | private volatile boolean isInterrupted = false; | ||
66 | private ModelResult modelResultByInternalSolver = null; | ||
67 | private Random random = new Random(); | ||
68 | |||
69 | // matchers for detecting the number of violations | ||
70 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> mustMatchers; | ||
71 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> mayMatchers; | ||
72 | |||
73 | // Encode the used activations of a particular state | ||
74 | private Map<Object, List<Object>> stateAndActivations; | ||
75 | private boolean allowMustViolation; | ||
76 | private Domain domain; | ||
77 | int targetSize; | ||
78 | public ActivationSelector activationSelector = new EvenActivationSelector(random); | ||
79 | // Statistics | ||
80 | private int numberOfStatecoderFail = 0; | ||
81 | private int numberOfPrintedModel = 0; | ||
82 | private int numberOfSolverCalls = 0; | ||
83 | private PartialInterpretationMetricDistance metricDistance; | ||
84 | private double currentStateValue = Double.MAX_VALUE; | ||
85 | private double currentNodeTypeDistance = 1; | ||
86 | private int numNodesToGenerate = 0; | ||
87 | public long explorationStarted = 0; | ||
88 | public long globalConstraintEvaluationTime = 0; | ||
89 | public long fitnessCalculationTime = 0; | ||
90 | |||
91 | public HillClimbingOnRealisticMetricStrategyForModelGeneration( | ||
92 | ReasonerWorkspace workspace, | ||
93 | ViatraReasonerConfiguration configuration, | ||
94 | ModelGenerationMethod method) | ||
95 | { | ||
96 | this.workspace = workspace; | ||
97 | this.configuration = configuration; | ||
98 | this.method = method; | ||
99 | } | ||
100 | |||
101 | public SolutionStoreWithCopy getSolutionStoreWithCopy() { | ||
102 | return solutionStoreWithCopy; | ||
103 | } | ||
104 | public SolutionStoreWithDiversityDescriptor getSolutionStoreWithDiversityDescriptor() { | ||
105 | return solutionStoreWithDiversityDescriptor; | ||
106 | } | ||
107 | public int getNumberOfStatecoderFail() { | ||
108 | return numberOfStatecoderFail; | ||
109 | } | ||
110 | |||
111 | public long getForwardTime() { | ||
112 | return context.getDesignSpaceManager().getForwardTime(); | ||
113 | } | ||
114 | public long getBacktrackingTime() { | ||
115 | return context.getDesignSpaceManager().getBacktrackingTime(); | ||
116 | } | ||
117 | |||
118 | @Override | ||
119 | public void initStrategy(ThreadContext context) { | ||
120 | this.context = context; | ||
121 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | ||
122 | domain = Domain.valueOf(configuration.domain); | ||
123 | |||
124 | ViatraQueryEngine engine = context.getQueryEngine(); | ||
125 | // // TODO: visualisation | ||
126 | mustMatchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
127 | mayMatchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
56 | 128 | ||
57 | // Running | 129 | // manully restict the number of super types of one class |
58 | private PriorityQueue<TrajectoryWithFitness> trajectoiresToExplore; | 130 | this.method.getInvalidWF().forEach(a ->{ |
59 | private SolutionStore solutionStore; | 131 | ViatraQueryMatcher<? extends IPatternMatch> matcher = a.getMatcher(engine); |
60 | private SolutionStoreWithCopy solutionStoreWithCopy; | 132 | mustMatchers.add(matcher); |
61 | private SolutionStoreWithDiversityDescriptor solutionStoreWithDiversityDescriptor; | 133 | }); |
62 | private volatile boolean isInterrupted = false; | ||
63 | private ModelResult modelResultByInternalSolver = null; | ||
64 | private Random random = new Random(); | ||
65 | 134 | ||
66 | // matchers for detecting the number of violations | 135 | this.method.getUnfinishedWF().forEach(a ->{ |
67 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> mustMatchers; | 136 | ViatraQueryMatcher<? extends IPatternMatch> matcher = a.getMatcher(engine); |
68 | private Collection<ViatraQueryMatcher<? extends IPatternMatch>> mayMatchers; | 137 | mayMatchers.add(matcher); |
138 | }); | ||
69 | 139 | ||
70 | // Encode the used activations of a particular state | ||
71 | private Map<Object, List<Object>> stateAndActivations; | ||
72 | private boolean allowMustViolation; | ||
73 | private Domain domain; | ||
74 | int targetSize; | ||
75 | |||
76 | // Statistics | ||
77 | private int numberOfStatecoderFail = 0; | ||
78 | private int numberOfPrintedModel = 0; | ||
79 | private int numberOfSolverCalls = 0; | ||
80 | private PartialInterpretationMetricDistance metricDistance; | ||
81 | private double currentStateValue = Double.MAX_VALUE; | ||
82 | private double currentNodeTypeDistance = 1; | ||
83 | private int numNodesToGenerate = 0; | ||
84 | 140 | ||
85 | public HillClimbingOnRealisticMetricStrategyForModelGeneration( | 141 | //set up comparator |
86 | ReasonerWorkspace workspace, | 142 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
87 | ViatraReasonerConfiguration configuration, | 143 | this.comparator = new Comparator<TrajectoryWithFitness>() { |
88 | ModelGenerationMethod method) | 144 | @Override |
89 | { | 145 | public int compare(TrajectoryWithFitness o1, TrajectoryWithFitness o2) { |
90 | this.workspace = workspace; | 146 | return objectiveComparatorHelper.compare(o2.fitness, o1.fitness); |
91 | this.configuration = configuration; | 147 | } |
92 | this.method = method; | 148 | }; |
93 | } | ||
94 | 149 | ||
95 | public SolutionStoreWithCopy getSolutionStoreWithCopy() { | 150 | this.solutionStoreWithCopy = new SolutionStoreWithCopy(); |
96 | return solutionStoreWithCopy; | 151 | this.solutionStoreWithDiversityDescriptor = new SolutionStoreWithDiversityDescriptor(configuration.diversityRequirement); |
97 | } | 152 | |
98 | public SolutionStoreWithDiversityDescriptor getSolutionStoreWithDiversityDescriptor() { | 153 | trajectoiresToExplore = new PriorityQueue<TrajectoryWithFitness>(11, comparator); |
99 | return solutionStoreWithDiversityDescriptor; | 154 | stateAndActivations = new HashMap<Object, List<Object>>(); |
155 | metricDistance = new PartialInterpretationMetricDistance(domain); | ||
156 | |||
157 | //set whether allows must violations during the realistic generation | ||
158 | allowMustViolation = configuration.allowMustViolations; | ||
159 | targetSize = configuration.typeScopes.maxNewElements + 2; | ||
160 | //this.numericSolver = new NumericSolver(method, this.configuration.runIntermediateNumericalConsistencyChecks, false); | ||
161 | } | ||
162 | |||
163 | @Override | ||
164 | public void explore() { | ||
165 | this.explorationStarted=System.nanoTime(); | ||
166 | if (!checkGlobalConstraints()) { | ||
167 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | ||
168 | return; | ||
100 | } | 169 | } |
101 | public int getNumberOfStatecoderFail() { | 170 | if (configuration.searchSpaceConstraints.maxDepth == 0) { |
102 | return numberOfStatecoderFail; | 171 | logger.info("Maximal depth is reached in the initial solution. Terminate."); |
172 | return; | ||
103 | } | 173 | } |
104 | |||
105 | @Override | ||
106 | public void initStrategy(ThreadContext context) { | ||
107 | this.context = context; | ||
108 | this.solutionStore = context.getGlobalContext().getSolutionStore(); | ||
109 | domain = Domain.valueOf(configuration.domain); | ||
110 | |||
111 | ViatraQueryEngine engine = context.getQueryEngine(); | ||
112 | // // TODO: visualisation | ||
113 | mustMatchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
114 | mayMatchers = new LinkedList<ViatraQueryMatcher<? extends IPatternMatch>>(); | ||
115 | |||
116 | // manully restict the number of super types of one class | ||
117 | this.method.getInvalidWF().forEach(a ->{ | ||
118 | ViatraQueryMatcher<? extends IPatternMatch> matcher = a.getMatcher(engine); | ||
119 | mustMatchers.add(matcher); | ||
120 | }); | ||
121 | |||
122 | this.method.getUnfinishedWF().forEach(a ->{ | ||
123 | ViatraQueryMatcher<? extends IPatternMatch> matcher = a.getMatcher(engine); | ||
124 | mayMatchers.add(matcher); | ||
125 | }); | ||
126 | 174 | ||
127 | 175 | final Fitness firstFittness = context.calculateFitness(); | |
128 | //set up comparator | 176 | |
129 | final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 177 | //final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); |
130 | this.comparator = new Comparator<TrajectoryWithFitness>() { | 178 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); |
131 | @Override | 179 | TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness); |
132 | public int compare(TrajectoryWithFitness o1, TrajectoryWithFitness o2) { | 180 | trajectoiresToExplore.add(currentTrajectoryWithFittness); |
133 | return objectiveComparatorHelper.compare(o2.fitness, o1.fitness); | 181 | Object lastState = null; |
182 | |||
183 | //if(configuration) | ||
184 | visualiseCurrentState(); | ||
185 | // the two is the True and False node generated at the beginning of the generation | ||
186 | int count = 0; | ||
187 | mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) { | ||
188 | |||
189 | if (currentTrajectoryWithFittness == null) { | ||
190 | if (trajectoiresToExplore.isEmpty()) { | ||
191 | logger.debug("State space is fully traversed."); | ||
192 | return; | ||
193 | } else { | ||
194 | currentTrajectoryWithFittness = selectState(); | ||
195 | if (logger.isDebugEnabled()) { | ||
196 | logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray())); | ||
197 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness); | ||
198 | } | ||
199 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory); | ||
200 | |||
201 | // reset the regression for this trajectory | ||
202 | metricDistance.getLinearModel().resetRegression(context.getCurrentStateId()); | ||
134 | } | 203 | } |
135 | }; | 204 | } |
136 | 205 | ||
137 | this.solutionStoreWithCopy = new SolutionStoreWithCopy(); | 206 | List<Object> activationIds = selectActivation(); |
138 | this.solutionStoreWithDiversityDescriptor = new SolutionStoreWithDiversityDescriptor(configuration.diversityRequirement); | 207 | PartialInterpretation model = (PartialInterpretation) context.getModel(); |
208 | System.out.println(model.getNewElements().size()); | ||
209 | System.out.println("# violations: " + getNumberOfViolations(mayMatchers)); | ||
139 | 210 | ||
140 | trajectoiresToExplore = new PriorityQueue<TrajectoryWithFitness>(11, comparator); | 211 | Map<Object, Double> valueMap = new HashMap<Object,Double>(); |
141 | stateAndActivations = new HashMap<Object, List<Object>>(); | ||
142 | metricDistance = new PartialInterpretationMetricDistance(domain); | ||
143 | 212 | ||
144 | //set whether allows must violations during the realistic generation | 213 | //init epsilon and draw |
145 | allowMustViolation = configuration.allowMustViolations; | 214 | MetricDistanceGroup heuristics = metricDistance.calculateMetricDistanceKS(model); |
146 | targetSize = configuration.typeScopes.maxNewElements + 2; | ||
147 | } | ||
148 | 215 | ||
149 | @Override | 216 | if(!stateAndActivations.containsKey(context.getCurrentStateId())) { |
150 | public void explore() { | 217 | stateAndActivations.put(context.getCurrentStateId(), new ArrayList<Object>()); |
151 | if (!context.checkGlobalConstraints()) { | ||
152 | logger.info("Global contraint is not satisifed in the first state. Terminate."); | ||
153 | return; | ||
154 | } | ||
155 | if (configuration.searchSpaceConstraints.maxDepth == 0) { | ||
156 | logger.info("Maximal depth is reached in the initial solution. Terminate."); | ||
157 | return; | ||
158 | } | 218 | } |
159 | 219 | ||
160 | final Fitness firstFittness = context.calculateFitness(); | 220 | // calculate values for epsilon greedy |
161 | 221 | double epsilon = 1.0/count; | |
162 | //final ObjectiveComparatorHelper objectiveComparatorHelper = context.getObjectiveComparatorHelper(); | 222 | double draw = Math.random(); |
163 | final Object[] firstTrajectory = context.getTrajectory().toArray(new Object[0]); | 223 | count++; |
164 | TrajectoryWithFitness currentTrajectoryWithFittness = new TrajectoryWithFitness(firstTrajectory, firstFittness); | 224 | this.currentNodeTypeDistance = heuristics.getNodeTypeDistance(); |
165 | trajectoiresToExplore.add(currentTrajectoryWithFittness); | 225 | numNodesToGenerate = model.getMaxNewElements(); |
166 | Object lastState = null; | 226 | System.out.println("NA distance: " + heuristics.getNADistance()); |
167 | 227 | System.out.println("MPC distance: " + heuristics.getMPCDistance()); | |
168 | //if(configuration) | 228 | System.out.println("Out degree distance:" + heuristics.getOutDegreeDistance()); |
169 | visualiseCurrentState(); | 229 | System.out.println("NodeType :" + currentNodeTypeDistance); |
170 | // the two is the True and False node generated at the beginning of the generation | ||
171 | int count = 0; | ||
172 | mainLoop: while (!isInterrupted && !configuration.progressMonitor.isCancelled()) { | ||
173 | 230 | ||
174 | if (currentTrajectoryWithFittness == null) { | ||
175 | if (trajectoiresToExplore.isEmpty()) { | ||
176 | logger.debug("State space is fully traversed."); | ||
177 | return; | ||
178 | } else { | ||
179 | currentTrajectoryWithFittness = selectState(); | ||
180 | if (logger.isDebugEnabled()) { | ||
181 | logger.debug("Current trajectory: " + Arrays.toString(context.getTrajectory().toArray())); | ||
182 | logger.debug("New trajectory is chosen: " + currentTrajectoryWithFittness); | ||
183 | } | ||
184 | context.getDesignSpaceManager().executeTrajectoryWithMinimalBacktrackWithoutStateCoding(currentTrajectoryWithFittness.trajectory); | ||
185 | |||
186 | // reset the regression for this trajectory | ||
187 | metricDistance.getLinearModel().resetRegression(context.getCurrentStateId()); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | List<Object> activationIds = selectActivation(); | ||
192 | PartialInterpretation model = (PartialInterpretation) context.getModel(); | ||
193 | // System.out.println(model.getNewElements().size()); | ||
194 | // System.out.println("# violations: " + getNumberOfViolations(mayMatchers)); | ||
195 | |||
196 | Map<Object, Double> valueMap = new HashMap<Object,Double>(); | ||
197 | |||
198 | //init epsilon and draw | ||
199 | MetricDistanceGroup heuristics = metricDistance.calculateMetricDistanceKS(model); | ||
200 | 231 | ||
201 | if(!stateAndActivations.containsKey(context.getCurrentStateId())) { | 232 | //TODO: the number of activations to be checked should be configurasble |
202 | stateAndActivations.put(context.getCurrentStateId(), new ArrayList<Object>()); | 233 | if(activationIds.size() > 50) { |
203 | } | 234 | activationIds = activationIds.subList(0, 50); |
235 | } | ||
236 | |||
237 | valueMap = sortWithWeight(activationIds); | ||
238 | lastState = context.getCurrentStateId(); | ||
239 | while (!isInterrupted && !configuration.progressMonitor.isCancelled() && activationIds.size() > 0) { | ||
240 | final Object nextActivation = drawWithEpsilonProbabilty(activationIds, valueMap, epsilon, draw); | ||
241 | |||
242 | stateAndActivations.get(context.getCurrentStateId()).add(nextActivation); | ||
243 | logger.debug("Executing new activation: " + nextActivation); | ||
244 | context.executeAcitvationId(nextActivation); | ||
245 | visualiseCurrentState(); | ||
246 | boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); | ||
247 | if(consistencyCheckResult == true) { continue mainLoop; } | ||
204 | 248 | ||
205 | // calculate values for epsilon greedy | 249 | // if (context.isCurrentStateAlreadyTraversed()) { |
206 | double epsilon = 1.0/count; | 250 | // logger.info("The new state is already visited."); |
207 | double draw = Math.random(); | 251 | // context.backtrack(); |
208 | count++; | 252 | // } else if (!checkGlobalConstraints()) { |
209 | this.currentNodeTypeDistance = heuristics.getNodeTypeDistance(); | 253 | // logger.debug("Global contraint is not satisifed."); |
210 | numNodesToGenerate = model.getMaxNewElements(); | 254 | // context.backtrack(); |
211 | // System.out.println("NA distance: " + heuristics.getNADistance()); | 255 | // } |
212 | // System.out.println("MPC distance: " + heuristics.getMPCDistance()); | ||
213 | // System.out.println("Out degree distance:" + heuristics.getOutDegreeDistance()); | ||
214 | // System.out.println("NodeType :" + currentNodeTypeDistance); | ||
215 | |||
216 | |||
217 | //TODO: the number of activations to be checked should be configurasble | ||
218 | if(activationIds.size() > 50) { | ||
219 | activationIds = activationIds.subList(0, 50); | ||
220 | } | ||
221 | 256 | ||
222 | valueMap = sortWithWeight(activationIds); | 257 | int currentSize = model.getNewElements().size(); |
223 | lastState = context.getCurrentStateId(); | 258 | int targetDiff = targetSize - currentSize; |
224 | while (!isInterrupted && !configuration.progressMonitor.isCancelled() && activationIds.size() > 0) { | 259 | boolean shouldFinish = currentSize >= targetSize; |
225 | final Object nextActivation = drawWithEpsilonProbabilty(activationIds, valueMap, epsilon, draw); | 260 | |
226 | 261 | // does not allow must violations | |
227 | stateAndActivations.get(context.getCurrentStateId()).add(nextActivation); | 262 | if((getNumberOfViolations(mustMatchers) > 0|| getNumberOfViolations(mayMatchers) > targetDiff) && !allowMustViolation && !shouldFinish) { |
228 | logger.debug("Executing new activation: " + nextActivation); | 263 | context.backtrack(); |
229 | context.executeAcitvationId(nextActivation); | 264 | }else { |
230 | visualiseCurrentState(); | 265 | final Fitness nextFitness = context.calculateFitness(); |
231 | boolean consistencyCheckResult = checkConsistency(currentTrajectoryWithFittness); | ||
232 | if(consistencyCheckResult == true) { continue mainLoop; } | ||
233 | |||
234 | int currentSize = model.getNewElements().size(); | ||
235 | int targetDiff = targetSize - currentSize; | ||
236 | boolean shouldFinish = currentSize >= targetSize; | ||
237 | 266 | ||
238 | // does not allow must violations | 267 | // the only hard objectives are configured in the config file |
239 | if((getNumberOfViolations(mustMatchers) > 0|| getNumberOfViolations(mayMatchers) > targetDiff) && !allowMustViolation && !shouldFinish) { | 268 | checkForSolution(nextFitness); |
269 | |||
270 | if (context.getDepth() > configuration.searchSpaceConstraints.maxDepth) { | ||
271 | logger.debug("Reached max depth."); | ||
240 | context.backtrack(); | 272 | context.backtrack(); |
241 | }else { | 273 | continue; |
242 | final Fitness nextFitness = context.calculateFitness(); | ||
243 | |||
244 | // the only hard objectives are configured in the config file | ||
245 | checkForSolution(nextFitness); | ||
246 | |||
247 | if (context.getDepth() > configuration.searchSpaceConstraints.maxDepth) { | ||
248 | logger.debug("Reached max depth."); | ||
249 | context.backtrack(); | ||
250 | continue; | ||
251 | } | ||
252 | |||
253 | //Record value for current trajectory | ||
254 | TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness( | ||
255 | context.getTrajectory().toArray(), nextFitness); | ||
256 | int nodeSize = ((PartialInterpretation) context.getModel()).getNewElements().size(); | ||
257 | int violation = getNumberOfViolations(mayMatchers); | ||
258 | double currentValue = calculateCurrentStateValue(nodeSize, violation); | ||
259 | metricDistance.getLinearModel().feedData(context.getCurrentStateId(), metricDistance.calculateFeature(nodeSize, violation), currentValue, lastState); | ||
260 | trajectoiresToExplore.add(nextTrajectoryWithFittness); | ||
261 | currentStateValue = currentValue; | ||
262 | //Currently, just go to the next state without considering the value of trajectory | ||
263 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | ||
264 | continue mainLoop; | ||
265 | |||
266 | } | 274 | } |
275 | |||
276 | //Record value for current trajectory | ||
277 | TrajectoryWithFitness nextTrajectoryWithFittness = new TrajectoryWithFitness( | ||
278 | context.getTrajectory().toArray(), nextFitness); | ||
279 | int nodeSize = ((PartialInterpretation) context.getModel()).getNewElements().size(); | ||
280 | int violation = getNumberOfViolations(mayMatchers); | ||
281 | double currentValue = calculateCurrentStateValue(nodeSize, violation); | ||
282 | metricDistance.getLinearModel().feedData(context.getCurrentStateId(), metricDistance.calculateFeature(nodeSize, violation), currentValue, lastState); | ||
283 | trajectoiresToExplore.add(nextTrajectoryWithFittness); | ||
284 | currentStateValue = currentValue; | ||
285 | //Currently, just go to the next state without considering the value of trajectory | ||
286 | currentTrajectoryWithFittness = nextTrajectoryWithFittness; | ||
287 | continue mainLoop; | ||
288 | |||
267 | } | 289 | } |
268 | logger.debug("State is fully traversed."); | ||
269 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
270 | currentTrajectoryWithFittness = null; | ||
271 | context.backtrack(); | ||
272 | } | 290 | } |
273 | logger.info("Interrupted."); | 291 | logger.debug("State is fully traversed."); |
292 | trajectoiresToExplore.remove(currentTrajectoryWithFittness); | ||
293 | currentTrajectoryWithFittness = null; | ||
294 | context.backtrack(); | ||
274 | } | 295 | } |
296 | logger.info("Interrupted."); | ||
297 | } | ||
275 | 298 | ||
276 | /** | 299 | private boolean checkGlobalConstraints() { |
277 | * | 300 | long start = System.nanoTime(); |
278 | * @param activationIds | 301 | boolean result = context.checkGlobalConstraints(); |
279 | * @return: activation to value map | 302 | globalConstraintEvaluationTime += System.nanoTime() - start; |
280 | */ | 303 | return result; |
281 | private Map<Object, Double> sortWithWeight(List<Object> activationIds){ | 304 | } |
282 | Map<Object, Double> valueMap = new HashMap<Object, Double>(); | 305 | |
283 | Object currentId = context.getCurrentStateId(); | 306 | private Fitness calculateFitness() { |
284 | // check for next states | 307 | long start = System.nanoTime(); |
285 | for(Object id : activationIds) { | 308 | Fitness fitness = context.calculateFitness(); |
286 | context.executeAcitvationId(id); | 309 | fitnessCalculationTime += System.nanoTime() - start; |
287 | int violation = getNumberOfViolations(mayMatchers); | 310 | return fitness; |
311 | } | ||
312 | |||
313 | /** | ||
314 | * | ||
315 | * @param activationIds | ||
316 | * @return: activation to value map | ||
317 | */ | ||
318 | private Map<Object, Double> sortWithWeight(List<Object> activationIds){ | ||
319 | Map<Object, Double> valueMap = new HashMap<Object, Double>(); | ||
320 | Object currentId = context.getCurrentStateId(); | ||
321 | // check for next states | ||
322 | for(Object id : activationIds) { | ||
323 | context.executeAcitvationId(id); | ||
324 | int violation = getNumberOfViolations(mayMatchers); | ||
288 | 325 | ||
289 | if(!allowMustViolation && getNumberOfViolations(mustMatchers) > 0) { | 326 | if(!allowMustViolation && getNumberOfViolations(mustMatchers) > 0) { |
290 | valueMap.put(id, Double.MAX_VALUE); | 327 | valueMap.put(id, Double.MAX_VALUE); |
291 | stateAndActivations.get(currentId).add(id); | 328 | stateAndActivations.get(currentId).add(id); |
292 | }else { | 329 | }else { |
293 | valueMap.put(id, calculateFutureStateValue(violation)); | 330 | valueMap.put(id, calculateFutureStateValue(violation)); |
294 | } | ||
295 | |||
296 | |||
297 | |||
298 | context.backtrack(); | ||
299 | } | 331 | } |
332 | |||
333 | |||
300 | 334 | ||
301 | //remove all the elements having large distance | 335 | context.backtrack(); |
302 | Collections.sort(activationIds, Comparator.comparing(li -> valueMap.get(li))); | ||
303 | return valueMap; | ||
304 | } | 336 | } |
305 | 337 | ||
306 | private double calculateFutureStateValue(int violation) { | 338 | //remove all the elements having large distance |
307 | long start = System.nanoTime(); | 339 | Collections.sort(activationIds, Comparator.comparing(li -> valueMap.get(li))); |
308 | int nodeSize = ((PartialInterpretation) context.getModel()).getNewElements().size(); | 340 | return valueMap; |
309 | double currentValue = calculateCurrentStateValue(nodeSize,violation); | 341 | } |
310 | double[] toPredict = metricDistance.calculateFeature(100, violation); | 342 | |
311 | if(Math.abs(currentValue - currentStateValue) < 0.001) { | 343 | private double calculateFutureStateValue(int violation) { |
312 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); | 344 | long start = System.nanoTime(); |
313 | return Double.MAX_VALUE; | 345 | int nodeSize = ((PartialInterpretation) context.getModel()).getNewElements().size(); |
314 | } | 346 | double currentValue = calculateCurrentStateValue(nodeSize,violation); |
315 | try { | 347 | double[] toPredict = metricDistance.calculateFeature(100, violation); |
316 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); | 348 | if(Math.abs(currentValue - currentStateValue) < 0.001) { |
317 | return metricDistance.getLinearModel().getPredictionForNextDataSample(metricDistance.calculateFeature(nodeSize, violation), currentValue, toPredict); | 349 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); |
318 | }catch(IllegalArgumentException e) { | 350 | return Double.MAX_VALUE; |
319 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); | 351 | } |
320 | return currentValue; | 352 | try { |
321 | } | 353 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); |
322 | 354 | return metricDistance.getLinearModel().getPredictionForNextDataSample(metricDistance.calculateFeature(nodeSize, violation), currentValue, toPredict); | |
355 | }catch(IllegalArgumentException e) { | ||
356 | this.method.getStatistics().addMetricCalculationTime(System.nanoTime() - start); | ||
357 | return currentValue; | ||
323 | } | 358 | } |
324 | private double calculateCurrentStateValue(int factor, int violation) { | ||
325 | PartialInterpretation model = (PartialInterpretation) context.getModel(); | ||
326 | MetricDistanceGroup g = metricDistance.calculateMetricDistanceKS(model); | ||
327 | if(configuration.realisticGuidance == RealisticGuidance.MPC) { | ||
328 | return g.getMPCDistance(); | ||
329 | }else if(configuration.realisticGuidance == RealisticGuidance.NodeActivity) { | ||
330 | return g.getNADistance(); | ||
331 | }else if(configuration.realisticGuidance == RealisticGuidance.OutDegree) { | ||
332 | return g.getOutDegreeDistance(); | ||
333 | }else if(configuration.realisticGuidance == RealisticGuidance.NodeType) { | ||
334 | return g.getNodeTypeDistance(); | ||
335 | }else if(configuration.realisticGuidance == RealisticGuidance.Composite) { | ||
336 | double consistenceWeights = 5 * factor / (configuration.typeScopes.maxNewElements + 2) * (1- 1.0/(1+violation)); | ||
337 | if(domain == Domain.Yakindumm) { | ||
338 | double unfinishFactor = 50 * (1 - (double)factor / targetSize); | ||
339 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
340 | double normalFactor = 5; | ||
341 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { | ||
342 | nodeTypeFactor = 0; | ||
343 | normalFactor = 100; | ||
344 | unfinishFactor = 0; | ||
345 | } | ||
346 | |||
347 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
348 | }else if (domain == Domain.Ecore) { | ||
349 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | ||
350 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
351 | double normalFactor = 5; | ||
352 | if(currentNodeTypeDistance <= 0.12 || numNodesToGenerate == 1) { | ||
353 | nodeTypeFactor = 0; | ||
354 | normalFactor = 100; | ||
355 | unfinishFactor *= 0.5; | ||
356 | } | ||
357 | |||
358 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
359 | }else { | ||
360 | double unfinishFactor = context.calculateFitness().get("CompositeUnfinishednessObjective"); | ||
361 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
362 | double normalFactor = 5; | ||
363 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { | ||
364 | nodeTypeFactor = 0; | ||
365 | normalFactor = 100; | ||
366 | //unfinishFactor *= 0.5; | ||
367 | } | ||
368 | |||
369 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + 2*g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
370 | } | ||
371 | 359 | ||
372 | }else if(configuration.realisticGuidance == RealisticGuidance.Composite_Without_Violations) { | 360 | } |
373 | if(domain == Domain.Yakindumm) { | 361 | private double calculateCurrentStateValue(int factor, int violation) { |
374 | double unfinishFactor = 50 * (1 - (double)factor / targetSize); | 362 | PartialInterpretation model = (PartialInterpretation) context.getModel(); |
375 | double nodeTypeFactor = g.getNodeTypeDistance(); | 363 | MetricDistanceGroup g = metricDistance.calculateMetricDistanceKS(model); |
376 | double normalFactor = 5; | 364 | if(configuration.realisticGuidance == RealisticGuidance.MPC) { |
377 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { | 365 | return g.getMPCDistance(); |
378 | nodeTypeFactor = 0; | 366 | }else if(configuration.realisticGuidance == RealisticGuidance.NodeActivity) { |
379 | normalFactor = 100; | 367 | return g.getNADistance(); |
380 | unfinishFactor = 0; | 368 | }else if(configuration.realisticGuidance == RealisticGuidance.OutDegree) { |
381 | } | 369 | return g.getOutDegreeDistance(); |
382 | 370 | }else if(configuration.realisticGuidance == RealisticGuidance.NodeType) { | |
383 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; | 371 | return g.getNodeTypeDistance(); |
384 | }else if (domain == Domain.Github) { | 372 | }else if(configuration.realisticGuidance == RealisticGuidance.Composite) { |
385 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | 373 | double consistenceWeights = 5 * factor / (configuration.typeScopes.maxNewElements + 2) * (1- 1.0/(1+violation)); |
386 | double nodeTypeFactor = g.getNodeTypeDistance(); | 374 | if(domain == Domain.Yakindumm) { |
387 | double normalFactor = 5; | 375 | double unfinishFactor = 50 * (1 - (double)factor / targetSize); |
388 | if(currentNodeTypeDistance <= 0.12 || numNodesToGenerate == 1) { | 376 | double nodeTypeFactor = g.getNodeTypeDistance(); |
389 | nodeTypeFactor = 0; | 377 | double normalFactor = 5; |
390 | normalFactor = 100; | 378 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { |
391 | unfinishFactor *= 0.5; | 379 | nodeTypeFactor = 0; |
392 | } | 380 | normalFactor = 100; |
393 | 381 | unfinishFactor = 0; | |
394 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; | ||
395 | } else { | ||
396 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | ||
397 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
398 | double normalFactor = 5; | ||
399 | if(currentNodeTypeDistance <= 0.20 || numNodesToGenerate == 1) { | ||
400 | nodeTypeFactor = 0; | ||
401 | normalFactor = 100; | ||
402 | unfinishFactor *= 0.5; | ||
403 | } | ||
404 | |||
405 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; | ||
406 | } | 382 | } |
383 | |||
384 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
385 | }else if (domain == Domain.Ecore) { | ||
386 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | ||
387 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
388 | double normalFactor = 5; | ||
389 | if(currentNodeTypeDistance <= 0.12 || numNodesToGenerate == 1) { | ||
390 | nodeTypeFactor = 0; | ||
391 | normalFactor = 100; | ||
392 | unfinishFactor *= 0.5; | ||
393 | } | ||
394 | |||
395 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | ||
407 | }else { | 396 | }else { |
408 | return violation; | 397 | double unfinishFactor = context.calculateFitness().get("CompositeUnfinishednessObjective"); |
409 | } | 398 | double nodeTypeFactor = g.getNodeTypeDistance(); |
410 | } | 399 | double normalFactor = 5; |
411 | 400 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { | |
412 | private int getNumberOfViolations(Collection<ViatraQueryMatcher<? extends IPatternMatch>> matchers) { | 401 | nodeTypeFactor = 0; |
413 | int violations = matchers.stream().mapToInt(m -> m.countMatches()).sum(); | 402 | normalFactor = 100; |
414 | 403 | //unfinishFactor *= 0.5; | |
415 | return violations; | 404 | } |
416 | } | 405 | |
417 | 406 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + 2*g.getMPCDistance() + 2*g.getOutDegreeDistance()) + normalFactor / 5*consistenceWeights + unfinishFactor; | |
418 | // Modified epsilon greedy choose for action based on value function | ||
419 | // with probability epsilon, choose the state with probability based on the weight | ||
420 | // with probability 1 - epsilon, choose the best state | ||
421 | // epsilon should decay w.r.t. time | ||
422 | private Object drawWithEpsilonProbabilty(List<Object> activationIds, Map<Object, Double> valueMap, double epsilon, double currentDraw) { | ||
423 | if(activationIds.size() <= 0) { | ||
424 | return null; | ||
425 | } | 407 | } |
426 | 408 | ||
427 | // if epsilon is smaller than current draw, return greedy choice | 409 | }else if(configuration.realisticGuidance == RealisticGuidance.Composite_Without_Violations) { |
428 | if(epsilon < currentDraw) { | 410 | if(domain == Domain.Yakindumm) { |
429 | return activationIds.remove(0); | 411 | double unfinishFactor = 50 * (1 - (double)factor / targetSize); |
430 | }else { | 412 | double nodeTypeFactor = g.getNodeTypeDistance(); |
431 | //else return draw with probability of the weights | 413 | double normalFactor = 5; |
432 | //find the sum of all 1-weights: the smaller the better | 414 | if(currentNodeTypeDistance <= 0.05 || numNodesToGenerate == 1) { |
433 | double sum = valueMap.values().stream().mapToDouble(d->1).sum(); | 415 | nodeTypeFactor = 0; |
434 | double rand = Math.random() * sum; | 416 | normalFactor = 100; |
435 | double iterator = 0.0; | 417 | unfinishFactor = 0; |
436 | Object idToReturn = null; | 418 | } |
437 | 419 | ||
438 | // draw an item with probability | 420 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; |
439 | for(Object o : valueMap.keySet()) { | 421 | }else if (domain == Domain.Github) { |
440 | iterator += (1); | 422 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); |
441 | if(rand < iterator) { | 423 | double nodeTypeFactor = g.getNodeTypeDistance(); |
442 | idToReturn = o; | 424 | double normalFactor = 5; |
443 | break; | 425 | if(currentNodeTypeDistance <= 0.12 || numNodesToGenerate == 1) { |
444 | } | 426 | nodeTypeFactor = 0; |
427 | normalFactor = 100; | ||
428 | unfinishFactor *= 0.5; | ||
429 | } | ||
430 | |||
431 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; | ||
432 | } else { | ||
433 | double unfinishFactor = 100 * (1 - (double)factor / targetSize); | ||
434 | double nodeTypeFactor = g.getNodeTypeDistance(); | ||
435 | double normalFactor = 5; | ||
436 | if(currentNodeTypeDistance <= 0.20 || numNodesToGenerate == 1) { | ||
437 | nodeTypeFactor = 0; | ||
438 | normalFactor = 100; | ||
439 | unfinishFactor *= 0.5; | ||
445 | } | 440 | } |
446 | 441 | ||
447 | //delete the item from the list | 442 | return 100*(nodeTypeFactor) + normalFactor*(2*g.getNADistance() + g.getMPCDistance() + 2*g.getOutDegreeDistance()) + unfinishFactor; |
448 | activationIds.remove(idToReturn); | ||
449 | valueMap.remove(idToReturn); | ||
450 | return idToReturn; | ||
451 | } | 443 | } |
444 | }else { | ||
445 | return violation; | ||
452 | } | 446 | } |
447 | } | ||
448 | |||
449 | private int getNumberOfViolations(Collection<ViatraQueryMatcher<? extends IPatternMatch>> matchers) { | ||
450 | int violations = matchers.stream().mapToInt(m -> m.countMatches()).sum(); | ||
453 | 451 | ||
454 | private List<Object> selectActivation() { | 452 | return violations; |
455 | List<Object> activationIds; | 453 | } |
456 | try { | 454 | |
457 | activationIds = new ArrayList<Object>(context.getCurrentActivationIds()); | 455 | // Modified epsilon greedy choose for action based on value function |
458 | if(stateAndActivations.containsKey(context.getCurrentStateId())) { | 456 | // with probability epsilon, choose the state with probability based on the weight |
459 | activationIds.removeAll(stateAndActivations.get(context.getCurrentStateId())); | 457 | // with probability 1 - epsilon, choose the best state |
458 | // epsilon should decay w.r.t. time | ||
459 | private Object drawWithEpsilonProbabilty(List<Object> activationIds, Map<Object, Double> valueMap, double epsilon, double currentDraw) { | ||
460 | if(activationIds.size() <= 0) { | ||
461 | return null; | ||
462 | } | ||
463 | |||
464 | // if epsilon is smaller than current draw, return greedy choice | ||
465 | if(epsilon < currentDraw) { | ||
466 | return activationIds.remove(0); | ||
467 | }else { | ||
468 | //else return draw with probability of the weights | ||
469 | //find the sum of all 1-weights: the smaller the better | ||
470 | double sum = valueMap.values().stream().mapToDouble(d->1).sum(); | ||
471 | double rand = Math.random() * sum; | ||
472 | double iterator = 0.0; | ||
473 | Object idToReturn = null; | ||
474 | |||
475 | // draw an item with probability | ||
476 | for(Object o : valueMap.keySet()) { | ||
477 | iterator += (1); | ||
478 | if(rand < iterator) { | ||
479 | idToReturn = o; | ||
480 | break; | ||
460 | } | 481 | } |
461 | Collections.shuffle(activationIds); | ||
462 | } catch (NullPointerException e) { | ||
463 | numberOfStatecoderFail++; | ||
464 | activationIds = Collections.emptyList(); | ||
465 | } | 482 | } |
466 | return activationIds; | 483 | |
484 | //delete the item from the list | ||
485 | activationIds.remove(idToReturn); | ||
486 | valueMap.remove(idToReturn); | ||
487 | return idToReturn; | ||
467 | } | 488 | } |
489 | } | ||
490 | |||
491 | private List<Object> selectActivation() { | ||
492 | List<Object> activationIds; | ||
493 | try { | ||
494 | activationIds = this.activationSelector.randomizeActivationIDs(context.getUntraversedActivationIds()); | ||
495 | } catch (NullPointerException e) { | ||
496 | numberOfStatecoderFail++; | ||
497 | activationIds = Collections.emptyList(); | ||
498 | } | ||
499 | return activationIds; | ||
500 | } | ||
468 | 501 | ||
469 | private void checkForSolution(final Fitness fittness) { | 502 | private void checkForSolution(final Fitness fittness) { |
470 | if (fittness.isSatisifiesHardObjectives()) { | 503 | if (fittness.isSatisifiesHardObjectives()) { |
471 | logger.debug("Solution Found!!"); | 504 | logger.debug("Solution Found!!"); |
472 | logger.debug("# violations: " + (getNumberOfViolations(mustMatchers))); | 505 | logger.debug("# violations: " + (getNumberOfViolations(mustMatchers))); |
473 | if (solutionStoreWithDiversityDescriptor.isDifferent(context)) { | 506 | if (solutionStoreWithDiversityDescriptor.isDifferent(context)) { |
474 | solutionStoreWithCopy.newSolution(context); | 507 | solutionStoreWithCopy.newSolution(context); |
475 | solutionStoreWithDiversityDescriptor.newSolution(context); | 508 | solutionStoreWithDiversityDescriptor.newSolution(context); |
476 | solutionStore.newSolution(context); | 509 | solutionStore.newSolution(context); |
477 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolution); | 510 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolutions); |
478 | 511 | ||
479 | logger.debug("Found a solution."); | 512 | logger.debug("Found a solution."); |
480 | } | ||
481 | } | 513 | } |
482 | } | 514 | } |
515 | } | ||
516 | |||
517 | public List<String> times = new LinkedList<String>(); | ||
518 | private void saveTimes() { | ||
519 | long forwardTime = context.getDesignSpaceManager().getForwardTime()/1000000; | ||
520 | long backtrackingTime = context.getDesignSpaceManager().getBacktrackingTime()/1000000; | ||
521 | long statecoderTime = ((NeighbourhoodBasedPartialInterpretationStateCoder)this.context.getStateCoder()).getStatecoderRuntime()/1000000; | ||
522 | long solutionCopy = solutionStoreWithCopy.getSumRuntime()/1000000; | ||
523 | long activationSelection = this.activationSelector.getRuntime()/1000000; | ||
524 | // long numericalSolverSumTime = this.numericSolver.getRuntime()/1000000; | ||
525 | // long numericalSolverProblemForming = this.numericSolver.getSolverSolvingProblem()/1000000; | ||
526 | // long numericalSolverSolving = this.numericSolver.getSolverSolvingProblem()/1000000; | ||
527 | // long numericalSolverInterpreting = this.numericSolver.getSolverSolution()/1000000; | ||
528 | long metricCalculationTime = this.method.getStatistics().metricCalculationTime / 1000000; | ||
529 | this.times.add( | ||
530 | "(TransformationExecutionTime"+method.getStatistics().transformationExecutionTime/1000000+ | ||
531 | "|ForwardTime:"+forwardTime+ | ||
532 | "|Backtrackingtime:"+backtrackingTime+ | ||
533 | "|StateCoderTime:"+statecoderTime+ | ||
534 | "|SolutionCopyTime:"+solutionCopy+ | ||
535 | "|ActivationSelectionTime:"+activationSelection+ | ||
536 | //"|NumericalSolverSumTime:"+numericalSolverSumTime+ | ||
537 | //"|NumericalSolverProblemFormingTime:"+numericalSolverProblemForming+ | ||
538 | //"|NumericalSolverSolvingTime:"+numericalSolverSolving+ | ||
539 | //"|NumericalSolverInterpretingSolution:"+numericalSolverInterpreting+ | ||
540 | "|MetricCalculationTime:"+metricCalculationTime + ")" | ||
541 | ); | ||
542 | |||
543 | } | ||
483 | 544 | ||
484 | @Override | 545 | @Override |
485 | public void interruptStrategy() { | 546 | public void interruptStrategy() { |
486 | isInterrupted = true; | 547 | isInterrupted = true; |
487 | } | 548 | } |
488 | 549 | ||
489 | 550 | ||
490 | private TrajectoryWithFitness selectState() { | 551 | private TrajectoryWithFitness selectState() { |
491 | int randomNumber = random.nextInt(configuration.randomBacktrackChance); | 552 | int randomNumber = random.nextInt(configuration.randomBacktrackChance); |
492 | if (randomNumber == 0) { | 553 | if (randomNumber == 0) { |
493 | int elements = trajectoiresToExplore.size(); | 554 | int elements = trajectoiresToExplore.size(); |
494 | int randomElementIndex = random.nextInt(elements); | 555 | int randomElementIndex = random.nextInt(elements); |
495 | logger.debug("Randomly backtract to the " + randomElementIndex + " best solution..."); | 556 | logger.debug("Randomly backtract to the " + randomElementIndex + " best solution..."); |
496 | Iterator<TrajectoryWithFitness> iterator = trajectoiresToExplore.iterator(); | 557 | Iterator<TrajectoryWithFitness> iterator = trajectoiresToExplore.iterator(); |
497 | while (randomElementIndex != 0) { | 558 | while (randomElementIndex != 0) { |
498 | iterator.next(); | 559 | iterator.next(); |
499 | randomElementIndex--; | 560 | randomElementIndex--; |
500 | } | 561 | } |
501 | TrajectoryWithFitness res = iterator.next(); | 562 | TrajectoryWithFitness res = iterator.next(); |
502 | if (res == null) { | 563 | if (res == null) { |
503 | return trajectoiresToExplore.element(); | ||
504 | } else { | ||
505 | return res; | ||
506 | } | ||
507 | } else { | ||
508 | return trajectoiresToExplore.element(); | 564 | return trajectoiresToExplore.element(); |
565 | } else { | ||
566 | return res; | ||
509 | } | 567 | } |
510 | } | 568 | } else { |
511 | 569 | return trajectoiresToExplore.element(); | |
570 | } | ||
571 | } | ||
572 | |||
512 | // private void logCurrentStateMetric() { | 573 | // private void logCurrentStateMetric() { |
513 | // if(this.configuration.documentationLevel != DocumentationLevel.NONE || workspace == null) { | 574 | // if(this.configuration.documentationLevel != DocumentationLevel.NONE || workspace == null) { |
514 | // return; | 575 | // return; |
@@ -518,77 +579,80 @@ public class HillClimbingOnRealisticMetricStrategyForModelGeneration implements | |||
518 | // PartialInterpretationMetric.calculateMetric(interpretation, "debug/metric/" + context.getModel().hashCode(), context.getCurrentStateId().toString()); | 579 | // PartialInterpretationMetric.calculateMetric(interpretation, "debug/metric/" + context.getModel().hashCode(), context.getCurrentStateId().toString()); |
519 | // } | 580 | // } |
520 | 581 | ||
521 | public void visualiseCurrentState() { | 582 | public void visualiseCurrentState() { |
522 | PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugCongiguration.partialInterpretatioVisualiser; | 583 | PartialInterpretationVisualiser partialInterpretatioVisualiser = configuration.debugConfiguration.partialInterpretatioVisualiser; |
523 | if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) { | 584 | if(partialInterpretatioVisualiser != null && this.configuration.documentationLevel == DocumentationLevel.FULL && workspace != null) { |
524 | PartialInterpretation p = (PartialInterpretation) (context.getModel()); | 585 | PartialInterpretation p = (PartialInterpretation) (context.getModel()); |
525 | int id = ++numberOfPrintedModel; | 586 | int id = ++numberOfPrintedModel; |
526 | if (id % configuration.debugCongiguration.partalInterpretationVisualisationFrequency == 0) { | 587 | if (id % configuration.debugConfiguration.partalInterpretationVisualisationFrequency == 0) { |
527 | PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); | 588 | PartialInterpretationVisualisation visualisation = partialInterpretatioVisualiser.visualiseConcretization(p); |
528 | visualisation.writeToFile(workspace, String.format("state%09d.png", id)); | 589 | logger.debug("Visualizing state: " + id + " (" + context.getDesignSpaceManager().getCurrentState() + ")"); |
529 | } | 590 | String name = String.format("state%09d", id); |
591 | visualisation.writeToFile(workspace, name + ".png"); | ||
592 | workspace.writeModel((EObject) context.getModel(), name + ".xmi"); | ||
530 | } | 593 | } |
531 | } | 594 | } |
595 | } | ||
532 | 596 | ||
533 | protected boolean checkConsistency(TrajectoryWithFitness t) { | 597 | protected boolean checkConsistency(TrajectoryWithFitness t) { |
534 | LogicReasoner internalIncosnsitencyDetector = configuration.internalConsistencyCheckerConfiguration.internalIncosnsitencyDetector; | 598 | LogicReasoner internalIncosnsitencyDetector = configuration.internalConsistencyCheckerConfiguration.internalIncosnsitencyDetector; |
535 | if (internalIncosnsitencyDetector!= null) { | 599 | if (internalIncosnsitencyDetector!= null) { |
536 | int id = ++numberOfSolverCalls; | 600 | int id = ++numberOfSolverCalls; |
537 | if (id % configuration.internalConsistencyCheckerConfiguration.incternalConsistencyCheckingFrequency == 0) { | 601 | if (id % configuration.internalConsistencyCheckerConfiguration.incternalConsistencyCheckingFrequency == 0) { |
538 | try { | 602 | try { |
539 | PartialInterpretation interpretation = (PartialInterpretation) (context.getModel()); | 603 | PartialInterpretation interpretation = (PartialInterpretation) (context.getModel()); |
540 | PartialInterpretation copied = EcoreUtil.copy(interpretation); | 604 | PartialInterpretation copied = EcoreUtil.copy(interpretation); |
541 | this.partialInterpretation2Logic.transformPartialIntepretation2Logic(copied.getProblem(), copied); | 605 | this.partialInterpretation2Logic.transformPartialIntepretation2Logic(copied.getProblem(), copied); |
542 | LogicProblem newProblem = copied.getProblem(); | 606 | LogicProblem newProblem = copied.getProblem(); |
543 | 607 | ||
544 | this.configuration.typeScopes.maxNewElements = interpretation.getMaxNewElements(); | 608 | this.configuration.typeScopes.maxNewElements = interpretation.getMaxNewElements(); |
545 | this.configuration.typeScopes.minNewElements = interpretation.getMinNewElements(); | 609 | this.configuration.typeScopes.minNewElements = interpretation.getMinNewElements(); |
546 | LogicResult result = internalIncosnsitencyDetector.solve(newProblem, configuration, workspace); | 610 | LogicResult result = internalIncosnsitencyDetector.solve(newProblem, configuration, workspace); |
547 | if (result instanceof InconsistencyResult) { | 611 | if (result instanceof InconsistencyResult) { |
548 | logger.debug("Solver found an Inconsistency!"); | 612 | logger.debug("Solver found an Inconsistency!"); |
549 | removeSubtreeFromQueue(t); | 613 | removeSubtreeFromQueue(t); |
550 | return true; | 614 | return true; |
551 | } else if (result instanceof ModelResult) { | 615 | } else if (result instanceof ModelResult) { |
552 | logger.debug("Solver found a model!"); | 616 | logger.debug("Solver found a model!"); |
553 | solutionStore.newSolution(context); | 617 | solutionStore.newSolution(context); |
554 | 618 | ||
555 | this.modelResultByInternalSolver = (ModelResult) result; | 619 | this.modelResultByInternalSolver = (ModelResult) result; |
556 | return true; | 620 | return true; |
557 | } else { | 621 | } else { |
558 | logger.debug("Failed consistency check."); | 622 | logger.debug("Failed consistency check."); |
559 | return false; | ||
560 | } | ||
561 | } catch (Exception e) { | ||
562 | logger.debug("Problem with internal consistency checking: "+e.getMessage()); | ||
563 | e.printStackTrace(); | ||
564 | return false; | 623 | return false; |
565 | } | 624 | } |
625 | } catch (Exception e) { | ||
626 | logger.debug("Problem with internal consistency checking: "+e.getMessage()); | ||
627 | e.printStackTrace(); | ||
628 | return false; | ||
566 | } | 629 | } |
567 | |||
568 | } | 630 | } |
569 | return false; | ||
570 | } | ||
571 | 631 | ||
572 | protected void removeSubtreeFromQueue(TrajectoryWithFitness t) { | ||
573 | PriorityQueue<TrajectoryWithFitness> previous = this.trajectoiresToExplore; | ||
574 | this.trajectoiresToExplore = new PriorityQueue<>(this.comparator); | ||
575 | for (TrajectoryWithFitness trajectoryWithFitness : previous) { | ||
576 | if (!containsAsSubstring(trajectoryWithFitness.trajectory, t.trajectory)) { | ||
577 | this.trajectoiresToExplore.add(trajectoryWithFitness); | ||
578 | } else { | ||
579 | logger.debug("State has been excluded due to inherent inconsistency"); | ||
580 | } | ||
581 | } | ||
582 | } | 632 | } |
633 | return false; | ||
634 | } | ||
583 | 635 | ||
584 | private boolean containsAsSubstring(Object[] full, Object[] substring) { | 636 | protected void removeSubtreeFromQueue(TrajectoryWithFitness t) { |
585 | if (substring.length > full.length) { | 637 | PriorityQueue<TrajectoryWithFitness> previous = this.trajectoiresToExplore; |
586 | return false; | 638 | this.trajectoiresToExplore = new PriorityQueue<>(this.comparator); |
587 | } else if (substring.length == full.length) { | 639 | for (TrajectoryWithFitness trajectoryWithFitness : previous) { |
588 | return Arrays.equals(full, substring); | 640 | if (!containsAsSubstring(trajectoryWithFitness.trajectory, t.trajectory)) { |
641 | this.trajectoiresToExplore.add(trajectoryWithFitness); | ||
589 | } else { | 642 | } else { |
590 | Object[] part = Arrays.copyOfRange(full, 0, substring.length); | 643 | logger.debug("State has been excluded due to inherent inconsistency"); |
591 | return Arrays.equals(part, substring); | ||
592 | } | 644 | } |
593 | } | 645 | } |
646 | } | ||
647 | |||
648 | private boolean containsAsSubstring(Object[] full, Object[] substring) { | ||
649 | if (substring.length > full.length) { | ||
650 | return false; | ||
651 | } else if (substring.length == full.length) { | ||
652 | return Arrays.equals(full, substring); | ||
653 | } else { | ||
654 | Object[] part = Arrays.copyOfRange(full, 0, substring.length); | ||
655 | return Arrays.equals(part, substring); | ||
656 | } | ||
657 | } | ||
594 | } | 658 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend new file mode 100644 index 00000000..2e039ca2 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/InconsistentScopeGlobalConstraint.xtend | |||
@@ -0,0 +1,25 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint | ||
4 | import org.eclipse.viatra.dse.base.ThreadContext | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
6 | |||
7 | class InconsistentScopeGlobalConstraint implements IGlobalConstraint { | ||
8 | |||
9 | override init(ThreadContext context) { | ||
10 | // Nothing to initialize. | ||
11 | } | ||
12 | |||
13 | override createNew() { | ||
14 | this | ||
15 | } | ||
16 | |||
17 | override getName() { | ||
18 | class.name | ||
19 | } | ||
20 | |||
21 | override checkGlobalConstraint(ThreadContext context) { | ||
22 | val partialModel = context.model as PartialInterpretation | ||
23 | partialModel.minNewElements <= partialModel.maxNewElements || partialModel.maxNewElements < 0 | ||
24 | } | ||
25 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend new file mode 100644 index 00000000..39ef5f9a --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/LoggerSolutionFoundHandler.xtend | |||
@@ -0,0 +1,24 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration | ||
4 | import org.apache.log4j.Logger | ||
5 | import org.eclipse.viatra.dse.api.SolutionTrajectory | ||
6 | import org.eclipse.viatra.dse.base.ThreadContext | ||
7 | import org.eclipse.viatra.dse.solutionstore.ISolutionFoundHandler | ||
8 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
9 | |||
10 | @FinalFieldsConstructor | ||
11 | class LoggerSolutionFoundHandler implements ISolutionFoundHandler { | ||
12 | val ViatraReasonerConfiguration configuration | ||
13 | |||
14 | val logger = Logger.getLogger(SolutionCopier) | ||
15 | |||
16 | override solutionFound(ThreadContext context, SolutionTrajectory trajectory) { | ||
17 | configuration.progressMonitor.workedModelFound(configuration.solutionScope.numberOfRequiredSolutions) | ||
18 | logger.debug("Found a solution.") | ||
19 | } | ||
20 | |||
21 | override solutionTriedToSave(ThreadContext context, SolutionTrajectory trajectory) { | ||
22 | // We are not interested in invalid solutions, ignore. | ||
23 | } | ||
24 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend index 9fc6853c..27208cf4 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ModelGenerationCompositeObjective.xtend | |||
@@ -1,99 +1,123 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import com.google.common.collect.ImmutableList | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ViatraReasonerConfiguration | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.IThreeValuedObjective | ||
3 | import java.util.Comparator | 7 | import java.util.Comparator |
4 | import java.util.List | 8 | import java.util.List |
5 | import org.eclipse.viatra.dse.base.ThreadContext | 9 | import org.eclipse.viatra.dse.base.ThreadContext |
6 | import org.eclipse.viatra.dse.objectives.Comparators | 10 | import org.eclipse.viatra.dse.objectives.Comparators |
7 | import org.eclipse.viatra.dse.objectives.IObjective | 11 | import org.eclipse.viatra.dse.objectives.IObjective |
8 | import org.eclipse.viatra.dse.objectives.impl.BaseObjective | 12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PrimitiveElement |
9 | 13 | ||
10 | //class ViatraReasonerNumbers { | 14 | class ModelGenerationCompositeObjective implements IThreeValuedObjective { |
11 | // public static val scopePriority = 2 | 15 | val IObjective scopeObjective |
12 | // public static val unfinishedMultiplicityPriority = 2 | ||
13 | // public static val unifinshedWFPriority = 2 | ||
14 | // //public static val complexityPriority = 4 | ||
15 | // | ||
16 | // public static val scopeWeigth = 1.0 | ||
17 | // public static val unfinishedMultiplicityWeigth = 1.5 | ||
18 | // public static val unfinishedWFWeigth = 1.5 | ||
19 | // //public static val complexityWeigth = 0.1 | ||
20 | // | ||
21 | // public static val useCompositeObjective = true | ||
22 | // public static val compositePriority = 2 | ||
23 | //} | ||
24 | |||
25 | class ModelGenerationCompositeObjective implements IObjective{ | ||
26 | val ScopeObjective scopeObjective | ||
27 | val List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives | 16 | val List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives |
28 | val UnfinishedWFObjective unfinishedWFObjective | 17 | val UnfinishedWFObjective unfinishedWFObjective |
29 | var boolean isWFOptional = false; | 18 | var PartialInterpretation model = null |
19 | val int scopeWeight | ||
20 | val int conaintmentWeight | ||
21 | val int nonContainmentWeight | ||
22 | val int unfinishedWFWeight | ||
30 | 23 | ||
31 | public new( | 24 | new( |
32 | ScopeObjective scopeObjective, | 25 | IObjective scopeObjective, |
26 | List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives, | ||
27 | UnfinishedWFObjective unfinishedWFObjective, | ||
28 | ViatraReasonerConfiguration configuration) | ||
29 | { | ||
30 | this( | ||
31 | scopeObjective, unfinishedMultiplicityObjectives, unfinishedWFObjective, | ||
32 | configuration.scopeWeight, configuration.conaintmentWeight, configuration.nonContainmentWeight, | ||
33 | configuration.unfinishedWFWeight | ||
34 | ) | ||
35 | } | ||
36 | |||
37 | new( | ||
38 | IObjective scopeObjective, | ||
33 | List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives, | 39 | List<UnfinishedMultiplicityObjective> unfinishedMultiplicityObjectives, |
34 | UnfinishedWFObjective unfinishedWFObjective, | 40 | UnfinishedWFObjective unfinishedWFObjective, |
35 | boolean isWFOptional) | 41 | int scopeWeight, int conaintmentWeight, int nonContainmentWeight, int unfinishedWFWeight) |
36 | { | 42 | { |
37 | this.scopeObjective = scopeObjective | 43 | this.scopeObjective = scopeObjective |
38 | this.unfinishedMultiplicityObjectives = unfinishedMultiplicityObjectives | 44 | this.unfinishedMultiplicityObjectives = unfinishedMultiplicityObjectives |
39 | this.unfinishedWFObjective = unfinishedWFObjective | 45 | this.unfinishedWFObjective = unfinishedWFObjective |
40 | this.isWFOptional = isWFOptional; | 46 | |
41 | } | 47 | this.scopeWeight = scopeWeight |
42 | 48 | this.conaintmentWeight = conaintmentWeight | |
43 | def getIsWFOptional(){ | 49 | this.nonContainmentWeight = nonContainmentWeight |
44 | return this.isWFOptional; | 50 | this.unfinishedWFWeight = unfinishedWFWeight |
45 | } | 51 | } |
46 | 52 | ||
47 | override init(ThreadContext context) { | 53 | override init(ThreadContext context) { |
54 | model = context.model as PartialInterpretation | ||
48 | this.scopeObjective.init(context) | 55 | this.scopeObjective.init(context) |
49 | this.unfinishedMultiplicityObjectives.forEach[it.init(context)] | 56 | this.unfinishedMultiplicityObjectives.forEach[it.init(context)] |
50 | this.unfinishedWFObjective.init(context) | 57 | this.unfinishedWFObjective.init(context) |
51 | } | 58 | } |
52 | 59 | ||
53 | override createNew() { | 60 | override createNew() { |
54 | return new ModelGenerationCompositeObjective( | 61 | return new ModelGenerationCompositeObjective( |
55 | this.scopeObjective, this.unfinishedMultiplicityObjectives, this.unfinishedWFObjective, this.isWFOptional) | 62 | scopeObjective.createNew, |
63 | ImmutableList.copyOf(unfinishedMultiplicityObjectives.map[createNew as UnfinishedMultiplicityObjective]), | ||
64 | unfinishedWFObjective.createNew as UnfinishedWFObjective, | ||
65 | scopeWeight, conaintmentWeight, nonContainmentWeight, unfinishedWFWeight | ||
66 | ) | ||
56 | } | 67 | } |
57 | 68 | ||
58 | override getComparator() { Comparators.LOWER_IS_BETTER } | 69 | override getComparator() { Comparators.LOWER_IS_BETTER } |
70 | |||
59 | override getFitness(ThreadContext context) { | 71 | override getFitness(ThreadContext context) { |
60 | var sum = 0.0 | 72 | |
61 | val scopeFitnes = scopeObjective.getFitness(context) | 73 | val scopeFitnes = scopeObjective.getFitness(context) |
62 | //val unfinishedMultiplicitiesFitneses = unfinishedMultiplicityObjectives.map[x|x.getFitness(context)] | 74 | val unfinishedWFsFitness = unfinishedWFObjective.getFitness(context) |
63 | 75 | ||
64 | sum+=scopeFitnes | 76 | var containmentMultiplicity = 0.0 |
65 | var multiplicity = 0.0 | 77 | var nonContainmentMultiplicity = 0.0 |
66 | for(multiplicityObjective : unfinishedMultiplicityObjectives) { | 78 | for(multiplicityObjective : unfinishedMultiplicityObjectives) { |
67 | multiplicity+=multiplicityObjective.getFitness(context)//*0.5 | 79 | val multiplicity = multiplicityObjective.getFitness(context) |
80 | // println(multiplicityObjective.name + "=" + multiplicity) | ||
81 | if(multiplicityObjective.containment) { | ||
82 | containmentMultiplicity+=multiplicity | ||
83 | } else { | ||
84 | nonContainmentMultiplicity+=multiplicity | ||
85 | } | ||
86 | |||
68 | } | 87 | } |
69 | sum+=multiplicity | ||
70 | 88 | ||
71 | // the WF can be optional when generating realistic models | 89 | var sum = 0.0 |
72 | if(!isWFOptional){ | 90 | sum += scopeFitnes*scopeWeight |
73 | val unfinishedWFsFitness = unfinishedWFObjective.getFitness(context) | 91 | sum += containmentMultiplicity*conaintmentWeight |
74 | sum += unfinishedWFsFitness//*0.5 | 92 | sum += nonContainmentMultiplicity*nonContainmentWeight |
75 | } | 93 | sum += unfinishedWFsFitness*unfinishedWFWeight |
76 | 94 | ||
77 | //println('''Sum=«sum»|Scope=«scopeFitnes»|Multiplicity=«multiplicity»|WFs=«unfinishedWFsFitness»''') | 95 | // println('''scope=«scopeFitnes», containment=«containmentMultiplicity», nonContainment=«nonContainmentMultiplicity», wf=«unfinishedWFsFitness», sum=«sum»''') |
78 | 96 | ||
79 | return sum | 97 | return sum |
80 | } | 98 | } |
81 | 99 | ||
82 | override getLevel() { 2 } | 100 | override getWorstPossibleFitness(ThreadContext threadContext) { |
83 | override getName() { "CompositeUnfinishednessObjective"} | 101 | Double.POSITIVE_INFINITY |
84 | def getObjective(){ | ||
85 | return this.unfinishedMultiplicityObjectives; | ||
86 | } | 102 | } |
87 | 103 | ||
104 | override getBestPossibleFitness(ThreadContext threadContext) { | ||
105 | 0.0 | ||
106 | } | ||
107 | |||
108 | override getLevel() { 2 } | ||
109 | |||
110 | override getName() { "CompositeUnfinishednessObjective" } | ||
111 | |||
88 | override isHardObjective() { true } | 112 | override isHardObjective() { true } |
89 | override satisifiesHardObjective(Double fitness) { fitness <= 0.001 } | 113 | |
90 | 114 | override satisifiesHardObjective(Double fitness) { fitness < 0.01 } | |
91 | 115 | ||
92 | override setComparator(Comparator<Double> comparator) { | 116 | override setComparator(Comparator<Double> comparator) { |
93 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 117 | throw new UnsupportedOperationException("Model generation objective comparator cannot be set.") |
94 | } | 118 | } |
119 | |||
95 | override setLevel(int level) { | 120 | override setLevel(int level) { |
96 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 121 | throw new UnsupportedOperationException("Model generation objective level cannot be set.") |
97 | } | 122 | } |
98 | 123 | } | |
99 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/NumericSolver.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/NumericSolver.xtend new file mode 100644 index 00000000..70e8e9c2 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/NumericSolver.xtend | |||
@@ -0,0 +1,192 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatra2logic.NumericTranslator | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.BooleanElement | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.IntegerElement | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PrimitiveElement | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.RealElement | ||
9 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.StringElement | ||
10 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.ModelGenerationMethod | ||
11 | import java.math.BigDecimal | ||
12 | import java.util.HashMap | ||
13 | import java.util.LinkedHashMap | ||
14 | import java.util.LinkedHashSet | ||
15 | import java.util.List | ||
16 | import java.util.Map | ||
17 | import org.eclipse.emf.ecore.EObject | ||
18 | import org.eclipse.viatra.dse.base.ThreadContext | ||
19 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
20 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
21 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
22 | |||
23 | class NumericSolver { | ||
24 | val ModelGenerationMethod method | ||
25 | var ThreadContext threadContext | ||
26 | val constraint2MustUnitPropagationPrecondition = new HashMap<PConstraint,ViatraQueryMatcher<? extends IPatternMatch>> | ||
27 | val constraint2CurrentUnitPropagationPrecondition = new HashMap<PConstraint,ViatraQueryMatcher<? extends IPatternMatch>> | ||
28 | NumericTranslator t = new NumericTranslator | ||
29 | |||
30 | val boolean intermediateConsistencyCheck | ||
31 | val boolean caching; | ||
32 | Map<LinkedHashMap<PConstraint, Iterable<List<Integer>>>,Boolean> satisfiabilityCache = new HashMap | ||
33 | |||
34 | var long runtime = 0 | ||
35 | var long cachingTime = 0 | ||
36 | var int numberOfSolverCalls = 0 | ||
37 | var int numberOfCachedSolverCalls = 0 | ||
38 | |||
39 | new(ModelGenerationMethod method, boolean intermediateConsistencyCheck, boolean caching) { | ||
40 | this.method = method | ||
41 | this.intermediateConsistencyCheck = intermediateConsistencyCheck | ||
42 | this.caching = caching | ||
43 | } | ||
44 | |||
45 | def init(ThreadContext context) { | ||
46 | // This makes the NumericSolver single-threaded, | ||
47 | // but that's not a problem, because we only use the solver on a single thread anyways. | ||
48 | this.threadContext = context | ||
49 | val engine = threadContext.queryEngine | ||
50 | for(entry : method.mustUnitPropagationPreconditions.entrySet) { | ||
51 | val constraint = entry.key | ||
52 | val querySpec = entry.value | ||
53 | val matcher = querySpec.getMatcher(engine); | ||
54 | constraint2MustUnitPropagationPrecondition.put(constraint,matcher) | ||
55 | } | ||
56 | for(entry : method.currentUnitPropagationPreconditions.entrySet) { | ||
57 | val constraint = entry.key | ||
58 | val querySpec = entry.value | ||
59 | val matcher = querySpec.getMatcher(engine); | ||
60 | constraint2CurrentUnitPropagationPrecondition.put(constraint,matcher) | ||
61 | } | ||
62 | } | ||
63 | |||
64 | def getRuntime(){runtime} | ||
65 | def getCachingTime(){cachingTime} | ||
66 | def getNumberOfSolverCalls(){numberOfSolverCalls} | ||
67 | def getNumberOfCachedSolverCalls(){numberOfCachedSolverCalls} | ||
68 | def getSolverFormingProblem(){this.t.formingProblemTime} | ||
69 | def getSolverSolvingProblem(){this.t.solvingProblemTime} | ||
70 | def getSolverSolution(){this.t.formingSolutionTime} | ||
71 | |||
72 | def boolean maySatisfiable() { | ||
73 | if(intermediateConsistencyCheck) { | ||
74 | return isSatisfiable(this.constraint2MustUnitPropagationPrecondition) | ||
75 | } else { | ||
76 | return true | ||
77 | } | ||
78 | } | ||
79 | def boolean currentSatisfiable() { | ||
80 | isSatisfiable(this.constraint2CurrentUnitPropagationPrecondition) | ||
81 | } | ||
82 | |||
83 | private def boolean isSatisfiable(Map<PConstraint,ViatraQueryMatcher<? extends IPatternMatch>> matches) { | ||
84 | val start = System.nanoTime | ||
85 | var boolean finalResult | ||
86 | if(matches.empty){ | ||
87 | finalResult=true | ||
88 | } else { | ||
89 | val propagatedConstraints = new HashMap | ||
90 | for(entry : matches.entrySet) { | ||
91 | val constraint = entry.key | ||
92 | //println(constraint) | ||
93 | val allMatches = entry.value.allMatches.map[it.toArray] | ||
94 | //println(allMatches.toList) | ||
95 | propagatedConstraints.put(constraint,allMatches) | ||
96 | } | ||
97 | if(propagatedConstraints.values.forall[empty]) { | ||
98 | finalResult=true | ||
99 | } else { | ||
100 | if(caching) { | ||
101 | val code = getCode(propagatedConstraints) | ||
102 | val cachedResult = satisfiabilityCache.get(code) | ||
103 | if(cachedResult === null) { | ||
104 | // println('''new problem, call solver''') | ||
105 | // for(entry : code.entrySet) { | ||
106 | // println('''«entry.key» -> «entry.value»''') | ||
107 | // } | ||
108 | //println(code.hashCode) | ||
109 | this.numberOfSolverCalls++ | ||
110 | val res = t.delegateIsSatisfiable(propagatedConstraints) | ||
111 | satisfiabilityCache.put(code,res) | ||
112 | finalResult=res | ||
113 | } else { | ||
114 | //println('''similar problem, answer from cache''') | ||
115 | finalResult=cachedResult | ||
116 | this.numberOfCachedSolverCalls++ | ||
117 | } | ||
118 | } else { | ||
119 | finalResult= t.delegateIsSatisfiable(propagatedConstraints) | ||
120 | this.numberOfSolverCalls++ | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | this.runtime+=System.nanoTime-start | ||
125 | return finalResult | ||
126 | } | ||
127 | |||
128 | def getCode(HashMap<PConstraint, Iterable<Object[]>> propagatedConstraints) { | ||
129 | val start = System.nanoTime | ||
130 | val involvedObjects = new LinkedHashSet(propagatedConstraints.values.flatten.map[toList].flatten.toList).toList | ||
131 | val res = new LinkedHashMap(propagatedConstraints.mapValues[matches | matches.map[objects | objects.map[object | involvedObjects.indexOf(object)].toList]]) | ||
132 | this.cachingTime += System.nanoTime-start | ||
133 | return res | ||
134 | } | ||
135 | |||
136 | def fillSolutionCopy(Map<EObject, EObject> trace) { | ||
137 | val model = threadContext.getModel as PartialInterpretation | ||
138 | val dataObjects = model.newElements.filter(PrimitiveElement).filter[!model.openWorldElements.contains(it)].toList | ||
139 | if(constraint2CurrentUnitPropagationPrecondition.empty) { | ||
140 | fillWithDefaultValues(dataObjects,trace) | ||
141 | } else { | ||
142 | val propagatedConstraints = new HashMap | ||
143 | for(entry : constraint2CurrentUnitPropagationPrecondition.entrySet) { | ||
144 | val constraint = entry.key | ||
145 | val allMatches = entry.value.allMatches.map[it.toArray] | ||
146 | propagatedConstraints.put(constraint,allMatches) | ||
147 | } | ||
148 | |||
149 | if(propagatedConstraints.values.forall[empty]) { | ||
150 | fillWithDefaultValues(dataObjects,trace) | ||
151 | } else { | ||
152 | val solution = t.delegateGetSolution(dataObjects,propagatedConstraints) | ||
153 | fillWithSolutions(dataObjects,solution,trace) | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | def protected fillWithDefaultValues(List<PrimitiveElement> elements, Map<EObject, EObject> trace) { | ||
159 | for(element : elements) { | ||
160 | if(element.valueSet==false) { | ||
161 | val value = getDefaultValue(element) | ||
162 | val target = trace.get(element) as PrimitiveElement | ||
163 | target.fillWithValue(value) | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | |||
168 | def protected dispatch getDefaultValue(BooleanElement e) {false} | ||
169 | def protected dispatch getDefaultValue(IntegerElement e) {0} | ||
170 | def protected dispatch getDefaultValue(RealElement e) {0.0} | ||
171 | def protected dispatch getDefaultValue(StringElement e) {""} | ||
172 | |||
173 | def protected fillWithSolutions(List<PrimitiveElement> elements, Map<PrimitiveElement, Number> solution, Map<EObject, EObject> trace) { | ||
174 | for(element : elements) { | ||
175 | if(element.valueSet==false) { | ||
176 | if(solution.containsKey(element)) { | ||
177 | val value = solution.get(element) | ||
178 | val target = trace.get(element) as PrimitiveElement | ||
179 | target.fillWithValue(value) | ||
180 | } else { | ||
181 | val target = trace.get(element) as PrimitiveElement | ||
182 | target.fillWithValue(target.defaultValue) | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | |||
188 | def protected dispatch fillWithValue(BooleanElement e, Object value) {e.valueSet=true e.value=value as Boolean} | ||
189 | def protected dispatch fillWithValue(IntegerElement e, Object value) {e.valueSet=true e.value=value as Integer} | ||
190 | def protected dispatch fillWithValue(RealElement e, Object value) {e.valueSet=true e.value=BigDecimal.valueOf(value as Double) } | ||
191 | def protected dispatch fillWithValue(StringElement e, Object value) {e.valueSet=true e.value=value as String} | ||
192 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PartialModelAsLogicInterpretation.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PartialModelAsLogicInterpretation.xtend index f61c7333..b48d0831 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PartialModelAsLogicInterpretation.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PartialModelAsLogicInterpretation.xtend | |||
@@ -22,12 +22,13 @@ import java.util.List | |||
22 | import java.util.Map | 22 | import java.util.Map |
23 | import java.util.TreeSet | 23 | import java.util.TreeSet |
24 | import org.eclipse.emf.ecore.EObject | 24 | import org.eclipse.emf.ecore.EObject |
25 | import org.eclipse.xtend.lib.annotations.Accessors | ||
25 | import org.eclipse.xtext.xbase.lib.Functions.Function1 | 26 | import org.eclipse.xtext.xbase.lib.Functions.Function1 |
26 | 27 | ||
27 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 28 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
28 | 29 | ||
29 | class PartialModelAsLogicInterpretation implements LogicModelInterpretation{ | 30 | class PartialModelAsLogicInterpretation implements LogicModelInterpretation{ |
30 | val PartialInterpretation partialInterpretation | 31 | @Accessors val PartialInterpretation partialInterpretation |
31 | val Map<EObject, EObject> trace; | 32 | val Map<EObject, EObject> trace; |
32 | val Map<TypeDeclaration,PartialComplexTypeInterpretation> type2Interpretation | 33 | val Map<TypeDeclaration,PartialComplexTypeInterpretation> type2Interpretation |
33 | val Map<RelationDeclaration,PartialRelationInterpretation> relation2Interpretation | 34 | val Map<RelationDeclaration,PartialRelationInterpretation> relation2Interpretation |
@@ -153,14 +154,70 @@ class PartialModelAsLogicInterpretation implements LogicModelInterpretation{ | |||
153 | } | 154 | } |
154 | 155 | ||
155 | override getAllIntegersInStructure() { | 156 | override getAllIntegersInStructure() { |
156 | new TreeSet(this.integerForwardTrace.keySet) | 157 | new TreeSet(allIntegersWithInterpretation.values) |
158 | } | ||
159 | |||
160 | override getAllIntegersWithInterpretation() { | ||
161 | val builder = new HashMap | ||
162 | for (entry : integerForwardTrace.entrySet) { | ||
163 | builder.put(entry.value, entry.key) | ||
164 | } | ||
165 | for (element : partialInterpretation.newElements) { | ||
166 | if (element instanceof IntegerElement) { | ||
167 | builder.put(element, element.value) | ||
168 | } | ||
169 | } | ||
170 | builder | ||
157 | } | 171 | } |
158 | 172 | ||
159 | override getAllRealsInStructure() { | 173 | override getAllRealsInStructure() { |
160 | new TreeSet(this.realForwardTrace.keySet) | 174 | new TreeSet(allRealsWithInterpretation.values) |
175 | } | ||
176 | |||
177 | override getAllRealsWithInterpretation() { | ||
178 | val builder = new HashMap | ||
179 | for (entry : realForwardTrace.entrySet) { | ||
180 | builder.put(entry.value, entry.key) | ||
181 | } | ||
182 | for (element : partialInterpretation.newElements) { | ||
183 | if (element instanceof RealElement) { | ||
184 | builder.put(element, element.value) | ||
185 | } | ||
186 | } | ||
187 | builder | ||
161 | } | 188 | } |
162 | 189 | ||
163 | override getAllStringsInStructure() { | 190 | override getAllStringsInStructure() { |
164 | new TreeSet(this.stringForwardTrace.keySet) | 191 | new TreeSet(allStringsWithInterpretation.values) |
192 | } | ||
193 | |||
194 | override getAllStringsWithInterpretation() { | ||
195 | val builder = new HashMap | ||
196 | for (entry : stringForwardTrace.entrySet) { | ||
197 | builder.put(entry.value, entry.key) | ||
198 | } | ||
199 | for (element : partialInterpretation.newElements) { | ||
200 | if (element instanceof StringElement) { | ||
201 | builder.put(element, element.value) | ||
202 | } | ||
203 | } | ||
204 | builder | ||
205 | } | ||
206 | |||
207 | override getAllBooleansInStructure() { | ||
208 | new TreeSet(allBooleansWithInterpretation.values) | ||
209 | } | ||
210 | |||
211 | override getAllBooleansWithInterpretation() { | ||
212 | val builder = new HashMap | ||
213 | for (entry : booleanForwardTrace.entrySet) { | ||
214 | builder.put(entry.value, entry.key) | ||
215 | } | ||
216 | for (element : partialInterpretation.newElements) { | ||
217 | if (element instanceof BooleanElement) { | ||
218 | builder.put(element, element.value) | ||
219 | } | ||
220 | } | ||
221 | builder | ||
165 | } | 222 | } |
166 | } \ No newline at end of file | 223 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PunishSizeObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PunishSizeObjective.xtend new file mode 100644 index 00000000..bad8e4d1 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/PunishSizeObjective.xtend | |||
@@ -0,0 +1,52 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PrimitiveElement | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.AbstractThreeValuedObjective | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold | ||
8 | import org.eclipse.viatra.dse.base.ThreadContext | ||
9 | |||
10 | class PunishSizeObjective extends AbstractThreeValuedObjective { | ||
11 | static val NAME = typeof(PunishSizeObjective).name | ||
12 | |||
13 | new(ObjectiveKind kind, int level) { | ||
14 | super(NAME, kind, ObjectiveThreshold.NO_THRESHOLD, level) | ||
15 | } | ||
16 | |||
17 | override createNew() { | ||
18 | new PunishSizeObjective(kind, level) | ||
19 | } | ||
20 | |||
21 | override init(ThreadContext context) { | ||
22 | // Nothing to initialize. | ||
23 | } | ||
24 | |||
25 | override getRawFitness(ThreadContext threadContext) { | ||
26 | val model = threadContext.model | ||
27 | if (model instanceof PartialInterpretation) { | ||
28 | val size = model.newObjectCount | ||
29 | // println('''size=«size»''') | ||
30 | size as double | ||
31 | } else { | ||
32 | throw new IllegalArgumentException("notifier must be a PartialInterpretation") | ||
33 | } | ||
34 | } | ||
35 | |||
36 | override getLowestPossibleFitness(ThreadContext threadContext) { | ||
37 | getRawFitness(threadContext) | ||
38 | } | ||
39 | |||
40 | override getHighestPossibleFitness(ThreadContext threadContext) { | ||
41 | val model = threadContext.model | ||
42 | if (model instanceof PartialInterpretation) { | ||
43 | (model.newObjectCount + model.maxNewElements) as double | ||
44 | } else { | ||
45 | throw new IllegalArgumentException("notifier must be a PartialInterpretation") | ||
46 | } | ||
47 | } | ||
48 | |||
49 | private def getNewObjectCount(PartialInterpretation interpretation) { | ||
50 | interpretation.newElements.reject[it instanceof PrimitiveElement].size | ||
51 | } | ||
52 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ScopeObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ScopeObjective.xtend index 69efe0d7..b61bd20b 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ScopeObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ScopeObjective.xtend | |||
@@ -23,9 +23,9 @@ class ScopeObjective implements IObjective{ | |||
23 | 23 | ||
24 | override getFitness(ThreadContext context) { | 24 | override getFitness(ThreadContext context) { |
25 | val interpretation = context.model as PartialInterpretation | 25 | val interpretation = context.model as PartialInterpretation |
26 | var res = interpretation.minNewElements.doubleValue | 26 | var res = interpretation.minNewElementsHeuristic.doubleValue |
27 | for(scope : interpretation.scopes) { | 27 | for(scope : interpretation.scopes) { |
28 | res += scope.minNewElements*2 | 28 | res += scope.minNewElementsHeuristic * 2 |
29 | } | 29 | } |
30 | return res | 30 | return res |
31 | } | 31 | } |
@@ -41,4 +41,4 @@ class ScopeObjective implements IObjective{ | |||
41 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 41 | throw new UnsupportedOperationException("TODO: auto-generated method stub") |
42 | } | 42 | } |
43 | override getLevel() { 2 } | 43 | override getLevel() { 2 } |
44 | } \ No newline at end of file | 44 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend new file mode 100644 index 00000000..888eda18 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionCopier.xtend | |||
@@ -0,0 +1,82 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import java.util.LinkedHashMap | ||
6 | import java.util.List | ||
7 | import java.util.Map | ||
8 | import org.eclipse.emf.ecore.EObject | ||
9 | import org.eclipse.emf.ecore.util.EcoreUtil | ||
10 | import org.eclipse.viatra.dse.base.ThreadContext | ||
11 | import org.eclipse.xtend.lib.annotations.Accessors | ||
12 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
13 | |||
14 | @FinalFieldsConstructor | ||
15 | class CopiedSolution { | ||
16 | @Accessors val PartialInterpretation partialInterpretations | ||
17 | @Accessors val Map<EObject, EObject> trace | ||
18 | @Accessors val long copierRuntime | ||
19 | @Accessors var boolean current = true | ||
20 | } | ||
21 | |||
22 | /** | ||
23 | * Based on {@link SolutionStore.BestSolutionSaver}. | ||
24 | * | ||
25 | * Will also automatically fill any missing numerical values in the saved solutions | ||
26 | * using the supplied {@link NumericSolver}. | ||
27 | */ | ||
28 | class SolutionCopier { | ||
29 | val copiedSolutions = new LinkedHashMap<Object, CopiedSolution> | ||
30 | |||
31 | @Accessors NumericSolver numericSolver | ||
32 | long startTime = System.nanoTime | ||
33 | @Accessors(PUBLIC_GETTER) long totalCopierRuntime = 0 | ||
34 | |||
35 | def void copySolution(ThreadContext context, Object solutionId) { | ||
36 | val existingCopy = copiedSolutions.get(solutionId) | ||
37 | if (existingCopy === null) { | ||
38 | val copyStart = System.nanoTime | ||
39 | val solution = context.model as PartialInterpretation | ||
40 | val copier = new EcoreUtil.Copier | ||
41 | val copiedPartialInterpretation = copier.copy(solution) as PartialInterpretation | ||
42 | copier.copyReferences | ||
43 | totalCopierRuntime += System.nanoTime - copyStart | ||
44 | val copierRuntime = System.nanoTime - startTime | ||
45 | val copiedSolution = new CopiedSolution(copiedPartialInterpretation, copier, copierRuntime) | ||
46 | //numericSolver?.fillSolutionCopy(copiedSolution.trace) | ||
47 | copiedSolutions.put(solutionId, copiedSolution) | ||
48 | } else { | ||
49 | existingCopy.current = true | ||
50 | } | ||
51 | } | ||
52 | |||
53 | def void markAsObsolete(Object solutionId) { | ||
54 | val copiedSolution = copiedSolutions.get(solutionId) | ||
55 | if (copiedSolution === null) { | ||
56 | throw new IllegalStateException("No solution to mark as obsolete for state code: " + solutionId) | ||
57 | } | ||
58 | copiedSolution.current = false | ||
59 | } | ||
60 | |||
61 | def List<PartialInterpretation> getPartialInterpretations(boolean currentOnly) { | ||
62 | getListOfCopiedSolutions(currentOnly).map[partialInterpretations] | ||
63 | } | ||
64 | |||
65 | def List<Map<EObject, EObject>> getTraces(boolean currentOnly) { | ||
66 | getListOfCopiedSolutions(currentOnly).map[trace] | ||
67 | } | ||
68 | |||
69 | def List<Long> getAllCopierRuntimes(boolean currentOnly) { | ||
70 | getListOfCopiedSolutions(currentOnly).map[copierRuntime] | ||
71 | } | ||
72 | |||
73 | def List<CopiedSolution> getListOfCopiedSolutions(boolean currentOnly) { | ||
74 | val values = copiedSolutions.values | ||
75 | val filteredSolutions = if (currentOnly) { | ||
76 | values.filter[current] | ||
77 | } else { | ||
78 | values | ||
79 | } | ||
80 | ImmutableList.copyOf(filteredSolutions) | ||
81 | } | ||
82 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend index a8b7301e..4bd2c349 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithCopy.xtend | |||
@@ -1,14 +1,12 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import java.util.List | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | 3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation |
5 | import java.util.LinkedList | 4 | import java.util.LinkedList |
6 | import org.eclipse.emf.ecore.EObject | 5 | import java.util.List |
7 | import java.util.Map | 6 | import java.util.Map |
7 | import org.eclipse.emf.ecore.EObject | ||
8 | import org.eclipse.emf.ecore.util.EcoreUtil | 8 | import org.eclipse.emf.ecore.util.EcoreUtil |
9 | import org.eclipse.viatra.dse.base.ThreadContext | 9 | import org.eclipse.viatra.dse.base.ThreadContext |
10 | import java.util.TreeMap | ||
11 | import java.util.SortedMap | ||
12 | 10 | ||
13 | class SolutionStoreWithCopy { | 11 | class SolutionStoreWithCopy { |
14 | 12 | ||
@@ -25,7 +23,7 @@ class SolutionStoreWithCopy { | |||
25 | newSolution(context) | 23 | newSolution(context) |
26 | }*/ | 24 | }*/ |
27 | 25 | ||
28 | def newSolution(ThreadContext context) { | 26 | def Map<EObject,EObject> newSolution(ThreadContext context) { |
29 | //print(System.nanoTime-initTime + ";") | 27 | //print(System.nanoTime-initTime + ";") |
30 | val copyStart = System.nanoTime | 28 | val copyStart = System.nanoTime |
31 | val solution = context.model as PartialInterpretation | 29 | val solution = context.model as PartialInterpretation |
@@ -36,6 +34,7 @@ class SolutionStoreWithCopy { | |||
36 | copyTraces.add(copier) | 34 | copyTraces.add(copier) |
37 | runtime += System.nanoTime - copyStart | 35 | runtime += System.nanoTime - copyStart |
38 | solutionTimes.add(System.nanoTime-sartTime) | 36 | solutionTimes.add(System.nanoTime-sartTime) |
37 | return copier | ||
39 | } | 38 | } |
40 | def getSumRuntime() { | 39 | def getSumRuntime() { |
41 | return runtime | 40 | return runtime |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend deleted file mode 100644 index 1e7f18a8..00000000 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SolutionStoreWithDiversityDescriptor.xtend +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.neighbourhood.PartialInterpretation2ImmutableTypeLattice | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.DiversityDescriptor | ||
6 | import java.util.LinkedList | ||
7 | import java.util.List | ||
8 | import org.eclipse.viatra.dse.base.ThreadContext | ||
9 | import java.util.HashSet | ||
10 | import java.util.Set | ||
11 | |||
12 | enum DiversityGranularity { | ||
13 | Nodewise, Graphwise | ||
14 | } | ||
15 | |||
16 | class SolutionStoreWithDiversityDescriptor { | ||
17 | val DiversityDescriptor descriptor | ||
18 | DiversityGranularity granularity | ||
19 | val PartialInterpretation2ImmutableTypeLattice solutionCoder = new PartialInterpretation2ImmutableTypeLattice | ||
20 | val Set<Integer> solutionCodeList = new HashSet | ||
21 | |||
22 | var long runtime | ||
23 | var int allCheck | ||
24 | var int successfulCheck | ||
25 | |||
26 | new(DiversityDescriptor descriptor) { | ||
27 | if(descriptor.ensureDiversity) { | ||
28 | this.descriptor = descriptor | ||
29 | this.granularity = DiversityGranularity::Nodewise | ||
30 | } else { | ||
31 | this.descriptor = null | ||
32 | this.granularity = DiversityGranularity::Nodewise | ||
33 | } | ||
34 | } | ||
35 | |||
36 | def public isActive() { | ||
37 | descriptor!==null | ||
38 | } | ||
39 | |||
40 | def getSumRuntime() { | ||
41 | return runtime | ||
42 | } | ||
43 | def getSuccessRate() { | ||
44 | return successfulCheck as double / allCheck | ||
45 | } | ||
46 | |||
47 | def isDifferent(ThreadContext context) { | ||
48 | if(active) { | ||
49 | val start = System.nanoTime | ||
50 | val model = context.model as PartialInterpretation | ||
51 | var boolean isDifferent | ||
52 | if(this.granularity == DiversityGranularity::Graphwise) { | ||
53 | val code = solutionCoder.createRepresentation(model, | ||
54 | descriptor.range, | ||
55 | descriptor.parallels, | ||
56 | descriptor.maxNumber, | ||
57 | descriptor.relevantTypes, | ||
58 | descriptor.relevantRelations).modelRepresentation.hashCode | ||
59 | |||
60 | isDifferent = !solutionCodeList.contains(code) | ||
61 | } else if(this.granularity == DiversityGranularity::Nodewise){ | ||
62 | val codes = solutionCoder.createRepresentation(model, | ||
63 | descriptor.range, | ||
64 | descriptor.parallels, | ||
65 | descriptor.maxNumber, | ||
66 | descriptor.relevantTypes, | ||
67 | descriptor.relevantRelations).modelRepresentation.keySet.map[hashCode].toList | ||
68 | val differentCodes = codes.filter[!solutionCodeList.contains(it)] | ||
69 | //println(differentCodes.size) | ||
70 | |||
71 | isDifferent = differentCodes.size>=1 | ||
72 | } else { | ||
73 | throw new UnsupportedOperationException('''Unsupported diversity type: «this.granularity»''') | ||
74 | } | ||
75 | |||
76 | runtime += System.nanoTime - start | ||
77 | allCheck++ | ||
78 | if(isDifferent) { successfulCheck++ } | ||
79 | return isDifferent | ||
80 | } else { | ||
81 | allCheck++ | ||
82 | successfulCheck++ | ||
83 | return true | ||
84 | } | ||
85 | } | ||
86 | |||
87 | def canBeDifferent(ThreadContext context) { | ||
88 | return true | ||
89 | } | ||
90 | |||
91 | def newSolution(ThreadContext context) { | ||
92 | if(active) { | ||
93 | val start = System.nanoTime | ||
94 | val model = context.model as PartialInterpretation | ||
95 | if(this.granularity == DiversityGranularity::Graphwise) { | ||
96 | val code = solutionCoder.createRepresentation(model, | ||
97 | descriptor.range, | ||
98 | descriptor.parallels, | ||
99 | descriptor.maxNumber, | ||
100 | descriptor.relevantTypes, | ||
101 | descriptor.relevantRelations).modelRepresentation.hashCode | ||
102 | |||
103 | solutionCodeList += code.hashCode | ||
104 | } else if(this.granularity == DiversityGranularity::Nodewise){ | ||
105 | val codes = solutionCoder.createRepresentation(model, | ||
106 | descriptor.range, | ||
107 | descriptor.parallels, | ||
108 | descriptor.maxNumber, | ||
109 | descriptor.relevantTypes, | ||
110 | descriptor.relevantRelations).modelRepresentation.keySet.map[hashCode].toList | ||
111 | |||
112 | solutionCodeList += codes.map[it.hashCode] | ||
113 | } else { | ||
114 | throw new UnsupportedOperationException('''Unsupported diversity type: «this.granularity»''') | ||
115 | } | ||
116 | |||
117 | runtime += System.nanoTime - start | ||
118 | } | ||
119 | } | ||
120 | } \ No newline at end of file | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend new file mode 100644 index 00000000..8ed3e912 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/SurelyViolatedObjectiveGlobalConstraint.xtend | |||
@@ -0,0 +1,27 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import org.eclipse.viatra.dse.base.ThreadContext | ||
4 | import org.eclipse.viatra.dse.objectives.IGlobalConstraint | ||
5 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
6 | |||
7 | @FinalFieldsConstructor | ||
8 | class SurelyViolatedObjectiveGlobalConstraint implements IGlobalConstraint { | ||
9 | val ViatraReasonerSolutionSaver solutionSaver | ||
10 | |||
11 | override init(ThreadContext context) { | ||
12 | // Nothing to initialize. | ||
13 | } | ||
14 | |||
15 | override createNew() { | ||
16 | this | ||
17 | } | ||
18 | |||
19 | override getName() { | ||
20 | class.name | ||
21 | } | ||
22 | |||
23 | override checkGlobalConstraint(ThreadContext context) { | ||
24 | val bestFitness = DseUtils.caclulateBestPossibleFitness(context) | ||
25 | bestFitness.satisifiesHardObjectives && solutionSaver.fitnessMayBeSaved(bestFitness) | ||
26 | } | ||
27 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend index aad9a448..e1582d3b 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedMultiplicityObjective.xtend | |||
@@ -1,15 +1,15 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.MultiplicityGoalConstraintCalculator | 3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.MultiplicityGoalConstraintCalculator |
4 | import java.util.Comparator | 4 | import java.util.Comparator |
5 | import org.eclipse.viatra.dse.base.ThreadContext | 5 | import org.eclipse.viatra.dse.base.ThreadContext |
6 | import org.eclipse.viatra.dse.objectives.IObjective | ||
7 | import org.eclipse.viatra.dse.objectives.Comparators | 6 | import org.eclipse.viatra.dse.objectives.Comparators |
7 | import org.eclipse.viatra.dse.objectives.IObjective | ||
8 | 8 | ||
9 | class UnfinishedMultiplicityObjective implements IObjective { | 9 | class UnfinishedMultiplicityObjective implements IObjective { |
10 | val MultiplicityGoalConstraintCalculator unfinishedMultiplicity; | 10 | val MultiplicityGoalConstraintCalculator unfinishedMultiplicity |
11 | 11 | ||
12 | public new(MultiplicityGoalConstraintCalculator unfinishedMultiplicity) { | 12 | new(MultiplicityGoalConstraintCalculator unfinishedMultiplicity) { |
13 | this.unfinishedMultiplicity = unfinishedMultiplicity | 13 | this.unfinishedMultiplicity = unfinishedMultiplicity |
14 | } | 14 | } |
15 | 15 | ||
@@ -29,9 +29,13 @@ class UnfinishedMultiplicityObjective implements IObjective { | |||
29 | override satisifiesHardObjective(Double fitness) { return fitness <=0.01 } | 29 | override satisifiesHardObjective(Double fitness) { return fitness <=0.01 } |
30 | 30 | ||
31 | override setComparator(Comparator<Double> comparator) { | 31 | override setComparator(Comparator<Double> comparator) { |
32 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 32 | throw new UnsupportedOperationException |
33 | } | 33 | } |
34 | override setLevel(int level) { | 34 | override setLevel(int level) { |
35 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 35 | throw new UnsupportedOperationException |
36 | } | ||
37 | |||
38 | def isContainment() { | ||
39 | return this.unfinishedMultiplicity.containment | ||
36 | } | 40 | } |
37 | } \ No newline at end of file | 41 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend index e0111cf6..1b61ffa5 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/UnfinishedWFObjective.xtend | |||
@@ -1,56 +1,64 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import org.eclipse.viatra.dse.objectives.IObjective | 3 | import java.util.ArrayList |
4 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
5 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
6 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
7 | import java.util.Collection | 4 | import java.util.Collection |
8 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | 5 | import java.util.Comparator |
9 | import org.eclipse.viatra.query.runtime.emf.EMFScope | ||
10 | import org.eclipse.viatra.dse.base.ThreadContext | ||
11 | import java.util.List | 6 | import java.util.List |
7 | import org.eclipse.viatra.dse.base.ThreadContext | ||
12 | import org.eclipse.viatra.dse.objectives.Comparators | 8 | import org.eclipse.viatra.dse.objectives.Comparators |
13 | import java.util.ArrayList | 9 | import org.eclipse.viatra.dse.objectives.IObjective |
14 | import java.util.Comparator | 10 | import org.eclipse.viatra.query.runtime.api.IPatternMatch |
11 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
12 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
15 | 13 | ||
16 | class UnfinishedWFObjective implements IObjective { | 14 | class UnfinishedWFObjective implements IObjective { |
17 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs | 15 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs |
18 | val List<ViatraQueryMatcher<?>> matchers | 16 | val List<ViatraQueryMatcher<?>> matchers |
19 | 17 | ||
20 | public new(Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs) { | 18 | new( |
19 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWFs) { | ||
21 | this.unfinishedWFs = unfinishedWFs | 20 | this.unfinishedWFs = unfinishedWFs |
22 | matchers = new ArrayList(unfinishedWFs.size) | 21 | matchers = new ArrayList(unfinishedWFs.size) |
23 | } | 22 | } |
23 | |||
24 | override getName() '''unfinishedWFs''' | 24 | override getName() '''unfinishedWFs''' |
25 | |||
25 | override createNew() { | 26 | override createNew() { |
26 | return new UnfinishedWFObjective(unfinishedWFs) | 27 | return new UnfinishedWFObjective(unfinishedWFs) |
27 | } | 28 | } |
29 | |||
28 | override init(ThreadContext context) { | 30 | override init(ThreadContext context) { |
29 | val engine = context.queryEngine//ViatraQueryEngine.on(new EMFScope(context.model)) | 31 | val engine = context.queryEngine // ViatraQueryEngine.on(new EMFScope(context.model)) |
30 | for(unfinishedWF : unfinishedWFs) { | 32 | for (unfinishedWF : unfinishedWFs) { |
31 | matchers += unfinishedWF.getMatcher(engine) | 33 | matchers += unfinishedWF.getMatcher(engine) |
32 | } | 34 | } |
33 | } | 35 | } |
34 | 36 | ||
35 | override getComparator() { Comparators.LOWER_IS_BETTER } | 37 | override getComparator() { Comparators.LOWER_IS_BETTER } |
38 | |||
36 | override getFitness(ThreadContext context) { | 39 | override getFitness(ThreadContext context) { |
37 | var sumOfMatches = 0 | 40 | var sumOfMatches = 0 |
38 | for(matcher : matchers) { | 41 | for (matcher : matchers) { |
39 | val number = matcher.countMatches | 42 | val number = matcher.countMatches |
40 | //println('''«matcher.patternName» = «number»''') | 43 | // if (number > 0) { |
41 | sumOfMatches+=number | 44 | // println('''«matcher.patternName» = «number»''') |
45 | // } | ||
46 | sumOfMatches += number | ||
42 | } | 47 | } |
43 | return sumOfMatches.doubleValue | 48 | return sumOfMatches.doubleValue |
44 | } | 49 | } |
45 | 50 | ||
46 | override getLevel() { 2 } | 51 | override getLevel() { 2 } |
52 | |||
47 | override isHardObjective() { true } | 53 | override isHardObjective() { true } |
48 | override satisifiesHardObjective(Double fitness) { return fitness <=0.01 } | 54 | |
49 | 55 | override satisifiesHardObjective(Double fitness) { return fitness <= 0.01 } | |
56 | |||
50 | override setComparator(Comparator<Double> comparator) { | 57 | override setComparator(Comparator<Double> comparator) { |
51 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 58 | throw new UnsupportedOperationException() |
52 | } | 59 | } |
60 | |||
53 | override setLevel(int level) { | 61 | override setLevel(int level) { |
54 | throw new UnsupportedOperationException("TODO: auto-generated method stub") | 62 | throw new UnsupportedOperationException() |
55 | } | 63 | } |
56 | } \ No newline at end of file | 64 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend new file mode 100644 index 00000000..e00f76ff --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/ViatraReasonerSolutionSaver.xtend | |||
@@ -0,0 +1,250 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Bounds | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.DirectionalThresholdObjective | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.IObjectiveBoundsProvider | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold | ||
7 | import java.util.HashMap | ||
8 | import java.util.Map | ||
9 | import org.eclipse.viatra.dse.api.DSEException | ||
10 | import org.eclipse.viatra.dse.api.Solution | ||
11 | import org.eclipse.viatra.dse.api.SolutionTrajectory | ||
12 | import org.eclipse.viatra.dse.base.ThreadContext | ||
13 | import org.eclipse.viatra.dse.objectives.Fitness | ||
14 | import org.eclipse.viatra.dse.objectives.IObjective | ||
15 | import org.eclipse.viatra.dse.objectives.ObjectiveComparatorHelper | ||
16 | import org.eclipse.viatra.dse.solutionstore.SolutionStore.ISolutionSaver | ||
17 | import org.eclipse.xtend.lib.annotations.Accessors | ||
18 | |||
19 | /** | ||
20 | * Based on {@link SolutionStore.BestSolutionSaver}. | ||
21 | * | ||
22 | * Will also automatically fill any missing numerical values in the saved solutions | ||
23 | * using the supplied {@link NumericSolver}. | ||
24 | */ | ||
25 | class ViatraReasonerSolutionSaver implements ISolutionSaver, IObjectiveBoundsProvider { | ||
26 | static val TOLERANCE = 1e-10 | ||
27 | |||
28 | @Accessors val SolutionCopier solutionCopier | ||
29 | @Accessors val DiversityChecker diversityChecker | ||
30 | val IObjective[][] leveledExtremalObjectives | ||
31 | val boolean hasExtremalObjectives | ||
32 | val int numberOfRequiredSolutions | ||
33 | val ObjectiveComparatorHelper comparatorHelper | ||
34 | val Map<SolutionTrajectory, Fitness> trajectories = new HashMap | ||
35 | |||
36 | @Accessors var NumericSolver numericSolver | ||
37 | @Accessors var Map<Object, Solution> solutionsCollection | ||
38 | |||
39 | new(IObjective[][] leveledExtremalObjectives, int numberOfRequiredSolutions, DiversityChecker diversityChecker) { | ||
40 | this.diversityChecker = diversityChecker | ||
41 | comparatorHelper = new ObjectiveComparatorHelper(leveledExtremalObjectives) | ||
42 | this.leveledExtremalObjectives = leveledExtremalObjectives | ||
43 | hasExtremalObjectives = leveledExtremalObjectives.exists[!empty] | ||
44 | this.numberOfRequiredSolutions = numberOfRequiredSolutions | ||
45 | this.solutionCopier = new SolutionCopier | ||
46 | } | ||
47 | |||
48 | def setNumericSolver(NumericSolver numericSolver) { | ||
49 | this.numericSolver = numericSolver | ||
50 | solutionCopier.numericSolver = numericSolver | ||
51 | } | ||
52 | |||
53 | override saveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
54 | if (hasExtremalObjectives) { | ||
55 | saveBestSolutionOnly(context, id, solutionTrajectory) | ||
56 | } else { | ||
57 | saveAnyDiverseSolution(context, id, solutionTrajectory) | ||
58 | } | ||
59 | } | ||
60 | |||
61 | private def saveBestSolutionOnly(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
62 | val fitness = context.lastFitness | ||
63 | if (!shouldSaveSolution(fitness, context)) { | ||
64 | return false | ||
65 | } | ||
66 | println("Found: " + fitness) | ||
67 | val dominatedTrajectories = newArrayList | ||
68 | for (entry : trajectories.entrySet) { | ||
69 | val isLastFitnessBetter = comparatorHelper.compare(fitness, entry.value) | ||
70 | if (isLastFitnessBetter < 0) { | ||
71 | // Found a trajectory that dominates the current one, no need to save | ||
72 | return false | ||
73 | } | ||
74 | if (isLastFitnessBetter > 0) { | ||
75 | dominatedTrajectories += entry.key | ||
76 | } | ||
77 | } | ||
78 | if (dominatedTrajectories.size == 0 && !needsMoreSolutionsWithSameFitness) { | ||
79 | return false | ||
80 | } | ||
81 | if (!diversityChecker.newSolution(context, id, dominatedTrajectories.map[solution.stateCode])) { | ||
82 | return false | ||
83 | } | ||
84 | // We must save the new trajectory before removing dominated trajectories | ||
85 | // to avoid removing the current solution when it is reachable only via dominated trajectories. | ||
86 | val solutionSaved = basicSaveSolution(context, id, solutionTrajectory, fitness) | ||
87 | for (dominatedTrajectory : dominatedTrajectories) { | ||
88 | trajectories -= dominatedTrajectory | ||
89 | val dominatedSolution = dominatedTrajectory.solution | ||
90 | if (!dominatedSolution.trajectories.remove(dominatedTrajectory)) { | ||
91 | throw new DSEException( | ||
92 | "Dominated solution is not reachable from dominated trajectory. This should never happen!") | ||
93 | } | ||
94 | if (dominatedSolution.trajectories.empty) { | ||
95 | val dominatedSolutionId = dominatedSolution.stateCode | ||
96 | solutionCopier.markAsObsolete(dominatedSolutionId) | ||
97 | solutionsCollection -= dominatedSolutionId | ||
98 | } | ||
99 | } | ||
100 | solutionSaved | ||
101 | } | ||
102 | |||
103 | private def saveAnyDiverseSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory) { | ||
104 | val fitness = context.lastFitness | ||
105 | if (!shouldSaveSolution(fitness, context)) { | ||
106 | return false | ||
107 | } | ||
108 | if (!diversityChecker.newSolution(context, id, emptyList)) { | ||
109 | return false | ||
110 | } | ||
111 | basicSaveSolution(context, id, solutionTrajectory, fitness) | ||
112 | } | ||
113 | |||
114 | private def shouldSaveSolution(Fitness fitness, ThreadContext context) { | ||
115 | fitness.satisifiesHardObjectives && (numericSolver === null || numericSolver.currentSatisfiable) | ||
116 | } | ||
117 | |||
118 | private def basicSaveSolution(ThreadContext context, Object id, SolutionTrajectory solutionTrajectory, | ||
119 | Fitness fitness) { | ||
120 | var boolean solutionSaved = false | ||
121 | var dseSolution = solutionsCollection.get(id) | ||
122 | if (dseSolution === null) { | ||
123 | solutionCopier.copySolution(context, id) | ||
124 | dseSolution = new Solution(id, solutionTrajectory) | ||
125 | solutionsCollection.put(id, dseSolution) | ||
126 | solutionSaved = true | ||
127 | } else { | ||
128 | solutionSaved = dseSolution.trajectories.add(solutionTrajectory) | ||
129 | } | ||
130 | if (solutionSaved) { | ||
131 | solutionTrajectory.solution = dseSolution | ||
132 | trajectories.put(solutionTrajectory, fitness) | ||
133 | } | ||
134 | solutionSaved | ||
135 | } | ||
136 | |||
137 | def fitnessMayBeSaved(Fitness fitness) { | ||
138 | if (!hasExtremalObjectives) { | ||
139 | return true | ||
140 | } | ||
141 | var boolean mayDominate | ||
142 | for (existingFitness : trajectories.values) { | ||
143 | val isNewFitnessBetter = comparatorHelper.compare(fitness, existingFitness) | ||
144 | if (isNewFitnessBetter < 0) { | ||
145 | return false | ||
146 | } | ||
147 | if (isNewFitnessBetter > 0) { | ||
148 | mayDominate = true | ||
149 | } | ||
150 | } | ||
151 | mayDominate || needsMoreSolutionsWithSameFitness | ||
152 | } | ||
153 | |||
154 | private def boolean needsMoreSolutionsWithSameFitness() { | ||
155 | if (solutionsCollection === null) { | ||
156 | // The solutions collection will only be initialized upon saving the first solution. | ||
157 | return true | ||
158 | } | ||
159 | solutionsCollection.size < numberOfRequiredSolutions | ||
160 | } | ||
161 | |||
162 | def getTotalCopierRuntime() { | ||
163 | solutionCopier.totalCopierRuntime | ||
164 | } | ||
165 | |||
166 | override computeRequiredBounds(IObjective objective, Bounds bounds) { | ||
167 | if (!hasExtremalObjectives) { | ||
168 | return | ||
169 | } | ||
170 | if (objective instanceof DirectionalThresholdObjective) { | ||
171 | switch (threshold : objective.threshold) { | ||
172 | case ObjectiveThreshold.NO_THRESHOLD: { | ||
173 | // No threshold to set. | ||
174 | } | ||
175 | ObjectiveThreshold.Exclusive: { | ||
176 | switch (kind : objective.kind) { | ||
177 | case HIGHER_IS_BETTER: | ||
178 | bounds.tightenLowerBound(Math.floor(threshold.threshold + 1) as int) | ||
179 | case LOWER_IS_BETTER: | ||
180 | bounds.tightenUpperBound(Math.ceil(threshold.threshold - 1) as int) | ||
181 | default: | ||
182 | throw new IllegalArgumentException("Unknown objective kind" + kind) | ||
183 | } | ||
184 | if (threshold.clampToThreshold) { | ||
185 | return | ||
186 | } | ||
187 | } | ||
188 | ObjectiveThreshold.Inclusive: { | ||
189 | switch (kind : objective.kind) { | ||
190 | case HIGHER_IS_BETTER: | ||
191 | bounds.tightenLowerBound(Math.ceil(threshold.threshold) as int) | ||
192 | case LOWER_IS_BETTER: | ||
193 | bounds.tightenUpperBound(Math.floor(threshold.threshold) as int) | ||
194 | default: | ||
195 | throw new IllegalArgumentException("Unknown objective kind" + kind) | ||
196 | } | ||
197 | if (threshold.clampToThreshold) { | ||
198 | return | ||
199 | } | ||
200 | } | ||
201 | default: | ||
202 | throw new IllegalArgumentException("Unknown threshold: " + threshold) | ||
203 | } | ||
204 | for (level : leveledExtremalObjectives) { | ||
205 | switch (level.size) { | ||
206 | case 0: { | ||
207 | // Nothing to do, wait for the next level. | ||
208 | } | ||
209 | case 1: { | ||
210 | val primaryObjective = level.get(0) | ||
211 | if (primaryObjective != objective) { | ||
212 | // There are no worst-case bounds for secondary objectives. | ||
213 | return | ||
214 | } | ||
215 | } | ||
216 | default: | ||
217 | // There are no worst-case bounds for Pareto front calculation. | ||
218 | return | ||
219 | } | ||
220 | } | ||
221 | val fitnessIterator = trajectories.values.iterator | ||
222 | if (!fitnessIterator.hasNext) { | ||
223 | return | ||
224 | } | ||
225 | val fitness = fitnessIterator.next.get(objective.name) | ||
226 | while (fitnessIterator.hasNext) { | ||
227 | val otherFitness = fitnessIterator.next.get(objective.name) | ||
228 | if (Math.abs(fitness - otherFitness) > TOLERANCE) { | ||
229 | throw new IllegalStateException("Inconsistent fitness: " + objective.name) | ||
230 | } | ||
231 | } | ||
232 | switch (kind : objective.kind) { | ||
233 | case HIGHER_IS_BETTER: | ||
234 | if (needsMoreSolutionsWithSameFitness) { | ||
235 | bounds.tightenLowerBound(Math.floor(fitness) as int) | ||
236 | } else { | ||
237 | bounds.tightenLowerBound(Math.floor(fitness + 1) as int) | ||
238 | } | ||
239 | case LOWER_IS_BETTER: | ||
240 | if (needsMoreSolutionsWithSameFitness) { | ||
241 | bounds.tightenUpperBound(Math.ceil(fitness) as int) | ||
242 | } else { | ||
243 | bounds.tightenUpperBound(Math.ceil(fitness - 1) as int) | ||
244 | } | ||
245 | default: | ||
246 | throw new IllegalArgumentException("Unknown objective kind" + kind) | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend index 5a528a9e..6d772f32 100644 --- a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/dse/WF2ObjectiveConverter.xtend | |||
@@ -1,5 +1,6 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse | 1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.dse |
2 | 2 | ||
3 | import com.google.common.collect.ImmutableList | ||
3 | import java.util.ArrayList | 4 | import java.util.ArrayList |
4 | import java.util.Collection | 5 | import java.util.Collection |
5 | import org.eclipse.viatra.dse.objectives.Comparators | 6 | import org.eclipse.viatra.dse.objectives.Comparators |
@@ -12,25 +13,33 @@ import org.eclipse.viatra.query.runtime.api.IQuerySpecification | |||
12 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | 13 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher |
13 | 14 | ||
14 | class WF2ObjectiveConverter { | 15 | class WF2ObjectiveConverter { |
15 | 16 | static val INVALIDATED_WFS_NAME = "invalidatedWFs" | |
17 | |||
16 | def createCompletenessObjective( | 18 | def createCompletenessObjective( |
17 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF) | 19 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> unfinishedWF) { |
18 | { | 20 | new UnfinishedWFObjective(unfinishedWF) |
19 | val res = new ConstraintsObjective('''unfinishedWFs''', | 21 | } |
20 | unfinishedWF.map[ | 22 | |
21 | new QueryConstraint(it.fullyQualifiedName,it,2.0) | 23 | def createInvalidationObjective( |
22 | ].toList | 24 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidatedByWF) { |
25 | createConstraintObjective(INVALIDATED_WFS_NAME, invalidatedByWF) | ||
26 | } | ||
27 | |||
28 | def IGlobalConstraint createInvalidationGlobalConstraint( | ||
29 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidatedByWF) { | ||
30 | new ModelQueriesGlobalConstraint(INVALIDATED_WFS_NAME, new ArrayList(invalidatedByWF)) | ||
31 | } | ||
32 | |||
33 | private def createConstraintObjective(String name, | ||
34 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> queries) { | ||
35 | val res = new ConstraintsObjective( | ||
36 | name, | ||
37 | ImmutableList.copyOf(queries.map [ | ||
38 | new QueryConstraint(it.fullyQualifiedName, it, 1.0) | ||
39 | ]) | ||
23 | ) | 40 | ) |
24 | res.withComparator(Comparators.LOWER_IS_BETTER) | 41 | res.withComparator(Comparators.LOWER_IS_BETTER) |
25 | res.level = 2 | 42 | res.level = 2 |
26 | return res | 43 | res |
27 | } | ||
28 | |||
29 | def IGlobalConstraint createInvalidationObjective( | ||
30 | Collection<? extends IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> invalidatedByWF) | ||
31 | { | ||
32 | return new ModelQueriesGlobalConstraint('''invalidatedWFs''', | ||
33 | new ArrayList(invalidatedByWF) | ||
34 | ) | ||
35 | } | 44 | } |
36 | } \ No newline at end of file | 45 | } |
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend new file mode 100644 index 00000000..cd911ab5 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/AbstractThreeValuedObjective.xtend | |||
@@ -0,0 +1,35 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import org.eclipse.viatra.dse.base.ThreadContext | ||
4 | |||
5 | abstract class AbstractThreeValuedObjective extends DirectionalThresholdObjective implements IThreeValuedObjective { | ||
6 | protected new(String name, ObjectiveKind kind, ObjectiveThreshold threshold, int level) { | ||
7 | super(name, kind, threshold, level) | ||
8 | } | ||
9 | |||
10 | abstract def double getLowestPossibleFitness(ThreadContext threadContext) | ||
11 | |||
12 | abstract def double getHighestPossibleFitness(ThreadContext threadContext) | ||
13 | |||
14 | override getWorstPossibleFitness(ThreadContext threadContext) { | ||
15 | switch (kind) { | ||
16 | case LOWER_IS_BETTER: | ||
17 | getHighestPossibleFitness(threadContext) | ||
18 | case HIGHER_IS_BETTER: | ||
19 | getLowestPossibleFitness(threadContext) | ||
20 | default: | ||
21 | throw new IllegalStateException("Unknown three valued objective kind: " + kind) | ||
22 | } | ||
23 | } | ||
24 | |||
25 | override getBestPossibleFitness(ThreadContext threadContext) { | ||
26 | switch (kind) { | ||
27 | case LOWER_IS_BETTER: | ||
28 | getLowestPossibleFitness(threadContext) | ||
29 | case HIGHER_IS_BETTER: | ||
30 | getHighestPossibleFitness(threadContext) | ||
31 | default: | ||
32 | throw new IllegalStateException("Unknown three valued objective kind: " + kind) | ||
33 | } | ||
34 | } | ||
35 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend new file mode 100644 index 00000000..0aa442f5 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CompositeDirectionalThresholdObjective.xtend | |||
@@ -0,0 +1,62 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import java.util.Collection | ||
5 | import org.eclipse.viatra.dse.base.ThreadContext | ||
6 | |||
7 | class CompositeDirectionalThresholdObjective extends DirectionalThresholdObjective { | ||
8 | val Collection<DirectionalThresholdObjective> objectives | ||
9 | |||
10 | new(String name, Collection<DirectionalThresholdObjective> objectives) { | ||
11 | this(name, objectives, getKind(objectives), getThreshold(objectives), getLevel(objectives)) | ||
12 | } | ||
13 | |||
14 | new(String name, DirectionalThresholdObjective... objectives) { | ||
15 | this(name, objectives as Collection<DirectionalThresholdObjective>) | ||
16 | } | ||
17 | |||
18 | protected new(String name, Iterable<DirectionalThresholdObjective> objectives, ObjectiveKind kind, | ||
19 | ObjectiveThreshold threshold, int level) { | ||
20 | super(name, kind, threshold, level) | ||
21 | this.objectives = ImmutableList.copyOf(objectives) | ||
22 | } | ||
23 | |||
24 | override createNew() { | ||
25 | new CompositeDirectionalThresholdObjective(name, objectives.map[createNew as DirectionalThresholdObjective], | ||
26 | kind, threshold, level) | ||
27 | } | ||
28 | |||
29 | override init(ThreadContext context) { | ||
30 | for (objective : objectives) { | ||
31 | objective.init(context) | ||
32 | } | ||
33 | } | ||
34 | |||
35 | override protected getRawFitness(ThreadContext context) { | ||
36 | var double fitness = 0 | ||
37 | for (objective : objectives) { | ||
38 | fitness += objective.getFitness(context) | ||
39 | } | ||
40 | fitness | ||
41 | } | ||
42 | |||
43 | private static def getKind(Collection<DirectionalThresholdObjective> objectives) { | ||
44 | val kinds = objectives.map[kind].toSet | ||
45 | if (kinds.size != 1) { | ||
46 | throw new IllegalArgumentException("Passed objectives must have the same kind") | ||
47 | } | ||
48 | kinds.head | ||
49 | } | ||
50 | |||
51 | private static def getThreshold(Collection<DirectionalThresholdObjective> objectives) { | ||
52 | objectives.map[threshold].reduce[a, b|a.merge(b)] | ||
53 | } | ||
54 | |||
55 | private static def int getLevel(Collection<DirectionalThresholdObjective> objectives) { | ||
56 | val levels = objectives.map[level].toSet | ||
57 | if (levels.size != 1) { | ||
58 | throw new IllegalArgumentException("Passed objectives must have the same level") | ||
59 | } | ||
60 | levels.head | ||
61 | } | ||
62 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostElementMatchers.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostElementMatchers.xtend new file mode 100644 index 00000000..885b14e8 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostElementMatchers.xtend | |||
@@ -0,0 +1,137 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicproblemPackage | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialinterpretationPackage | ||
6 | import java.util.List | ||
7 | import org.eclipse.emf.ecore.EObject | ||
8 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
9 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
10 | import org.eclipse.xtend.lib.annotations.Data | ||
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | ||
12 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
13 | |||
14 | @FunctionalInterface | ||
15 | interface ParameterScopeBound { | ||
16 | def double getUpperBound() | ||
17 | } | ||
18 | |||
19 | @Data | ||
20 | class CostElementMatch { | ||
21 | val IPatternMatch match | ||
22 | val boolean must | ||
23 | |||
24 | def isMulti() { | ||
25 | CostElementMatchers.isMultiMatch(match) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | @Data | ||
30 | class CostElementMatchers { | ||
31 | val ViatraQueryMatcher<? extends IPatternMatch> currentMatcher | ||
32 | val ViatraQueryMatcher<? extends IPatternMatch> mayMatcher | ||
33 | val ViatraQueryMatcher<? extends IPatternMatch> mustMatcher | ||
34 | val List<ParameterScopeBound> parameterScopeBounds | ||
35 | val int weight | ||
36 | |||
37 | def getCurrentNumberOfMatches() { | ||
38 | currentMatcher.countMatches | ||
39 | } | ||
40 | |||
41 | def getMinimumNumberOfMatches() { | ||
42 | mustMatcher.countMatches | ||
43 | } | ||
44 | |||
45 | def getMaximumNumberOfMatches() { | ||
46 | var double sum = 0 | ||
47 | val iterator = mayMatcher.streamAllMatches.iterator | ||
48 | while (iterator.hasNext) { | ||
49 | val match = iterator.next | ||
50 | var double product = 1 | ||
51 | val numberOfParameters = parameterScopeBounds.size | ||
52 | for (var int i = 0; i < numberOfParameters; i++) { | ||
53 | if (isMulti(match.get(i + 2))) { | ||
54 | val scopeBound = parameterScopeBounds.get(i) | ||
55 | product *= scopeBound.upperBound | ||
56 | } | ||
57 | |||
58 | } | ||
59 | sum += product | ||
60 | } | ||
61 | sum | ||
62 | } | ||
63 | |||
64 | def getMatches() { | ||
65 | ImmutableList.copyOf(mayMatcher.streamAllMatches.iterator.map [ match | | ||
66 | new CostElementMatch(match, mustMatcher.isMatch(match)) | ||
67 | ]) | ||
68 | } | ||
69 | |||
70 | def projectMayMatch(IPatternMatch match, int... indices) { | ||
71 | mayMatcher.projectMatch(match, indices) | ||
72 | } | ||
73 | |||
74 | private static def <T extends IPatternMatch> projectMatch(ViatraQueryMatcher<T> matcher, IPatternMatch match, int... indices) { | ||
75 | checkMatch(match) | ||
76 | val n = matcher.specification.parameters.length - 2 | ||
77 | if (indices.length != n) { | ||
78 | throw new IllegalArgumentException("Invalid number of projection indices") | ||
79 | } | ||
80 | val newMatch = matcher.newEmptyMatch | ||
81 | newMatch.set(0, match.get(0)) | ||
82 | newMatch.set(1, match.get(1)) | ||
83 | for (var int i = 0; i < n; i++) { | ||
84 | newMatch.set(i + 2, match.get(indices.get(i))) | ||
85 | } | ||
86 | if (!matcher.hasMatch(newMatch)) { | ||
87 | throw new IllegalArgumentException("Projected match does not exist") | ||
88 | } | ||
89 | return newMatch | ||
90 | } | ||
91 | |||
92 | private static def <T extends IPatternMatch> isMatch(ViatraQueryMatcher<T> matcher, IPatternMatch match) { | ||
93 | val n = matcher.specification.parameters.length | ||
94 | if (n != match.specification.parameters.length) { | ||
95 | throw new IllegalArgumentException("Invalid number of match arguments") | ||
96 | } | ||
97 | val newMatch = matcher.newEmptyMatch | ||
98 | for (var int i = 0; i < n; i++) { | ||
99 | newMatch.set(i, match.get(i)) | ||
100 | } | ||
101 | return matcher.hasMatch(newMatch) | ||
102 | } | ||
103 | |||
104 | static def isMulti(Object o) { | ||
105 | if (o instanceof EObject) { | ||
106 | switch (feature : o.eContainmentFeature) { | ||
107 | case LogicproblemPackage.eINSTANCE.logicProblem_Elements, | ||
108 | case PartialinterpretationPackage.eINSTANCE.partialInterpretation_NewElements: | ||
109 | false | ||
110 | case PartialinterpretationPackage.eINSTANCE.partialInterpretation_OpenWorldElements: | ||
111 | true | ||
112 | default: | ||
113 | throw new IllegalStateException("Unknown containment feature for element: " + feature) | ||
114 | } | ||
115 | } else { | ||
116 | false | ||
117 | } | ||
118 | } | ||
119 | |||
120 | static def isMultiMatch(IPatternMatch match) { | ||
121 | checkMatch(match) | ||
122 | val n = match.specification.parameters.length | ||
123 | for (var int i = 2; i < n; i++) { | ||
124 | if (isMulti(match.get(i))) { | ||
125 | return true | ||
126 | } | ||
127 | } | ||
128 | false | ||
129 | } | ||
130 | |||
131 | private static def checkMatch(IPatternMatch match) { | ||
132 | val n = match.specification.parameters.length | ||
133 | if (n < 2 || !(match.get(0) instanceof LogicProblem) || !(match.get(1) instanceof PartialInterpretation)) { | ||
134 | throw new IllegalArgumentException("Match is not from the partial interpretation") | ||
135 | } | ||
136 | } | ||
137 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostObjectiveHint.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostObjectiveHint.xtend new file mode 100644 index 00000000..2434073d --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/CostObjectiveHint.xtend | |||
@@ -0,0 +1,68 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.BoundSaturationListener | ||
4 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.ExtendedLinearExpressionBuilder | ||
5 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeConstraintHint | ||
6 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.LinearTypeExpressionBuilderFactory | ||
7 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronExtensionOperator | ||
8 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.PatternGenerator | ||
9 | import java.util.Map | ||
10 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | ||
11 | import org.eclipse.xtend.lib.annotations.Accessors | ||
12 | |||
13 | abstract class CostObjectiveHint implements LinearTypeConstraintHint, BoundSaturationListener { | ||
14 | @Accessors ThreeValuedCostObjective objective | ||
15 | @Accessors IObjectiveBoundsProvider boundsProvider | ||
16 | |||
17 | Integer bestUpper = null | ||
18 | |||
19 | override getAdditionalPatterns(PatternGenerator patternGenerator, Map<String, PQuery> fqnToPQuery) { | ||
20 | '''''' | ||
21 | } | ||
22 | |||
23 | override createConstraintUpdater(LinearTypeExpressionBuilderFactory builderFactory) { | ||
24 | null | ||
25 | } | ||
26 | |||
27 | def isExact() { | ||
28 | false | ||
29 | } | ||
30 | |||
31 | def PolyhedronExtensionOperator createPolyhedronExtensionOperator( | ||
32 | Map<String, CostElementMatchers> costElementMatchers) { | ||
33 | null | ||
34 | } | ||
35 | |||
36 | def setObjective(ThreeValuedCostObjective objective) { | ||
37 | if (this.objective !== null) { | ||
38 | throw new IllegalStateException("Objective was already set") | ||
39 | } | ||
40 | this.objective = objective | ||
41 | } | ||
42 | |||
43 | def setBoundsProvider(IObjectiveBoundsProvider boundsProvider) { | ||
44 | if (this.boundsProvider !== null) { | ||
45 | throw new IllegalStateException("Objective bounds provider was already set") | ||
46 | } | ||
47 | this.boundsProvider = boundsProvider | ||
48 | } | ||
49 | |||
50 | protected def buildWithBounds(ExtendedLinearExpressionBuilder builder) { | ||
51 | val bounds = builder.build(this) | ||
52 | if (objective !== null && boundsProvider !== null) { | ||
53 | boundsProvider.computeRequiredBounds(objective, bounds) | ||
54 | } | ||
55 | if (exact && bestUpper !== null) { | ||
56 | bounds.tightenLowerBound(bestUpper) | ||
57 | } | ||
58 | bounds | ||
59 | } | ||
60 | |||
61 | override boundsSaturated(Integer lower, Integer upper) { | ||
62 | if (upper !== null && (bestUpper === null || bestUpper < upper)) { | ||
63 | bestUpper = upper | ||
64 | } | ||
65 | objective?.boundsSaturated(lower, upper) | ||
66 | } | ||
67 | |||
68 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend new file mode 100644 index 00000000..376e3d1a --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/DirectionalThresholdObjective.xtend | |||
@@ -0,0 +1,164 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import java.util.Comparator | ||
4 | import org.eclipse.viatra.dse.base.ThreadContext | ||
5 | import org.eclipse.viatra.dse.objectives.IObjective | ||
6 | import org.eclipse.xtend.lib.annotations.Accessors | ||
7 | import org.eclipse.xtend.lib.annotations.Data | ||
8 | import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor | ||
9 | |||
10 | abstract class ObjectiveThreshold { | ||
11 | public static val NO_THRESHOLD = new ObjectiveThreshold { | ||
12 | override isHard() { | ||
13 | false | ||
14 | } | ||
15 | |||
16 | override satisfiesThreshold(double cost, Comparator<Double> comparator) { | ||
17 | true | ||
18 | } | ||
19 | |||
20 | override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) { | ||
21 | cost | ||
22 | } | ||
23 | |||
24 | override ObjectiveThreshold merge(ObjectiveThreshold other) { | ||
25 | if (other == NO_THRESHOLD) { | ||
26 | NO_THRESHOLD | ||
27 | } else { | ||
28 | throw new IllegalArgumentException("Merged thresholds must have the same type") | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | |||
33 | private new() { | ||
34 | } | ||
35 | |||
36 | def boolean isHard() { | ||
37 | true | ||
38 | } | ||
39 | |||
40 | def boolean satisfiesThreshold(double cost, ObjectiveKind kind) { | ||
41 | satisfiesThreshold(cost, kind.comparator) | ||
42 | } | ||
43 | |||
44 | def boolean satisfiesThreshold(double cost, Comparator<Double> comparator) | ||
45 | |||
46 | def double postProcessCost(double cost, ObjectiveKind kind) { | ||
47 | if (satisfiesThreshold(cost, kind)) { | ||
48 | postProcessSatisfactoryCost(cost, kind) | ||
49 | } else { | ||
50 | cost | ||
51 | } | ||
52 | } | ||
53 | |||
54 | protected def double postProcessSatisfactoryCost(double cost, ObjectiveKind kind) | ||
55 | |||
56 | def ObjectiveThreshold merge(ObjectiveThreshold other) | ||
57 | |||
58 | @Data | ||
59 | static class Exclusive extends ObjectiveThreshold { | ||
60 | static val EPSILON = 0.1 | ||
61 | |||
62 | val double threshold | ||
63 | val boolean clampToThreshold | ||
64 | |||
65 | @FinalFieldsConstructor | ||
66 | new() { | ||
67 | } | ||
68 | |||
69 | new(double threshold) { | ||
70 | this(threshold, true) | ||
71 | } | ||
72 | |||
73 | override satisfiesThreshold(double cost, Comparator<Double> comparator) { | ||
74 | comparator.compare(threshold, cost) < 0 | ||
75 | } | ||
76 | |||
77 | override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) { | ||
78 | if (clampToThreshold) { | ||
79 | threshold + Math.signum(kind.satisfiedValue) * EPSILON | ||
80 | } else { | ||
81 | cost | ||
82 | } | ||
83 | } | ||
84 | |||
85 | override ObjectiveThreshold merge(ObjectiveThreshold other) { | ||
86 | if (other instanceof Exclusive) { | ||
87 | new Exclusive(threshold + other.threshold) | ||
88 | } else { | ||
89 | throw new IllegalArgumentException("Merged thresholds must have the same type") | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
94 | @Data | ||
95 | static class Inclusive extends ObjectiveThreshold { | ||
96 | val double threshold | ||
97 | val boolean clampToThreshold | ||
98 | |||
99 | @FinalFieldsConstructor | ||
100 | new() { | ||
101 | } | ||
102 | |||
103 | new(double threshold) { | ||
104 | this(threshold, true) | ||
105 | } | ||
106 | |||
107 | override satisfiesThreshold(double cost, Comparator<Double> comparator) { | ||
108 | comparator.compare(threshold, cost) <= 0 | ||
109 | } | ||
110 | |||
111 | override protected postProcessSatisfactoryCost(double cost, ObjectiveKind kind) { | ||
112 | if (clampToThreshold) { | ||
113 | threshold | ||
114 | } else { | ||
115 | cost | ||
116 | } | ||
117 | } | ||
118 | |||
119 | override ObjectiveThreshold merge(ObjectiveThreshold other) { | ||
120 | if (other instanceof Inclusive) { | ||
121 | new Inclusive(threshold + other.threshold) | ||
122 | } else { | ||
123 | throw new IllegalArgumentException("Merged thresholds must have the same type") | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | abstract class DirectionalThresholdObjective implements IObjective { | ||
130 | @Accessors val String name | ||
131 | @Accessors ObjectiveKind kind | ||
132 | @Accessors ObjectiveThreshold threshold | ||
133 | @Accessors int level | ||
134 | |||
135 | protected new(String name, ObjectiveKind kind, ObjectiveThreshold threshold, int level) { | ||
136 | this.name = name | ||
137 | this.kind = kind | ||
138 | this.threshold = threshold | ||
139 | this.level = level | ||
140 | } | ||
141 | |||
142 | override isHardObjective() { | ||
143 | threshold.hard | ||
144 | } | ||
145 | |||
146 | override satisifiesHardObjective(Double fitness) { | ||
147 | threshold.satisfiesThreshold(fitness, comparator) | ||
148 | } | ||
149 | |||
150 | override getComparator() { | ||
151 | kind.comparator | ||
152 | } | ||
153 | |||
154 | override setComparator(Comparator<Double> comparator) { | ||
155 | kind = ObjectiveKind.fromComparator(comparator) | ||
156 | } | ||
157 | |||
158 | override getFitness(ThreadContext context) { | ||
159 | val fitness = getRawFitness(context) | ||
160 | threshold.postProcessCost(fitness, kind) | ||
161 | } | ||
162 | |||
163 | protected def double getRawFitness(ThreadContext context) | ||
164 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IObjectiveBoundsProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IObjectiveBoundsProvider.xtend new file mode 100644 index 00000000..3c4d36a5 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IObjectiveBoundsProvider.xtend | |||
@@ -0,0 +1,8 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.Bounds | ||
4 | import org.eclipse.viatra.dse.objectives.IObjective | ||
5 | |||
6 | interface IObjectiveBoundsProvider { | ||
7 | def void computeRequiredBounds(IObjective objective, Bounds bounds) | ||
8 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend new file mode 100644 index 00000000..4a870a3e --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/IThreeValuedObjective.xtend | |||
@@ -0,0 +1,10 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import org.eclipse.viatra.dse.base.ThreadContext | ||
4 | import org.eclipse.viatra.dse.objectives.IObjective | ||
5 | |||
6 | interface IThreeValuedObjective extends IObjective { | ||
7 | def Double getWorstPossibleFitness(ThreadContext threadContext) | ||
8 | |||
9 | def Double getBestPossibleFitness(ThreadContext threadContext) | ||
10 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend new file mode 100644 index 00000000..a0c6a2c1 --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/MatchCostObjective.xtend | |||
@@ -0,0 +1,52 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import java.util.Collection | ||
5 | import org.eclipse.viatra.dse.base.ThreadContext | ||
6 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
7 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
8 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
9 | import org.eclipse.xtend.lib.annotations.Data | ||
10 | |||
11 | @Data | ||
12 | class MatchCostElement { | ||
13 | val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification | ||
14 | val double weight | ||
15 | } | ||
16 | |||
17 | class MatchCostObjective extends DirectionalThresholdObjective { | ||
18 | val Collection<MatchCostElement> costElements | ||
19 | Collection<CostElementMatcher> matchers | ||
20 | |||
21 | new(String name, Collection<MatchCostElement> costElements, ObjectiveKind kind, ObjectiveThreshold threshold, | ||
22 | int level) { | ||
23 | super(name, kind, threshold, level) | ||
24 | this.costElements = costElements | ||
25 | } | ||
26 | |||
27 | override createNew() { | ||
28 | new MatchCostObjective(name, costElements, kind, threshold, level) | ||
29 | } | ||
30 | |||
31 | override init(ThreadContext context) { | ||
32 | val queryEngine = context.queryEngine | ||
33 | matchers = ImmutableList.copyOf(costElements.map [ | ||
34 | val matcher = querySpecification.getMatcher(queryEngine) | ||
35 | new CostElementMatcher(matcher, weight) | ||
36 | ]) | ||
37 | } | ||
38 | |||
39 | override protected getRawFitness(ThreadContext context) { | ||
40 | var double cost = 0 | ||
41 | for (it : matchers) { | ||
42 | cost += weight * matcher.countMatches | ||
43 | } | ||
44 | cost | ||
45 | } | ||
46 | |||
47 | @Data | ||
48 | private static class CostElementMatcher { | ||
49 | val ViatraQueryMatcher<? extends IPatternMatch> matcher | ||
50 | val double weight | ||
51 | } | ||
52 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java new file mode 100644 index 00000000..cbbaaafd --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ObjectiveKind.java | |||
@@ -0,0 +1,60 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization; | ||
2 | |||
3 | import java.util.Comparator; | ||
4 | |||
5 | import org.eclipse.viatra.dse.objectives.Comparators; | ||
6 | |||
7 | public enum ObjectiveKind { | ||
8 | LOWER_IS_BETTER { | ||
9 | |||
10 | @Override | ||
11 | public Comparator<Double> getComparator() { | ||
12 | return Comparators.LOWER_IS_BETTER; | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public double getInvalidValue() { | ||
17 | return Double.POSITIVE_INFINITY; | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public double getSatisfiedValue() { | ||
22 | return Double.NEGATIVE_INFINITY; | ||
23 | } | ||
24 | |||
25 | }, | ||
26 | HIGHER_IS_BETTER { | ||
27 | |||
28 | @Override | ||
29 | public Comparator<Double> getComparator() { | ||
30 | return Comparators.HIGHER_IS_BETTER; | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public double getInvalidValue() { | ||
35 | return Double.NEGATIVE_INFINITY; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public double getSatisfiedValue() { | ||
40 | return Double.POSITIVE_INFINITY; | ||
41 | } | ||
42 | |||
43 | }; | ||
44 | |||
45 | public abstract Comparator<Double> getComparator(); | ||
46 | |||
47 | public abstract double getInvalidValue(); | ||
48 | |||
49 | public abstract double getSatisfiedValue(); | ||
50 | |||
51 | public static ObjectiveKind fromComparator(Comparator<Double> comparator) { | ||
52 | if (Comparators.LOWER_IS_BETTER.equals(comparator)) { | ||
53 | return ObjectiveKind.LOWER_IS_BETTER; | ||
54 | } else if (Comparators.HIGHER_IS_BETTER.equals(comparator)) { | ||
55 | return ObjectiveKind.HIGHER_IS_BETTER; | ||
56 | } else { | ||
57 | throw new IllegalStateException("Only LOWER_IS_BETTER and HIGHER_IS_BETTER comparators are supported."); | ||
58 | } | ||
59 | } | ||
60 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend new file mode 100644 index 00000000..d355f5be --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/QueryBasedObjective.xtend | |||
@@ -0,0 +1,48 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import org.eclipse.viatra.dse.base.ThreadContext | ||
4 | import org.eclipse.viatra.query.runtime.api.IPatternMatch | ||
5 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | ||
6 | import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher | ||
7 | |||
8 | class QueryBasedObjective extends DirectionalThresholdObjective { | ||
9 | val IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification | ||
10 | ViatraQueryMatcher<? extends IPatternMatch> matcher | ||
11 | |||
12 | new(IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>> querySpecification, | ||
13 | ObjectiveKind kind, ObjectiveThreshold threshold, int level) { | ||
14 | super(querySpecification.simpleName + " objective", kind, threshold, level) | ||
15 | if (querySpecification.parameters.size != 1) { | ||
16 | throw new IllegalArgumentException("Objective query must have a single parameter") | ||
17 | } | ||
18 | this.querySpecification = querySpecification | ||
19 | } | ||
20 | |||
21 | override createNew() { | ||
22 | new QueryBasedObjective(querySpecification, kind, threshold, level) | ||
23 | } | ||
24 | |||
25 | override init(ThreadContext context) { | ||
26 | matcher = querySpecification.getMatcher(context.queryEngine) | ||
27 | } | ||
28 | |||
29 | override protected getRawFitness(ThreadContext context) { | ||
30 | val iterator = matcher.allMatches.iterator | ||
31 | if (!iterator.hasNext) { | ||
32 | return invalidValue | ||
33 | } | ||
34 | val value = iterator.next.get(0) | ||
35 | if (iterator.hasNext) { | ||
36 | throw new IllegalStateException("Multiple matches for objective query") | ||
37 | } | ||
38 | if (value instanceof Number) { | ||
39 | value.doubleValue | ||
40 | } else { | ||
41 | throw new IllegalStateException("Objective value is not an instance of Number") | ||
42 | } | ||
43 | } | ||
44 | |||
45 | private def getInvalidValue() { | ||
46 | kind.invalidValue | ||
47 | } | ||
48 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend new file mode 100644 index 00000000..9b1a7e9f --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjective.xtend | |||
@@ -0,0 +1,80 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.BoundSaturationListener | ||
4 | import java.util.Map | ||
5 | import org.eclipse.viatra.dse.base.ThreadContext | ||
6 | import org.eclipse.xtend.lib.annotations.Accessors | ||
7 | |||
8 | class ThreeValuedCostObjective extends AbstractThreeValuedObjective implements BoundSaturationListener { | ||
9 | @Accessors val Map<String, CostElementMatchers> matchers | ||
10 | double lowerBoundHint = Double.NEGATIVE_INFINITY | ||
11 | double upperBoundHint = Double.POSITIVE_INFINITY | ||
12 | |||
13 | new(String name, Map<String, CostElementMatchers> matchers, ObjectiveKind kind, ObjectiveThreshold threshold, | ||
14 | int level) { | ||
15 | super(name, kind, threshold, level) | ||
16 | this.matchers = matchers | ||
17 | } | ||
18 | |||
19 | override createNew() { | ||
20 | // new ThreeValuedCostObjective(name, matchers, kind, threshold, level) | ||
21 | throw new UnsupportedOperationException("ThreeValuedCostObjective can only be used from a single thread") | ||
22 | } | ||
23 | |||
24 | override init(ThreadContext context) { | ||
25 | } | ||
26 | |||
27 | override getRawFitness(ThreadContext context) { | ||
28 | var double cost = 0 | ||
29 | for (matcher : matchers.values) { | ||
30 | cost += matcher.weight * matcher.currentNumberOfMatches | ||
31 | } | ||
32 | cost | ||
33 | } | ||
34 | |||
35 | override getLowestPossibleFitness(ThreadContext threadContext) { | ||
36 | var double cost = 0 | ||
37 | for (matcher : matchers.values) { | ||
38 | if (matcher.weight >= 0) { | ||
39 | cost += matcher.weight * matcher.minimumNumberOfMatches | ||
40 | } else { | ||
41 | cost += matcher.weight * matcher.maximumNumberOfMatches | ||
42 | } | ||
43 | } | ||
44 | val boundWithHint = Math.max(lowerBoundHint, cost) | ||
45 | if (boundWithHint > upperBoundHint) { | ||
46 | throw new IllegalStateException("Inconsistent cost bounds") | ||
47 | } | ||
48 | boundWithHint | ||
49 | } | ||
50 | |||
51 | override getHighestPossibleFitness(ThreadContext threadContext) { | ||
52 | var double cost = 0 | ||
53 | for (matcher : matchers.values) { | ||
54 | if (matcher.weight <= 0) { | ||
55 | cost += matcher.weight * matcher.minimumNumberOfMatches | ||
56 | } else { | ||
57 | cost += matcher.weight * matcher.maximumNumberOfMatches | ||
58 | } | ||
59 | } | ||
60 | val boundWithHint = Math.min(upperBoundHint, cost) | ||
61 | if (boundWithHint < lowerBoundHint) { | ||
62 | throw new IllegalStateException("Inconsistent cost bounds") | ||
63 | } | ||
64 | boundWithHint | ||
65 | } | ||
66 | |||
67 | override boundsSaturated(Integer lower, Integer upper) { | ||
68 | lowerBoundHint = if (lower === null) { | ||
69 | Double.NEGATIVE_INFINITY | ||
70 | } else { | ||
71 | lower | ||
72 | } | ||
73 | upperBoundHint = if (upper === null) { | ||
74 | Double.POSITIVE_INFINITY | ||
75 | } else { | ||
76 | upper | ||
77 | } | ||
78 | println('''Bounds saturated: «lower»..«upper»''') | ||
79 | } | ||
80 | } | ||
diff --git a/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjectiveProvider.xtend b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjectiveProvider.xtend new file mode 100644 index 00000000..c2750acd --- /dev/null +++ b/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjectiveProvider.xtend | |||
@@ -0,0 +1,205 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization | ||
2 | |||
3 | import com.google.common.collect.ImmutableList | ||
4 | import com.google.common.collect.ImmutableMap | ||
5 | import com.google.common.collect.Lists | ||
6 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference | ||
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | ||
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference | ||
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference | ||
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation | ||
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference | ||
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration | ||
13 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeReference | ||
14 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery | ||
15 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronExtensionOperator | ||
16 | import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries | ||
17 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialBooleanInterpretation | ||
18 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation | ||
19 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialIntegerInterpretation | ||
20 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation | ||
21 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRealInterpretation | ||
22 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialStringInterpretation | ||
23 | import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope | ||
24 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.CostObjectiveConfiguration | ||
25 | import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.CostObjectiveElementConfiguration | ||
26 | import java.util.Collection | ||
27 | import java.util.Map | ||
28 | import org.eclipse.viatra.dse.objectives.IObjective | ||
29 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine | ||
30 | import org.eclipse.xtend.lib.annotations.Data | ||
31 | |||
32 | @Data | ||
33 | class ThreeValuedCostObjectiveProviderResult { | ||
34 | val Collection<IObjective> objectives | ||
35 | val Collection<CostObjectiveHint> hints | ||
36 | val Collection<PolyhedronExtensionOperator> extensionOperators | ||
37 | val IObjective[][] leveledExtremalObjectives | ||
38 | val boolean optimizationProblem | ||
39 | } | ||
40 | |||
41 | class ThreeValuedCostObjectiveProvider { | ||
42 | static val COST_OBJECTIVE_LEVEL = 3 | ||
43 | |||
44 | val ViatraQueryEngine queryEngine | ||
45 | val Map<String, ModalPatternQueries> modalRelationQueries | ||
46 | val Map<String, Relation> qualifiedNameToRelationMap | ||
47 | val ParameterScopeBound defaultBounds | ||
48 | val ParameterScopeBound booleanBounds | ||
49 | val ParameterScopeBound integerBounds | ||
50 | val ParameterScopeBound realBounds | ||
51 | val ParameterScopeBound stringBounds | ||
52 | val Map<TypeDeclaration, ParameterScopeBound> typeDeclarationToBoundsMap | ||
53 | |||
54 | new(ViatraQueryEngine queryEngine, PartialInterpretation interpretation, | ||
55 | Map<String, ModalPatternQueries> modalRelationQueries) { | ||
56 | this.queryEngine = queryEngine | ||
57 | this.modalRelationQueries = modalRelationQueries | ||
58 | qualifiedNameToRelationMap = ImmutableMap.copyOf( | ||
59 | interpretation.problem.annotations.filter(TransfomedViatraQuery). | ||
60 | toMap([patternFullyQualifiedName], [target])) | ||
61 | defaultBounds = new PartialInterpretationBasedParameterScopeBound(interpretation) | ||
62 | var ParameterScopeBound booleanBounds = null | ||
63 | var ParameterScopeBound integerBounds = null | ||
64 | var ParameterScopeBound realBounds = null | ||
65 | var ParameterScopeBound stringBounds = null | ||
66 | val typeDeclarationToBoundsMapBuilder = ImmutableMap.builder | ||
67 | for (scope : interpretation.scopes) { | ||
68 | val bounds = new ScopeBasedParameterScopeBound(scope) | ||
69 | switch (typeInterpretation : scope.targetTypeInterpretation) { | ||
70 | PartialBooleanInterpretation: | ||
71 | if (booleanBounds === null) { | ||
72 | booleanBounds = bounds | ||
73 | } else { | ||
74 | throw new IllegalStateException("Duplicate partial boolean interpretation") | ||
75 | } | ||
76 | PartialIntegerInterpretation: | ||
77 | if (integerBounds === null) { | ||
78 | integerBounds = bounds | ||
79 | } else { | ||
80 | throw new IllegalStateException("Duplicate partial integer interpretation") | ||
81 | } | ||
82 | PartialRealInterpretation: | ||
83 | if (realBounds === null) { | ||
84 | realBounds = bounds | ||
85 | } else { | ||
86 | throw new IllegalStateException("Duplicate partial real interpretation") | ||
87 | } | ||
88 | PartialStringInterpretation: | ||
89 | if (stringBounds === null) { | ||
90 | stringBounds = bounds | ||
91 | } else { | ||
92 | throw new IllegalStateException("Duplicate partial string interpretation") | ||
93 | } | ||
94 | PartialComplexTypeInterpretation: | ||
95 | typeDeclarationToBoundsMapBuilder.put(typeInterpretation.interpretationOf, bounds) | ||
96 | } | ||
97 | } | ||
98 | this.booleanBounds = booleanBounds ?: defaultBounds | ||
99 | this.integerBounds = integerBounds ?: defaultBounds | ||
100 | this.realBounds = realBounds ?: defaultBounds | ||
101 | this.stringBounds = stringBounds ?: defaultBounds | ||
102 | typeDeclarationToBoundsMap = typeDeclarationToBoundsMapBuilder.build | ||
103 | } | ||
104 | |||
105 | def getCostObjectives(Collection<CostObjectiveConfiguration> costObjectives) { | ||
106 | val objectives = ImmutableList.<IObjective>builder | ||
107 | val hints = ImmutableList.<CostObjectiveHint>builder | ||
108 | val extensionOperators = ImmutableList.<PolyhedronExtensionOperator>builder | ||
109 | val extremalObjectives = Lists.newArrayListWithExpectedSize(costObjectives.size) | ||
110 | for (entry : costObjectives.indexed) { | ||
111 | val objectiveName = '''costObjective«entry.key»''' | ||
112 | val objectiveConfig = entry.value | ||
113 | val costObjective = transformCostObjective(objectiveConfig, objectiveName) | ||
114 | objectives.add(costObjective) | ||
115 | if (objectiveConfig.findExtremum) { | ||
116 | extremalObjectives += costObjective | ||
117 | } | ||
118 | val hint = objectiveConfig.hint | ||
119 | if (hint !== null) { | ||
120 | hints.add(hint) | ||
121 | hint.objective = costObjective | ||
122 | val extensionOperator = hint.createPolyhedronExtensionOperator(costObjective.matchers) | ||
123 | if (extensionOperator !== null) { | ||
124 | extensionOperators.add(extensionOperator) | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | new ThreeValuedCostObjectiveProviderResult( | ||
129 | objectives.build, | ||
130 | hints.build, | ||
131 | extensionOperators.build, | ||
132 | newArrayList(extremalObjectives), | ||
133 | !extremalObjectives.empty | ||
134 | ) | ||
135 | } | ||
136 | |||
137 | private def transformCostObjective(CostObjectiveConfiguration configuration, String name) { | ||
138 | val costElements = ImmutableMap.copyOf(configuration.elements.toMap([patternQualifiedName], [ | ||
139 | transformCostElement | ||
140 | ])) | ||
141 | new ThreeValuedCostObjective(name, costElements, configuration.kind, configuration.threshold, | ||
142 | COST_OBJECTIVE_LEVEL) | ||
143 | } | ||
144 | |||
145 | private def transformCostElement(CostObjectiveElementConfiguration elementConfig) { | ||
146 | val relationName = elementConfig.patternQualifiedName | ||
147 | val modalQueries = modalRelationQueries.get(relationName) | ||
148 | if (modalQueries === null) { | ||
149 | throw new IllegalArgumentException("Unknown relation queries: " + relationName) | ||
150 | } | ||
151 | val relation = qualifiedNameToRelationMap.get(relationName) | ||
152 | if (relation === null) { | ||
153 | throw new IllegalArgumentException("Unknown transformed relation: " + relationName) | ||
154 | } | ||
155 | val parameterBounds = ImmutableList.copyOf(relation.parameters.map[parameterBound]) | ||
156 | new CostElementMatchers( | ||
157 | queryEngine.getMatcher(modalQueries.currentQuery), | ||
158 | queryEngine.getMatcher(modalQueries.mayQuery), | ||
159 | queryEngine.getMatcher(modalQueries.mustQuery), | ||
160 | parameterBounds, | ||
161 | elementConfig.weight | ||
162 | ) | ||
163 | } | ||
164 | |||
165 | private def getParameterBound(TypeReference typeReference) { | ||
166 | switch (typeReference) { | ||
167 | BoolTypeReference: booleanBounds | ||
168 | IntTypeReference: integerBounds | ||
169 | RealTypeReference: realBounds | ||
170 | StringTypeReference: stringBounds | ||
171 | ComplexTypeReference: typeDeclarationToBoundsMap.getOrDefault(typeReference.referred, defaultBounds) | ||
172 | } | ||
173 | } | ||
174 | |||
175 | private static abstract class AbstractParameterScopeBound implements ParameterScopeBound { | ||
176 | override getUpperBound() { | ||
177 | val rawValue = rawUpperBound | ||
178 | if (rawValue < 0) { | ||
179 | Double.POSITIVE_INFINITY | ||
180 | } else { | ||
181 | rawValue | ||
182 | } | ||
183 | } | ||
184 | |||
185 | protected def int getRawUpperBound() | ||
186 | } | ||
187 | |||
188 | @Data | ||
189 | private static class ScopeBasedParameterScopeBound extends AbstractParameterScopeBound { | ||
190 | val Scope scope | ||
191 | |||
192 | override protected getRawUpperBound() { | ||
193 | scope.maxNewElements | ||
194 | } | ||
195 | } | ||
196 | |||
197 | @Data | ||
198 | private static class PartialInterpretationBasedParameterScopeBound extends AbstractParameterScopeBound { | ||
199 | val PartialInterpretation interpretation | ||
200 | |||
201 | override protected getRawUpperBound() { | ||
202 | interpretation.maxNewElements | ||
203 | } | ||
204 | } | ||
205 | } | ||