aboutsummaryrefslogtreecommitdiffstats
path: root/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kris7topher@gmail.com>2019-05-21 17:00:01 -0400
committerLibravatar Kristóf Marussy <kris7topher@gmail.com>2019-05-21 17:00:01 -0400
commitfd3684b5440dacca0c4bf4be15930555a79e2100 (patch)
tree24120a5c7fdae1532529fa0c4687dc1078cd1cde /Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps
parentInterval hull aggregation operator (diff)
downloadVIATRA-Generator-fd3684b5440dacca0c4bf4be15930555a79e2100.tar.gz
VIATRA-Generator-fd3684b5440dacca0c4bf4be15930555a79e2100.tar.zst
VIATRA-Generator-fd3684b5440dacca0c4bf4be15930555a79e2100.zip
VIATRA DSE and COIN-OR CBC implementations of CPS case study
Diffstat (limited to 'Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps')
-rw-r--r--Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/cplex/CbcCpsMain.xtend53
-rw-r--r--Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/cplex/CpsToLpTranslator.xtend171
-rw-r--r--Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/CpsStateCoder.xtend134
-rw-r--r--Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsMain.xtend39
-rw-r--r--Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsSolver.xtend74
-rw-r--r--Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/generator/CpsGenerator.xtend7
-rw-r--r--Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/queries/CpsQueries.vql82
7 files changed, 547 insertions, 13 deletions
diff --git a/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/cplex/CbcCpsMain.xtend b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/cplex/CbcCpsMain.xtend
new file mode 100644
index 00000000..7ec0f84d
--- /dev/null
+++ b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/cplex/CbcCpsMain.xtend
@@ -0,0 +1,53 @@
1package hu.bme.mit.inf.dslreasoner.domains.cps.cplex
2
3import hu.bme.mit.inf.dslreasoner.domains.cps.CpsPackage
4import hu.bme.mit.inf.dslreasoner.domains.cps.generator.CpsGenerator
5import java.io.BufferedReader
6import java.io.BufferedWriter
7import java.io.FileReader
8import java.io.FileWriter
9import org.eclipse.emf.ecore.EPackage
10import org.eclipse.emf.ecore.resource.Resource
11import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl
12import java.util.concurrent.TimeUnit
13
14class CbcCpsMain {
15 static val PROBLEM_FILE = "problem.lp"
16 static val SOLUTION_FILE = "solution.txt"
17
18 private new() {
19 new IllegalStateException("This is a static utility class and should not be instantiated directly.")
20 }
21
22 static def void main(String[] args) {
23 Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put(Resource.Factory.Registry.DEFAULT_EXTENSION,
24 new XMIResourceFactoryImpl)
25 EPackage.Registry.INSTANCE.put(CpsPackage.eNS_URI, CpsPackage.eINSTANCE)
26 val generator = new CpsGenerator(1, 4, 1)
27 val problem = generator.generateCpsProblem
28 val toLp = new CpsToLpTranslator(problem, 10, true)
29 val lp = toLp.lpProblem
30 val writer = new BufferedWriter(new FileWriter(PROBLEM_FILE))
31 try {
32 writer.append(lp)
33 } finally {
34 writer.close
35 }
36 val process = new ProcessBuilder().inheritIO.command("cbc", PROBLEM_FILE, "solve", "solu", SOLUTION_FILE).start
37 if (!process.waitFor(120, TimeUnit.SECONDS)) {
38 System.err.println("Timeout reached")
39 process.destroyForcibly
40 System.exit(-1)
41 }
42 if (process.exitValue != 0) {
43 System.err.println("Unexpected exit value " + process.exitValue)
44 System.exit(-1)
45 }
46 val reader = new BufferedReader(new FileReader(SOLUTION_FILE))
47 try {
48 reader.lines.forEach[println(it)]
49 } finally {
50 reader.close
51 }
52 }
53}
diff --git a/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/cplex/CpsToLpTranslator.xtend b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/cplex/CpsToLpTranslator.xtend
new file mode 100644
index 00000000..c38af3a0
--- /dev/null
+++ b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/cplex/CpsToLpTranslator.xtend
@@ -0,0 +1,171 @@
1package hu.bme.mit.inf.dslreasoner.domains.cps.cplex
2
3import com.google.common.collect.ImmutableList
4import com.google.common.collect.ImmutableMap
5import hu.bme.mit.inf.dslreasoner.domains.cps.ApplicationType
6import hu.bme.mit.inf.dslreasoner.domains.cps.CyberPhysicalSystem
7import hu.bme.mit.inf.dslreasoner.domains.cps.HostType
8import hu.bme.mit.inf.dslreasoner.domains.cps.Requirement
9import java.util.List
10import java.util.Map
11
12class CpsToLpTranslator {
13 static val MINIMUM_MEMORY_USAGE = 0.25
14 static val MINIMUM_HDD_USAGE = 0.25
15
16 val CyberPhysicalSystem cps
17 val Map<Requirement, ? extends List<String>> appInstances
18 val Map<HostType, ? extends List<String>> hostInstances
19 val boolean breakSymmetry
20
21 new(CyberPhysicalSystem cps, int hostInstanceCount, boolean breakSymmetry) {
22 this.cps = cps
23 appInstances = createAppInstances
24 hostInstances = createHostInstances(hostInstanceCount)
25 this.breakSymmetry = breakSymmetry
26 }
27
28 private def createAppInstances() {
29 val builder = ImmutableMap.builder
30 var int i = 0
31 for (req : requirements) {
32 val listBuilder = ImmutableList.builder
33 for (var int j = 0; j < req.count; j++) {
34 listBuilder.add('''r«i»a«j»''')
35 }
36 builder.put(req, listBuilder.build)
37 i++
38 }
39 builder.build
40 }
41
42 private def createHostInstances(int hostInstanceCount) {
43 val builder = ImmutableMap.builder
44 var int i = 0
45 for (hostType : cps.hostTypes) {
46 val listBuilder = ImmutableList.builder
47 for (var int j = 0; j < hostInstanceCount; j++) {
48 listBuilder.add('''h«i»i«j»''')
49 }
50 builder.put(hostType, listBuilder.build)
51 i++
52 }
53 builder.build
54 }
55
56 def getLpProblem() {
57 '''
58 Minimize
59 total_cost: «objective»
60 Subject To
61 «constraints»
62 Bounds
63 «bounds»
64 Binary
65 «binaryVariables»
66 End
67 '''
68 }
69
70 private def getObjective() {
71 '''«FOR pair : hostInstancesWithType SEPARATOR " + "»«pair.key.cost» «pair.value.existsVariable»«ENDFOR»'''
72 }
73
74 private def getConstraints() {
75 '''
76 «FOR appPair : appInstancesWithType»
77 «appPair.value»_allocated: «FOR host : appPair.key.possibleHostInstances SEPARATOR " + "»«getAllocatedToVariable(appPair.value, host)»«ENDFOR» = 1
78 «FOR host : appPair.key.possibleHostInstances»
79 «appPair.value»_to_«host»_exists: «host.existsVariable» - «getAllocatedToVariable(appPair.value, host)» >= 0
80 «ENDFOR»
81 «ENDFOR»
82 «FOR hostPair : hostInstancesWithType»
83 «hostPair.value»_mem_use: «FOR appPair : hostPair.key.possibleAppInstancesWithRequirements SEPARATOR " + "»«appPair.key.requiredMemory» «getAllocatedToVariable(appPair.value, hostPair.value)»«ENDFOR» - «hostPair.key.defaultMemory» «hostPair.value.memoryUsageVariable» = 0
84 «hostPair.value»_hdd_use: «FOR appPair : hostPair.key.possibleAppInstancesWithRequirements SEPARATOR " + "»«appPair.key.requiredHdd» «getAllocatedToVariable(appPair.value, hostPair.value)»«ENDFOR» - «hostPair.key.defaultHdd» «hostPair.value.hddUsageVariable» = 0
85 «ENDFOR»
86 average_mem: «FOR host : allHostInstances SEPARATOR " + "»«host.memoryUsageVariable» - «MINIMUM_MEMORY_USAGE» «host.existsVariable»«ENDFOR» >= 0
87 average_hdd: «FOR host : allHostInstances SEPARATOR " + "»«host.memoryUsageVariable» - «MINIMUM_HDD_USAGE» «host.existsVariable»«ENDFOR» >= 0
88 «FOR reqPair : requirements.filter[count > 1].indexed»
89 «FOR host : reqPair.value.type.requirements.flatMap[hostInstances.get(hostType)]»
90 r«reqPair.key»_«host»_redundant: «FOR app : appInstances.get(reqPair.value) SEPARATOR " + "»«getAllocatedToVariable(app, host)»«ENDFOR» <= 1
91 «ENDFOR»
92 «ENDFOR»
93 «IF breakSymmetry»
94 «FOR hosts : hostInstances.values»
95 «FOR i : 0 ..< (hosts.size - 1)»
96 «hosts.get(i + 1)»_after_«hosts.get(i)»: «hosts.get(i).existsVariable» - «hosts.get(i + 1).existsVariable» >= 0
97 «ENDFOR»
98 «ENDFOR»
99 «ENDIF»
100 '''
101 }
102
103 private def getBounds() {
104 '''
105 «FOR host : allHostInstances»
106 0 <= «host.memoryUsageVariable» <= 1
107 0 <= «host.hddUsageVariable» <= 1
108 «ENDFOR»
109 '''
110 }
111
112 private def getBinaryVariables() {
113 '''
114 «FOR host : allHostInstances»
115 «host.existsVariable»
116 «ENDFOR»
117 «FOR appPair : appInstancesWithType»
118 «FOR host : appPair.key.possibleHostInstances»
119 «getAllocatedToVariable(appPair.value, host)»
120 «ENDFOR»
121 «ENDFOR»
122 '''
123 }
124
125 private def getRequirements() {
126 cps.requests.flatMap[requirements]
127 }
128
129 private def getAllHostInstances() {
130 hostInstances.values.flatMap[it]
131 }
132
133 private def getHostInstancesWithType() {
134 hostInstances.entrySet.flatMap[pair|pair.value.map[pair.key -> it]]
135 }
136
137 private def getAppInstancesWithType() {
138 appInstances.entrySet.flatMap[pair|pair.value.map[pair.key.type -> it]]
139 }
140
141 private def getPossibleHostInstances(ApplicationType appType) {
142 appType.requirements.flatMap[req|hostInstances.get(req.hostType)]
143 }
144
145 private def getPossibleAppInstancesWithRequirements(HostType hostType) {
146 appInstances.entrySet.flatMap [ pair |
147 val resourceReq = pair.key.type.requirements.findFirst[it.hostType == hostType]
148 if (resourceReq === null) {
149 emptyList
150 } else {
151 pair.value.map[resourceReq -> it]
152 }
153 ]
154 }
155
156 private def getExistsVariable(String hostInstance) {
157 '''«hostInstance»_exists'''
158 }
159
160 private def getMemoryUsageVariable(String hostInstance) {
161 '''«hostInstance»_mem'''
162 }
163
164 private def getHddUsageVariable(String hostInstance) {
165 '''«hostInstance»_hdd'''
166 }
167
168 private def getAllocatedToVariable(String appInstance, String hostInstance) {
169 '''«appInstance»_to_«hostInstance»'''
170 }
171}
diff --git a/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/CpsStateCoder.xtend b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/CpsStateCoder.xtend
new file mode 100644
index 00000000..223cee03
--- /dev/null
+++ b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/CpsStateCoder.xtend
@@ -0,0 +1,134 @@
1package hu.bme.mit.inf.dslreasoner.domains.cps.dse
2
3import hu.bme.mit.inf.dslreasoner.domains.cps.ApplicationInstance
4import hu.bme.mit.inf.dslreasoner.domains.cps.CyberPhysicalSystem
5import hu.bme.mit.inf.dslreasoner.domains.cps.HostInstance
6import hu.bme.mit.inf.dslreasoner.domains.cps.HostType
7import hu.bme.mit.inf.dslreasoner.domains.cps.Request
8import hu.bme.mit.inf.dslreasoner.domains.cps.Requirement
9import org.eclipse.emf.common.notify.Notifier
10import org.eclipse.emf.ecore.resource.Resource
11import org.eclipse.emf.ecore.resource.ResourceSet
12import org.eclipse.viatra.dse.statecode.IStateCoder
13import org.eclipse.viatra.dse.statecode.IStateCoderFactory
14import org.eclipse.viatra.query.runtime.api.IPatternMatch
15import org.eclipse.xtend2.lib.StringConcatenationClient
16
17class CpsStateCoder implements IStateCoder {
18 CyberPhysicalSystem cps
19
20 protected new() {
21 }
22
23 override init(Notifier notifier) {
24 cps = switch (notifier) {
25 ResourceSet: getCpsFromResourceSet(notifier)
26 Resource: getCpsFromResource(notifier)
27 CyberPhysicalSystem: notifier
28 default: throw new IllegalArgumentException("notifier is not a CyberPhysicalSystem")
29 }
30 }
31
32 private def getCpsFromResourceSet(ResourceSet resourceSet) {
33 if (resourceSet.resources.empty) {
34 throw new IllegalArgumentException("No Resource in ResourceSet")
35 }
36 val resource = resourceSet.resources.head
37 getCpsFromResource(resource)
38 }
39
40 private def getCpsFromResource(Resource resource) {
41 if (resource.contents.empty) {
42 throw new IllegalArgumentException("No EObject in Resource")
43 }
44 val cps = resource.contents.head
45 if (cps instanceof CyberPhysicalSystem) {
46 cps
47 } else {
48 throw new IllegalArgumentException("EObject in Resource is not a CyberPhysicalSystem")
49 }
50 }
51
52 override String createStateCode() {
53 '''«createRequestsCode»«createHostTypesCode»'''
54 }
55
56 private def StringConcatenationClient createRequestsCode() {
57 '''«FOR request : cps.requests»«createRequestCode(request)»«ENDFOR»'''
58 }
59
60 private def StringConcatenationClient createRequestCode(Request request) {
61 '''[«FOR requirement : request.requirements»«createRequirementCode(requirement)»«ENDFOR»]'''
62 }
63
64 private def StringConcatenationClient createRequirementCode(Requirement requirement) {
65 '''[«FOR app : requirement.instances SEPARATOR ","»«createAppCode(app)»«ENDFOR»]'''
66 }
67
68 private def createAppCode(ApplicationInstance app) {
69 if (app.allocatedTo === null) {
70 "-"
71 } else {
72 createMatchArgumentCode(app.allocatedTo)
73 }
74 }
75
76 private def createHostTypesCode() {
77 '''(«FOR hostType : cps.hostTypes SEPARATOR ","»«hostType.instances.size»«ENDFOR»)'''
78 }
79
80 override String createActivationCode(IPatternMatch match) {
81 '''«match.specification.simpleName»(«FOR arg : match.toArray SEPARATOR ","»«createMatchArgumentCode(arg)»«ENDFOR»)'''
82 }
83
84 protected dispatch def String createMatchArgumentCode(Requirement requirement) {
85 val request = requirement.eContainer
86 if (request instanceof Request) {
87 if (request.eContainer != cps) {
88 throw new IllegalArgumentException("Request is not contained in the CPS")
89 }
90 val requestIndex = cps.requests.indexOf(request)
91 val requirementIndex = request.requirements.indexOf(requirement)
92 requestIndex + "." + requirementIndex
93 } else {
94 throw new IllegalArgumentException("Requirement is not contained in a request")
95 }
96 }
97
98 protected dispatch def String createMatchArgumentCode(ApplicationInstance app) {
99 val requirement = app.requirement
100 if (requirement === null) {
101 throw new IllegalArgumentException("Application instance is not associated with a requirement")
102 }
103 val instanceIndex = requirement.instances.indexOf(app)
104 createMatchArgumentCode(requirement) + "." + instanceIndex
105 }
106
107 protected dispatch def String createMatchArgumentCode(HostInstance host) {
108 val hostType = host.eContainer
109 if (hostType instanceof HostType) {
110 val hostIndex = hostType.instances.indexOf(host)
111 createMatchArgumentCode(hostType) + "." + hostIndex
112 } else {
113 throw new IllegalArgumentException("Host is not contained in a host type")
114 }
115 }
116
117 protected dispatch def String createMatchArgumentCode(HostType hostType) {
118 if (hostType.eContainer != cps) {
119 throw new IllegalArgumentException("Host type is not contained in the CPS")
120 }
121 val hostTypeIndex = cps.hostTypes.indexOf(hostType)
122 hostTypeIndex.toString
123 }
124
125 protected dispatch def createMatchArgumentCode(Object object) {
126 throw new IllegalArgumentException("Unknown match argument: ")
127 }
128
129 static class Factory implements IStateCoderFactory {
130 override createStateCoder() {
131 new CpsStateCoder
132 }
133 }
134}
diff --git a/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsMain.xtend b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsMain.xtend
new file mode 100644
index 00000000..b2cc0063
--- /dev/null
+++ b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsMain.xtend
@@ -0,0 +1,39 @@
1package hu.bme.mit.inf.dslreasoner.domains.cps.dse
2
3import hu.bme.mit.inf.dslreasoner.domains.cps.CpsPackage
4import hu.bme.mit.inf.dslreasoner.domains.cps.generator.CpsGenerator
5import hu.bme.mit.inf.dslreasoner.domains.cps.queries.CpsQueries
6import org.eclipse.emf.ecore.EPackage
7import org.eclipse.emf.ecore.EStructuralFeature
8import org.eclipse.emf.ecore.resource.Resource
9import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl
10import org.eclipse.viatra.addon.querybasedfeatures.runtime.QueryBasedFeatureSettingDelegateFactory
11import org.eclipse.viatra.addon.querybasedfeatures.runtime.handler.QueryBasedFeatures
12import org.eclipse.viatra.dse.api.DesignSpaceExplorer
13import org.eclipse.viatra.dse.api.DesignSpaceExplorer.DseLoggingLevel
14import org.eclipse.viatra.query.runtime.extensibility.SingletonQueryGroupProvider
15import org.eclipse.viatra.query.runtime.registry.QuerySpecificationRegistry
16import org.eclipse.viatra.query.runtime.registry.connector.QueryGroupProviderSourceConnector
17
18class RuleBasedCpsMain {
19 private new() {
20 new IllegalStateException("This is a static utility class and should not be instantiated directly.")
21 }
22
23 static def void main(String[] args) {
24 DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.VERBOSE_FULL)
25 Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put(Resource.Factory.Registry.DEFAULT_EXTENSION,
26 new XMIResourceFactoryImpl)
27 EStructuralFeature.Internal.SettingDelegate.Factory.Registry.INSTANCE.put(QueryBasedFeatures.ANNOTATION_SOURCE,
28 new QueryBasedFeatureSettingDelegateFactory)
29 EPackage.Registry.INSTANCE.put(CpsPackage.eNS_URI, CpsPackage.eINSTANCE)
30 QuerySpecificationRegistry.instance.addSource(
31 new QueryGroupProviderSourceConnector("CpsQueries", new SingletonQueryGroupProvider(CpsQueries.instance),
32 true))
33 val generator = new CpsGenerator(1, 4, 1)
34 val problem = generator.generateCpsProblem
35// problem.eResource.save(emptyMap)
36 val solver = new RuleBasedCpsSolver
37 solver.solve(problem)
38 }
39}
diff --git a/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsSolver.xtend b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsSolver.xtend
new file mode 100644
index 00000000..e4c758f0
--- /dev/null
+++ b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsSolver.xtend
@@ -0,0 +1,74 @@
1package hu.bme.mit.inf.dslreasoner.domains.cps.dse
2
3import hu.bme.mit.inf.dslreasoner.domains.cps.CpsFactory
4import hu.bme.mit.inf.dslreasoner.domains.cps.CpsPackage
5import hu.bme.mit.inf.dslreasoner.domains.cps.CyberPhysicalSystem
6import hu.bme.mit.inf.dslreasoner.domains.cps.queries.Allocate
7import hu.bme.mit.inf.dslreasoner.domains.cps.queries.AverageFreeHddMetric
8import hu.bme.mit.inf.dslreasoner.domains.cps.queries.AverageFreeMemoryMetric
9import hu.bme.mit.inf.dslreasoner.domains.cps.queries.CostMetric
10import hu.bme.mit.inf.dslreasoner.domains.cps.queries.CreateHostInstance
11import hu.bme.mit.inf.dslreasoner.domains.cps.queries.GuidanceObjective
12import hu.bme.mit.inf.dslreasoner.domains.cps.queries.RequirementNotSatisfied
13import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.CompositeDirectionalThresholdObjective
14import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind
15import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold
16import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.QueryBasedObjective
17import org.eclipse.viatra.dse.api.DesignSpaceExplorer
18import org.eclipse.viatra.dse.evolutionary.EvolutionaryStrategyBuilder
19import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRuleFactory
20
21class RuleBasedCpsSolver {
22 extension val BatchTransformationRuleFactory = new BatchTransformationRuleFactory
23 extension val CpsFactory = CpsFactory.eINSTANCE
24
25 def solve(CyberPhysicalSystem problem) {
26// for (request : problem.requests) {
27// for (req : request.requirements) {
28// for (i : 0 ..< req.count) {
29// val app = createApplicationInstance
30// req.type.instances += app
31// req.instances += app
32// }
33// }
34// }
35 val dse = new DesignSpaceExplorer
36 dse.addMetaModelPackage(CpsPackage.eINSTANCE)
37 dse.initialModel = problem.eResource.resourceSet
38 dse.addTransformationRule(createRule(RequirementNotSatisfied.instance).action [
39 val app = createApplicationInstance
40 req.type.instances += app
41 req.instances += app
42 ].build)
43 dse.addTransformationRule(createRule(Allocate.instance).action [
44 app.allocatedTo = host
45 ].build)
46// dse.addTransformationRule(createRule(UnallocateAppInstance.instance).action [
47// app.allocatedTo = null
48// ].build)
49 dse.addTransformationRule(createRule(CreateHostInstance.instance).action [
50 hostType.instances += createHostInstance
51 ].build)
52// dse.addTransformationRule(createRule(RemoveHostInstance.instance).action [
53// hostInstance.type.instances -= hostInstance
54// ].build)
55 dse.addObjective(
56 new CompositeDirectionalThresholdObjective("Composite",
57 new QueryBasedObjective(GuidanceObjective.instance, ObjectiveKind.LOWER_IS_BETTER,
58 new ObjectiveThreshold.Inclusive(0), 0),
59 new QueryBasedObjective(AverageFreeMemoryMetric.instance, ObjectiveKind.LOWER_IS_BETTER,
60 new ObjectiveThreshold.Inclusive(0.75), 0),
61 new QueryBasedObjective(AverageFreeHddMetric.instance, ObjectiveKind.LOWER_IS_BETTER,
62 new ObjectiveThreshold.Inclusive(0.75), 0)))
63 dse.addObjective(
64 new QueryBasedObjective(CostMetric.instance, ObjectiveKind.LOWER_IS_BETTER,
65 ObjectiveThreshold.NO_THRESHOLD, 0))
66 dse.maxNumberOfThreads = 1
67 dse.stateCoderFactory = new CpsStateCoder.Factory
68 val strategy = EvolutionaryStrategyBuilder.createNsga2Strategy(25)
69 dse.startExplorationWithTimeout(strategy, 2 * 60 * 1000)
70 for (solution : dse.solutions) {
71 println("Found solution: " + solution.stateCode + " " + solution.arbitraryTrajectory.fitness)
72 }
73 }
74}
diff --git a/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/generator/CpsGenerator.xtend b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/generator/CpsGenerator.xtend
index 0a510f0f..390d13d3 100644
--- a/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/generator/CpsGenerator.xtend
+++ b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/generator/CpsGenerator.xtend
@@ -5,6 +5,8 @@ import hu.bme.mit.inf.dslreasoner.domains.cps.CyberPhysicalSystem
5import hu.bme.mit.inf.dslreasoner.domains.cps.HostType 5import hu.bme.mit.inf.dslreasoner.domains.cps.HostType
6import java.util.Collection 6import java.util.Collection
7import java.util.Random 7import java.util.Random
8import org.eclipse.emf.common.util.URI
9import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl
8 10
9class CpsGenerator { 11class CpsGenerator {
10 extension val CpsFactory = CpsFactory.eINSTANCE 12 extension val CpsFactory = CpsFactory.eINSTANCE
@@ -28,8 +30,11 @@ class CpsGenerator {
28 } 30 }
29 31
30 def generateCpsProblem() { 32 def generateCpsProblem() {
33 val resourceSet = new ResourceSetImpl
34 val resource = resourceSet.createResource(URI.createFileURI("dummy.dummyext"))
31 createCyberPhysicalSystem => [ 35 createCyberPhysicalSystem => [
32 val cps = it 36 val cps = it
37 resource.contents += cps
33 createLowCpuHostTypes 38 createLowCpuHostTypes
34 val highCpuHostTypes = createHighCpuHostTypes 39 val highCpuHostTypes = createHighCpuHostTypes
35 for (var int i = 0; i < applicationTypeCount; i++) { 40 for (var int i = 0; i < applicationTypeCount; i++) {
@@ -58,6 +63,7 @@ class CpsGenerator {
58 val hdd = nextInt(MIN_HDD, MAX_HDD) 63 val hdd = nextInt(MIN_HDD, MAX_HDD)
59 for (hostType : allowedHostTypes) { 64 for (hostType : allowedHostTypes) {
60 appType.requirements += createResourceRequirement => [ 65 appType.requirements += createResourceRequirement => [
66 it.hostType = hostType
61 requiredMemory = memory 67 requiredMemory = memory
62 requiredHdd = hdd 68 requiredHdd = hdd
63 ] 69 ]
@@ -83,6 +89,7 @@ class CpsGenerator {
83 89
84 private def createHostType(CyberPhysicalSystem it, int cost, int memory, int hdd) { 90 private def createHostType(CyberPhysicalSystem it, int cost, int memory, int hdd) {
85 val hostType = createHostType => [ 91 val hostType = createHostType => [
92 it.cost = cost
86 defaultMemory = memory 93 defaultMemory = memory
87 defaultHdd = hdd 94 defaultHdd = hdd
88 ] 95 ]
diff --git a/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/queries/CpsQueries.vql b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/queries/CpsQueries.vql
index 40337443..aa78dc38 100644
--- a/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/queries/CpsQueries.vql
+++ b/Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/queries/CpsQueries.vql
@@ -3,28 +3,23 @@ package hu.bme.mit.inf.dslreasoner.domains.cps.queries
3import "http://www.eclipse.org/emf/2002/Ecore" 3import "http://www.eclipse.org/emf/2002/Ecore"
4import "http://www.example.org/cps" 4import "http://www.example.org/cps"
5 5
6@QueryBasedFeature(feature = "applications") 6private pattern cpsApplications(Cps : CyberPhysicalSystem, AppInstance : ApplicationInstance) {
7pattern cpsApplications(Cps : CyberPhysicalSystem, AppInstance : ApplicationInstance) {
8 CyberPhysicalSystem.applicationTypes.instances(Cps, AppInstance); 7 CyberPhysicalSystem.applicationTypes.instances(Cps, AppInstance);
9} 8}
10 9
11@QueryBasedFeature(feature = "hosts") 10private pattern cpsHosts(Cps : CyberPhysicalSystem, HostInstance : HostInstance) {
12pattern cpsHosts(Cps : CyberPhysicalSystem, HostInstance : HostInstance) {
13 CyberPhysicalSystem.hostTypes.instances(Cps, HostInstance); 11 CyberPhysicalSystem.hostTypes.instances(Cps, HostInstance);
14} 12}
15 13
16@QueryBasedFeature(feature = "totalMemory") 14private pattern totalMemory(Host : HostInstance, Memory : EInt) {
17pattern totalMemory(Host : HostInstance, Memory : EInt) {
18 HostInstance.type.defaultMemory(Host, Memory); 15 HostInstance.type.defaultMemory(Host, Memory);
19} 16}
20 17
21@QueryBasedFeature(feature = "totalHdd") 18private pattern totalHdd(Host : HostInstance, Hdd : EInt) {
22pattern totalHdd(Host : HostInstance, Hdd : EInt) {
23 HostInstance.type.defaultHdd(Host, Hdd); 19 HostInstance.type.defaultHdd(Host, Hdd);
24} 20}
25 21
26@QueryBasedFeature(feature = "availableMemory") 22private pattern availableMemory(Host : HostInstance, Memory : java Integer) {
27pattern availableMemory(Host : HostInstance, Memory : java Integer) {
28 find totalMemory(Host, TotalMemory); 23 find totalMemory(Host, TotalMemory);
29 RequiredMemory == sum find memoryRequirement(Host, _, #_); 24 RequiredMemory == sum find memoryRequirement(Host, _, #_);
30 Memory == eval(TotalMemory - RequiredMemory); 25 Memory == eval(TotalMemory - RequiredMemory);
@@ -35,8 +30,7 @@ private pattern memoryRequirement(Host : HostInstance, App : ApplicationInstance
35 ResourceRequirement.requiredMemory(Req, Memory); 30 ResourceRequirement.requiredMemory(Req, Memory);
36} 31}
37 32
38@QueryBasedFeature(feature = "availableHdd") 33private pattern availableHdd(Host : HostInstance, Hdd : java Integer) {
39pattern availableHdd(Host : HostInstance, Hdd : java Integer) {
40 find totalHdd(Host, TotalHdd); 34 find totalHdd(Host, TotalHdd);
41 RequiredHdd == sum find hddRequirement(Host, _, #_); 35 RequiredHdd == sum find hddRequirement(Host, _, #_);
42 Hdd == eval(TotalHdd - RequiredHdd); 36 Hdd == eval(TotalHdd - RequiredHdd);
@@ -47,7 +41,7 @@ private pattern hddRequirement(Host : HostInstance, App : ApplicationInstance, H
47 ResourceRequirement.requiredHdd(Req, Hdd); 41 ResourceRequirement.requiredHdd(Req, Hdd);
48} 42}
49 43
50private pattern resourceRequirement(Host : HostInstance, App : ApplicationInstance, Req : ResourceRequirement) { 44pattern resourceRequirement(Host : HostInstance, App : ApplicationInstance, Req : ResourceRequirement) {
51 ApplicationInstance.allocatedTo(App, Host); 45 ApplicationInstance.allocatedTo(App, Host);
52 ApplicationInstance.type.requirements(App, Req); 46 ApplicationInstance.type.requirements(App, Req);
53 HostInstance.type(Host, HostType); 47 HostInstance.type(Host, HostType);
@@ -106,6 +100,12 @@ pattern redundantInstancesOnSameHost(Req : Requirement) {
106 ApplicationInstance.allocatedTo(App2, Host); 100 ApplicationInstance.allocatedTo(App2, Host);
107} 101}
108 102
103//
104// Metrics
105//
106
107// Free memory
108
109pattern averageFreeMemoryMetric(Average : java Double) { 109pattern averageFreeMemoryMetric(Average : java Double) {
110 Average == avg find freeMemoryPercentage(_, #_); 110 Average == avg find freeMemoryPercentage(_, #_);
111} 111}
@@ -116,6 +116,8 @@ private pattern freeMemoryPercentage(Host : HostInstance, Free : java Double) {
116 Free == eval((Available as double) / Total); 116 Free == eval((Available as double) / Total);
117} 117}
118 118
119// Free HDD
120
119pattern averageFreeHddMetric(Average : java Double) { 121pattern averageFreeHddMetric(Average : java Double) {
120 Average == avg find freeHddPercentage(_, #_); 122 Average == avg find freeHddPercentage(_, #_);
121} 123}
@@ -126,6 +128,8 @@ private pattern freeHddPercentage(Host : HostInstance, Free : java Double) {
126 Free == eval((Available as double) / Total); 128 Free == eval((Available as double) / Total);
127} 129}
128 130
131// Total cost
132
129pattern costMetric(Cost : java Integer) { 133pattern costMetric(Cost : java Integer) {
130 Cost == sum find cpsCost(_, #_); 134 Cost == sum find cpsCost(_, #_);
131} 135}
@@ -140,3 +144,55 @@ private pattern hostInstanceCost(Cps : CyberPhysicalSystem, Host : HostInstance,
140 find cpsHosts(Cps, Host); 144 find cpsHosts(Cps, Host);
141 HostInstance.type.cost(Host, Cost); 145 HostInstance.type.cost(Host, Cost);
142} 146}
147
148//
149// Transformation rule preconditions for rule-based DSE
150//
151
152pattern allocate(App : ApplicationInstance, Host : HostInstance) {
153 ApplicationInstance.type.requirements(App, Req);
154 ResourceRequirement.hostType.instances(Req, Host);
155 find unallocatedAppInstance(App);
156 find availableMemory(Host, AvailableMem);
157 find availableHdd(Host, AvailableHdd);
158 ResourceRequirement.requiredMemory(Req, RequiredMem);
159 ResourceRequirement.requiredHdd(Req, RequiredHdd);
160 check(AvailableMem >= RequiredMem);
161 check(AvailableHdd >= RequiredHdd);
162 neg ApplicationInstance.requirement.instances.allocatedTo(App, Host);
163}
164
165pattern unallocateAppInstance(App : ApplicationInstance) {
166 ApplicationInstance.allocatedTo(App, _);
167}
168
169pattern createHostInstance(HostType : HostType) {
170 find unallocatedAppInstance(App);
171 ApplicationInstance.type.requirements.hostType(App, HostType);
172}
173
174pattern removeHostInstance(HostInstance : HostInstance) {
175 neg HostInstance.applications(HostInstance, _);
176}
177
178private pattern unallocatedAppInstance(App : ApplicationInstance) {
179 neg ApplicationInstance.allocatedTo(App, _);
180}
181
182private pattern requiredAppInstances(Req : Requirement, Remaining : java Integer) {
183 Instances == count find satisfyingInstance(Req, _);
184 Requirement.count(Req, RequiredCount);
185 Remaining == eval(RequiredCount - Instances);
186}
187
188private pattern noHostToAllocateTo(App : ApplicationInstance) {
189 find unallocatedAppInstance(App);
190 neg find allocate(App, _);
191}
192
193pattern guidanceObjective(Value : java Integer) {
194 UnallocatedInstances == count find unallocatedAppInstance(_);
195 RequiredInstances == sum find requiredAppInstances(_, #_);
196 NoHostToAllocate == count find noHostToAllocateTo(_);
197 Value == eval(2 * UnallocatedInstances + 4 * RequiredInstances + NoHostToAllocate);
198}