diff --git a/.gitignore b/.gitignore
index bde6c8e745c0d31daefd49b6ed4dbf9d2a24e29a..dc2f2ae7b0ad629b9f1825efdaabfe1c518f384c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,4 @@ hs_err_pid*
 .settings/
 .classpath
 .project
+results/
diff --git a/README.md b/README.md
index 1cf35c2e5ad5d73c5dc094ffc32926b72cac3c40..2e2f6da1497ab337adb0b11cd0de34146e65a7a8 100644
--- a/README.md
+++ b/README.md
@@ -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)
diff --git a/jastadd-mquat-benchmark/build.gradle b/jastadd-mquat-benchmark/build.gradle
index eaafbc051d26d58a19aed720a692799fa8d99ab0..f9da75cbda62ed00328be82fa96c00050055db9f 100644
--- a/jastadd-mquat-benchmark/build.gradle
+++ b/jastadd-mquat-benchmark/build.gradle
@@ -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(','))
     }
diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java
index 3a28cd527edf9480cafd5a88342d1fef2c6f6da7..4afb9e4334a7de967603f1056f01bbcaeb768949 100644
--- a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java
@@ -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;
diff --git a/jastadd-mquat-benchmark/src/main/resources/scenarios.json b/jastadd-mquat-benchmark/src/main/resources/scenarios.json
index 42a8d7b7e3d8435a7dac189021350f4d5736de23..d68e08faef22bb22c3110e01146a738555b94f42 100644
--- a/jastadd-mquat-benchmark/src/main/resources/scenarios.json
+++ b/jastadd-mquat-benchmark/src/main/resources/scenarios.json
@@ -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 }
   ]
 }
diff --git a/jastadd-mquat-solver-emfer/libs/libEMFER.jar b/jastadd-mquat-solver-emfer/libs/libEMFER.jar
index b4797b38d2a2fe903daeac6180408e3ab95512b1..2e9952b882ea7f4b4d91fac33d51afec05e4a234 100644
Binary files a/jastadd-mquat-solver-emfer/libs/libEMFER.jar and b/jastadd-mquat-solver-emfer/libs/libEMFER.jar differ
diff --git a/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRSolver.java b/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRSolver.java
index a638bae0fa95e280d4d217046ce9be9a919a5abf..b6eaaeab93a6838ffe6b49280b637dc01fd48f5d 100644
--- a/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRSolver.java
+++ b/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRSolver.java
@@ -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;
+   }
 }
diff --git a/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRTrafos.java b/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRTrafos.java
index 228b6ffa8fd9eebdcd2a0e4a0a84166e005e8117..13eec82110e5c80b58180f7e2ebe29abab26c410 100644
--- a/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRTrafos.java
+++ b/jastadd-mquat-solver-emfer/src/main/java/uniks/EMFeRTrafos.java
@@ -1,12 +1,15 @@
 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());
+
+         dSubAssignment.setImplementation(subImpl);
+
+         Instance theInstance = findInstance(implementation, "the_" + eSubAssignment.getCompName());
+
+         componentMapping.setInstance(theInstance);
+         componentMapping.setAssignment(dSubAssignment);
+         dAssignment.getComponentMappings().add(componentMapping);
+
+         transformSubAssignments(dSubAssignment, eSubAssignment, subImpl);
+
+         if (eSubAssignment.getNodeName() == null)
+         {
+            continue;
+         }
+
+         for (Instance instance : subImpl.getResourceRequirement().getInstances())
+         {
+            Resource resource = findResource(eSubAssignment.getNodeName());
+            ResourceMapping resourceMapping = new ResourceMapping(instance, resource, new List<>());
+            SolverUtils.populateResourceMapping(resourceMapping, subImpl.getResourceRequirement(), resource);
+            dSubAssignment.setResourceMapping(resourceMapping);
+
+            if (dSubAssignment.isValid())
+            {
+               break;
+            }
+         }
+
+      }
+   }
+
+
+
    ArrayList<Resource> availableResources = null;
 
    public Solution transform(ESolution eSolution)
@@ -97,6 +194,10 @@ public class EMFeRTrafos
 
          Component comp = findComp(model, eAssignment.getCompName());
          Implementation implementation = findImplementation(comp, eAssignment.getImplName());
+         if (implementation == null)
+         {
+            continue;
+         }
          dAssignment.setImplementation(implementation);
 
          transformSubAssignments(dAssignment, eAssignment, implementation);
@@ -139,7 +240,10 @@ public class EMFeRTrafos
 
          Component subComp = findComp(model, eSubAssignment.getCompName());
          Implementation subImpl = findImplementation(subComp, eSubAssignment.getImplName());
-
+         if (subImpl == null)
+         {
+            continue;
+         }
          dSubAssignment.setImplementation(subImpl);
 
          for (Instance instance : subImpl.getResourceRequirement().getInstances())
@@ -234,4 +338,335 @@ public class EMFeRTrafos
       }
       return null;
    }
