diff --git a/src/plugins/uk.ac.kcl.mdeoptimise.ui/src/uk/ac/kcl/ui/launch/RunOptimisation.xtend b/src/plugins/uk.ac.kcl.mdeoptimise.ui/src/uk/ac/kcl/ui/launch/RunOptimisation.xtend index bac5989b0..2365d0814 100644 --- a/src/plugins/uk.ac.kcl.mdeoptimise.ui/src/uk/ac/kcl/ui/launch/RunOptimisation.xtend +++ b/src/plugins/uk.ac.kcl.mdeoptimise.ui/src/uk/ac/kcl/ui/launch/RunOptimisation.xtend @@ -56,11 +56,10 @@ class RunOptimisation { val resource = resourceSetProvider.get().getResource(URI.createFileURI(moptFile.getAbsolutePath()), true) val optimisationModel = resource.contents.head as Optimisation - val mdeoResultsOutput = new MDEOResultsOutput(new Date(), new Path(moptProjectPath), - new Path(configuredMoptFilePath), optimisationModel - ); - if(optimisationModel !== null){ + + val mdeoResultsOutput = new MDEOResultsOutput(new Date(), new Path(moptProjectPath), + new Path(configuredMoptFilePath), optimisationModel); var experimentId = 0; do { diff --git a/src/plugins/uk.ac.kcl.mdeoptimise.ui/src/uk/ac/kcl/ui/output/MDEOResultsOutput.xtend b/src/plugins/uk.ac.kcl.mdeoptimise.ui/src/uk/ac/kcl/ui/output/MDEOResultsOutput.xtend index ada9e66af..595f1f948 100644 --- a/src/plugins/uk.ac.kcl.mdeoptimise.ui/src/uk/ac/kcl/ui/output/MDEOResultsOutput.xtend +++ b/src/plugins/uk.ac.kcl.mdeoptimise.ui/src/uk/ac/kcl/ui/output/MDEOResultsOutput.xtend @@ -1,23 +1,24 @@ package uk.ac.kcl.ui.output +import com.google.common.io.Files +import java.io.File +import java.io.PrintWriter +import java.nio.charset.Charset +import java.text.SimpleDateFormat import java.util.Date -import java.util.List +import java.util.HashMap import java.util.LinkedList +import java.util.List +import java.util.Map +import java.util.TimeZone +import org.eclipse.core.runtime.IPath +import org.eclipse.emf.common.util.URI +import org.eclipse.emf.ecore.EObject import org.eclipse.emf.ecore.resource.ResourceSet -import uk.ac.kcl.mdeoptimise.Optimisation import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl -import org.eclipse.emf.ecore.EObject -import java.util.Collections -import java.text.SimpleDateFormat +import org.eclipse.emf.ecore.xmi.XMIResource +import uk.ac.kcl.mdeoptimise.Optimisation import uk.ac.kcl.optimisation.moea.MoeaOptimisationSolution -import java.io.PrintWriter -import java.io.File -import org.eclipse.emf.common.util.URI -import org.eclipse.core.runtime.IPath -import java.util.TimeZone -import java.util.HashMap -import com.google.common.io.Files -import java.nio.charset.Charset class MDEOResultsOutput { @@ -42,7 +43,7 @@ class MDEOResultsOutput { batches.add(batch); } - def String outputBatchSummary(MDEOBatch batch, IPath outcomePath) { + def String outputBatchSummary(MDEOBatch batch, IPath outcomePath, IPath metaModelOutputPath) { var batchOutputPath = outcomePath.append(String.format("batch-%s/", batch.id)) var batchInfoPath = batchOutputPath.append("outcome.txt") @@ -69,7 +70,7 @@ class MDEOResultsOutput { val solution = batch.solutions.get(i); val modelPath = batchOutputPath + String.format("%08X", solution.model.hashCode) + ".xmi" - solution.model.writeModel(modelPath) + solution.model.writeModel(modelPath, metaModelOutputPath.toPortableString) storeSolutionData(batchWriter, modelPath, solution) } @@ -130,25 +131,47 @@ class MDEOResultsOutput { } } + def IPath copyMetaModel(IPath outcomePath){ + val metaModelInputPath = projectRoot.append(moptConfiguration.basepath.location).append(moptConfiguration.metamodel.location) + val metaModelOutputPath = outcomePath.append(metaModelInputPath.lastSegment) + + if (!metaModelInputPath.empty) { + val outputFile = metaModelOutputPath.toFile + Files.createParentDirs(outputFile) + Files.copy(metaModelInputPath.toFile, outputFile) + } + return metaModelOutputPath + } + def void saveOutcome(){ val experimentDate = new SimpleDateFormat("yyMMdd-HHmmss").format(experimentStartTime); val outcomePath = projectRoot.append(String.format("mdeo-results/experiment-%s/", experimentDate)); + + val metaModelOutputPath = copyMetaModel(outcomePath) val batchesOutput = new StringBuilder(); - batches.forEach[ batch | batchesOutput.append(outputBatchSummary(batch, outcomePath))] + batches.forEach[ batch | batchesOutput.append(outputBatchSummary(batch, outcomePath, metaModelOutputPath))] outputExperimentSummary(batches, outcomePath, moptFile, batchesOutput) } - def writeModel(EObject model, String path) { - val resource = resourceSet.createResource(URI.createFileURI(path)) + def writeModel(EObject model, String path, String metaModelPath) { + val resource = resourceSet.createResource(URI.createFileURI(new File(path).absolutePath)) if (resource.loaded) { resource.contents.clear } resource.contents.add(model) - resource.save(Collections.EMPTY_MAP) + + // Change URI of model package to reference the meta model copied to output location + model.eClass.EPackage.eResource.URI = URI.createFileURI(metaModelPath) + + // Keep schema location in output models + val Map options = new HashMap(); + options.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE); + + resource.save(options) } private def storeSolutionData(PrintWriter infoWriter, String modelPath, MoeaOptimisationSolution solution){ diff --git a/src/plugins/uk.ac.kcl.mdeoptimise/src/uk/ac/kcl/optimisation/SolutionGenerator.xtend b/src/plugins/uk.ac.kcl.mdeoptimise/src/uk/ac/kcl/optimisation/SolutionGenerator.xtend index 5964a1944..6a31ee37f 100644 --- a/src/plugins/uk.ac.kcl.mdeoptimise/src/uk/ac/kcl/optimisation/SolutionGenerator.xtend +++ b/src/plugins/uk.ac.kcl.mdeoptimise/src/uk/ac/kcl/optimisation/SolutionGenerator.xtend @@ -1,30 +1,29 @@ package uk.ac.kcl.optimisation import java.util.ArrayList +import java.util.Arrays import java.util.Iterator import java.util.List import java.util.Random import org.eclipse.emf.ecore.EObject import org.eclipse.emf.ecore.EPackage import org.eclipse.emf.ecore.util.EcoreUtil +import org.eclipse.emf.henshin.interpreter.EGraph import org.eclipse.emf.henshin.interpreter.Engine import org.eclipse.emf.henshin.interpreter.impl.ChangeImpl import org.eclipse.emf.henshin.interpreter.impl.EGraphImpl import org.eclipse.emf.henshin.interpreter.impl.EngineImpl import org.eclipse.emf.henshin.interpreter.impl.RuleApplicationImpl +import org.eclipse.emf.henshin.interpreter.impl.UnitApplicationImpl +import org.eclipse.emf.henshin.model.HenshinPackage +import org.eclipse.emf.henshin.model.ParameterKind import org.eclipse.emf.henshin.model.Unit import uk.ac.kcl.interpreter.IModelProvider +import uk.ac.kcl.interpreter.evolvers.parameters.EvolverParametersFactory +import uk.ac.kcl.interpreter.evolvers.parameters.IEvolverParametersFactory import uk.ac.kcl.mdeoptimise.Optimisation import static org.eclipse.emf.henshin.interpreter.impl.ChangeImpl.* -import org.eclipse.emf.henshin.model.Rule -import org.eclipse.emf.henshin.interpreter.impl.UnitApplicationImpl -import uk.ac.kcl.interpreter.evolvers.parameters.IEvolverParametersFactory -import org.eclipse.emf.henshin.model.HenshinPackage -import org.eclipse.emf.henshin.interpreter.EGraph -import java.util.Arrays -import uk.ac.kcl.interpreter.evolvers.parameters.EvolverParametersFactory -import org.eclipse.emf.henshin.model.ParameterKind class SolutionGenerator { @@ -84,12 +83,16 @@ class SolutionGenerator { * @returns a list of results offspring */ def List crossover(List parents) { - - val crossoverParents = new ArrayList; - parents.forEach[parent | crossoverParents.add(EcoreUtil.copy(parent))] + val firstRunParents = new ArrayList; + val secondRunParents = new ArrayList; + + parents.forEach[parent | firstRunParents.add(EcoreUtil.copy(parent))] + parents.reverseView.forEach[parent | secondRunParents.add(EcoreUtil.copy(parent))] + + val firstRunGraph = new EGraphImpl(firstRunParents); + val secondRunGraph = new EGraphImpl(secondRunParents); - val graph = new EGraphImpl(crossoverParents) val triedOperators = new ArrayList() // Randomly pick one unit @@ -100,14 +103,19 @@ class SolutionGenerator { if(operator.eClass().getClassifierID() == HenshinPackage.RULE){ //Run the selected Henshin Rule - if(runRuleOperator(operator, graph, parents)){ + + if(runRuleOperator(operator, firstRunGraph, firstRunParents) + && runRuleOperator(operator, secondRunGraph, secondRunParents) + ){ //println("Could run mutation" + matchToUse.name) - return graph.roots + return #[firstRunGraph.roots.get(1), secondRunGraph.roots.get(1)] } } else { - if(runUnitOperator(operator, graph, parents)){ + if(runUnitOperator(operator, firstRunGraph, firstRunParents) + && runUnitOperator(operator, secondRunGraph, secondRunParents) + ){ //println("Could run mutation" + matchToUse.name) - return graph.roots + return #[firstRunGraph.roots.get(1), secondRunGraph.roots.get(1)] } } @@ -134,10 +142,9 @@ class SolutionGenerator { ruleRunner.EGraph = graph ruleRunner.unit = operator - if(operator.parameters != null){ - //TODO Not sure about this filter. Check what kind of parameter we would expect people - //to pass in - var inParameters = operator.parameters.filter[parameter | parameter.kind.equals(ParameterKind.IN)] + if(operator.parameters !== null){ + var inParameters = operator.parameters.filter[parameter | parameter.kind.equals(ParameterKind.IN) + || parameter.kind.equals(ParameterKind.INOUT)] if(!inParameters.empty){ inParameters.forEach[ @@ -159,8 +166,9 @@ class SolutionGenerator { unitRunner.EGraph = graph unitRunner.unit = operator - var inParameters = operator.parameters.filter[parameter | parameter.kind.equals(ParameterKind.IN)] - + var inParameters = operator.parameters.filter[parameter | parameter.kind.equals(ParameterKind.IN) + || parameter.kind.equals(ParameterKind.INOUT)] + if(!inParameters.empty){ inParameters.forEach[ parameter | unitRunner.setParameterValue( diff --git a/src/plugins/uk.ac.kcl.mdeoptimise/src/uk/ac/kcl/optimisation/moea/MoeaProbabilisticVariation.xtend b/src/plugins/uk.ac.kcl.mdeoptimise/src/uk/ac/kcl/optimisation/moea/MoeaProbabilisticVariation.xtend index b47d10a3d..6c1fbc4a3 100644 --- a/src/plugins/uk.ac.kcl.mdeoptimise/src/uk/ac/kcl/optimisation/moea/MoeaProbabilisticVariation.xtend +++ b/src/plugins/uk.ac.kcl.mdeoptimise/src/uk/ac/kcl/optimisation/moea/MoeaProbabilisticVariation.xtend @@ -45,20 +45,18 @@ class MoeaProbabilisticVariation implements Variation { println("Not running crossover this run") } - var solutions = new LinkedList(); - for(var i = 0; i < result.length; i++){ var mutationProbability = random.nextDouble if(mutationProbability <= mutationRate){ println("Running mutation with probability: " + mutationProbability) - solutions.addAll(mutationOperator.evolve(#[result.get(i)])) + result.set(i, mutationOperator.evolve(#[result.get(i)]).get(0)) } else { println("Not running mutation this run") } } - return solutions; + return result; }