diff --git a/gradle.properties b/gradle.properties index 6e0801f892720a1742cb422b03dda5d813a51cd5..a0eb503a16d7367e0eb623f3b9a3ce1ea26a77fb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -glpkPath = /usr/local/lib/jni +glpkPath = C:/ProgrammeAlbert/glpk-4.65/w64 diff --git a/jastadd-mquat-solver-emfer/.gitignore b/jastadd-mquat-solver-emfer/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..567609b1234a9b8806c5a05da6c866e480aa148d --- /dev/null +++ b/jastadd-mquat-solver-emfer/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/jastadd-mquat-solver-emfer/build.gradle b/jastadd-mquat-solver-emfer/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..9c88b3719c4486cf81cec0d7d5a7abbca59ae6d6 --- /dev/null +++ b/jastadd-mquat-solver-emfer/build.gradle @@ -0,0 +1,35 @@ + +apply plugin: 'java' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0' + compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0' + compile project(':jastadd-mquat-base') + compile project(':jastadd-mquat-solver') + compile "org.eclipse.emf:org.eclipse.emf.ecore:2.9.0-v20130528-0742" + compile "org.eclipse.emf:org.eclipse.emf.common:2.9.0-v20130528-0742" + // compile "org.eclipse.emf:org.eclipse.emf.ecore.xmi:2.9.0-v20130528-0742" + compile files("./libs/libEMFER.jar") + testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile project(path: ':jastadd-mquat-solver', configuration: 'testArtifacts') +} +group 'de.tudresden.inf.st' +version '1.0.0-SNAPSHOT' + +apply plugin: 'java' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.12' +} diff --git a/jastadd-mquat-solver-emfer/libs/libEMFER.jar b/jastadd-mquat-solver-emfer/libs/libEMFER.jar new file mode 100644 index 0000000000000000000000000000000000000000..ad56ac74b12afb1e057eb1e61566945e513bb11a Binary files /dev/null and b/jastadd-mquat-solver-emfer/libs/libEMFER.jar differ diff --git a/jastadd-mquat-solver-emfer/message.txt b/jastadd-mquat-solver-emfer/message.txt new file mode 100644 index 0000000000000000000000000000000000000000..5e1c309dae7f45e0f39b1bf3ac3cd9db12e7d689 --- /dev/null +++ b/jastadd-mquat-solver-emfer/message.txt @@ -0,0 +1 @@ +Hello World \ No newline at end of file diff --git a/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRSolver.java b/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRSolver.java new file mode 100644 index 0000000000000000000000000000000000000000..d58e06d912c6593b3b8094e83b5d8c054084cf6a --- /dev/null +++ b/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRSolver.java @@ -0,0 +1,211 @@ +package uniks; + +import de.tudresden.inf.st.mquat.jastadd.model.*; +import de.tudresden.inf.st.mquat.solving.BenchmarkableSolver; +import de.tudresden.inf.st.mquat.solving.Solver; +import de.tudresden.inf.st.mquat.solving.SolverUtils; +import de.tudresden.inf.st.mquat.solving.SolvingException; +import de.tudresden.inf.st.mquat.utils.StopWatch; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import uniks.ttc18.ECompMapping; +import uniks.ttc18.ESolution; +import uniks.ttc18.Ttc18Factory; + +import java.util.*; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class EMFeRSolver implements BenchmarkableSolver { + + private static final Logger logger = LogManager.getLogger(EMFeRSolver.class); + + private Solution lastSolution; + private long lastSolvingTime; + + private int solutionCounter; + + private StopWatch stopWatch; + + private long maxSolvingTime; + private boolean timedOut; + + public EMFeRSolver() { + this(Long.MAX_VALUE); + } + + public EMFeRSolver(long maxSolvingTime) { + this.maxSolvingTime = maxSolvingTime; + reset(); + } + + private static void assignResource(Assignment assignment, Resource resource) { + Implementation impl = assignment.getImplementation(); + + ResourceMapping mapping = new ResourceMapping(impl.getResourceRequirement().getInstance(0), resource, new de.tudresden.inf.st.mquat.jastadd.model.List<>()); + SolverUtils.populateResourceMapping(mapping, impl.getResourceRequirement(), resource); + assignment.setResourceMapping(mapping); + } + + private int checkAssignment(Solution solution, List<Solution> solutions, List<Assignment> assignments, List<Set<Resource>> possibleResources, int index, Stack<Resource> usedResources) { + int checkCounter = 0; + + Assignment assignment = assignments.get(index); + for (Resource resource : possibleResources.get(index)) { + + if (stopWatch.time(TimeUnit.MILLISECONDS) > maxSolvingTime) { + return checkCounter; + } + + if (usedResources.contains(resource)) continue; + assignResource(assignment, resource); + usedResources.push(resource); + checkCounter++; + if (index == assignments.size() - 1) { + if (solution.isValid()) { + solutionCounter++; + if (solutions.isEmpty() || solution.computeObjective() < solutions.get(solutions.size() - 1).computeObjective()) { + Solution clone = solution.deepCopy(); + solutions.add(clone); + logger.info("found a better solution with an objective of {}.", solution.computeObjective()); + } + + } + } else { + checkCounter += checkAssignment(solution, solutions, assignments, possibleResources, index + 1, usedResources); + } + usedResources.pop(); + } + return checkCounter; + } + + @Override + public Solution solve(Root model) throws SolvingException { + reset(); + if (model.getNumRequest() == 0) { + return Solution.emptySolutionOf(model); + } + + ESolution eSolution = Ttc18Factory.eINSTANCE.createESolution(); + + EMFeRTrafos emFeRTrafos = new EMFeRTrafos(model); + + emFeRTrafos.createTopLevelMappings(eSolution); + + for (ECompMapping compMapping : eSolution.getCompMappings()) + { + emFeRTrafos.createAssignments(eSolution, compMapping); + } + + int numAssignments = 0; + int numSoftwareSolutions = 0; + int numTotalSoftwareSolutions = 0; + + stopWatch = StopWatch.start(); + + List<Solution> solutions = new ArrayList<>(); + + // iterate all possible assignments + // Note, that this only considers assignments of one configuration to each hardware component + + + Solution currentSolution = Solution.createSoftwareSolution(model); + + Solution emferSolution = emFeRTrafos.transform(eSolution); + + // currentSolution.trace().process(new LoggerProcessor()); + + de.tudresden.inf.st.mquat.jastadd.model.List<Resource> resources = model.getHardwareModel().getResources(); + + boolean hasNextSoftwareAssignment; + do { + + numTotalSoftwareSolutions++; + + if (currentSolution.isSoftwareValid()) { + + numSoftwareSolutions++; + + List<Assignment> assignments = currentSolution.allAssignments(); + + // initialize the lists of possible assignments + List<Set<Resource>> possibleResources = new ArrayList<>(assignments.size()); + + for (Assignment assignment : assignments) { + Set<Resource> resourceList = new HashSet<>(); + for (Resource resource : resources) { + assignResource(assignment, resource); + if (assignment.isValid()) { + resourceList.add(resource); + } + } + possibleResources.add(resourceList); + } + + numAssignments += checkAssignment(currentSolution, solutions, assignments, possibleResources, 0, new Stack<>()); + } + + if (stopWatch.time(TimeUnit.MILLISECONDS) > maxSolvingTime) { + this.timedOut = true; + logger.warn("Timeout! Solving terminated!"); + break; + } + + hasNextSoftwareAssignment = currentSolution.nextSoftwareAssignment(); + } while (hasNextSoftwareAssignment); + + logger.info("Number of total software solutions: {}", numTotalSoftwareSolutions); + logger.info("Number of iterated software solutions: {}", numSoftwareSolutions); + logger.info("Number of iterated solutions: {}", numAssignments); + logger.info("Number of correct solutions: {}", solutionCounter); + + if (solutions.size() > 0) { + lastSolution = solutions.get(solutions.size() - 1); + } else { + lastSolution = Solution.emptySolutionOf(model); + logger.warn("Found no solution!"); + } + + lastSolvingTime = stopWatch.time(TimeUnit.MILLISECONDS); + + return lastSolution; + } + + private void reset() { + this.lastSolution = null; + this.solutionCounter = 0; + this.lastSolvingTime = 0; + this.timedOut = false; + } + + @Override + public String getName() { + return "simple"; + } + + @Override + public long getLastSolvingTime() { + return lastSolvingTime; + } + + @Override + public double getLastObjective() { + if (lastSolution != null) { + return lastSolution.computeObjective(); + } else { + // TODO throw exception or do something reasonable + return 0d; + } + } + + @Override + public Solver setTimeout(long timeoutValue, TimeUnit timeoutUnit) { + this.maxSolvingTime = timeoutUnit.toMillis(timeoutValue); + return this; + } + + @Override + public boolean hadTimeout() { + return this.timedOut; + } +} diff --git a/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRTrafos.java b/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRTrafos.java new file mode 100644 index 0000000000000000000000000000000000000000..d0c104f1eda572afde181004898e3433ce3e20c4 --- /dev/null +++ b/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRTrafos.java @@ -0,0 +1,110 @@ +package uniks; + +import de.tudresden.inf.st.mquat.jastadd.model.*; +import uniks.ttc18.EAssignment; +import uniks.ttc18.ECompMapping; +import uniks.ttc18.ESolution; +import uniks.ttc18.Ttc18Factory; + +import java.io.IOException; +import java.nio.file.*; + +public class EMFeRTrafos +{ + private Root model; + + public EMFeRTrafos(Root model) + { + this.model = model; + } + + public void createTopLevelMappings(ESolution eSolution) + { + org.eclipse.emf.common.util.EList<ECompMapping> compMappings = eSolution.getCompMappings(); + + if ( ! compMappings.isEmpty()) + { + return; + } + + for ( Request request : model.getRequests()) + { + String requName = request.getName().toString(); + ComponentRef target = request.getTarget(); + Name targetName = target.getName(); + + ECompMapping eCompMapping = Ttc18Factory.eINSTANCE.createECompMapping(); + eCompMapping.setRequName(requName); + eCompMapping.setCompName(targetName.toString()); + compMappings.add(eCompMapping); + } + } + + public void createAssignments(ESolution eSolution, ECompMapping compMapping) + { + String compName = compMapping.getCompName(); + Component comp = findComp(model, compName); + Implementation implementation = comp.getImplementation(0); + EAssignment eAssignment = Ttc18Factory.eINSTANCE.createEAssignment(); + String implName = implementation.getName().toString(); + eAssignment.setImplName(implName); + compMapping.setAssignment(eAssignment); + + + for (ComponentRequirement componentRequirement : implementation.getComponentRequirements()) + { + String requCompName = componentRequirement.getComponentRef().getRef().getName().toString(); + + ECompMapping subMapping = Ttc18Factory.eINSTANCE.createECompMapping(); + subMapping.setRequName(implName); + subMapping.setCompName(requCompName); + eAssignment.getCompMappings().add(subMapping); + + createAssignments(eSolution, subMapping); + } + + } + + private Component findComp(Root model, String compName) + { + for (Component comp : model.getSoftwareModel().getComponents()) + { + if (comp.getName().toString().equals(compName)) + { + return comp; + } + } + return null; + } + + public Solution transform(ESolution eSolution) + { + Solution result = new Solution(); + result.setModel(model); + + + + // top level + for (ECompMapping eCompMap : eSolution.getCompMappings()) + { + Assignment assignment = new Assignment(); + assignment.setRequest(findRequest(eCompMap.getRequName())); + assignment.setTopLevel(true); + result.addAssignment(assignment); + } + + return result; + } + + private Request findRequest(String requName) + { + for (Request r : model.getRequests()) + { + if (r.getName().toString().equals(requName)) + { + return r; + } + } + return null; + } +} diff --git a/jastadd-mquat-solver-emfer/src/test/java/de/tudresden/inf/st/mquat/solving/EMFeRHandwrittenTest.java b/jastadd-mquat-solver-emfer/src/test/java/de/tudresden/inf/st/mquat/solving/EMFeRHandwrittenTest.java new file mode 100644 index 0000000000000000000000000000000000000000..db93225ab06c59e9589879cdd0c8d723d93c2900 --- /dev/null +++ b/jastadd-mquat-solver-emfer/src/test/java/de/tudresden/inf/st/mquat/solving/EMFeRHandwrittenTest.java @@ -0,0 +1,11 @@ +package de.tudresden.inf.st.mquat.solving; + +import uniks.EMFeRSolver; + +public class EMFeRHandwrittenTest extends HandwrittenTestSuite { + + @Override + protected Solver getSolver() { + return new EMFeRSolver(10000); + } +} diff --git a/jastadd-mquat-solver-emfer/src/test/java/de/tudresden/inf/st/mquat/solving/EMFeRSolverTest.java b/jastadd-mquat-solver-emfer/src/test/java/de/tudresden/inf/st/mquat/solving/EMFeRSolverTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ab6ae20d1ea5b0aa4be9468633d7b42df97fa060 --- /dev/null +++ b/jastadd-mquat-solver-emfer/src/test/java/de/tudresden/inf/st/mquat/solving/EMFeRSolverTest.java @@ -0,0 +1,94 @@ +package de.tudresden.inf.st.mquat.solving; + +import de.tudresden.inf.st.mquat.generator.ScenarioDescription; +import de.tudresden.inf.st.mquat.generator.ScenarioGenerator; +import de.tudresden.inf.st.mquat.jastadd.model.Root; +import de.tudresden.inf.st.mquat.jastadd.model.Solution; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import uniks.EMFeRSolver; + +import java.io.IOException; +import java.nio.file.*; + +public class EMFeRSolverTest { + + private static Logger logger; + + @BeforeClass + public static void initLogger() { + logger = LogManager.getLogger(EMFeRSolverTest.class); + } + + /** + * tests the simple solver with one very simple use case + */ + @Test + public void testSimpleSolver() throws SolvingException { + int tlc = 1; + int iac = 2; + int isd = 0; + int cac = 0; + int csd = 0; + int dep = 2; + int imp = 1; + int mod = 3; + double res = 1.5d; + int nfp = 0; + int req = 1; + int cpu = 1; + int seed = 0; + + ScenarioGenerator generator = new ScenarioGenerator(new ScenarioDescription(tlc, iac, isd, cac, csd, dep, imp, res, req, cpu, seed)); + + Root model = generator.generate(); + EMFeRSolver solver = new EMFeRSolver(20000); + + Solution solution = solver.solve(model); + + Assert.assertNotNull(solution); + + logger.info("the best solution is {} and has an objective of {}.", (solution.isValid() ? "valid" : "invalid"), solution.computeObjective()); + + } + + @Test + public void testListener() + { + Path path = Paths.get("."); + + try + { + WatchService watcher = FileSystems.getDefault().newWatchService(); + path.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY); + + Files.write(Paths.get("./message.txt"), "Hello World".getBytes()); + + WatchKey event = watcher.take(); + + for (WatchEvent we : event.pollEvents()) + { + System.out.println("" + we.kind() + " " + we.context()); + + String context = we.context().toString(); + + String content = new String(Files.readAllBytes(Paths.get(context))); + + System.out.println(content); + } + + } + catch (IOException e) + { + e.printStackTrace(); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + +} diff --git a/settings.gradle b/settings.gradle index 00ff37f0ee12bb9f694350d30e9c45f27ed3ef0f..e6ec605b4b6a0cfc2bf60b28f153b9c9ee023035 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,4 +5,6 @@ include ':jastadd-mquat-benchmark' include ':jastadd-mquat-solver' include ':jastadd-mquat-solver-ilp' include ':jastadd-mquat-solver-simple' +include ':jastadd-mquat-solver-emfer' +include 'jastadd-mquat-solver-emfer'