Commit ac2070a5 authored by Albert Zuendorf's avatar Albert Zuendorf
Browse files

first running solution, almost as good as the simple solver (:

parent 0c86ca15
......@@ -30,3 +30,4 @@ hs_err_pid*
.settings/
.classpath
.project
results/
......@@ -34,7 +34,8 @@ The following steps need to be completed:
1. Add an include of your project to `settings.gradle`
1. Optional step: Create a test case by extending the [`HandwrittenTestSuite`](https://git-st.inf.tu-dresden.de/stgroup/ttc18/blob/master/jastadd-mquat-solver/src/test/java/de/tudresden/inf/st/mquat/solving/HandwrittenTestSuite.java)
1. Add a compile dependency to your project in `build.gradle` of the project `jastadd-mquat-benchmark`
1. Update [`de.tudresden.inf.st.mquat.benchmark.SolverFactory.createAvailableSolversIfNeeded`](https://git-st.inf.tu-dresden.de/stgroup/ttc18/blob/master/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java#L22) to create a new instance of your solver
1. Update [`de.tudresden.inf.st.mquat.benchmark.SolverFactory.createAvailableSolversIfNeeded`]
(https://git-st.inf.tu-dresden.de/stgroup/ttc18/blob/master/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java#L22) to create a new instance of your solver
1. Add the name of your solver to the benchmark settings
- Use `jastadd-mquat-benchmark/src/main/resources/scenarios.json` for the Gradle task `benchmarkFull`
- Use `jastadd-mquat-benchmark/src/main/resources/local-benchmark-settings.json` for the Gralde task `benchmarkCustom` (see [Custom Benchmark](#custom-benchmark) for details)
......
......@@ -11,6 +11,7 @@ dependencies {
compile project(':jastadd-mquat-base')
compile project(':jastadd-mquat-solver')
compile project(':jastadd-mquat-solver-ilp')
compile project(':jastadd-mquat-solver-emfer')
compile project(':jastadd-mquat-solver-simple')
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.8.1'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0'
......@@ -30,7 +31,7 @@ task benchmarkFull(type: JavaExec, dependsOn: assemble) {
classpath = sourceSets.test.runtimeClasspath
main = 'de.tudresden.inf.st.mquat.benchmark.FullBenchmarkMain'
systemProperty "java.library.path", project.glpkPath
// jvmArgs("-Xmx=4096m")
// jvmArgs("-Xmx=2g")
if (project.hasProperty("scenario")) {
args(scenario.split(','))
}
......
......@@ -4,6 +4,7 @@ import de.tudresden.inf.st.mquat.solving.BenchmarkableSolver;
import de.tudresden.inf.st.mquat.solving.ilp.ILPDirectSolver;
import de.tudresden.inf.st.mquat.solving.ilp.ILPExternalSolver;
import de.tudresden.inf.st.mquat.solving.simple.SimpleSolver;
import uniks.EMFeRSolver;
import java.util.Map;
import java.util.function.Function;
......@@ -22,9 +23,10 @@ public class SolverFactory {
private static Map<String, BenchmarkableSolver> createAvailableSolversIfNeeded() {
if (availableSolvers == null) {
availableSolvers = Stream.of(
new ILPExternalSolver(),
new ILPDirectSolver(),
new SimpleSolver()
new EMFeRSolver(),
// new ILPExternalSolver(),
new ILPDirectSolver(),
new SimpleSolver()
).collect(Collectors.toMap(BenchmarkableSolver::getName, Function.identity()));
}
return availableSolvers;
......
......@@ -2,11 +2,12 @@
"path": "results",
"logLevel": "info",
"solvers": [
"ilp-direct"
"ilp-direct",
// "ilp-external",
// "simple"
"emfer",
"simple"
],
"timeoutValue": 15,
"timeoutValue": 2,
"timeoutUnit": "MINUTES",
"seed": 0,
// "repetitions": 10,
......@@ -17,12 +18,12 @@
{ "id": 3, "name": "small-complex-sw", "variants": 2, "requests": 1, "depth": 5, "resources": 1.5 },
{ "id": 4, "name": "medium", "variants": 10, "requests": 15, "depth": 2, "resources": 1.5 },
{ "id": 5, "name": "medium-many-hw", "variants": 10, "requests": 15, "depth": 2, "resources": 5 },
{ "id": 6, "name": "medium-complex-sw", "variants": 5, "requests": 10, "depth": 5, "resources": 1.5 },
{ "id": 7, "name": "large", "variants": 20, "requests": 20, "depth": 2, "resources": 1.5 },
{ "id": 8, "name": "large-many-hw", "variants": 20, "requests": 20, "depth": 2, "resources": 5 },
{ "id": 9, "name": "large-complex-sw", "variants": 10, "requests": 20, "depth": 5, "resources": 1.5 },
{ "id": 10, "name": "huge", "variants": 50, "requests": 50, "depth": 2, "resources": 1.5 },
{ "id": 11, "name": "huge-many-hw", "variants": 50, "requests": 50, "depth": 2, "resources": 5 },
{ "id": 12, "name": "huge-complex-sw", "variants": 20, "requests": 50, "depth": 5, "resources": 1.5 }
{ "id": 6, "name": "medium-complex-sw", "variants": 5, "requests": 10, "depth": 5, "resources": 1.5 }
// { "id": 7, "name": "large", "variants": 20, "requests": 20, "depth": 2, "resources": 1.5 },
// { "id": 8, "name": "large-many-hw", "variants": 20, "requests": 20, "depth": 2, "resources": 5 },
// { "id": 9, "name": "large-complex-sw", "variants": 10, "requests": 20, "depth": 5, "resources": 1.5 },
// { "id": 10, "name": "huge", "variants": 50, "requests": 50, "depth": 2, "resources": 1.5 },
// { "id": 11, "name": "huge-many-hw", "variants": 50, "requests": 50, "depth": 2, "resources": 5 },
// { "id": 12, "name": "huge-complex-sw", "variants": 20, "requests": 50, "depth": 5, "resources": 1.5 }
]
}
......@@ -6,210 +6,227 @@ 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 emfer.EMFeR;
import emfer.reachability.ReachableState;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EcorePackage;
import uniks.ttc18.EAssignment;
import uniks.ttc18.ESolution;
import uniks.ttc18.Ttc18Factory;
import java.util.*;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.TimeUnit;
public class EMFeRSolver implements BenchmarkableSolver {
private static final Logger logger = LogManager.getLogger(EMFeRSolver.class);
private static final Logger logger = LogManager.getLogger(EMFeRSolver.class);
private Solution lastSolution;
private long lastSolvingTime;
private Solution lastSolution;
private long lastSolvingTime;
private int solutionCounter;
private int solutionCounter;
private StopWatch stopWatch;
private StopWatch stopWatch;
private long maxSolvingTime;
private boolean timedOut;
private long maxSolvingTime;
private boolean timedOut;
public EMFeRSolver() {
this(Long.MAX_VALUE);
}
public EMFeRSolver() {
this(Long.MAX_VALUE);
}
public EMFeRSolver(long maxSolvingTime) {
this.maxSolvingTime = maxSolvingTime;
reset();
}
public EMFeRSolver(long maxSolvingTime) {
this.maxSolvingTime = maxSolvingTime;
reset();
}
private static void assignResource(Assignment assignment, Resource resource) {
Implementation impl = assignment.getImplementation();
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);
}
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;
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)) {
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;
}
if (stopWatch.time(TimeUnit.MILLISECONDS) > maxSolvingTime) {
return checkCounter;
}
@Override
public Solution solve(Root model) throws SolvingException {
reset();
if (model.getNumRequest() == 0) {
return Solution.emptySolutionOf(model);
}
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());
}
ESolution eSolution = Ttc18Factory.eINSTANCE.createESolution();
}
} else {
checkCounter += checkAssignment(solution, solutions, assignments, possibleResources, index + 1, usedResources);
}
usedResources.pop();
}
return checkCounter;
}
EMFeRTrafos emFeRTrafos = new EMFeRTrafos(model);
@Override
public Solution solve(Root model) throws SolvingException
{
stopWatch = StopWatch.start();
emFeRTrafos.createTopLevelAssignments(eSolution);
EMFeRTrafos emFeRTrafos = new EMFeRTrafos(model);
for (EAssignment topAssignment : eSolution.getAssignments())
{
emFeRTrafos.createSubAssignments(eSolution, topAssignment);
}
ESolution eSolution = Ttc18Factory.eINSTANCE.createESolution();
emFeRTrafos.createTopLevelAssignments(eSolution);
int numAssignments = 0;
int numSoftwareSolutions = 0;
int numTotalSoftwareSolutions = 0;
EDataType eString = EcorePackage.eINSTANCE.getEString();
EObject eObj = null;
stopWatch = StopWatch.start();
// HashMap<String, Collection<String>> implementation2NodeListMap = emFeRTrafos.computeImplementation2NodeListMap();
List<Solution> solutions = new ArrayList<>();
EMFeR emfer = new EMFeR()
.withStart(eSolution)
.withMaxNoOfNewStates(100 * 1000)
.withMetric(root -> -1 * emFeRTrafos.getNumberOfOpenIssues(root))
.withTrafo("choose implementation", root -> emFeRTrafos.getImplementationChoices(root), (root, impl) -> emFeRTrafos.applyImplementationChoice(root, impl))
.withTrafo("assign node", root -> emFeRTrafos.getComputeNodeChoices(root), (root, node) -> emFeRTrafos.assignComputeNode(root, node))
;
// iterate all possible assignments
// Note, that this only considers assignments of one configuration to each hardware component
int noOfStates = emfer.explore();
Solution bestSolution = null;
double bestObjective = Double.MAX_VALUE;
int noOfCompleteSolutions = 0;
Solution currentSolution = Solution.createSoftwareSolution(model);
System.out.println("emfer searching for best solution in " + noOfStates);
Solution emferSolution = emFeRTrafos.transform(eSolution);
for (ReachableState state : emfer.getReachabilityGraph().getStates())
{
ESolution newSolution = (ESolution) state.getRoot();
boolean valid = emferSolution.isValid();
// currentSolution = emferSolution;
// currentSolution.trace().process(new LoggerProcessor());
if (bestSolution == null)
{
bestSolution = emFeRTrafos.transformPartial(newSolution);
}
logger.info("emfer found a solution with an objective of {}.", emferSolution.computeObjective());
if (emFeRTrafos.getNumberOfOpenIssues(newSolution) == 0)
{
noOfCompleteSolutions ++;
Solution emferSolution = emFeRTrafos.transformPartial(newSolution);
de.tudresden.inf.st.mquat.jastadd.model.List<Resource> resources = model.getHardwareModel().getResources();
if ( ! emferSolution.isValid())
{
// System.out.println("solution is invalid: " + newSolution);
continue;
}
boolean hasNextSoftwareAssignment;
do {
double newObjective = emferSolution.computeObjective();
numTotalSoftwareSolutions++;
// System.out.println("objective " + newObjective + "\n" + newSolution);
if (newObjective < bestObjective)
{
bestSolution = emferSolution;
bestObjective = newObjective;
System.out.println("Found solution with objective: " + bestObjective);
}
}
}
if (currentSolution.isSoftwareValid()) {
if (bestSolution != null)
{
logger.info("emfer found a solution with an objective of {}. Number of complete solutions {} ", bestSolution.computeObjective(), noOfCompleteSolutions );
}
numSoftwareSolutions++;
lastSolvingTime = stopWatch.time(TimeUnit.MILLISECONDS);
List<Assignment> assignments = currentSolution.allAssignments();
return bestSolution;
}
// initialize the lists of possible assignments
List<Set<Resource>> possibleResources = new ArrayList<>(assignments.size());
private boolean isCompleteSolution(ESolution eSolution)
{
for (EAssignment eAssignment : eSolution.getAssignments())
{
if ( ! isCompleteSolution(eAssignment))
{
return false;
}
}
for (Assignment assignment : assignments) {
Set<Resource> resourceList = new HashSet<>();
for (Resource resource : resources) {
// assignResource(assignment, resource);
if (assignment.isValid()) {
resourceList.add(resource);
return true;
}
private boolean isCompleteSolution(EAssignment eAssignment)
{
if (eAssignment.getImplName() != null && eAssignment.getNodeName() != null)
{
for (EAssignment kid : eAssignment.getAssignments())
{
if ( ! isCompleteSolution(kid))
{
return false;
}
}
possibleResources.add(resourceList);
}
}
numAssignments += checkAssignment(currentSolution, solutions, assignments, possibleResources, 0, new Stack<>());
return true;
}
if (stopWatch.time(TimeUnit.MILLISECONDS) > maxSolvingTime) {
this.timedOut = true;
logger.warn("Timeout! Solving terminated!");
break;
else
{
return false;
}
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;
}
}
private void reset() {
this.lastSolution = null;
this.solutionCounter = 0;
this.lastSolvingTime = 0;
this.timedOut = false;
}
@Override
public String getName() {
return "emfer";
}
@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;
}
}
package uniks;
import de.tudresden.inf.st.mquat.jastadd.model.*;
import de.tudresden.inf.st.mquat.jastadd.model.List;
import de.tudresden.inf.st.mquat.solving.SolverUtils;
import org.eclipse.emf.ecore.EObject;
import uniks.ttc18.EAssignment;
import uniks.ttc18.EChoice;
import uniks.ttc18.ESolution;
import uniks.ttc18.Ttc18Factory;
import java.util.ArrayList;
import java.util.*;
public class EMFeRTrafos
{
......@@ -37,9 +40,9 @@ public class EMFeRTrafos
EAssignment topAssignment = Ttc18Factory.eINSTANCE.createEAssignment();
topAssignment.setRequestName(requName);
topAssignment.setCompName(targetName.toString());
String nodeName = model.getHardwareModel().getResource(resourceNum).getName().toString();
resourceNum++;
topAssignment.setNodeName(nodeName);
// String nodeName = model.getHardwareModel().getResource(resourceNum).getName().toString();
// resourceNum++;
// topAssignment.setNodeName(nodeName);
assignments.add(topAssignment);
}
}
......@@ -71,6 +74,100 @@ public class EMFeRTrafos
}
public Solution transformPartial(ESolution eSolution)
{
Solution result = new Solution();
result.setModel(model);
// top level
for (EAssignment eAssignment : eSolution.getAssignments())
{
Assignment dAssignment = new Assignment();
Request request = findRequest(eAssignment.getRequestName());
dAssignment.setRequest(request);
dAssignment.setTopLevel(true);
Component comp = findComp(model, eAssignment.getCompName());
Implementation implementation = findImplementation(comp, eAssignment.getImplName());
dAssignment.setImplementation(implementation);
if (eAssignment.getNodeName() == null)
{
continue;
}
transformPartialSubAssignments(dAssignment, eAssignment, implementation);
for (Instance instance : implementation.getResourceRequirement().getInstances())
{
Resource resource = findResource(eAssignment.getNodeName());
ResourceMapping resourceMapping = new ResourceMapping(instance, resource, new List<>());
SolverUtils.populateResourceMapping(resourceMapping, implementation.getResourceRequirement(), resource);
dAssignment.setResourceMapping(resourceMapping);
// if (dAssignment.isValid())
// {
// System.out.println("assignment is valid " + dAssignment.getImplementation().getName() + " on " + resource.getName());
// }
}
result.addAssignment(dAssignment);
}
return result;
}
private void transformPartialSubAssignments(Assignment dAssignment, EAssignment eAssignment, Implementation implementation)
{
for (EAssignment eSubAssignment : eAssignment.getAssignments())
{
ComponentMapping componentMapping = new ComponentMapping();
Assignment dSubAssignment = new Assignment();
Request request = dAssignment.getRequest();
dSubAssignment.setRequest(request);
dSubAssignment.setTopLevel(false);
Component subComp = findComp(model, eSubAssignment.getCompName());
Implementation subImpl = findImplementation(subComp, eSubAssignment.getImplName());