From fd3684b5440dacca0c4bf4be15930555a79e2100 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Tue, 21 May 2019 17:00:01 -0400 Subject: VIATRA DSE and COIN-OR CBC implementations of CPS case study --- .../domains/cps/dse/CpsStateCoder.xtend | 134 +++++++++++++++++++++ .../domains/cps/dse/RuleBasedCpsMain.xtend | 39 ++++++ .../domains/cps/dse/RuleBasedCpsSolver.xtend | 74 ++++++++++++ 3 files changed, 247 insertions(+) create mode 100644 Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/CpsStateCoder.xtend create mode 100644 Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsMain.xtend create mode 100644 Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse/RuleBasedCpsSolver.xtend (limited to 'Domains/hu.bme.mit.inf.dslreasoner.domains.cps/src/hu/bme/mit/inf/dslreasoner/domains/cps/dse') 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 @@ +package hu.bme.mit.inf.dslreasoner.domains.cps.dse + +import hu.bme.mit.inf.dslreasoner.domains.cps.ApplicationInstance +import hu.bme.mit.inf.dslreasoner.domains.cps.CyberPhysicalSystem +import hu.bme.mit.inf.dslreasoner.domains.cps.HostInstance +import hu.bme.mit.inf.dslreasoner.domains.cps.HostType +import hu.bme.mit.inf.dslreasoner.domains.cps.Request +import hu.bme.mit.inf.dslreasoner.domains.cps.Requirement +import org.eclipse.emf.common.notify.Notifier +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.emf.ecore.resource.ResourceSet +import org.eclipse.viatra.dse.statecode.IStateCoder +import org.eclipse.viatra.dse.statecode.IStateCoderFactory +import org.eclipse.viatra.query.runtime.api.IPatternMatch +import org.eclipse.xtend2.lib.StringConcatenationClient + +class CpsStateCoder implements IStateCoder { + CyberPhysicalSystem cps + + protected new() { + } + + override init(Notifier notifier) { + cps = switch (notifier) { + ResourceSet: getCpsFromResourceSet(notifier) + Resource: getCpsFromResource(notifier) + CyberPhysicalSystem: notifier + default: throw new IllegalArgumentException("notifier is not a CyberPhysicalSystem") + } + } + + private def getCpsFromResourceSet(ResourceSet resourceSet) { + if (resourceSet.resources.empty) { + throw new IllegalArgumentException("No Resource in ResourceSet") + } + val resource = resourceSet.resources.head + getCpsFromResource(resource) + } + + private def getCpsFromResource(Resource resource) { + if (resource.contents.empty) { + throw new IllegalArgumentException("No EObject in Resource") + } + val cps = resource.contents.head + if (cps instanceof CyberPhysicalSystem) { + cps + } else { + throw new IllegalArgumentException("EObject in Resource is not a CyberPhysicalSystem") + } + } + + override String createStateCode() { + '''«createRequestsCode»«createHostTypesCode»''' + } + + private def StringConcatenationClient createRequestsCode() { + '''«FOR request : cps.requests»«createRequestCode(request)»«ENDFOR»''' + } + + private def StringConcatenationClient createRequestCode(Request request) { + '''[«FOR requirement : request.requirements»«createRequirementCode(requirement)»«ENDFOR»]''' + } + + private def StringConcatenationClient createRequirementCode(Requirement requirement) { + '''[«FOR app : requirement.instances SEPARATOR ","»«createAppCode(app)»«ENDFOR»]''' + } + + private def createAppCode(ApplicationInstance app) { + if (app.allocatedTo === null) { + "-" + } else { + createMatchArgumentCode(app.allocatedTo) + } + } + + private def createHostTypesCode() { + '''(«FOR hostType : cps.hostTypes SEPARATOR ","»«hostType.instances.size»«ENDFOR»)''' + } + + override String createActivationCode(IPatternMatch match) { + '''«match.specification.simpleName»(«FOR arg : match.toArray SEPARATOR ","»«createMatchArgumentCode(arg)»«ENDFOR»)''' + } + + protected dispatch def String createMatchArgumentCode(Requirement requirement) { + val request = requirement.eContainer + if (request instanceof Request) { + if (request.eContainer != cps) { + throw new IllegalArgumentException("Request is not contained in the CPS") + } + val requestIndex = cps.requests.indexOf(request) + val requirementIndex = request.requirements.indexOf(requirement) + requestIndex + "." + requirementIndex + } else { + throw new IllegalArgumentException("Requirement is not contained in a request") + } + } + + protected dispatch def String createMatchArgumentCode(ApplicationInstance app) { + val requirement = app.requirement + if (requirement === null) { + throw new IllegalArgumentException("Application instance is not associated with a requirement") + } + val instanceIndex = requirement.instances.indexOf(app) + createMatchArgumentCode(requirement) + "." + instanceIndex + } + + protected dispatch def String createMatchArgumentCode(HostInstance host) { + val hostType = host.eContainer + if (hostType instanceof HostType) { + val hostIndex = hostType.instances.indexOf(host) + createMatchArgumentCode(hostType) + "." + hostIndex + } else { + throw new IllegalArgumentException("Host is not contained in a host type") + } + } + + protected dispatch def String createMatchArgumentCode(HostType hostType) { + if (hostType.eContainer != cps) { + throw new IllegalArgumentException("Host type is not contained in the CPS") + } + val hostTypeIndex = cps.hostTypes.indexOf(hostType) + hostTypeIndex.toString + } + + protected dispatch def createMatchArgumentCode(Object object) { + throw new IllegalArgumentException("Unknown match argument: ") + } + + static class Factory implements IStateCoderFactory { + override createStateCoder() { + new CpsStateCoder + } + } +} 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 @@ +package hu.bme.mit.inf.dslreasoner.domains.cps.dse + +import hu.bme.mit.inf.dslreasoner.domains.cps.CpsPackage +import hu.bme.mit.inf.dslreasoner.domains.cps.generator.CpsGenerator +import hu.bme.mit.inf.dslreasoner.domains.cps.queries.CpsQueries +import org.eclipse.emf.ecore.EPackage +import org.eclipse.emf.ecore.EStructuralFeature +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl +import org.eclipse.viatra.addon.querybasedfeatures.runtime.QueryBasedFeatureSettingDelegateFactory +import org.eclipse.viatra.addon.querybasedfeatures.runtime.handler.QueryBasedFeatures +import org.eclipse.viatra.dse.api.DesignSpaceExplorer +import org.eclipse.viatra.dse.api.DesignSpaceExplorer.DseLoggingLevel +import org.eclipse.viatra.query.runtime.extensibility.SingletonQueryGroupProvider +import org.eclipse.viatra.query.runtime.registry.QuerySpecificationRegistry +import org.eclipse.viatra.query.runtime.registry.connector.QueryGroupProviderSourceConnector + +class RuleBasedCpsMain { + private new() { + new IllegalStateException("This is a static utility class and should not be instantiated directly.") + } + + static def void main(String[] args) { + DesignSpaceExplorer.turnOnLogging(DseLoggingLevel.VERBOSE_FULL) + Resource.Factory.Registry.INSTANCE.extensionToFactoryMap.put(Resource.Factory.Registry.DEFAULT_EXTENSION, + new XMIResourceFactoryImpl) + EStructuralFeature.Internal.SettingDelegate.Factory.Registry.INSTANCE.put(QueryBasedFeatures.ANNOTATION_SOURCE, + new QueryBasedFeatureSettingDelegateFactory) + EPackage.Registry.INSTANCE.put(CpsPackage.eNS_URI, CpsPackage.eINSTANCE) + QuerySpecificationRegistry.instance.addSource( + new QueryGroupProviderSourceConnector("CpsQueries", new SingletonQueryGroupProvider(CpsQueries.instance), + true)) + val generator = new CpsGenerator(1, 4, 1) + val problem = generator.generateCpsProblem +// problem.eResource.save(emptyMap) + val solver = new RuleBasedCpsSolver + solver.solve(problem) + } +} 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 @@ +package hu.bme.mit.inf.dslreasoner.domains.cps.dse + +import hu.bme.mit.inf.dslreasoner.domains.cps.CpsFactory +import hu.bme.mit.inf.dslreasoner.domains.cps.CpsPackage +import hu.bme.mit.inf.dslreasoner.domains.cps.CyberPhysicalSystem +import hu.bme.mit.inf.dslreasoner.domains.cps.queries.Allocate +import hu.bme.mit.inf.dslreasoner.domains.cps.queries.AverageFreeHddMetric +import hu.bme.mit.inf.dslreasoner.domains.cps.queries.AverageFreeMemoryMetric +import hu.bme.mit.inf.dslreasoner.domains.cps.queries.CostMetric +import hu.bme.mit.inf.dslreasoner.domains.cps.queries.CreateHostInstance +import hu.bme.mit.inf.dslreasoner.domains.cps.queries.GuidanceObjective +import hu.bme.mit.inf.dslreasoner.domains.cps.queries.RequirementNotSatisfied +import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.CompositeDirectionalThresholdObjective +import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveKind +import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.ObjectiveThreshold +import hu.bme.mit.inf.dslreasoner.viatrasolver.reasoner.optimization.QueryBasedObjective +import org.eclipse.viatra.dse.api.DesignSpaceExplorer +import org.eclipse.viatra.dse.evolutionary.EvolutionaryStrategyBuilder +import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRuleFactory + +class RuleBasedCpsSolver { + extension val BatchTransformationRuleFactory = new BatchTransformationRuleFactory + extension val CpsFactory = CpsFactory.eINSTANCE + + def solve(CyberPhysicalSystem problem) { +// for (request : problem.requests) { +// for (req : request.requirements) { +// for (i : 0 ..< req.count) { +// val app = createApplicationInstance +// req.type.instances += app +// req.instances += app +// } +// } +// } + val dse = new DesignSpaceExplorer + dse.addMetaModelPackage(CpsPackage.eINSTANCE) + dse.initialModel = problem.eResource.resourceSet + dse.addTransformationRule(createRule(RequirementNotSatisfied.instance).action [ + val app = createApplicationInstance + req.type.instances += app + req.instances += app + ].build) + dse.addTransformationRule(createRule(Allocate.instance).action [ + app.allocatedTo = host + ].build) +// dse.addTransformationRule(createRule(UnallocateAppInstance.instance).action [ +// app.allocatedTo = null +// ].build) + dse.addTransformationRule(createRule(CreateHostInstance.instance).action [ + hostType.instances += createHostInstance + ].build) +// dse.addTransformationRule(createRule(RemoveHostInstance.instance).action [ +// hostInstance.type.instances -= hostInstance +// ].build) + dse.addObjective( + new CompositeDirectionalThresholdObjective("Composite", + new QueryBasedObjective(GuidanceObjective.instance, ObjectiveKind.LOWER_IS_BETTER, + new ObjectiveThreshold.Inclusive(0), 0), + new QueryBasedObjective(AverageFreeMemoryMetric.instance, ObjectiveKind.LOWER_IS_BETTER, + new ObjectiveThreshold.Inclusive(0.75), 0), + new QueryBasedObjective(AverageFreeHddMetric.instance, ObjectiveKind.LOWER_IS_BETTER, + new ObjectiveThreshold.Inclusive(0.75), 0))) + dse.addObjective( + new QueryBasedObjective(CostMetric.instance, ObjectiveKind.LOWER_IS_BETTER, + ObjectiveThreshold.NO_THRESHOLD, 0)) + dse.maxNumberOfThreads = 1 + dse.stateCoderFactory = new CpsStateCoder.Factory + val strategy = EvolutionaryStrategyBuilder.createNsga2Strategy(25) + dse.startExplorationWithTimeout(strategy, 2 * 60 * 1000) + for (solution : dse.solutions) { + println("Found solution: " + solution.stateCode + " " + solution.arbitraryTrajectory.fitness) + } + } +} -- cgit v1.2.3-54-g00ecf