aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner/src/hu/bme/mit/inf/dslreasoner/viatrasolver/reasoner/optimization/ThreeValuedCostObjectiveProvider.xtend
blob: c2750acd47f26ec532aa04d434c64d6fbfc61d8c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization

import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import com.google.common.collect.Lists
import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.BoolTypeReference
import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference
import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.IntTypeReference
import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RealTypeReference
import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Relation
import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.StringTypeReference
import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeDeclaration
import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeReference
import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery
import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.cardinality.PolyhedronExtensionOperator
import hu.bme.mit.inf.dslreasoner.viatrasolver.logic2viatra.patterns.ModalPatternQueries
import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialBooleanInterpretation
import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialComplexTypeInterpretation
import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialIntegerInterpretation
import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialInterpretation
import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialRealInterpretation
import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.PartialStringInterpretation
import hu.bme.mit.inf.dslreasoner.viatrasolver.partialinterpretationlanguage.partialinterpretation.Scope
import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.CostObjectiveConfiguration
import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.CostObjectiveElementConfiguration
import java.util.Collection
import java.util.Map
import org.eclipse.viatra.dse.objectives.IObjective
import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine
import org.eclipse.xtend.lib.annotations.Data

@Data
class ThreeValuedCostObjectiveProviderResult {
	val Collection<IObjective> objectives
	val Collection<CostObjectiveHint> hints
	val Collection<PolyhedronExtensionOperator> extensionOperators
	val IObjective[][] leveledExtremalObjectives
	val boolean optimizationProblem
}

class ThreeValuedCostObjectiveProvider {
	static val COST_OBJECTIVE_LEVEL = 3

	val ViatraQueryEngine queryEngine
	val Map<String, ModalPatternQueries> modalRelationQueries
	val Map<String, Relation> qualifiedNameToRelationMap
	val ParameterScopeBound defaultBounds
	val ParameterScopeBound booleanBounds
	val ParameterScopeBound integerBounds
	val ParameterScopeBound realBounds
	val ParameterScopeBound stringBounds
	val Map<TypeDeclaration, ParameterScopeBound> typeDeclarationToBoundsMap

	new(ViatraQueryEngine queryEngine, PartialInterpretation interpretation,
		Map<String, ModalPatternQueries> modalRelationQueries) {
		this.queryEngine = queryEngine
		this.modalRelationQueries = modalRelationQueries
		qualifiedNameToRelationMap = ImmutableMap.copyOf(
			interpretation.problem.annotations.filter(TransfomedViatraQuery).
				toMap([patternFullyQualifiedName], [target]))
		defaultBounds = new PartialInterpretationBasedParameterScopeBound(interpretation)
		var ParameterScopeBound booleanBounds = null
		var ParameterScopeBound integerBounds = null
		var ParameterScopeBound realBounds = null
		var ParameterScopeBound stringBounds = null
		val typeDeclarationToBoundsMapBuilder = ImmutableMap.builder
		for (scope : interpretation.scopes) {
			val bounds = new ScopeBasedParameterScopeBound(scope)
			switch (typeInterpretation : scope.targetTypeInterpretation) {
				PartialBooleanInterpretation:
					if (booleanBounds === null) {
						booleanBounds = bounds
					} else {
						throw new IllegalStateException("Duplicate partial boolean interpretation")
					}
				PartialIntegerInterpretation:
					if (integerBounds === null) {
						integerBounds = bounds
					} else {
						throw new IllegalStateException("Duplicate partial integer interpretation")
					}
				PartialRealInterpretation:
					if (realBounds === null) {
						realBounds = bounds
					} else {
						throw new IllegalStateException("Duplicate partial real interpretation")
					}
				PartialStringInterpretation:
					if (stringBounds === null) {
						stringBounds = bounds
					} else {
						throw new IllegalStateException("Duplicate partial string interpretation")
					}
				PartialComplexTypeInterpretation:
					typeDeclarationToBoundsMapBuilder.put(typeInterpretation.interpretationOf, bounds)
			}
		}
		this.booleanBounds = booleanBounds ?: defaultBounds
		this.integerBounds = integerBounds ?: defaultBounds
		this.realBounds = realBounds ?: defaultBounds
		this.stringBounds = stringBounds ?: defaultBounds
		typeDeclarationToBoundsMap = typeDeclarationToBoundsMapBuilder.build
	}