+
+   public Collection<EAssignment> getOpenAssignments(ESolution eSolution)
+   {
+      ArrayList<EAssignment> result = new ArrayList<>();
+
+      for (EAssignment eAssignment : eSolution.getAssignments())
+      {
+         if (eAssignment.getImplName() == null)
+         {
+            result.add(eAssignment);
+         }
+
+         getOpenSubAssignments(eAssignment, result);
+      }
+
+      return result;
+   }
+
+   private void getOpenSubAssignments(EAssignment eAssignment, ArrayList<EAssignment> result)
+   {
+      for (EAssignment subAssignment : eAssignment.getAssignments())
+      {
+         if (subAssignment.getImplName() == null)
+         {
+            result.add(subAssignment);
+         }
+
+         getOpenSubAssignments(subAssignment, result);
+      }
+   }
+
+   public Collection<EObject> getImplementationChoices(EObject root)
+   {
+      ArrayList<EObject> result = new ArrayList<>();
+
+      ESolution eSolution = (ESolution) root;
+
+      for (EAssignment eAssignment : getOpenAssignments(eSolution))
+      {
+         Component comp = findComp(model, eAssignment.getCompName());
+
+         for (Implementation dImpl : comp.getImplementations())
+         {
+            EChoice eImpl = Ttc18Factory.eINSTANCE.createEChoice();
+            eImpl.setAssignment(eAssignment);
+            eImpl.setResName(dImpl.getName().toString());
+            result.add(eImpl);
+         }
+
+         return result;
+      }
+
+      return result;
+   }
+
+   public void applyImplementationChoice(EObject root, EObject handle)
+   {
+      EChoice eImpl = (EChoice) handle;
+
+      EAssignment topAssignment = eImpl.getAssignment();
+      topAssignment.setImplName(eImpl.getResName());
+
+      Component comp = findComp(model, topAssignment.getCompName());
+
+      Implementation dImpl = findImplementation(comp, eImpl.getResName());
+
+      for (ComponentRequirement componentRequirement : dImpl.getComponentRequirementList())
+      {
+         String kidCompName = componentRequirement.getComponentRef().getRef().getName().toString();
+
+         EAssignment kidAssignment = Ttc18Factory.eINSTANCE.createEAssignment();
+         kidAssignment.setRequestName(topAssignment.getRequestName());
+         kidAssignment.setCompName(kidCompName);
+
+         topAssignment.getAssignments().add(kidAssignment);
+      }
+   }
+
+   public Collection getComputeNodeChoices(EObject root)
+   {
+      ESolution eSolution = (ESolution) root;
+      ArrayList<EChoice> result = new ArrayList<>();
+
+      // find assignment that is ready to be deployed
+      EAssignment eAssignment = getNextUndeployedAssignment(eSolution);
+
+      if (eAssignment == null)
+      {
+         return result;
+      }
+
+      HashSet<String> alreadInUseComputeNodes = getAlreadInUseComputeNodes(eSolution);
+
+      // loop through all compute nodes
+      for (Resource compNode : model.getHardwareModel().getResourceList())
+      {
+         String compNodeName = compNode.getName().toString();
+
+//         if (alreadInUseComputeNodes.contains(compNodeName))
+//         {
+//            continue;
+//         }
+
+         eAssignment.setNodeName(compNodeName);
+
+         // create dSolution
+         Solution dSolution = transformPartial(eSolution);
+
+
+         // if assignment is valid, add choice
+         boolean allValid = checkAssignments(dSolution);
+
+         if (allValid)
+         {
+            EChoice eChoice = Ttc18Factory.eINSTANCE.createEChoice();
+            eChoice.setAssignment(eAssignment);
+            eChoice.setResName(compNodeName);
+            result.add(eChoice);
+
+//            if (result.size() >= 4)
+//            {
+//               break;
+//            }
+         }
+      }
+
+      eAssignment.setNodeName(null);
+
+      if (result.size() == 0)
+      {
+         System.out.println("did not find hardware for \n" + eAssignment);
+      }
+
+      return result;
+   }
+
+   private boolean checkAssignments(Solution dSolution)
+   {
+      for (Assignment dAssignment : dSolution.getAssignmentList())
+      {
+         if (dAssignment.getResource() != null)
+         {
+            if (dAssignment.isValid())
+            {
+               // check kids
+               checkAssignments(dAssignment);
+            }
+            else
+            {
+               return false;
+            }
+         }
+      }
+
+      return true;
+   }
+
+
+   private boolean checkAssignments(Assignment parent)
+   {
+      for (ComponentMapping componentMapping : parent.getComponentMappingList())
+      {
+         Assignment dAssignment = componentMapping.getAssignment();
+
+         if (dAssignment.getResourceMapping() != null && dAssignment.getResource() != null)
+         {
+            if (dAssignment.isValid())
+            {
+               // check kids
+               checkAssignments(dAssignment);
+            }
+            else
+            {
+               return false;
+            }
+         }
+      }
+
+      return true;
+   }
+
+
+   private EAssignment getNextUndeployedAssignment(ESolution eSolution)
+   {
+      for (EAssignment eAssignment : eSolution.getAssignments())
+      {
+         if ( ! allAssignmentsInTreeHaveAnImplementation(eAssignment))
+         {
+            continue;
+         }
+
+         if (eAssignment.getNodeName() == null)
+         {
+            return eAssignment;
+         }
+
+         EAssignment kid = getNextUndeployedAssignment(eAssignment);
+
+         if (kid != null)
+         {
+            return kid;
+         }
+      }
+
+      return null;
+   }
+
+   private boolean allAssignmentsInTreeHaveAnImplementation(EAssignment eAssignment)
+   {
+      if (eAssignment.getImplName() == null)
+      {
+         return false;
+      }
+
+      for (EAssignment kid : eAssignment.getAssignments())
+      {
+         if (! allAssignmentsInTreeHaveAnImplementation(kid))
+         {
+            return false;
+         }
+      }
+
+      return true;
+   }
+
+   private EAssignment getNextUndeployedAssignment(EAssignment eAssignment)
+   {
+      for (EAssignment kid : eAssignment.getAssignments())
+      {
+         if (kid.getImplName() == null)
+         {
+            continue;
+         }
+
+         if (kid.getNodeName() == null)
+         {
+            return kid;
+         }
+
+         EAssignment grandKid = getNextUndeployedAssignment(kid);
+
+         if (grandKid != null)
+         {
+            return grandKid;
+         }
+      }
+
+      return null;
+   }
+
+
+
+   private HashSet<String> getAlreadInUseComputeNodes(ESolution eSolution)
+   {
+      HashSet<String> result = new HashSet<>();
+
+      for (EAssignment eAssignment : eSolution.getAssignments())
+      {
+         getAlreadInUseComputeNodes(eAssignment, result);
+      }
+
+      return result;
+   }
+
+
+
+      private void getAlreadInUseComputeNodes(EAssignment eAssignment, Set<String> alreadInUseComputeNodes)
+   {
+      if (eAssignment.getNodeName() != null)
+      {
+         alreadInUseComputeNodes.add(eAssignment.getNodeName());
+      }
+
+      for (EAssignment kidAssignment : eAssignment.getAssignments())
+      {
+         getAlreadInUseComputeNodes(kidAssignment, alreadInUseComputeNodes);
+      }
+   }
+
+   private Collection<EAssignment> getNoComputeNodeAssignments(ESolution eSolution)
+   {
+      ArrayList<EAssignment> result = new ArrayList<>();
+
+      for (EAssignment eAssignment : eSolution.getAssignments())
+      {
+         if (eAssignment.getNodeName() == null)
+         {
+            result.add(eAssignment);
+         }
+
+         getOpenSubAssignments(eAssignment, result);
+      }
+
+      return result;
+   }
+
+
+
+   public void assignComputeNode(EObject root, EObject node)
+   {
+      EChoice eChoice = (EChoice) node;
+      eChoice.getAssignment().setNodeName(eChoice.getResName());
+   }
+
+   public double getNumberOfOpenIssues(EObject root)
+   {
+      ESolution eSolution = (ESolution) root;
+
+      int result = 0;
+
+      for (EAssignment eAssignment : eSolution.getAssignments())
+      {
+         result +=  getNumberOfAssignmentOpenIssues(eAssignment);
+      }
+
+      return result;
+   }
+
+   private int getNumberOfAssignmentOpenIssues(EAssignment eAssignment)
+   {
+      int result = 0;
+      if (eAssignment.getImplName() == null) result++;
+      if (eAssignment.getNodeName() == null) result++;
+
+      for (EAssignment kid : eAssignment.getAssignments())
+      {
+         result += getNumberOfAssignmentOpenIssues(kid);
+      }
+
+      return result;
+   }
 }
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
index d953849a6efcfc90366a63bb4835925fdc6780a3..9d21b6842e2ef79f5f1b74de6f408c5229ca626a 100644
--- 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
@@ -40,11 +40,12 @@ public class EMFeRSolverTest {
     int nfp = 0;
     int req = 3;
     int cpu = 1;
-    int seed = 0;
+    int seed = 1;
 
     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);
diff --git a/jastadd-mquat-solver-simple/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleSolverTest.java b/jastadd-mquat-solver-simple/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleSolverTest.java
index 7647d3e01efa490e23754e80ac4097ce18947842..572b2539b81015fe8c77e6ea1a2bc55d01ea3c98 100644
--- a/jastadd-mquat-solver-simple/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleSolverTest.java
+++ b/jastadd-mquat-solver-simple/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleSolverTest.java
@@ -37,7 +37,7 @@ public class SimpleSolverTest {
     int nfp = 0;
     int req = 3;
     int cpu = 1;
-    int seed = 0;
+    int seed = 1;
 
     ScenarioGenerator generator = new ScenarioGenerator(new ScenarioDescription(tlc, iac, isd, cac, csd, dep, imp, res, req, cpu, seed));
 
diff --git a/settings.gradle b/settings.gradle
index e6ec605b4b6a0cfc2bf60b28f153b9c9ee023035..fcba86cf70b92028702f540a33c9b8477b3033b9 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -4,7 +4,6 @@ include ':jastadd-mquat-base'
 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'
+include ':jastadd-mquat-solver-simple'