	def getCostObjectives(Collection<CostObjectiveConfiguration> costObjectives) {
		val objectives = ImmutableList.<IObjective>builder
		val hints = ImmutableList.<CostObjectiveHint>builder
		val extensionOperators = ImmutableList.<PolyhedronExtensionOperator>builder
		val extremalObjectives = Lists.newArrayListWithExpectedSize(costObjectives.size)
		for (entry : costObjectives.indexed) {
			val objectiveName = '''costObjective«entry.key»'''
			val objectiveConfig = entry.value
			val costObjective = transformCostObjective(objectiveConfig, objectiveName)
			objectives.add(costObjective)
			if (objectiveConfig.findExtremum) {
				extremalObjectives += costObjective
			}
			val hint = objectiveConfig.hint
			if (hint !== null) {
				hints.add(hint)
				hint.objective = costObjective
				val extensionOperator = hint.createPolyhedronExtensionOperator(costObjective.matchers)
				if (extensionOperator !== null) {
					extensionOperators.add(extensionOperator)
				}
			}
		}
		new ThreeValuedCostObjectiveProviderResult(
			objectives.build,
			hints.build,
			extensionOperators.build,
			newArrayList(extremalObjectives),
			!extremalObjectives.empty
		)
	}

	private def transformCostObjective(CostObjectiveConfiguration configuration, String name) {
		val costElements = ImmutableMap.copyOf(configuration.elements.toMap([patternQualifiedName], [
			transformCostElement
		]))
		new ThreeValuedCostObjective(name, costElements, configuration.kind, configuration.threshold,
			COST_OBJECTIVE_LEVEL)
	}

	private def transformCostElement(CostObjectiveElementConfiguration elementConfig) {
		val relationName = elementConfig.patternQualifiedName
		val modalQueries = modalRelationQueries.get(relationName)
		if (modalQueries === null) {
			throw new IllegalArgumentException("Unknown relation queries: " + relationName)
		}
		val relation = qualifiedNameToRelationMap.get(relationName)
		if (relation === null) {
			throw new IllegalArgumentException("Unknown transformed relation: " + relationName)
		}
		val parameterBounds = ImmutableList.copyOf(relation.parameters.map[parameterBound])
		new CostElementMatchers(
			queryEngine.getMatcher(modalQueries.currentQuery),
			queryEngine.getMatcher(modalQueries.mayQuery),
			queryEngine.getMatcher(modalQueries.mustQuery),
			parameterBounds,
			elementConfig.weight
		)
	}

	private def getParameterBound(TypeReference typeReference) {
		switch (typeReference) {
			BoolTypeReference: booleanBounds
			IntTypeReference: integerBounds
			RealTypeReference: realBounds
			StringTypeReference: stringBounds
			ComplexTypeReference: typeDeclarationToBoundsMap.getOrDefault(typeReference.referred, defaultBounds)
		}
	}

	private static abstract class AbstractParameterScopeBound implements ParameterScopeBound {
		override getUpperBound() {
			val rawValue = rawUpperBound
			if (rawValue < 0) {
				Double.POSITIVE_INFINITY
			} else {
				rawValue
			}
		}

		protected def int getRawUpperBound()
	}

	@Data
	private static class ScopeBasedParameterScopeBound extends AbstractParameterScopeBound {
		val Scope scope

		override protected getRawUpperBound() {
			scope.maxNewElements
		}
	}

	@Data
	private static class PartialInterpretationBasedParameterScopeBound extends AbstractParameterScopeBound {
		val PartialInterpretation interpretation

		override protected getRawUpperBound() {
			interpretation.maxNewElements
		}
	}
}