diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..2dacd4500719662ef5b3a794fe6f4fb154aafdb4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,73 @@
+# TTC 2018: Case 1 "Quality-based Software-Selection and Hardware-Mapping as Model Transformation Problem"
+
+## Getting started
+
+In order to get the case working, perform the following steps:
+
+- clone the repository: `git clone git@git-st.inf.tu-dresden.de:stgroup/ttc18.git && cd ttc18`
+- build it: `./gradlew build` (or `gradlew.bat build` on Windows)
+- run the benchmark: `./gradlew benchmarkFull`
+	- as this might take long, running a single scenario is possible with `./gradlew benchmarkFull '-Pscenario=1'`
+
+## Overview over the repository structure
+
+All modules are prefixed with `jastadd-mquat`, as this is an implementation of MQuAT (Multi-Quality AutoTuning) based on [JastAdd](http://www.jastadd.org). There are 5 modules:
+
+- `base`: Contains the specifications for grammar and attributes, (de-)serializers and the model generator
+- `benchmark`: Benchmark infrastructure and settings
+- `solver`: Interfaces for solvers, and a small testsuite
+- `solver-ilp`: Reference implementation using ILP
+- `solver-simple`: Naïve, brute-force solver written in Java
+
+**TODO: Check links** https://git-st.inf.tu-dresden.de/stgroup/ttc18/blob/master/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/BenchmarkableSolver.java
+
+## Creating a solution
+
+A new solution should be created using a new module (or multiple, if necessary). You can use the simple-solver module as an example.
+The following steps need to be completed:
+
+1. Create an implementation of [`de.tudresden.inf.st.mquat.solving.BenchmarkableSolver`](https://git-st.inf.tu-dresden.de/stgroup/ttc18/blob/master/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/BenchmarkableSolver.java) (which extends the [`Solver`](https://git-st.inf.tu-dresden.de/stgroup/ttc18/blob/master/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/Solver.java) interface). The main method here is `public Solution solve(Root model) throws SolvingException`, which takes a model as input an returns a solution
+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. 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)
+1. Run the benchmark, either `./gradlew benchmarkFull` or `./gradlew benchmarkCustom`
+
+## Custom Benchmark
+
+To test your solution, the Gradle task `benchmarkCustom` can be used. This task generates a custom set of models and runs a benchmark for them.
+All default parameters are specified in the file `benchmark-settings.json` within the directory `jastadd-mquat-benchmark/src/main/resources`.
+To change them, create a new file in this directory named `local-benchmark-settings.json`.
+In this local version, all parameter values override the default settings, but are ignored when committing.
+
+To test your solver with the name `fancy-solver` along with the reference implementation using a model with `10` and `15` requests and a timeout of 50 seconds, the file `local-benchmark-settings.json` would be as follows.
+
+```json
+{
+  "solvers": [
+    "ilp-direct",
+    "fancy-solver"
+  ],
+  "basic": {
+    "verbose": true,
+    "minRequests": 10,
+    "maxRequests": 15,
+    "stepRequests": 5,
+    "timeoutValue": 50,
+    "timeoutUnit": "SECONDS",
+    "total": 2
+  }
+}
+```
+
+The value `total` is used to constrain the total number of models to be generated. Set this to `null` (the default) to generate all value for the defined parameter ranges.
+Refer to [`de.tudresden.inf.st.mquat.generator.ScenarioDescription`](https://git-st.inf.tu-dresden.de/stgroup/ttc18/blob/master/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ScenarioDescription.java) for a description of the possible parameters.
+
+## Notes and Troubleshooting
+
+- please use the gradle wrapper script, as different version of Gradle might not work with the setup
+	- the wrapper script uses version `3.3`
+- if anything is not working as expected, feel free to contact on of the authors of the TTC case or open an [issue](https://git-st.inf.tu-dresden.de/stgroup/ttc18/issues/new)
diff --git a/attributes.json b/attributes.json
new file mode 100644
index 0000000000000000000000000000000000000000..eca98ea53bee044563994a8f94d4f2d04f78cce4
--- /dev/null
+++ b/attributes.json
@@ -0,0 +1,194 @@
+{
+  "resolveProperty": {
+    "returntype": "Property", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "Component"
+    ]
+  }, 
+  "isSoftwareDesignator": {
+    "returntype": "boolean", 
+    "kind": "syn", 
+    "args": "", 
+    "eqs": [
+      "Designator"
+    ]
+  }, 
+  "findPropertyByName": {
+    "returntype": "Property", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "SoftwareModel"
+    ]
+  }, 
+  "asPropertyResourceDesignator": {
+    "returntype": "PropertyResourceDesignator", 
+    "kind": "syn", 
+    "args": "", 
+    "eqs": [
+      "Designator"
+    ]
+  }, 
+  "isMetaParameterDesignator": {
+    "returntype": "boolean", 
+    "kind": "syn", 
+    "args": "", 
+    "eqs": [
+      "Designator"
+    ]
+  }, 
+  "asSoftwareDesignator": {
+    "returntype": "SoftwareDesignator", 
+    "kind": "syn", 
+    "args": "", 
+    "eqs": [
+      "Designator"
+    ]
+  }, 
+  "isPropertyResourceDesignator": {
+    "returntype": "boolean", 
+    "kind": "syn", 
+    "args": "", 
+    "eqs": [
+      "Designator"
+    ]
+  }, 
+  "findImplementationByName": {
+    "returntype": "Implementation", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "Root"
+    ]
+  }, 
+  "getRequiringClauseValue": {
+    "returntype": "double", 
+    "kind": "syn", 
+    "args": "ResourceType type, String propertyName, int index", 
+    "eqs": [
+      "Implementation"
+    ]
+  }, 
+  "findInstanceByName": {
+    "returntype": "Instance", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "ResourceRequirement"
+    ]
+  }, 
+  "findResourceTypeByName": {
+    "returntype": "ResourceType", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "HardwareModel"
+    ]
+  }, 
+  "findSubResourceByTypeName": {
+    "returntype": "Resource", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "Resource"
+    ]
+  }, 
+  "resolveMetaParameter": {
+    "returntype": "MetaParameter", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "SoftwareModel"
+    ]
+  }, 
+  "findResourceByName": {
+    "returntype": "Resource", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "Resource"
+    ]
+  }, 
+  "getCurrentValueByProperty": {
+    "returntype": "double", 
+    "kind": "syn", 
+    "args": "Property property", 
+    "eqs": [
+      "Resource"
+    ]
+  }, 
+  "findSubResourceTypeByName": {
+    "returntype": "ResourceType", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "ResourceType"
+    ]
+  }, 
+  "getRequiringClauseInstance": {
+    "returntype": "Instance", 
+    "kind": "syn", 
+    "args": "ResourceType type, String propertyName, int index", 
+    "eqs": [
+      "Implementation"
+    ]
+  }, 
+  "findFirstProvidingClause": {
+    "returntype": "Clause", 
+    "kind": "syn", 
+    "args": "Property property", 
+    "eqs": [
+      "Implementation"
+    ]
+  }, 
+  "findRequestByName": {
+    "returntype": "Request", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "Root"
+    ]
+  }, 
+  "getCurrentValueByPropertyName": {
+    "returntype": "double", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "Resource"
+    ]
+  }, 
+  "getConstraintValueByName": {
+    "returntype": "double", 
+    "kind": "syn", 
+    "args": "String name", 
+    "eqs": [
+      "Request"
+    ]
+  }, 
+  "resolveQualifiedName": {
+    "returntype": "Designator", 
+    "kind": "syn", 
+    "args": "QualifiedName qn", 
+    "eqs": [
+      "Implementation"
+    ]
+  }, 
+  "root": {
+    "returntype": "Root", 
+    "kind": "syn", 
+    "args": "", 
+    "eqs": [
+      "ASTNode"
+    ]
+  }, 
+  "asMetaParameterDesignator": {
+    "returntype": "MetaParameterDesignator", 
+    "kind": "syn", 
+    "args": "", 
+    "eqs": [
+      "Designator"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..412985c3957b8b3a523bab858e7029393663e584
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,40 @@
+allprojects  {
+	group = 'de.tudresden.inf.st'
+	version = '1.0.0-SNAPSHOT'
+}
+
+subprojects {
+	apply plugin: 'java'
+	sourceCompatibility = 1.8
+	targetCompatibility = 1.8
+
+	task packageSources(type: Jar) {
+		classifier = 'sources'
+		from sourceSets.main.allSource
+	}
+
+	artifacts.archives packageSources
+
+	task longRunningTest(type: Test, description: 'Runs long running tests.', group: 'verification') {
+		outputs.upToDateWhen {false}
+		systemProperty "de.tudresden.inf.st.mquat.longRunningTest", "true"
+	}
+
+	configurations {
+		testArtifacts.extendsFrom testRuntime
+	}
+
+	task testJar(type: Jar) {
+		classifier "test"
+		from sourceSets.test.output
+	}
+
+	artifacts {
+		testArtifacts testJar
+	}
+
+	repositories {
+		maven { url "https://www.xypron.de/repository" }
+	}
+
+}
diff --git a/checkSolution.sh b/checkSolution.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4136722f0b60960e02750e72311fb0680aeacc98
--- /dev/null
+++ b/checkSolution.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+./gradlew checkSolution -PfileNames="$(realpath $1)","$(realpath $2)"
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..6e0801f892720a1742cb422b03dda5d813a51cd5
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1 @@
+glpkPath = /usr/local/lib/jni
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1b828b92f450d58e9dcd248cec2f932f12769bc0
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Jan 15 16:36:10 CET 2018
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000000000000000000000000000000000000..4453ccea33d960069d9137ee65f6b21fc65e7e92
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save ( ) {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000000000000000000000000000000000000..e95643d6a2ca62258464e83c72f5156dc941c609
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/jastadd-mquat-base/.gitignore b/jastadd-mquat-base/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..cebd2f80655a5da0c591d1dc9c2999f354871b9b
--- /dev/null
+++ b/jastadd-mquat-base/.gitignore
@@ -0,0 +1,9 @@
+out/
+.gradle
+src/gen
+src/gen-res
+build
+coverage
+/bin/
+/build/
+/out/
diff --git a/jastadd-mquat-base/DrAST.cfg b/jastadd-mquat-base/DrAST.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..c229f19b6e4a7ae45494a802615a084bd488a49c
--- /dev/null
+++ b/jastadd-mquat-base/DrAST.cfg
@@ -0,0 +1,4 @@
+dynamic-values=0
+NTA-computed=0
+NTA-cached=1
+NTA-depth=1
diff --git a/jastadd-mquat-base/DrASTGUI.cfg b/jastadd-mquat-base/DrASTGUI.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..4299b902e6d23c601c7f39bfb7a73ce3217140d4
--- /dev/null
+++ b/jastadd-mquat-base/DrASTGUI.cfg
@@ -0,0 +1,9 @@
+nodeThreshold=1000
+showNodes=1
+showEdges=1
+niceEdges=1
+normalEdgeWidth=1.0
+refEdgeWidth=2.0
+dashedEdgeWidth=0.2
+normalVertexEdgeWidth=1.0
+dashedVertexEdgeWidth=0.2
diff --git a/jastadd-mquat-base/build.gradle b/jastadd-mquat-base/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..f9bcd7a73c1732abd0c94f305d6229800304de87
--- /dev/null
+++ b/jastadd-mquat-base/build.gradle
@@ -0,0 +1,121 @@
+group 'de.tudresden.inf.st'
+version '1.0-SNAPSHOT'
+
+apply plugin: 'java'
+apply plugin: 'jastadd'
+apply plugin: 'application'
+
+//mainClassName = 'de.tudresden.inf.st.mquat.Main'
+
+sourceCompatibility = 1.8
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.8.1'
+    compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
+    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'
+
+    testCompile 'junit:junit:4.12'
+    testCompile files('libs/DrAST-1.2.2.jar')
+    testCompile fileTree(dir: "${System.properties['java.home']}", include: '**/jfxrt.jar')
+}
+
+run {
+    mainClassName = 'de.tudresden.inf.st.mquat.Main'
+    standardInput = System.in
+    if (project.hasProperty("appArgs")) {
+        args Eval.me(appArgs)
+    }
+}
+
+task toEcl(type: JavaExec, dependsOn: assemble) {
+    group "application"
+    classpath = sourceSets.test.runtimeClasspath
+    main = 'de.tudresden.inf.st.mquat.Main'
+}
+
+task checkSolution(type: JavaExec, dependsOn: assemble) {
+    group "application"
+    classpath = sourceSets.test.runtimeClasspath
+    main = 'de.tudresden.inf.st.mquat.MainCheck'
+    if (project.hasProperty("fileNames")) {
+        args(fileNames.split(','))
+    }
+}
+
+buildscript {
+    repositories.mavenLocal()
+    repositories.mavenCentral()
+    dependencies {
+        classpath 'org.jastadd:jastaddgradle:1.10.3'
+    }
+}
+
+
+jar {
+  manifest {
+    attributes(
+      'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
+      'Main-Class': 'de.tudresden.inf.st.mquat.Main'
+    )
+  }
+}
+
+javadoc {
+    // this is only run to get the index file etc.
+    failOnError = false
+}
+
+task DrAST(type: JavaExec, dependsOn:jar) {
+    group = "verification"
+    description = 'run the DrAST visual debugger tool'
+    classpath = sourceSets.test.runtimeClasspath
+    main = 'de.tudresden.inf.st.mquat.DrAstRunner'
+}
+
+task RagDoll(type: Javadoc, dependsOn:javadoc) {
+    doFirst {
+        options.addStringOption("ragroot", "./src/main/jastadd")
+    }
+    group = "documentation"
+    description = 'create a RagDoll documentation'
+    classpath = javadoc.classpath
+    destinationDir = javadoc.destinationDir
+    excludes = javadoc.excludes
+    executable = javadoc.executable
+    failOnError = false
+    includes = javadoc.includes
+    options.doclet = "ragdoll.RagDollDoclet"
+    options.docletpath = files('libs/RagDoll.jar').asList()
+
+    source = javadoc.source
+    options.linkSource = true
+
+    // title not working for some reason
+    title = ""
+    doLast {
+        println "Visit: file://" + destinationDir + "/index.html"
+    }
+}
+
+jastadd {
+    configureModuleBuild()
+    modules "jastadd_modules"
+
+    module = "expressions"
+
+    extraJastAddOptions = ['--cache=none']
+
+    astPackage = 'de.tudresden.inf.st.mquat.jastadd.model'
+    genDir = 'src/gen/java'
+
+    buildInfoDir = 'src/gen-res'
+    parser.name = 'MquatParser'
+
+    scanner.genDir = "src/gen/java/de/tudresden/inf/st/mquat/jastadd/scanner"
+    parser.genDir = "src/gen/java/de/tudresden/inf/st/mquat/jastadd/parser"
+}
diff --git a/jastadd-mquat-base/filter.fcl b/jastadd-mquat-base/filter.fcl
new file mode 100644
index 0000000000000000000000000000000000000000..e7b570413653ed74f6e9fb3e07d824aa50aa1c0d
--- /dev/null
+++ b/jastadd-mquat-base/filter.fcl
@@ -0,0 +1,25 @@
+/*
+This filter is autogenerated.
+
+ - Add the name of the filters you want to use in the configs block. 
+ - Write the name of the node types you want to see in the AST inside your filters.
+     . Add a : to the begining of each name.
+     . Child classes of a type will also be included in the graph.
+
+You can filter on attributes and AST-position, show attributes in the graph and style the nodes. 
+see https://bitbucket.org/jastadd/jastadddebugger-exjobb/wiki/The%20Filter%20Configuration%20Language
+for full documentation.
+*/
+configs{
+    use = include;
+}
+filter include{
+    /**/
+    :ASTNode{
+        when{}
+        subtree{}
+        show{}
+        style{}
+    }
+    /**/
+}
diff --git a/jastadd-mquat-base/jastadd_modules b/jastadd-mquat-base/jastadd_modules
new file mode 100644
index 0000000000000000000000000000000000000000..4e0695125cef630350ba65950bb2052cd0c2d6da
--- /dev/null
+++ b/jastadd-mquat-base/jastadd_modules
@@ -0,0 +1,23 @@
+module("expressions") {
+
+	java {
+		basedir "src/main/java/"
+		include "**/*.java"
+	}
+
+	jastadd {
+		basedir "src/main/jastadd/"
+		include "**/*.ast"
+		include "**/*.jadd"
+		include "**/*.jrag"
+	}
+
+	scanner {
+	    include "src/main/jastadd/mquat.flex"
+	}
+
+	parser {
+	    include "src/main/jastadd/mquat.parser"
+	}
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/ASTPrinting.jadd b/jastadd-mquat-base/src/main/jastadd/ASTPrinting.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..925d104e7c75d37147719ab31e6d3b476d060431
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/ASTPrinting.jadd
@@ -0,0 +1,43 @@
+/**
+ * contains a method to display a debug text output of the AST
+ */
+aspect ASTPrinting {
+
+  public String ASTNode.getASTString() {
+
+    String result = this.getClass().getSimpleName() + "\n";
+
+    for (java.lang.reflect.Method method : this.getClass().getMethods()) {
+      ASTNodeAnnotation.Token annotation = method.getAnnotation(ASTNodeAnnotation.Token.class);
+      if (annotation != null) {
+        try {
+          result += "|--" + annotation.name() + ": " + method.invoke(this);
+        } catch (IllegalAccessException e) {
+          e.printStackTrace();
+        } catch (java.lang.reflect.InvocationTargetException e) {
+          e.printStackTrace();
+        }
+        result += "\n";
+      }
+    }
+
+    for(int childIndex = 0; childIndex < getNumChildNoTransform(); childIndex++) {
+
+      ASTNode<?> child = getChildNoTransform(childIndex);
+      String childString = "NULL\n";
+      if(child != null) {
+        childString = child.getASTString();
+      }
+
+      if(childIndex < getNumChildNoTransform() - 1) {
+        childString = childString.replaceAll("(?m)^", "|  ");
+      } else {
+        childString = childString.replaceAll("(?m)^", "   ");
+      }
+
+      result += "|\n|--" + childString.substring(3);
+    }
+
+    return result;
+  }
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/Analysis.jrag b/jastadd-mquat-base/src/main/jastadd/Analysis.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..e1e4667db6926a73ae2ac0e071bdf90aff346364
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Analysis.jrag
@@ -0,0 +1,18 @@
+/**
+ * This aspect contains commonly used attributes to easier navigate the model
+ */
+aspect Analysis {
+
+  syn boolean Clause.isRequiringClause() = getClauseType() == ClauseType.REQUIRING;
+  syn boolean Clause.isProvidingClause() = getClauseType() == ClauseType.PROVIDING;
+
+  inh boolean Designator.inProvidingClause();
+  eq Root.getSoftwareModel().inProvidingClause() = false;
+  eq Clause.getExpression().inProvidingClause() = isProvidingClause();
+  eq Clause.getDesignator().inProvidingClause() = isProvidingClause();
+
+  inh boolean Designator.inRequiringClause();
+  eq Root.getSoftwareModel().inRequiringClause() = false;
+  eq Clause.getExpression().inRequiringClause() = isRequiringClause();
+  eq Clause.getDesignator().inRequiringClause() = isRequiringClause();
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/Clauses.jrag b/jastadd-mquat-base/src/main/jastadd/Clauses.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..fb760fb8cb0fb997e804cfde265d44e5227ad399
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Clauses.jrag
@@ -0,0 +1,24 @@
+aspect Clauses {
+
+  uncache Clause.checkUsing(Assignment assignment);
+  syn boolean Clause.checkUsing(Assignment assignment) {
+    double leftSide = getDesignator().evalUsing(assignment);
+    double rightSide = getExpression().evalUsing(assignment);
+    switch (getClauseComparator()) {
+      case LT:
+        return leftSide < rightSide;
+      case LE:
+        return leftSide <= rightSide;
+      case EQ:
+        return leftSide == rightSide;
+      case NE:
+        return leftSide != rightSide;
+      case GE:
+        return leftSide >= rightSide;
+      case GT:
+        return leftSide > rightSide;
+    }
+    throw new RuntimeException("Unknown clause comparator. This should never happen!");
+  }
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/Enums.jadd b/jastadd-mquat-base/src/main/jastadd/Enums.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..9b388586f236509efe31a77c78ff029ee0986493
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Enums.jadd
@@ -0,0 +1,22 @@
+aspect Enums {
+	public enum PropertyAggregation {
+		SUM,
+		MAX
+	}
+
+	public enum ClauseType {
+    REQUIRING,
+    PROVIDING
+	}
+
+	public enum ClauseComparator {
+    LT { public String symbol() { return "<";  } },
+    LE { public String symbol() { return "<="; } },
+    EQ { public String symbol() { return "=";  } },
+    NE { public String symbol() { return "!="; } },
+    GE { public String symbol() { return ">="; } },
+    GT { public String symbol() { return ">";  } };
+
+    public String symbol() { throw new AbstractMethodError(); }
+	}
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/Eval.jrag b/jastadd-mquat-base/src/main/jastadd/Eval.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..6f0e30ba20a9fdb6eed5eb694b6f807a83db2661
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Eval.jrag
@@ -0,0 +1,111 @@
+aspect eval {
+
+
+  uncache Clause.checkUsing(Request request, Resource resource);
+  syn boolean Clause.checkUsing(Request request, Resource resource) = checkUsing(simpleAssignment(request, resource));
+
+  syn double Expression.evalAsDouble();
+
+  eq LiteralExpression.evalAsDouble() = getValue();
+  eq ParenthesizedExpression.evalAsDouble() = getExpression().evalAsDouble();
+
+  eq AddExpression.evalAsDouble() = getLeft().evalAsDouble() + getRight().evalAsDouble();
+  eq SubExpression.evalAsDouble() = getLeft().evalAsDouble() - getRight().evalAsDouble();
+  eq MultExpression.evalAsDouble() = getLeft().evalAsDouble() * getRight().evalAsDouble();
+  eq DivExpression.evalAsDouble() = getLeft().evalAsDouble() / getRight().evalAsDouble();
+  eq PowerExpression.evalAsDouble() = Math.pow(getLeft().evalAsDouble(), getRight().evalAsDouble());
+
+  syn double Designator.evalAsDouble();
+  eq QualifiedNameDesignator.evalAsDouble() {
+    throw new RuntimeException("This attribute should not be called because a QualifiedNameDesignator is a temporary node!");
+    }
+  eq SoftwareDesignator.evalAsDouble() {
+    throw new RuntimeException("TODO implement ParentResourceDesignator.evalAsDouble()");
+  }
+  eq PropertyResourceDesignator.evalAsDouble() {
+    if (inRequiringClause()) {
+      // TODO
+    }
+    throw new RuntimeException("TODO implement PropertyResourceDesignator.evalAsDouble()");
+  }
+  eq MetaParameterDesignator.evalAsDouble() {
+    throw new RuntimeException("TODO implement MetaParameterDesignator.evalAsDouble()");
+  }
+
+  uncache Clause.evalUsing(Request request, Resource target);
+  syn double Clause.evalUsing(Request request, Resource target) = evalUsing(simpleAssignment(request, target));
+
+  // eval using for assignments
+  uncache Clause.evalUsing(Assignment assignment);
+  syn double Clause.evalUsing(Assignment assignment) = getExpression().evalUsing(assignment);
+
+  uncache Expression.evalUsing(Assignment assignment);
+  syn double Expression.evalUsing(Assignment assignment);
+
+  eq LiteralExpression.evalUsing(Assignment assignment) = getValue();
+  eq ParenthesizedExpression.evalUsing(Assignment assignment) = getExpression().evalUsing(assignment);
+
+  eq AddExpression.evalUsing(Assignment assignment) = getLeft().evalUsing(assignment) + getRight().evalUsing(assignment);
+  eq SubExpression.evalUsing(Assignment assignment) = getLeft().evalUsing(assignment) - getRight().evalUsing(assignment);
+  eq MultExpression.evalUsing(Assignment assignment) = getLeft().evalUsing(assignment) * getRight().evalUsing(assignment);
+  eq DivExpression.evalUsing(Assignment assignment) = getLeft().evalUsing(assignment) / getRight().evalUsing(assignment);
+  eq PowerExpression.evalUsing(Assignment assignment) = Math.pow(getLeft().evalUsing(assignment), getRight().evalUsing(assignment));
+
+  uncache Designator.evalUsing(Assignment assignment);
+  syn double Designator.evalUsing(Assignment assignment);
+  eq QualifiedNameDesignator.evalUsing(Assignment assignment) {
+    throw new RuntimeException("This attribute should not be called because a QualifiedNameDesignator is a temporary node!");
+  }
+  eq SoftwareDesignator.evalUsing(Assignment assignment) {
+    Assignment providingAssignment;
+    if (this.hasInstanceRef()) {
+      // referencing a required component
+      providingAssignment = assignment.mappedAssignment(this.getInstanceRef().getRef());
+    } else {
+      // use given implementation for resolving
+      providingAssignment = assignment;
+    }
+    if (providingAssignment == null) {
+      MquatWriteSettings settings = new MquatWriteSettings("");
+      logger.error("Could not evaluate {} in {} of {}",
+        this.print(settings), containingClause().print(settings),
+    ((ModelElement)containingClause().getParent()).name());
+      return 0;
+    }
+    for (Clause clause : providingAssignment.getImplementation().getClauseList()) {
+      if (clause.isProvidingClause()) {
+        if (clause.getDesignator().isSoftwareDesignator()) {
+          SoftwareDesignator sd = clause.getDesignator().asSoftwareDesignator();
+          if (!sd.hasInstanceRef()) {
+            if (sd.getPropertyRef().getRef().equals(this.getPropertyRef().getRef())) {
+              return clause.getExpression().evalUsing(providingAssignment);
+            }
+            // found another provision clause with a different property
+          }
+        }
+      }
+    }
+    throw new RuntimeException("this should not be happening!");
+  }
+  eq PropertyResourceDesignator.evalUsing(Assignment assignment) {
+    Resource resource = assignment.mappedResource(this.getInstanceRef().getRef());
+    return resource.getCurrentValueByProperty(this.getPropertyRef().getRef());
+  }
+  eq MetaParameterDesignator.evalUsing(Assignment assignment) {
+    LiteralExpression litExp = assignment.getRequest().getMetaParameterExpression(getMetaParameterRef().getRef());
+    if (litExp != null) {
+      // TODO could also using evalAsDouble here
+      return litExp.evalUsing(assignment);
+    }
+    logger.error("evalUsing: Request did not have assignment for meta {}, returning 0", getMetaParameterRef().name());
+    return 0;
+  }
+
+  rewrite QualifiedNameDesignator {
+    to Designator {
+      MquatWriteSettings settings = new MquatWriteSettings(" ");
+      return containingClause().resolveQualifiedName(this.getQualifiedName());
+    }
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/Expression.ast b/jastadd-mquat-base/src/main/jastadd/Expression.ast
new file mode 100644
index 0000000000000000000000000000000000000000..48341a26f5643eecabddefaae8952ae7fce5c46b
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Expression.ast
@@ -0,0 +1,17 @@
+// Expression Language
+
+abstract Expression ;
+
+LiteralExpression:Expression ::= <Value:double> ;
+
+// variation point of the expression language:
+abstract Designator:Expression ;
+
+ParenthesizedExpression:Expression ::= Expression ;
+
+abstract BinaryExpression:Expression ::= Left:Expression Right:Expression ;
+AddExpression:BinaryExpression ;
+SubExpression:BinaryExpression ;
+MultExpression:BinaryExpression ;
+DivExpression:BinaryExpression ;
+PowerExpression:BinaryExpression ;
diff --git a/jastadd-mquat-base/src/main/jastadd/Helpers.jadd b/jastadd-mquat-base/src/main/jastadd/Helpers.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..36cbd529954bc90bbc67a9db7ad2fd5ef5c84539
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Helpers.jadd
@@ -0,0 +1,25 @@
+aspect Helpers {
+
+  public java.util.Collection<T> List.asJavaCollection() {
+    java.util.List<T> javaList = new java.util.ArrayList();
+    for (T child : this) {
+      javaList.add(child);
+    }
+    return javaList;
+  }
+
+  public int ASTNode.posInParent() {
+    if (getParent() == null) {
+      throw new RuntimeException();
+    } else {
+      return getParent().getIndexOfChild(this);
+    }
+  }
+
+  public ASTNode[] List.toArray() {
+    ASTNode[] result = new ASTNode[numChildren];
+    System.arraycopy(children, 0, result, 0, numChildren);
+    return result;
+  }
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/Imports.jadd b/jastadd-mquat-base/src/main/jastadd/Imports.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..2ab67fea787603bcf4aa9f82cead0e06cc828f0f
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Imports.jadd
@@ -0,0 +1,15 @@
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Stack;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.NoSuchElementException;
+
+aspect X {
+
+  syn Set Clause.x() = null;
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/Logging.jadd b/jastadd-mquat-base/src/main/jastadd/Logging.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..a5e2deb4fb9b6954da104611fd2975e5053cc396
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Logging.jadd
@@ -0,0 +1,54 @@
+aspect Logging {
+
+  protected static final org.apache.logging.log4j.Logger AddExpression.logger = org.apache.logging.log4j.LogManager.getLogger(AddExpression.class);
+  protected static final org.apache.logging.log4j.Logger Assignment.logger = org.apache.logging.log4j.LogManager.getLogger(Assignment.class);
+  protected static final org.apache.logging.log4j.Logger ASTNode.logger = org.apache.logging.log4j.LogManager.getLogger(ASTNode.class);
+  protected static final org.apache.logging.log4j.Logger Clause.logger = org.apache.logging.log4j.LogManager.getLogger(Clause.class);
+  protected static final org.apache.logging.log4j.Logger Component.logger = org.apache.logging.log4j.LogManager.getLogger(Component.class);
+  protected static final org.apache.logging.log4j.Logger ComponentMapping.logger = org.apache.logging.log4j.LogManager.getLogger(ComponentMapping.class);
+  protected static final org.apache.logging.log4j.Logger ComponentRequirement.logger = org.apache.logging.log4j.LogManager.getLogger(ComponentRequirement.class);
+  protected static final org.apache.logging.log4j.Logger CurrentResourceValue.logger = org.apache.logging.log4j.LogManager.getLogger(CurrentResourceValue.class);
+  protected static final org.apache.logging.log4j.Logger Designator.logger = org.apache.logging.log4j.LogManager.getLogger(Designator.class);
+  protected static final org.apache.logging.log4j.Logger DivExpression.logger = org.apache.logging.log4j.LogManager.getLogger(DivExpression.class);
+  protected static final org.apache.logging.log4j.Logger Expression.logger = org.apache.logging.log4j.LogManager.getLogger(Expression.class);
+  protected static final org.apache.logging.log4j.Logger HardwareModel.logger = org.apache.logging.log4j.LogManager.getLogger(HardwareModel.class);
+  protected static final org.apache.logging.log4j.Logger ILP.logger = org.apache.logging.log4j.LogManager.getLogger(ILP.class);
+  protected static final org.apache.logging.log4j.Logger IlpAllResourcesVariable.logger = org.apache.logging.log4j.LogManager.getLogger(IlpAllResourcesVariable.class);
+  protected static final org.apache.logging.log4j.Logger IlpBound.logger = org.apache.logging.log4j.LogManager.getLogger(IlpBound.class);
+  protected static final org.apache.logging.log4j.Logger IlpConstraint.logger = org.apache.logging.log4j.LogManager.getLogger(IlpConstraint.class);
+  protected static final org.apache.logging.log4j.Logger IlpLeftHandSide.logger = org.apache.logging.log4j.LogManager.getLogger(IlpLeftHandSide.class);
+  protected static final org.apache.logging.log4j.Logger IlpMappingVariable.logger = org.apache.logging.log4j.LogManager.getLogger(IlpMappingVariable.class);
+  protected static final org.apache.logging.log4j.Logger IlpObjective.logger = org.apache.logging.log4j.LogManager.getLogger(IlpObjective.class);
+  protected static final org.apache.logging.log4j.Logger IlpString.logger = org.apache.logging.log4j.LogManager.getLogger(IlpString.class);
+  protected static final org.apache.logging.log4j.Logger IlpTerm.logger = org.apache.logging.log4j.LogManager.getLogger(IlpTerm.class);
+  protected static final org.apache.logging.log4j.Logger IlpVariable.logger = org.apache.logging.log4j.LogManager.getLogger(IlpVariable.class);
+  protected static final org.apache.logging.log4j.Logger IlpVarInfo.logger = org.apache.logging.log4j.LogManager.getLogger(IlpVarInfo.class);
+  protected static final org.apache.logging.log4j.Logger Implementation.logger = org.apache.logging.log4j.LogManager.getLogger(Implementation.class);
+  protected static final org.apache.logging.log4j.Logger Instance.logger = org.apache.logging.log4j.LogManager.getLogger(Instance.class);
+  protected static final org.apache.logging.log4j.Logger LiteralExpression.logger = org.apache.logging.log4j.LogManager.getLogger(LiteralExpression.class);
+  protected static final org.apache.logging.log4j.Logger MetaParameter.logger = org.apache.logging.log4j.LogManager.getLogger(MetaParameter.class);
+  protected static final org.apache.logging.log4j.Logger MetaParameterAssignment.logger = org.apache.logging.log4j.LogManager.getLogger(MetaParameterAssignment.class);
+  protected static final org.apache.logging.log4j.Logger MetaParameterDesignator.logger = org.apache.logging.log4j.LogManager.getLogger(MetaParameterDesignator.class);
+  protected static final org.apache.logging.log4j.Logger ModelElement.logger = org.apache.logging.log4j.LogManager.getLogger(ModelElement.class);
+  protected static final org.apache.logging.log4j.Logger MultExpression.logger = org.apache.logging.log4j.LogManager.getLogger(MultExpression.class);
+  protected static final org.apache.logging.log4j.Logger Name.logger = org.apache.logging.log4j.LogManager.getLogger(Name.class);
+  protected static final org.apache.logging.log4j.Logger Objective.logger = org.apache.logging.log4j.LogManager.getLogger(Objective.class);
+  protected static final org.apache.logging.log4j.Logger ParenthesizedExpression.logger = org.apache.logging.log4j.LogManager.getLogger(ParenthesizedExpression.class);
+  protected static final org.apache.logging.log4j.Logger PowerExpression.logger = org.apache.logging.log4j.LogManager.getLogger(PowerExpression.class);
+  protected static final org.apache.logging.log4j.Logger Property.logger = org.apache.logging.log4j.LogManager.getLogger(Property.class);
+  protected static final org.apache.logging.log4j.Logger PropertyAggregation.logger = org.apache.logging.log4j.LogManager.getLogger(PropertyAggregation.class);
+  protected static final org.apache.logging.log4j.Logger PropertyResourceDesignator.logger = org.apache.logging.log4j.LogManager.getLogger(PropertyResourceDesignator.class);
+  protected static final org.apache.logging.log4j.Logger QualifiedName.logger = org.apache.logging.log4j.LogManager.getLogger(QualifiedName.class);
+  protected static final org.apache.logging.log4j.Logger QualifiedNameDesignator.logger = org.apache.logging.log4j.LogManager.getLogger(QualifiedNameDesignator.class);
+  protected static final org.apache.logging.log4j.Logger Request.logger = org.apache.logging.log4j.LogManager.getLogger(Request.class);
+  protected static final org.apache.logging.log4j.Logger Resource.logger = org.apache.logging.log4j.LogManager.getLogger(Resource.class);
+  protected static final org.apache.logging.log4j.Logger ResourceMapping.logger = org.apache.logging.log4j.LogManager.getLogger(ResourceMapping.class);
+  protected static final org.apache.logging.log4j.Logger ResourceRequirement.logger = org.apache.logging.log4j.LogManager.getLogger(ResourceRequirement.class);
+  protected static final org.apache.logging.log4j.Logger ResourceType.logger = org.apache.logging.log4j.LogManager.getLogger(ResourceType.class);
+  protected static final org.apache.logging.log4j.Logger Root.logger = org.apache.logging.log4j.LogManager.getLogger(Root.class);
+  protected static final org.apache.logging.log4j.Logger SoftwareDesignator.logger = org.apache.logging.log4j.LogManager.getLogger(SoftwareDesignator.class);
+  protected static final org.apache.logging.log4j.Logger SoftwareModel.logger = org.apache.logging.log4j.LogManager.getLogger(SoftwareModel.class);
+  protected static final org.apache.logging.log4j.Logger Solution.logger = org.apache.logging.log4j.LogManager.getLogger(Solution.class);
+  protected static final org.apache.logging.log4j.Logger SubExpression.logger = org.apache.logging.log4j.LogManager.getLogger(SubExpression.class);
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/ModelStatistics.jrag b/jastadd-mquat-base/src/main/jastadd/ModelStatistics.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..19897bb5c3b99523bd81c68e1d40bc90b5a4c492
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/ModelStatistics.jrag
@@ -0,0 +1,49 @@
+aspect ModelStatistics {
+
+  syn int Root.numComponents() {
+    return getSoftwareModel().getNumComponent();
+  }
+
+  syn int Root.numImplementations() {
+    int result = 0;
+    for (Component component : getSoftwareModel().getComponentList()) {
+      result += component.getNumImplementation();
+    }
+    return result;
+  }
+
+  syn int Root.numResources() {
+    int result = 0;
+    for (Resource resource : getHardwareModel().getResourceList()) {
+      result += resource.numResources();
+    }
+    return result;
+  }
+
+  syn int Resource.numResources() {
+    return 1 + getNumSubResource();
+  }
+
+  syn int Root.numContainers() {
+    int result = 0;
+    for (Resource resource : getHardwareModel().getResourceList()) {
+      result += resource.numContainers();
+    }
+    return result;
+  }
+
+  syn int Resource.numContainers() {
+    int total = (getType().getRef().getContainer() ? 1 : 0);
+    for (Resource sub : getSubResourceList()) {
+      total += sub.numContainers();
+    }
+    return total;
+  }
+
+  syn String Root.description() = " ["
+    + numComponents() + " component(s), "
+    + numImplementations() + " implementation(s), "
+    + getNumRequest() + " request(s), "
+    + numContainers() + " container(s)]";
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/Mquat.ast b/jastadd-mquat-base/src/main/jastadd/Mquat.ast
new file mode 100644
index 0000000000000000000000000000000000000000..6dbb4ba335d2094af8e3f340c524a5fc7fa2f559
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Mquat.ast
@@ -0,0 +1,77 @@
+Root ::= HardwareModel SoftwareModel Request* Objective /ILP/ ;
+
+// =====================================================================================================================
+// Low-Level Grammar Rules
+// =====================================================================================================================
+
+Name                  ::= <Name:String> ;
+QualifiedName         ::= Name* ;
+abstract ModelElement ::= Name ;
+
+// =====================================================================================================================
+// Top-Level Grammar Rules
+// =====================================================================================================================
+
+Instance:ModelElement ;
+InstanceRef ::= Name <Ref:Instance> ;
+
+// =====================================================================================================================
+// Hardware
+// =====================================================================================================================
+
+HardwareModel ::= ResourceType* Resource* Property* ;
+
+ResourceType:ModelElement ::= <Container:Boolean> SubType:ResourceType* Property* PropertyRef* ;
+ResourceTypeRef ::= Name <Ref:ResourceType> ;
+ResourceRequirement ::= ResourceTypeRef Instance* ResourceRequirement* ;
+
+Resource:ModelElement ::= Type:ResourceTypeRef SubResource:Resource* CurrentResourceValue* ;
+
+CurrentResourceValue ::= PropertyRef Value:LiteralExpression ;
+
+// =====================================================================================================================
+// Software
+// =====================================================================================================================
+
+SoftwareModel ::= MetaParameter* Component* Property* ;
+
+Component:ModelElement ::= Implementation* Property* PropertyRef* ;
+ComponentRef ::= Name <Ref:Component> ;
+ComponentRequirement ::= ComponentRef Instance* ;
+
+Implementation:ModelElement ::= ComponentRequirement* ResourceRequirement Clause* ;
+
+// =====================================================================================================================
+// Clauses and Designators
+// =====================================================================================================================
+
+// clauses are not differentiated in the CGF (except for requires/provides)
+// ClauseType { REQUIRING, PROVIDING }
+// ClauseComparator { LT,LE,EQ,NE,GE,GT }
+Clause ::= <ClauseType:ClauseType> Designator <ClauseComparator:ClauseComparator> Expression ;
+
+QualifiedNameDesignator:Designator    ::= QualifiedName ;
+SoftwareDesignator:Designator         ::= [InstanceRef] PropertyRef ;
+PropertyResourceDesignator:Designator ::= InstanceRef PropertyRef ;
+MetaParameterDesignator:Designator    ::= MetaParameterRef ;
+
+// =====================================================================================================================
+// Properties and Meta-Parameters
+// =====================================================================================================================
+
+Property:ModelElement ::= <Unit:String> ;
+PropertyRef ::= Name <Ref:Property> ;
+
+MetaParameter:ModelElement ;
+MetaParameterRef ::= Name <Ref:MetaParameter> ;
+
+MetaParameterAssignment ::= MetaParameterRef LiteralExpression ;
+
+// =====================================================================================================================
+// Requests
+// =====================================================================================================================
+
+Request ::= MetaParameterAssignment* Target:ComponentRef Constraint:Clause* /Name:Name/;
+
+// PropertyAggregation { SUM, MAX }
+Objective ::= PropertyRef <Agg:PropertyAggregation> ;
diff --git a/jastadd-mquat-base/src/main/jastadd/Names.jrag b/jastadd-mquat-base/src/main/jastadd/Names.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..6296a4a45798c6281038c0409231636756677d16
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Names.jrag
@@ -0,0 +1,44 @@
+aspect Names {
+
+  /**
+   * @return the string identifier of the model element
+   */
+  syn String ModelElement.name() = getName().getName();
+
+  /**
+   * @return the string identifier of the referenced element
+   */
+  syn String InstanceRef.name() = getRef().name();
+
+  /**
+   * @return the string identifier of the referenced element
+   */
+  syn String ResourceTypeRef.name() = getRef().name();
+
+  /**
+   * @return the string identifier of the referenced element
+   */
+  syn String ComponentRef.name() = getRef().name();
+
+  /**
+   * @return the string identifier of the referenced element
+   */
+  syn String PropertyRef.name() = getRef().name();
+
+  /**
+   * @return the string identifier of the referenced element
+   */
+  syn String MetaParameterRef.name() = getRef().name();
+
+  /**
+   * @return the string identifier of the referenced element
+   */
+  syn String Request.name() = getName().getName();
+
+  syn String Designator.simpleName();
+  eq QualifiedNameDesignator.simpleName() = getQualifiedName().getName(getQualifiedName().getNumName()-1).getName();
+  eq SoftwareDesignator.simpleName() = getPropertyRef().name();
+  eq PropertyResourceDesignator.simpleName() = getPropertyRef().name();
+  eq MetaParameterDesignator.simpleName() = getMetaParameterRef().name();
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/Navigation.jrag b/jastadd-mquat-base/src/main/jastadd/Navigation.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..0619a9e0c132871dd69bfc01b75606382e5ef59f
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Navigation.jrag
@@ -0,0 +1,526 @@
+aspect Navigation {
+
+  // upwards search ====================================================================================================
+
+  //--- root ---//
+
+  syn Root ASTNode.root();
+  eq Root.root() = this;
+  eq ASTNode.root() = getParent().root();
+
+  //--- containingImplementation ---//
+
+  inh Implementation Clause.containingImplementation();
+  eq Implementation.getClause().containingImplementation() = this;
+  eq Request.getConstraint().containingImplementation() = null;
+
+  //--- containingComponent ---//
+
+  inh Component Implementation.containingComponent();
+  eq Component.getImplementation().containingComponent() = this;
+
+  //--- containingClause ---//
+
+  inh Clause Designator.containingClause();
+  eq Clause.getDesignator().containingClause() = this;
+
+  inh Clause Expression.containingClause();
+  eq Clause.getExpression().containingClause() = this;
+  eq BinaryExpression.getLeft().containingClause() = containingClause();
+  eq BinaryExpression.getRight().containingClause() = containingClause();
+  eq CurrentResourceValue.getValue().containingClause() = null;
+  eq MetaParameterAssignment.getLiteralExpression().containingClause() = null;
+
+
+  // downwards search ==================================================================================================
+
+
+  //--- findRequestByName ---//
+
+  syn Request Root.findRequestByName(String name) {
+    for (Request request : getRequestList()) {
+      if (request.name().equals(name)) {
+        return request;
+      }
+    }
+    throw new java.util.NoSuchElementException(name);
+  }
+
+  //--- findImplementationByName ---//
+
+  syn Implementation Root.findImplementationByName(String name) {
+    for (Component component : getSoftwareModel().getComponentList()) {
+      for (Implementation impl : component.getImplementationList()) {
+        if (impl.name().equals(name)) {
+          return impl;
+        }
+      }
+    }
+    throw new java.util.NoSuchElementException(name);
+  }
+
+  //--- findResourceByName ---//
+
+  syn Resource Root.findResourceByName(String name) {
+    for (Resource resource : getHardwareModel().getResourceList()) {
+      if (resource.findResourceByName(name) != null) {
+        return resource.findResourceByName(name);
+      }
+    }
+    throw new java.util.NoSuchElementException(name);
+  }
+
+  syn Resource Resource.findResourceByName(String name) {
+    if (name().equals(name)) {
+      return this;
+    }
+    for (Resource sub : getSubResourceList()) {
+      if (sub.findResourceByName(name) != null) {
+        return sub.findResourceByName(name);
+      }
+    }
+    return null;
+  }
+
+  //--- findInstanceByName ---//
+
+  syn Instance Implementation.findInstanceByName(String name) {
+    for (ComponentRequirement cr : getComponentRequirementList()) {
+      for (Instance instance : cr.getInstanceList()) {
+        if (instance.name().equals(name)) {
+          return instance;
+        }
+      }
+    }
+    for (Instance instance : getResourceRequirement().getInstanceList()) {
+      if (instance.name().equals(name)) {
+        return instance;
+      }
+    }
+    throw new java.util.NoSuchElementException(name);
+  }
+
+  syn Instance ResourceRequirement.findInstanceByName(String name) {
+    // search sub resource requirements
+    for (ResourceRequirement subRequirement : getResourceRequirementList()) {
+      for (Instance instance : subRequirement.getInstanceList()) {
+        if (instance.name().equals(name)) {
+          return instance;
+        }
+      }
+    }
+    throw new java.util.NoSuchElementException(name);
+  }
+
+  //--- findResourceTypeByName ---//
+
+  syn ResourceType HardwareModel.findResourceTypeByName(String name) {
+    for (ResourceType type: getResourceTypeList()) {
+      if (type.name().equals(name)) {
+        return type;
+      }
+    }
+    throw new RuntimeException("Did not find resource type '" + name + "'");
+  }
+
+  //--- findSubResourceByName ---//
+
+  syn ResourceType ResourceType.findSubResourceTypeByName(String name) {
+    for (ResourceType sub: getSubTypeList()) {
+      if (sub.name().equals(name)) {
+        return sub;
+      }
+    }
+    throw new RuntimeException("Did not find sub-resource type '" + name + "'");
+  }
+
+  syn Resource Resource.findSubResourceByTypeName(String name) {
+    for (Resource sub: getSubResourceList()) {
+      if (sub.getType().getRef().name().equals(name)) {
+        return sub;
+      }
+    }
+    throw new RuntimeException("Did not find sub-resource '" + name + "'");
+  }
+
+  syn java.util.List<Resource> Resource.findSubResourcesByTypeName(String name) {
+    java.util.List<Resource> result = new java.util.ArrayList<Resource>();
+    for (Resource sub: getSubResourceList()) {
+      if (sub.getType().getRef().name().equals(name)) {
+        result.add(sub);
+      }
+    }
+    return result;
+  }
+
+
+
+  //--- getPropertyByName ---//
+
+  syn Property ResourceType.findPropertyByName(String name) {
+    // TODO rename to resolveProperty
+    for (Property property: getPropertyList()) {
+      if (property.name().equals(name)) {
+        return property;
+      }
+    }
+
+    for (PropertyRef ref: getPropertyRefList()) {
+      if (ref.getRef().name().equals(name)) {
+        return ref.getRef();
+      }
+    }
+    throw new RuntimeException("Did not find property '" + name + "'");
+  }
+
+  syn Property SoftwareModel.findPropertyByName(String name) {
+    for (Property property: getPropertyList()) {
+      if (property.name().equals(name)) {
+        return property;
+      }
+    }
+    throw new RuntimeException("Did not find property '" + name + "'");
+  }
+
+  //--- requirementClauses ---//
+
+  syn java.util.List<Clause> Implementation.requirementClauses() {
+    java.util.List<Clause> result = new java.util.ArrayList<>();
+    for (Clause clause : getClauseList()) {
+      if (clause.isRequiringClause()) {
+        result.add(clause);
+      }
+    }
+    return result;
+  }
+
+  //--- allImplementations ---//
+
+  syn java.util.List<Implementation> Root.allImplementations() {
+    java.util.List<Implementation> result = new java.util.ArrayList<>();
+    for (Component component : this.getSoftwareModel().getComponents()) {
+      for (Implementation implementation : component.getImplementations()) {
+        result.add(implementation);
+      }
+    }
+    return result;
+  }
+
+  syn Clause Implementation.findFirstProvidingClause(Property property) {
+    for (Clause clause : getClauseList()) {
+      if (clause.getClauseType() != ClauseType.PROVIDING) continue;
+      Designator designator = clause.getDesignator();
+      if (designator.isSoftwareDesignator() && designator.asSoftwareDesignator().getPropertyRef().getRef().equals(property)) {
+        return clause;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Searches in all implementations of the required component for providing clauses.
+   */
+  syn java.util.List<Tuple<Implementation, Clause>> Clause.providingClausesOfRequiredComponent() {
+    java.util.List<Tuple<Implementation, Clause>> result = new java.util.ArrayList<>();
+    if (getDesignator().isSoftwareDesignator()) {
+      SoftwareDesignator swDesignator = getDesignator().asSoftwareDesignator();
+      Property prop = swDesignator.getPropertyRef().getRef();
+      if (swDesignator.hasInstanceRef()) {
+        Component reqComponent = getDesignator().asSoftwareDesignator().getInstanceRef().getRef().referringComponent();
+        for (Implementation reqImpl : reqComponent.getImplementationList()) {
+          // TODO maybe implement findFirstProvidingClause for Implementation
+          Clause providingClause = reqImpl.findFirstProvidingClause(prop);
+          if (providingClause != null) { result.add(new Tuple<>(reqImpl, providingClause)); }
+        }
+      }
+    }
+    return result;
+  }
+
+  // name resolution ===================================================================================================
+
+
+
+  //--- resolveQualifiedName ---//
+
+  inh Designator Clause.resolveQualifiedName(QualifiedName qn);
+
+  eq Request.getConstraint().resolveQualifiedName(QualifiedName qn) {
+      // this designator refers either to a MetaParameter ...
+      MetaParameter meta = resolveMetaParameter(qn.getName(0).getName());
+      if (meta != null) {
+        return new MetaParameterDesignator(meta.createRef());
+      }
+      // ... or to a property of the target component
+      return new SoftwareDesignator(new Opt<>(), getTarget().getRef().resolveProperty(qn.getName(0).getName()).createRef());
+  }
+
+  eq Implementation.getClause().resolveQualifiedName(QualifiedName qn) = resolveQualifiedName(qn);
+
+  syn Designator Implementation.resolveQualifiedName(QualifiedName qn) {
+    if (qn.getNumName() == 1) {
+      // we have a meta parameter or something in the current context
+      MetaParameter meta=resolveMetaParameter(qn.getName(0).getName());
+      if(meta!=null) {
+        return new MetaParameterDesignator(meta.createRef());
+      }
+      // else, interpret the property as a local one of the current component
+      // this might cause an exception of the property can not be resolved
+      Property property=containingComponent().resolveProperty(qn.getName(0).getName());
+      return new SoftwareDesignator(new Opt<>(),property.createRef());
+    } else {
+
+      // first, check if it is a component requirement
+      // TODO right now, component requirements are not "deep", so can assume that qn has two names, one for the
+      // component instance and another for the property
+      String instanceName = qn.getName(0).getName();
+      String propertyName = qn.getName(1).getName();
+      for (ComponentRequirement requirement : getComponentRequirementList()) {
+        for(Instance instance:requirement.getInstanceList()){
+          if(instance.name().equals(instanceName)){
+            // now resolve property of the type of the instance. we know, the instance refers to a component.
+            Component component=instance.referringComponent();
+            return new SoftwareDesignator(new Opt<>(instance.createRef()),
+                component.resolveProperty(propertyName).createRef());
+          }
+        }
+      }
+
+      // if no component instance has been found, look for a resource instance
+      ResourceRequirement currentRequirement = null;
+      Instance currentInstance = null;
+      for (int currentName = 0; currentName < qn.getNumName() - 1; currentName++) {
+        if (currentRequirement == null) {
+          currentRequirement = getResourceRequirement();
+          // TODO this has to be extended if the one resource requirement there is has more than one instance
+          currentInstance = getResourceRequirement().getInstance(0);
+        } else {
+          for (ResourceRequirement newResourceRequirement : currentRequirement.getResourceRequirementList())
+            for (Instance instance : newResourceRequirement.getInstanceList()) {
+              if (instance.name().equals(qn.getName(currentName).getName())) {
+                currentRequirement = newResourceRequirement;
+                currentInstance = instance;
+              }
+            }
+          }
+        }
+      // now, currentRequirement refers to the final resource type
+      return new PropertyResourceDesignator(currentInstance.createRef(), currentRequirement.getResourceTypeRef().getRef().findPropertyByName(qn.getName(qn.getNumName()-1).getName()).createRef());
+    }
+  }
+
+  //--- resolveProperty ---//
+
+  syn Property Component.resolveProperty(String name) {
+    for (Property p : getPropertyList()) {
+      if (p.name().equals(name)) {
+        return p;
+      }
+    }
+    for (PropertyRef ref : getPropertyRefList()) {
+      if (ref.name().equals(name)) {
+        return ref.getRef();
+      }
+    }
+    // TODO resolvePropertyGeneral should actually not be needed anymore (all properties must be def'ed in Component)
+    return resolvePropertyGeneral(name);
+  }
+
+  //--- resolvePropertyGeneral ---//
+
+  inh Property Component.resolvePropertyGeneral(String name);
+
+  eq SoftwareModel.getComponent().resolvePropertyGeneral(String name) {
+    for (Property p : getPropertyList()) {
+      if (p.name().equals(name)) {
+        return p;
+      }
+    }
+    throw new RuntimeException("Property not found: " + name);
+  }
+
+  //--- resolveMetaParameter ---//
+
+  syn MetaParameter SoftwareModel.resolveMetaParameter(String name) {
+    for (MetaParameter meta : getMetaParameterList()) {
+      if (meta.name().equals(name)) {
+        return meta;
+      }
+    }
+    // TODO maybe add a note here for unsuccessful resolving. or throw something?
+    return null;
+  }
+
+  inh MetaParameter Component.resolveMetaParameter(String name);
+  eq SoftwareModel.getComponent().resolveMetaParameter(String name) = resolveMetaParameter(name);
+
+  inh MetaParameter Implementation.resolveMetaParameter(String name);
+  eq Component.getImplementation().resolveMetaParameter(String name) = resolveMetaParameter(name);
+
+  inh MetaParameter Request.resolveMetaParameter(String name);
+  eq Root.getRequest().resolveMetaParameter(String name) = getSoftwareModel().resolveMetaParameter(name);
+
+
+  //--- getRequiringClauseInstance ---//
+
+  syn Instance Implementation.getRequiringClauseInstance(ResourceType type, String propertyName) {
+    for (Clause clause: getClauseList()) {
+      Designator designator = clause.getDesignator();
+      if (clause.getClauseType() == ClauseType.REQUIRING
+              && designator.isPropertyResourceDesignator()
+              && designator.asPropertyResourceDesignator().getInstanceRef().getRef().referringResourceType().equals(type)
+              && designator.simpleName().equals(propertyName)) {
+          return designator.asPropertyResourceDesignator().getInstanceRef().getRef();
+      }
+    }
+    return null;
+  }
+
+  syn Instance Implementation.getRequiringClauseInstance(ResourceType type, String propertyName, int index) {
+    int i = 0;
+    for (Clause clause: getClauseList()) {
+      Designator designator = clause.getDesignator();
+      if (clause.getClauseType() == ClauseType.REQUIRING
+          && designator.isPropertyResourceDesignator()
+          && designator.asPropertyResourceDesignator().getInstanceRef().getRef().referringResourceType().equals(type)
+          && designator.simpleName().equals(propertyName)) {
+        if (i==index) {
+          return designator.asPropertyResourceDesignator().getInstanceRef().getRef();
+        } else {
+          i++;
+        }
+      }
+    }
+    return null;
+  }
+
+
+
+
+  //--- containingResourceRequirement ---//
+
+  inh ResourceRequirement Instance.containingResourceRequirement();
+  eq ComponentRequirement.getInstance().containingResourceRequirement() {
+    throw new RuntimeException("There is no resource requirement for an instance of a component.");
+  }
+  eq ResourceRequirement.getInstance().containingResourceRequirement() = this;
+
+  //--- referringResourceType ---//
+
+  inh ResourceType Instance.referringResourceType();
+  eq ComponentRequirement.getInstance().referringResourceType() {
+    throw new RuntimeException("There is no resource for an instance of a component.");
+  }
+  eq ResourceRequirement.getInstance().referringResourceType() = getResourceTypeRef().getRef();
+
+  //--- referringComponent ---//
+
+  inh Component Instance.referringComponent();
+  eq ComponentRequirement.getInstance(int i).referringComponent() = getComponentRef().getRef();
+  eq ResourceRequirement.getInstance(int i).referringComponent() = null;
+
+
+  syn java.util.Collection<Component> Implementation.getRequiredComponents() {
+    java.util.List<Component> result = new java.util.ArrayList();
+    for (ComponentRequirement cr: getComponentRequirementList()) {
+      if (cr.getNumInstance()==0) {
+        result.add(cr.getComponentRef().getRef());
+      } else {
+        for (Instance instance: cr.getInstanceList()) {
+          result.add(cr.getComponentRef().getRef());
+        }
+      }
+    }
+    return result;
+  }
+
+  // subtyping =========================================================================================================
+
+  syn boolean Designator.isSoftwareDesignator() = false;
+  eq SoftwareDesignator.isSoftwareDesignator() = true;
+
+  syn SoftwareDesignator Designator.asSoftwareDesignator() = null;
+  eq SoftwareDesignator.asSoftwareDesignator() = this;
+
+  syn boolean Designator.isPropertyResourceDesignator() = false;
+  eq PropertyResourceDesignator.isPropertyResourceDesignator() = true;
+
+  syn PropertyResourceDesignator Designator.asPropertyResourceDesignator() = null;
+  eq PropertyResourceDesignator.asPropertyResourceDesignator() = this;
+
+  syn boolean Designator.isMetaParameterDesignator() = false;
+  eq MetaParameterDesignator.isMetaParameterDesignator() = true;
+
+  syn MetaParameterDesignator Designator.asMetaParameterDesignator() = null;
+  eq MetaParameterDesignator.asMetaParameterDesignator() = this;
+
+  // evaluation ========================================================================================================
+
+  //--- getCurrentValueByPropertyName ---//
+
+  syn double Resource.getCurrentValueByPropertyName(String name) {
+    for (CurrentResourceValue value: getCurrentResourceValueList()) {
+      if (value.getPropertyRef().getRef().name().equals(name)) {
+        return value.getValue().evalAsDouble();
+      }
+    }
+    throw new RuntimeException("Did not find a value for a property '" + name + "'");
+  }
+
+  //--- getCurrentValueByProperty ---//
+
+  syn double Resource.getCurrentValueByProperty(Property property) {
+    for (CurrentResourceValue value: getCurrentResourceValueList()) {
+      if (value.getPropertyRef().getRef() == property) {
+        return value.getValue().evalAsDouble();
+      }
+    }
+    throw new RuntimeException("Did not find a value for a property '" + property.name() + "'");
+  }
+
+  //--- getConstraintValueByName ---//
+
+  syn double Request.getConstraintValueByName(String name) {
+    for (Clause clause: getConstraintList()) {
+      if (clause.getDesignator().simpleName().equals(name)) {
+        return clause.getExpression().evalAsDouble();
+      }
+    }
+    throw new RuntimeException("Did not find a constraint '" + name + "'");
+  }
+
+  //--- getRequiringClauseValue ---//
+
+  syn double Implementation.getRequiringClauseValue(ResourceType type, String propertyName) {
+    for (Clause clause: getClauseList()) {
+      Designator designator = clause.getDesignator();
+      if (clause.getClauseType() == ClauseType.REQUIRING
+          && designator.isPropertyResourceDesignator()
+          && designator.asPropertyResourceDesignator().getInstanceRef().getRef().referringResourceType().equals(type)
+          && designator.simpleName().equals(propertyName)) {
+        return clause.getExpression().evalAsDouble();
+      }
+    }
+    throw new RuntimeException("Did not find a requiring clause for designator '" + propertyName + "'");
+  }
+
+  syn double Implementation.getRequiringClauseValue(ResourceType type, String propertyName, int index) {
+    int i = 0;
+    for (Clause clause: getClauseList()) {
+      Designator designator = clause.getDesignator();
+      if (clause.getClauseType() == ClauseType.REQUIRING
+          && designator.isPropertyResourceDesignator()
+          && designator.asPropertyResourceDesignator().getInstanceRef().getRef().referringResourceType().equals(type)
+          && designator.simpleName().equals(propertyName)) {
+        if (i==index) {
+          return clause.getExpression().evalAsDouble();
+        } else {
+          i++;
+        }
+      }
+    }
+    throw new RuntimeException("Did not find a requiring clause for designator '" + propertyName + "'");
+  }
+
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/Printing.jadd b/jastadd-mquat-base/src/main/jastadd/Printing.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..6afdf6b96620e09a01def72b0ee6d3e39ad906fe
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Printing.jadd
@@ -0,0 +1,90 @@
+aspect Printing {
+
+  public String ASTNode.toString(){
+    return print(new MquatWriteSettings("")).toString();
+  }
+
+  public class MquatString {
+    boolean newline;
+    StringBuilder buffer;
+    MquatWriteSettings settings;
+    int indentationLevel;
+
+    public MquatString(MquatWriteSettings settings, int indentationLevel) {
+      this.buffer = new java.lang.StringBuilder();
+      this.settings = settings;
+      this.indentationLevel = indentationLevel;
+      this.newline = false;
+    }
+
+    public int getIndentationLevel() {
+      return this.indentationLevel;
+    }
+
+    public MquatString ind() {
+      this.indentationLevel += 1;
+      return this;
+    }
+
+    public MquatString und() {
+      if (this.indentationLevel > 0) this.indentationLevel -= 1;
+      return this;
+    }
+
+    private void flushNewline() {
+      if (newline) {
+        this.buffer.append("\n");
+        for (int i = 0; i < indentationLevel; i++) {
+          this.buffer.append(settings.getIndentString());
+        }
+        newline = false;
+      }
+    }
+
+    public MquatString lb() {
+      this.newline = true;
+      return this;
+    }
+
+    public MquatString append(Object o) {
+      flushNewline();
+      buffer.append(o);
+      return this;
+    }
+
+
+    public MquatString append(final MquatString s) {
+      flushNewline();
+
+      buffer.append(s.getBuffer());
+      if (s.newlinePending()) {
+        newline = true;
+      }
+      return this;
+    }
+
+    protected boolean newlinePending() {
+      return newline;
+    }
+
+    public StringBuilder getBuffer() {
+      return buffer;
+    }
+
+    public String toString() {
+      flushNewline();
+      return buffer.toString();
+    }
+  }
+
+  public class MquatWriteSettings {
+    String indentString;
+
+    public MquatWriteSettings(String indentString) {
+      this.indentString = indentString;
+    }
+    public String getIndentString() {
+      return this.indentString;
+    }
+  }
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/Printing.jrag b/jastadd-mquat-base/src/main/jastadd/Printing.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..4f42d58a62547c2e8865c0b764660033f1e43148
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Printing.jrag
@@ -0,0 +1,460 @@
+aspect Printing {
+
+  syn MquatString ASTNode.print(MquatWriteSettings settings) = print(settings, 0);
+
+  syn MquatString ASTNode.print(MquatWriteSettings settings, int indentationLevel);
+
+  eq ASTNode.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    logger.error("Missing print() implementation for class {}", this.getClass().getSimpleName());
+
+    java.util.Iterator iterator = this.astChildIterator();
+    while (iterator.hasNext()) {
+      ASTNode child = (ASTNode)iterator.next();
+      if (child != null) result.append(child.print(settings, indentationLevel));
+    }
+
+    return result;
+  }
+
+  eq List.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    for (ASTNode child : this) {
+      if (child != null) result.append(child.print(settings, indentationLevel));
+    }
+
+    return result;
+  }
+
+  eq Root.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getHardwareModel().print(settings, indentationLevel))
+          .lb().lb()
+          .append(getSoftwareModel().print(settings, indentationLevel))
+          .lb().lb();
+    for (Request r : getRequestList()) {
+      result.append(r.print(settings, indentationLevel));
+    }
+    result.append(getObjective().print(settings, indentationLevel));
+    return result;
+  }
+
+// =====================================================================================================================
+// Low-Level Grammar Rules
+// =====================================================================================================================
+
+  eq Name.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getName());
+    return result;
+  }
+
+  eq QualifiedName.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    boolean first = true;
+    for (Name name : getNameList()) {
+      if (first) {
+        first = false;
+      } else {
+        result.append(".");
+      }
+      result.append(name.print(settings, indentationLevel)).append(".");
+    }
+    return result;
+  }
+
+// =====================================================================================================================
+// Top-Level Grammar Rules
+// =====================================================================================================================
+
+  eq Instance.print(MquatWriteSettings settings, int indentationLevel) {
+    return getName().print(settings, indentationLevel);
+  }
+
+  eq InstanceRef.print(MquatWriteSettings settings, int indentationLevel) {
+    return getName().print(settings, indentationLevel);
+  }
+
+// =====================================================================================================================
+// Hardware
+// =====================================================================================================================
+
+  eq HardwareModel.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    for (ResourceType resourceType : getResourceTypeList()) {
+      result.append(resourceType.print(settings, indentationLevel));
+    }
+
+    for (Resource resource : getResourceList()) {
+      result.append(resource.print(settings, indentationLevel));
+    }
+
+    for (Property property : getPropertyList()) {
+      result.append(property.print(settings, indentationLevel));
+    }
+
+    return result;
+  }
+
+  eq ResourceType.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    if (getContainer()) {
+      result.append("container ");
+    }
+    result.append("resource type ").append(getName().print(settings, indentationLevel)).append(" {").lb().ind();
+    indentationLevel++;
+    for (ResourceType subType: getSubTypeList()) {
+      result.append(subType.print(settings, indentationLevel));
+    }
+    for (Property property: getPropertyList()) {
+      result.append(property.print(settings, indentationLevel));
+    }
+    for (PropertyRef ref: getPropertyRefList()) {
+      result.append("using property ").append(ref.print(settings, indentationLevel)).lb();
+    }
+    indentationLevel--;
+    result.und().append("}").lb();
+    return result;
+  }
+
+  eq ResourceTypeRef.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getName().print(settings, indentationLevel));
+    return result;
+  }
+
+  eq ResourceRequirement.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    boolean first = true;
+    for (Instance instance: getInstanceList()) {
+      if (!first) {
+        result.append(", ");
+      }
+      result.append(instance.print(settings, indentationLevel));
+      first = false;
+    }
+    if (getInstanceList().numChildren() > 0) {
+      result.append(" ");
+    }
+    result.append("of type ").append(getResourceTypeRef().print(settings, indentationLevel));
+    if (getNumResourceRequirement() > 0) {
+      // iterate over nested requirements
+      result.append(" with {").ind().lb();
+      for (ResourceRequirement subReq : getResourceRequirementList()) {
+        result.append(subReq.print(settings, indentationLevel + 1));
+      }
+      result.und().lb().append("}");
+    }
+    result.lb();
+    return result;
+  }
+
+  eq Resource.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append("resource ").append(getName().print(settings, indentationLevel)).append(":").
+        append(getType().print(settings, indentationLevel)).append(" {").lb().ind();
+    indentationLevel++;
+    for (Resource subResource: getSubResourceList()) {
+      result.append(subResource.print(settings, indentationLevel));
+    }
+    for (CurrentResourceValue value: getCurrentResourceValueList()) {
+      result.append(value.print(settings, indentationLevel));
+    }
+    indentationLevel--;
+    result.und().append("}").lb();
+    return result;
+  }
+
+  eq CurrentResourceValue.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getPropertyRef().print(settings, indentationLevel)).append(" = ")
+        .append(getValue().print(settings, indentationLevel)).lb();
+    return result;
+  }
+
+// =====================================================================================================================
+// Software
+// =====================================================================================================================
+
+  eq SoftwareModel.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    for (MetaParameter m: getMetaParameterList()) {
+      result.append(m.print(settings, indentationLevel)).lb();
+    }
+    result.lb();
+
+    for (Property property : getPropertyList()) {
+      result.append(property.print(settings, indentationLevel));
+    }
+    result.lb();
+
+    for (Component component : getComponentList()) {
+      result.append(component.print(settings, indentationLevel));
+    }
+    return result;
+  }
+
+  eq Component.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("component ").append(getName().print(settings, indentationLevel)).append(" {").ind().lb();
+
+    indentationLevel += 1;
+    for (Implementation implementation : getImplementationList()) {
+      result.append(implementation.print(settings, indentationLevel));
+    }
+
+    for (Property property : getPropertyList()) {
+      result.append(property.print(settings, indentationLevel));
+    }
+
+    for (PropertyRef propertyRef : getPropertyRefList()) {
+      result.append("using property ").append(propertyRef.print(settings, indentationLevel)).lb();
+    }
+
+    indentationLevel -= 1;
+    result.und().lb().append("}").lb().append("").lb();
+
+    return result;
+  }
+
+  eq ComponentRef.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getName().print(settings, indentationLevel));
+    return result;
+  }
+
+  eq ComponentRequirement.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("requires component ");
+    boolean first = true;
+    for (Instance instance: getInstanceList()) {
+      if (!first) {
+        result.append(", ");
+      }
+      result.append(instance.print(settings, indentationLevel));
+      first = false;
+    }
+    if (getInstanceList().numChildren() > 0) {
+      result.append(" ");
+    }
+    result.append("of type ").append(getComponentRef().print(settings, indentationLevel)).lb();
+    return result;
+  }
+
+  eq Implementation.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("contract ").append(getName().print(settings, indentationLevel)).append(" {").ind().lb();
+
+    indentationLevel += 1;
+
+    for (ComponentRequirement componentRequirement : getComponentRequirementList()) {
+      result.append(componentRequirement.print(settings, indentationLevel));
+    }
+
+    result.append("requires resource ");
+    result.append(getResourceRequirement().print(settings, indentationLevel));
+
+    for (Clause clause : getClauseList()) {
+      result.append(clause.print(settings, indentationLevel)).lb();
+    }
+
+    result.append("").lb();
+
+    indentationLevel -= 1;
+    result.und().append("}").lb();
+
+    return result;
+  }
+
+// =====================================================================================================================
+// Clauses and Designators
+// =====================================================================================================================
+
+  eq Clause.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    if (getClauseType() == ClauseType.REQUIRING) {
+      result.append("requiring ");
+    } else if(getClauseType() == ClauseType.PROVIDING) {
+      result.append("providing ");
+    }
+
+    result.append(getDesignator().print(settings, indentationLevel)).append(' ').append(getClauseComparator().symbol());
+    result.append(' ').append(getExpression().print(settings, indentationLevel));
+
+    return result;
+  }
+
+  eq QualifiedNameDesignator.print(MquatWriteSettings settings, int indentationLevel) {
+    return getQualifiedName().print(settings, indentationLevel);
+  }
+
+  eq SoftwareDesignator.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    if (hasInstanceRef()) {
+      result.append(getInstanceRef().print(settings, indentationLevel)).append(".");
+    }
+
+    result.append(getPropertyRef().print(settings, indentationLevel));
+
+    return result;
+  }
+
+  eq PropertyResourceDesignator.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append(getInstanceRef().print(settings, indentationLevel)).append(".");
+
+    result.append(getPropertyRef().print(settings, indentationLevel));
+
+    return result;
+  }
+
+  eq MetaParameterDesignator.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append(getMetaParameterRef().print(settings, indentationLevel));
+
+    return result;
+  }
+
+// =====================================================================================================================
+// Properties and Meta-Parameters
+// =====================================================================================================================
+
+  eq Property.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append(" property ").append(getName().print(settings, indentationLevel)).append(" [");
+    result.append(getUnit()).append("]").lb();
+
+    return result;
+  }
+
+  eq PropertyRef.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getName().print(settings, indentationLevel));
+    return result;
+  }
+
+  eq MetaParameter.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("meta ").append(getName().print(settings, indentationLevel));
+
+    return result;
+  }
+
+  eq MetaParameterRef.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getName().print(settings, indentationLevel));
+    return result;
+  }
+
+  eq MetaParameterAssignment.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("meta ").append(getMetaParameterRef().print(settings, indentationLevel)).append(" = ")
+        .append(getLiteralExpression().print(settings, indentationLevel));
+
+    return result;
+  }
+
+// =====================================================================================================================
+// Requests
+// =====================================================================================================================
+
+  eq Request.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("request ").append(getName().print(settings, indentationLevel)).append(" for ")
+        .append(getTarget().print(settings, indentationLevel)).append(" {").lb().ind();
+    for (MetaParameterAssignment p: getMetaParameterAssignmentList()) {
+      result.append(p.print(settings, indentationLevel)).lb();
+    }
+    for (Clause c: getConstraintList()) {
+      result.append(c.print(settings, indentationLevel));
+    }
+    result.und().lb().append("}").lb();
+    return result;
+  }
+
+  eq Objective.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    if (getAgg() == PropertyAggregation.SUM) {
+      return result.append("minimize sum(").append(getPropertyRef().print(settings, indentationLevel)).append(")").lb();
+    } else if (getAgg() == PropertyAggregation.MAX) {
+      return result.append("minimize maximum(").append(getPropertyRef().print(settings, indentationLevel)).append(")").lb();
+    }
+    return result;
+  }
+
+
+// =====================================================================================================================
+// Expressions
+// =====================================================================================================================
+
+  eq LiteralExpression.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getValue());
+    return result;
+  }
+
+  eq AddExpression.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("(").append(getLeft().print(settings, indentationLevel)).append("+").append(getRight().print(settings, indentationLevel)).append(")");
+
+    return result;
+  }
+
+  eq SubExpression.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("(").append(getLeft().print(settings, indentationLevel)).append("-").append(getRight().print(settings, indentationLevel)).append(")");
+
+    return result;
+  }
+
+  eq MultExpression.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("(").append(getLeft().print(settings, indentationLevel)).append("*").append(getRight().print(settings, indentationLevel)).append(")");
+
+    return result;
+  }
+
+  eq DivExpression.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("(").append(getLeft().print(settings, indentationLevel)).append("/").append(getRight().print(settings, indentationLevel)).append(")");
+
+    return result;
+  }
+
+  eq PowerExpression.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+
+    result.append("(").append(getLeft().print(settings, indentationLevel)).append("^").append(getRight().print(settings, indentationLevel)).append(")");
+
+    return result;
+  }
+
+  syn String Root.info() {
+    SoftwareModel sw = getSoftwareModel();
+    return  "Top-Level Components: " + sw.getNumComponent() + "\n" +
+            "Impls of first comp: " + sw.getComponent(0).getNumImplementation() + "\n" +
+            "Resources: " + getHardwareModel().getNumResource() + "\n" +
+            "Requests: " + getNumRequest();
+  }
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/ReferenceHelper.jadd b/jastadd-mquat-base/src/main/jastadd/ReferenceHelper.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..fb557e087d6e3fddb4b4a3e833680f40bd4bbec9
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/ReferenceHelper.jadd
@@ -0,0 +1,21 @@
+aspect ReferenceHelper {
+  public ComponentRef Component.createRef() {
+    return new ComponentRef(new Name(name()), this);
+  }
+
+  public ResourceTypeRef ResourceType.createRef() {
+    return new ResourceTypeRef(new Name(name()), this);
+  }
+
+  public InstanceRef Instance.createRef() {
+    return new InstanceRef(new Name(name()), this);
+  }
+
+  public PropertyRef Property.createRef() {
+    return new PropertyRef(new Name(name()), this);
+  }
+
+  public MetaParameterRef MetaParameter.createRef() {
+    return new MetaParameterRef(new Name(name()), this);
+  }
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/Requests.jrag b/jastadd-mquat-base/src/main/jastadd/Requests.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..e6bf36891a6668e92416ea0520318ab4923d75c0
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/Requests.jrag
@@ -0,0 +1,53 @@
+aspect Requests {
+
+  //--- getName ---//
+
+  inh Name Request.getName();
+  eq Root.getRequest(int i).getName() {
+    return new Name("request" + String.valueOf(i));
+  }
+
+//  //--- relevantImplementations ---//
+//
+//  /** Implementations of target component and all possibly required implementations */
+//  syn java.util.List<Implementation> Request.relevantImplementations() {
+//    java.util.List<Implementation> result = new java.util.ArrayList<>();
+//    for (Component comp : relevantComponents()) {
+//      for (Implementation impl: comp.getImplementationList()) {
+//        result.add(impl);
+//      };
+//    }
+//    return result;
+//  }
+
+  //--- relevantComponents ---//
+
+  /** Target component and all possibly required components */
+  syn java.util.Set<Component> Request.relevantComponents() {
+    return getTarget().getRef().relevantComponents();
+  }
+
+  /** This component and all possibly required components */
+  syn java.util.Set<Component> Component.relevantComponents() {
+    java.util.Set<Component> result = new java.util.HashSet<>();
+    result.add(this);
+    for (Implementation impl : getImplementationList()) {
+      for (ComponentRequirement cr : impl.getComponentRequirementList()) {
+        result.addAll(cr.getComponentRef().getRef().relevantComponents());
+      }
+    }
+    return result;
+  }
+
+    //--- getMetaParameterExpression ---//
+
+  syn LiteralExpression Request.getMetaParameterExpression(MetaParameter meta) {
+    for (MetaParameterAssignment assignment : getMetaParameterAssignmentList()) {
+      if (assignment.getMetaParameterRef().getRef().equals(meta)) {
+        return assignment.getLiteralExpression();
+      }
+    }
+    return null;
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/SimpleHardwareModel.jrag b/jastadd-mquat-base/src/main/jastadd/SimpleHardwareModel.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..2b156b217a1d1438bf0137b64b9a9dcfffe090e6
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/SimpleHardwareModel.jrag
@@ -0,0 +1,111 @@
+/**
+ * This aspect should contain attributes that are specific to the specific hardware component model also defined here
+ */
+aspect SimpleHardwareModel {
+
+  /**
+   * create a simple haredware model
+   */
+  public static HardwareModel Root.createSimpleHardwareModel() {
+    HardwareModel hardwareModel = new HardwareModel();
+
+    // common properties of several hardware resources
+    Property total = new Property(new Name("total"), "MB");
+    hardwareModel.addProperty(total);
+
+    Property free = new Property(new Name("free"), "MB");
+    hardwareModel.addProperty(free);
+
+    // the top-level resource type
+    ResourceType type = new ResourceType();
+    type.setName(new Name("ComputeNode"));
+    type.setContainer(true);
+
+    // subtype CPU
+    ResourceType cpu = new ResourceType();
+    cpu.setContainer(false);
+    cpu.setName(new Name("CPU"));
+    Property frequency = new Property(new Name("frequency"), "Hz");
+    Property load = new Property(new Name("load"), "%");
+    cpu.addProperty(frequency);
+    cpu.addProperty(load);
+    type.addSubType(cpu);
+
+
+    // subtype memory
+    ResourceType ram = new ResourceType();
+    ram.setName(new Name("RAM"));
+    ram.setContainer(false);
+    ram.addPropertyRef(total.createRef());
+    ram.addPropertyRef(free.createRef());
+    type.addSubType(ram);
+
+    // subtype disk
+    ResourceType disk = new ResourceType();
+    disk.setName(new Name("DISK"));
+    disk.setContainer(false);
+    disk.addPropertyRef(total.createRef());
+    disk.addPropertyRef(free.createRef());
+    type.addSubType(disk);
+
+    // subtype network
+    ResourceType network = new ResourceType();
+    network.setName(new Name("NETWORK"));
+    network.setContainer(false);
+    Property latency = new Property(new Name("latency"), "ms");
+    Property throughput = new Property(new Name("throughput"), "kB/s");
+    network.addProperty(latency);
+    network.addProperty(throughput);
+    type.addSubType(network);
+
+    hardwareModel.addResourceType(type);
+
+    return hardwareModel;
+  }
+
+  syn ResourceType HardwareModel.computeResourceType() {
+    for (ResourceType resourceType : getResourceTypeList()) {
+      if ("ComputeNode".equals(resourceType.name())) {
+        return resourceType;
+      }
+    }
+    return null;
+  }
+
+  syn ResourceType HardwareModel.cpuType() {
+    for (ResourceType resourceType : computeResourceType().getSubTypeList()) {
+      if ("CPU".equals(resourceType.name())) {
+        return resourceType;
+      }
+    }
+    return null;
+  }
+
+  syn ResourceType HardwareModel.ramType() {
+    for (ResourceType resourceType : computeResourceType().getSubTypeList()) {
+      if ("RAM".equals(resourceType.name())) {
+        return resourceType;
+      }
+    }
+    return null;
+  }
+
+  syn ResourceType HardwareModel.diskType() {
+    for (ResourceType resourceType : computeResourceType().getSubTypeList()) {
+      if ("DISK".equals(resourceType.name())) {
+        return resourceType;
+      }
+    }
+    return null;
+  }
+
+  syn ResourceType HardwareModel.networkType() {
+    for (ResourceType resourceType : computeResourceType().getSubTypeList()) {
+      if ("NETWORK".equals(resourceType.name())) {
+        return resourceType;
+      }
+    }
+    return null;
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/mquat.flex b/jastadd-mquat-base/src/main/jastadd/mquat.flex
new file mode 100644
index 0000000000000000000000000000000000000000..52881bc84f94b2c923df00533c59d4caba4e293f
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/mquat.flex
@@ -0,0 +1,100 @@
+package de.tudresden.inf.st.mquat.jastadd.scanner;
+
+import de.tudresden.inf.st.mquat.jastadd.parser.MquatParser.Terminals;
+
+%%
+
+// define the signature for the generated scanner
+%public
+%final
+%class MquatScanner
+%extends beaver.Scanner
+
+// the interface between the scanner and the parser is the nextToken() method
+%type beaver.Symbol
+%function nextToken
+%yylexthrow beaver.Scanner.Exception
+
+// store line and column information in the tokens
+%line
+%column
+
+// this code will be inlined in the body of the generated scanner class
+%{
+  private beaver.Symbol sym(short id) {
+    return new beaver.Symbol(id, yyline + 1, yycolumn + 1, yylength(), yytext());
+  }
+%}
+
+WhiteSpace = [ ] | \t | \f | \n | \r | \r\n
+Identifier = [:jletter:][:jletterdigit:]*
+Unit       = "[" [^\]]* "]"
+
+Integer = [:digit:]+ // | "+" [:digit:]+ | "-" [:digit:]+
+Real    = [:digit:]+ "." [:digit:]* | "." [:digit:]+
+
+Comment = "//" [^\n\r]+
+
+%%
+
+// discard whitespace information and comments
+{WhiteSpace}  { }
+{Comment}     { }
+
+// token definitions
+
+"type"        { return sym(Terminals.TYPE); }
+"meta"        { return sym(Terminals.META); }
+"of type"     { return sym(Terminals.OFTYPE); }
+"resources"   { return sym(Terminals.RESOURCE); }
+"resource"    { return sym(Terminals.RESOURCE); }
+"request"     { return sym(Terminals.REQUEST); }
+"request"     { return sym(Terminals.REQUEST); }
+// TODO there should be a maximize too
+"minimize"    { return sym(Terminals.MINIMIZE); }
+"container"   { return sym(Terminals.CONTAINER); }
+//"static"      { return sym(Terminals.STATIC); }
+//"runtime"     { return sym(Terminals.RUNTIME); }
+//"derived"     { return sym(Terminals.DERIVED); }
+"using"       { return sym(Terminals.USING); }
+"property"    { return sym(Terminals.PROPERTY); }
+"requires"    { return sym(Terminals.REQUIRES); }
+//"provides"    { return sym(Terminals.PROVIDES); }
+"requiring"   { return sym(Terminals.REQUIRING); }
+"providing"   { return sym(Terminals.PROVIDING); }
+"contract"    { return sym(Terminals.CONTRACT); }
+"component"   { return sym(Terminals.COMPONENT); }
+"with"        { return sym(Terminals.WITH); }
+//"mode"        { return sym(Terminals.MODE); }
+//"from"        { return sym(Terminals.FROM); }
+//"to"          { return sym(Terminals.TO); }
+//"parameter"   { return sym(Terminals.PARAMETER); }
+"solution"    { return sym(Terminals.SOLUTION); }
+"->"          { return sym(Terminals.RIGHT_ARROW); }
+","           { return sym(Terminals.COMMA); }
+"."           { return sym(Terminals.DOT); }
+"<"           { return sym(Terminals.LE); }
+"<="          { return sym(Terminals.LT); }
+"="           { return sym(Terminals.EQ); }
+"!="          { return sym(Terminals.NE); }
+">"           { return sym(Terminals.GT); }
+">="          { return sym(Terminals.GE); }
+"+"           { return sym(Terminals.PLUS); }
+"*"           { return sym(Terminals.MULT); }
+"-"           { return sym(Terminals.MINUS); }
+"/"           { return sym(Terminals.DIV); }
+"^"           { return sym(Terminals.POW); }
+//"sin"         { return sym(Terminals.SIN); }
+//"cos"         { return sym(Terminals.COS); }
+"("           { return sym(Terminals.LB_ROUND); } // was LP
+")"           { return sym(Terminals.RB_ROUND); } // was RP
+"{"           { return sym(Terminals.LB_CURLY); } // was LB
+"}"           { return sym(Terminals.RB_CURLY); } // was RB
+//"["           { return sym(Terminals.LB_SQUARE); } // was LBRACKET
+//"]"           { return sym(Terminals.RB_SQUARE); } // was RBRACKET
+":"           { return sym(Terminals.COLON); }
+{Identifier}  { return sym(Terminals.NAME); }
+{Real}        { return sym(Terminals.REAL); }
+{Integer}     { return sym(Terminals.INTEGER); }
+{Unit}        { return sym(Terminals.UNIT); }
+<<EOF>>       { return sym(Terminals.EOF); }
diff --git a/jastadd-mquat-base/src/main/jastadd/mquat.parser b/jastadd-mquat-base/src/main/jastadd/mquat.parser
new file mode 100644
index 0000000000000000000000000000000000000000..e9c1856b59380eaf477d368584c159d0edd5ba90
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/mquat.parser
@@ -0,0 +1,335 @@
+%header {:
+package de.tudresden.inf.st.mquat.jastadd.parser;
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import de.tudresden.inf.st.mquat.parser.MquatParserHelper;
+import java.util.Map;
+import java.util.HashMap;
+:} ;
+
+%embed {:
+  private MquatParserHelper mph = new MquatParserHelper();
+  private static <T extends ASTNode<?>> void insertZero(List<T> listNode, T child) {
+    listNode.insertChild(child, 0);
+  }
+
+
+  /**
+   * Post processing step after parsing a model, to resolve all references within the model.
+   * @throws java.util.NoSuchElementException if a reference can not be resolved
+   */
+  public void resolveReferences() {
+    mph.resolveReferences();
+  }
+
+
+  /**
+   * Post processing step after parsing a solution, to resolve all references.
+   * @param model the model to resolve the references
+   * @throws RuntimeException if assignments are malformed
+   * @throws java.util.NoSuchElementException if a reference can not be resolved
+   */
+  public void resolveSolutionReferencesWith(Root model) {
+    mph.resolveSolutionReferencesWith(model);
+  }
+:} ;
+
+%goal goal;
+%goal solution;
+
+Request request =
+    REQUEST component_ref.c LB_CURLY request_body.b RB_CURLY {: b.setTarget(c); return b; :}
+  ;
+
+Request request_body =
+    meta_parameter_assignment.m request_body.b  {: insertZero(b.getMetaParameterAssignmentList(), m); return b; :}
+  | clause.c request_body.b                     {: insertZero(b.getConstraintList(), c); return b; :}
+  | meta_parameter_assignment.m  {: return new Request(new List<>(m), null, new List<>()); :}
+  | clause.c                     {: return new Request(new List<>(), null, new List<>(c)); :}
+  ;
+
+MetaParameterAssignment meta_parameter_assignment =
+    META meta_parameter_ref.n EQ literal_expression.e {: return new MetaParameterAssignment(n, e); :}
+  ;
+
+%left RB_ROUND;
+%left MULT, DIV;
+%left PLUS, MINUS;
+%left POW;
+
+Expression expression =
+    LB_ROUND expression.a MULT  expression.b RB_ROUND     {: return new MultExpression(a, b); :}
+  | LB_ROUND expression.a DIV   expression.b RB_ROUND     {: return new DivExpression(a, b); :}
+  | LB_ROUND expression.a PLUS  expression.b RB_ROUND     {: return new AddExpression(a, b); :}
+  | LB_ROUND expression.a MINUS expression.b RB_ROUND     {: return new SubExpression(a, b); :}
+  | LB_ROUND expression.a POW expression.b RB_ROUND       {: return new PowerExpression(a, b); :}
+  | literal_expression.l                {: return l; :}
+  | designator.d                        {: return d; :}
+  | LB_ROUND expression.e RB_ROUND      {: return new ParenthesizedExpression(e); :}
+  ;
+
+LiteralExpression literal_expression =
+    INTEGER.n             {: return new LiteralExpression(Integer.parseInt(n)); :}
+  | REAL.n                {: return new LiteralExpression(Double.parseDouble(n));   :}
+  ;
+
+Objective objective =
+    MINIMIZE NAME.n LB_ROUND property_ref.p RB_ROUND
+    {:
+      if (n.equals("sum")) {
+        return new Objective(p, PropertyAggregation.SUM);
+      } else if (n.equals("maximum")) {
+        return new Objective(p, PropertyAggregation.MAX);
+      }
+    :}
+  ;
+
+Root goal =
+    hardware_model.h software_model.s request.r* objective.o  {: return new Root(h,s,r,o); :}
+  ;
+
+MetaParameter meta_parameter =
+    META name.n
+    {:
+      MetaParameter m = new MetaParameter(n);
+      mph.metaParameterMap.put(n.getName(), m);
+      return m;
+    :}
+  ;
+
+MetaParameterRef meta_parameter_ref =
+    name.n
+    {:
+      MetaParameterRef ref = new MetaParameterRef(n, null);
+      mph.metaParameterRefList.add(ref);
+      return ref;
+    :}
+  ;
+
+Name name =
+    NAME.i {: return new Name(i); :}
+  ;
+
+QualifiedName qualified_name =
+    name.n DOT qualified_name.q {: insertZero(q.getNameList(), n); return q; :}
+  | name.n                      {: List<Name> names = new List<>(); names.add(n); return new QualifiedName(names); :}
+  ;
+
+Property property =
+    PROPERTY name.n UNIT.u
+    {:
+      Property p = new Property(n, u.substring(1, u.length() - 1));
+      mph.propertyMap.put(n.getName(), p);
+      return p;
+    :}
+  ;
+
+PropertyRef property_ref =
+    name.n {: PropertyRef ref = new PropertyRef(n, null); mph.propertyRefList.add(ref); return ref; :}
+  ;
+
+SoftwareModel software_model =
+    meta_parameter.a software_model.m  {: insertZero(m.getMetaParameterList(), a); return m; :}
+  | component.c software_model.m       {: insertZero(m.getComponentList(), c); return m; :}
+  | property.p software_model.m        {: insertZero(m.getPropertyList(), p); return m; :}
+  | meta_parameter.m  {: return new SoftwareModel(new List<>(m), new List<>(), new List<>()); :}
+  | component.c       {: return new SoftwareModel(new List<>(), new List<>(c), new List<>()); :}
+  | property.p        {: return new SoftwareModel(new List<>(), new List<>(), new List<>(p)); :}
+  ;
+
+Component component =
+    COMPONENT name.n LB_CURLY component_body.r RB_CURLY
+    {:
+      r.setName(n);
+      mph.componentMap.put(n.getName(), r);
+      return r;
+    :}
+  ;
+
+Component component_body =
+    implementation.i component_body.b               {: insertZero(b.getImplementationList(), i); return b; :}
+  | property.p component_body.b                     {: insertZero(b.getPropertyList(), p); return b; :}
+  | USING PROPERTY property_ref.r component_body.b  {: insertZero(b.getPropertyRefList(), r); return b; :}
+  | implementation.i                  {: return new Component(null, new List<>(i), new List<>(), new List<>()); :}
+  | property.p                        {: return new Component(null, new List<>(), new List<>(p), new List<>()); :}
+  | USING PROPERTY property_ref.r     {: return new Component(null, new List<>(), new List<>(), new List<>(r)); :}
+  ;
+
+ComponentRef component_ref =
+    name.n {: ComponentRef ref = new ComponentRef(n, null); mph.componentRefList.add(ref); return ref; :}
+  ;
+
+HardwareModel hardware_model =
+    resource_type.r hardware_model.m  {: insertZero(m.getResourceTypeList(), r); return m;  :}
+  | resource.s hardware_model.m       {: insertZero(m.getResourceList(), s); return m; :}
+  | property.p hardware_model.m       {: insertZero(m.getPropertyList(), p); return m; :}
+  | resource_type.r                   {: return new HardwareModel(new List<>(r), new List<>(), new List<>()); :}
+  | resource.s                        {: return new HardwareModel(new List<>(), new List<>(s), new List<>()); :}
+  | property.p                        {: return new HardwareModel(new List<>(), new List<>(), new List<>(p)); :}
+  ;
+
+ResourceType resource_type =
+    RESOURCE TYPE name.n LB_CURLY resource_type_body.opt? RB_CURLY
+    {:
+      ResourceType b;
+      if (opt.getNumChild() > 0) {
+        b = (ResourceType) opt.getChild(0);
+      } else {
+        b = new ResourceType(null, false, new List<>(), new List<>(), new List<>());
+      }
+      b.setName(n);
+      b.setContainer(false);
+      mph.resourceTypeMap.put(n.getName(), b);
+      return b;
+    :}
+  | CONTAINER RESOURCE TYPE name.n LB_CURLY resource_type_body.opt? RB_CURLY
+    {:
+      ResourceType b;
+      if (opt.getNumChild() > 0) {
+        b = (ResourceType) opt.getChild(0);
+      } else {
+        b = new ResourceType(null, false, new List<>(), new List<>(), new List<>());
+      }
+      b.setName(n);
+      b.setContainer(true);
+      mph.resourceTypeMap.put(n.getName(), b);
+      return b;
+    :}
+  ;
+
+ResourceType resource_type_body =
+    resource_type.r resource_type_body.b                 {: insertZero(b.getSubTypeList(), r); return b; :}
+  | property.p resource_type_body.b                      {: insertZero(b.getPropertyList(), p); return b; :}
+  | USING PROPERTY property_ref.pr resource_type_body.b  {: insertZero(b.getPropertyRefList(), pr); return b; :}
+  | resource_type.r                 {: return new ResourceType(null, false, new List<>(r), new List<>(), new List<>()); :}
+  | property.p                      {: return new ResourceType(null, false, new List<>(), new List<>(p), new List<>()); :}
+  | USING PROPERTY property_ref.pr  {: return new ResourceType(null, false, new List<>(), new List<>(), new List<>(pr)); :}
+  ;
+
+ResourceTypeRef resource_type_ref =
+    name.n
+    {:
+      ResourceTypeRef ref = new ResourceTypeRef(n, null);
+      mph.resourceTypeRefList.add(ref);
+      return ref;
+    :}
+  ;
+
+Resource resource =
+    RESOURCE name.n COLON resource_type_ref.r LB_CURLY RB_CURLY
+    {:
+      return new Resource(n, r, new List<>(), new List<>());
+    :}
+  | RESOURCE name.n COLON resource_type_ref.r LB_CURLY resource_body.b RB_CURLY
+    {:
+      b.setName(n);
+      b.setType(r);
+      return b;
+    :}
+  ;
+
+Resource resource_body =
+    resource.r resource_body.b                {: insertZero(b.getSubResourceList(), r); return b; :}
+  | current_resource_value.v resource_body.b  {: insertZero(b.getCurrentResourceValueList(), v); return b; :}
+  | resource.r                {: return new Resource(null, null, new List<>(r), new List<>()); :}
+  | current_resource_value.v  {: return new Resource(null, null, new List<>(), new List<>(v)); :}
+  ;
+
+CurrentResourceValue current_resource_value =
+    property_ref.r EQ literal_expression.l {: return new CurrentResourceValue(r,l); :}
+  ;
+
+Implementation implementation =
+    CONTRACT name.n LB_CURLY implementation_body.b RB_CURLY {: b.setName(n); return b; :}
+  ;
+
+Instance instance =
+    name.n {: return new Instance(n); :}
+  ;
+
+List instance_list =
+    instance.i COMMA instance_list.l {: insertZero(l, i); :}
+  | instance.i {: return new List<>(i); :}
+  ;
+
+ComponentRequirement component_requirement =
+    REQUIRES COMPONENT instance_list.l OFTYPE component_ref.cr {: return new ComponentRequirement(cr, l); :}
+  ;
+
+ResourceRequirement resource_requirement =
+    REQUIRES RESOURCE instance_list.l OFTYPE resource_type_ref.rr WITH LB_CURLY inner_resource_requirement.irr* RB_CURLY {: return new ResourceRequirement(rr, l, irr); :}
+  | REQUIRES RESOURCE instance_list.l OFTYPE resource_type_ref.rr {: return new ResourceRequirement(rr, l, new List<>()); :}
+  ;
+
+ResourceRequirement inner_resource_requirement =
+    instance_list.l OFTYPE resource_type_ref.rr WITH LB_CURLY inner_resource_requirement.irr* RB_CURLY {: return new ResourceRequirement(rr, l, irr); :}
+  | instance_list.l OFTYPE resource_type_ref.rr {: return new ResourceRequirement(rr, l, new List<>()); :}
+  ;
+
+Designator designator =
+    qualified_name.n {: return new QualifiedNameDesignator(n); :}
+  ;
+
+Clause clause =
+    REQUIRING designator.d LT expression.e {: return new Clause(ClauseType.REQUIRING, d, ClauseComparator.LT, e); :}
+  | REQUIRING designator.d LE expression.e {: return new Clause(ClauseType.REQUIRING, d, ClauseComparator.LE, e); :}
+  | REQUIRING designator.d EQ expression.e {: return new Clause(ClauseType.REQUIRING, d, ClauseComparator.EQ, e); :}
+  | REQUIRING designator.d NE expression.e {: return new Clause(ClauseType.REQUIRING, d, ClauseComparator.NE, e); :}
+  | REQUIRING designator.d GE expression.e {: return new Clause(ClauseType.REQUIRING, d, ClauseComparator.GE, e); :}
+  | REQUIRING designator.d GT expression.e {: return new Clause(ClauseType.REQUIRING, d, ClauseComparator.GT, e); :}
+  | PROVIDING designator.d LT expression.e {: return new Clause(ClauseType.PROVIDING, d, ClauseComparator.LT, e); :}
+  | PROVIDING designator.d LE expression.e {: return new Clause(ClauseType.PROVIDING, d, ClauseComparator.LE, e); :}
+  | PROVIDING designator.d EQ expression.e {: return new Clause(ClauseType.PROVIDING, d, ClauseComparator.EQ, e); :}
+  | PROVIDING designator.d NE expression.e {: return new Clause(ClauseType.PROVIDING, d, ClauseComparator.NE, e); :}
+  | PROVIDING designator.d GE expression.e {: return new Clause(ClauseType.PROVIDING, d, ClauseComparator.GE, e); :}
+  | PROVIDING designator.d GT expression.e {: return new Clause(ClauseType.PROVIDING, d, ClauseComparator.GT, e); :}
+  ;
+
+Implementation implementation_body =
+    component_requirement.cr implementation_body.b  {: insertZero(b.getComponentRequirementList(), cr); return b; :}
+  | resource_requirement.rr implementation_body.b   {: b.setResourceRequirement(rr); return b; :}
+  | clause.c implementation_body.b                  {: insertZero(b.getClauseList(), c); return b; :}
+  | component_requirement.cr  {: return new Implementation(null, new List<>(cr), null, new List<>()); :}
+  | resource_requirement.rr   {: return new Implementation(null, new List<>(), rr, new List<>()); :}
+  | clause.c                  {: return new Implementation(null, new List<>(), null, new List<>(c)); :}
+  ;
+
+Solution solution =
+    SOLUTION LB_CURLY assignment.al* RB_CURLY
+    {:
+      mph.unfinishedSolution = new Solution(null, al);
+      return mph.unfinishedSolution;
+    :}
+  ;
+
+Assignment assignment =
+    NAME.i RIGHT_ARROW NAME.impl LB_CURLY resource_mapping.rm component_mapping.cml* RB_CURLY
+    {:
+      Assignment result = new Assignment(true, null, null, rm, cml);
+      mph.assignmentTerminals.put(result, new Tuple<>(i, impl));
+      return result;
+    :}
+  ;
+
+ResourceMapping resource_mapping =
+    NAME.i RIGHT_ARROW NAME.res
+    {:
+      ResourceMapping result = new ResourceMapping();
+      mph.resourceMappingTerminals.put(result, new Tuple<>(i, res));
+      return result;
+    :}
+  | NAME.i RIGHT_ARROW NAME.res LB_CURLY resource_mapping.rml* RB_CURLY
+    {:
+      ResourceMapping result = new ResourceMapping(null, null, rml);
+      mph.resourceMappingTerminals.put(result, new Tuple<>(i, res));
+      return result;
+    :}
+  ;
+
+ComponentMapping component_mapping =
+    assignment.a
+    {:
+      a.setTopLevel(false);
+      ComponentMapping result = new ComponentMapping(null, a);
+      return result;
+    :}
+  ;
diff --git a/jastadd-mquat-base/src/main/jastadd/solution/Checking.jadd b/jastadd-mquat-base/src/main/jastadd/solution/Checking.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..64e64e03d7c066fdd91c4ab9ea3cc21d6c78410b
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solution/Checking.jadd
@@ -0,0 +1,64 @@
+aspect Checking {
+  public void Solution.explain() {
+    Set<Request> requestSet = new HashSet<>();
+    Map<Resource, Assignment> resourceSet = new HashMap<>();
+    logger.info(this.toString());
+    // check assignments
+    for (Assignment assignment : allAssignments()) {
+      if (!assignment.isValid()) {
+        logger.warn("Invalid assignment found");
+        assignment.explain();
+        return;
+      } else {
+        if (assignment.getImplementation().containingComponent() ==
+            assignment.getRequest().getTarget().getRef()) {
+          requestSet.add(assignment.getRequest());
+        }
+        if (resourceSet.containsKey(assignment.getResource())) {
+          logger.warn("Two assignments to the same resource found:\n {}---\n{}",
+              assignment.toString(), resourceSet.get(assignment.getResource()));
+          return;
+        }
+        resourceSet.put(assignment.getResource(), assignment);
+      }
+    }
+    // check if all requests have (at least) one assignment
+    if (requestSet.size() != getModel().getRequests().getNumChild()) {
+      logger.warn("There are only assignments for {} of {} requests!", requestSet.size(), getModel().getRequests().getNumChild());
+      return;
+    }
+    logger.info("Solution is valid");
+  }
+
+  public void Assignment.explain() {
+    if (getRequest() == null) {
+      logger.warn("incomplete assignment: request missing");
+      return;
+    } else if (getResource() == null) {
+      logger.warn("incomplete assignment: resource missing");
+      return;
+    } else if (getImplementation() == null) {
+      logger.warn("incomplete assignment: implementation missing");
+      return;
+    }
+
+    for (Clause clause : getImplementation().requirementClauses()) {
+      if (!clause.checkUsing(this)) {
+        logger.warn("Requirement {} of {} for {} not met",
+            clause.print(new MquatWriteSettings("")),
+            getImplementation().name(), this.name());
+      }
+    }
+
+    // if this is a "top-level" assignment, check the properties from the request
+    if (this.getRequest().getTarget().getRef().equals(getImplementation().containingComponent())) {
+      for (Clause clause : getRequest().getConstraintList()) {
+        if (clause.isRequiringClause() && !clause.checkUsing(this)) {
+          logger.warn("Request requirement {} of {} for {} not met",
+              clause.print(new MquatWriteSettings("")),
+              getRequest().name(), this.name());
+        }
+      }
+    }
+  }
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/solution/Checking.jrag b/jastadd-mquat-base/src/main/jastadd/solution/Checking.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..fc587981b331ad854188dec5f323404c1fc0b217
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solution/Checking.jrag
@@ -0,0 +1,139 @@
+aspect Checking {
+
+  syn boolean Solution.isValid() {
+    Set<Request> requestSet = new HashSet<>();
+    Set<Resource> resourceSet = new HashSet<>();
+
+    // check assignments
+    Iterator<Assignment> assignmentIterator = this.assignmentIterator();
+    while (assignmentIterator.hasNext()) {
+      Assignment assignment = assignmentIterator.next();
+      if (!assignment.isValid()) {
+        return false;
+      } else {
+        if (assignment.getImplementation().containingComponent() ==
+            assignment.getRequest().getTarget().getRef()) {
+          requestSet.add(assignment.getRequest());
+        }
+        if (resourceSet.contains(assignment.getResource())) {
+          return false;
+        }
+        resourceSet.add(assignment.getResource());
+      }
+    }
+
+    // check if all requests have (at least) one assignment
+    return requestSet.size() == getModel().getRequests().getNumChild();
+  }
+
+
+
+  syn boolean Assignment.isValid() {
+    if (getRequest() == null || getResource() == null || getImplementation() == null) { return false; }
+    for (Clause clause : getImplementation().requirementClauses()) {
+      if (!clause.checkUsing(this)) {
+        return false;
+      }
+    }
+    // if this is a "top-level" assignment, check the properties from the request
+    if (this.getRequest().getTarget().getRef().equals(getImplementation().containingComponent())) {
+      for (Clause clause : getRequest().getConstraintList()) {
+        if (clause.isRequiringClause() && !clause.checkUsing(this)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  syn boolean Solution.isSoftwareValid() {
+
+    // check assignments
+    Iterator<Assignment> assignmentIterator = this.assignmentIterator();
+    while (assignmentIterator.hasNext()) {
+      if (!assignmentIterator.next().isSoftwareValid()) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  syn boolean Assignment.isSoftwareValid() {
+    if (getRequest() == null) {
+      logger.warn("incomplete assignment: request missing");
+      return false;
+    } else if (getImplementation() == null) {
+      logger.warn("incomplete assignment: implementation missing");
+      return false;
+    }
+
+    for (Clause clause : getImplementation().requirementClauses()) {
+      if (clause.getDesignator().isSoftwareDesignator()) {
+        if (!clause.checkUsing(this)) {
+          return false;
+        }
+      }
+
+    }
+
+    // if this is a "top-level" assignment, check the properties from the request
+    if (this.getRequest().getTarget().getRef().equals(getImplementation().containingComponent())) {
+      for (Clause clause : getRequest().getConstraintList()) {
+        if (clause.isRequiringClause() && clause.getDesignator().isSoftwareDesignator()) {
+          if (!clause.checkUsing(this)) {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  syn double Solution.computeObjective() {
+    Objective objective = getModel().getObjective();
+
+    Iterator<Assignment> solutionIterator;
+    switch (objective.getAgg()) {
+      case MAX:
+        double max = Double.NEGATIVE_INFINITY;
+        solutionIterator = this.assignmentIterator();
+        while (solutionIterator.hasNext()) {
+          max = Math.max(max, solutionIterator.next().computeObjective());
+        }
+        return max;
+      case SUM:
+        double sum = 0;
+        solutionIterator = this.assignmentIterator();
+        while (solutionIterator.hasNext()) {
+          sum += solutionIterator.next().computeObjective();
+        }
+        return sum;
+    }
+    throw new RuntimeException("java is stupid.");
+  }
+
+  syn double Assignment.computeObjective() {
+    Objective objective = getRequest().root().getObjective();
+    Property property = objective.getPropertyRef().getRef();
+
+    // compute objective property for the implementation
+    for (Clause clause : getImplementation().getClauseList()) {
+      if (clause.isProvidingClause()) {
+        if (clause.getDesignator().isSoftwareDesignator()) {
+          SoftwareDesignator softwareDesignator = clause.getDesignator().asSoftwareDesignator();
+          if (!softwareDesignator.hasInstanceRef()) {
+            // the s.d. has no instance ref, so this is about this very implementation!
+            if (softwareDesignator.getPropertyRef().getRef().equals(property)) {
+              return clause.getExpression().evalUsing(this);
+            }
+          }
+        }
+      }
+    }
+    // TODO what if there is no rule to
+    throw new RuntimeException("Objective could not be computed!");
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/solution/Helpers.jadd b/jastadd-mquat-base/src/main/jastadd/solution/Helpers.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..04a927add418ae65c1962127960d3e99fd9645f9
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solution/Helpers.jadd
@@ -0,0 +1,50 @@
+aspect Helpers {
+
+  /**
+   * @return a deep copy of the assignment
+   */
+  public Assignment Assignment.deepCopy() {
+    Assignment copy = new Assignment();
+    copy.setImplementation(this.getImplementation());
+    copy.setRequest(this.getRequest());
+    copy.setTopLevel(this.getTopLevel());
+
+    for (ComponentMapping subAssignment : getComponentMappingList()) {
+      Assignment subAssignmentClone = subAssignment.getAssignment().deepCopy();
+      copy.addComponentMapping(new ComponentMapping(subAssignment.getInstance(), subAssignmentClone));
+    }
+
+    copy.setResourceMapping(getResourceMapping().deepCopy());
+
+    return copy;
+  }
+
+  /**
+   * @return a deep copy of the resource mapping
+   */
+  public ResourceMapping ResourceMapping.deepCopy() {
+    ResourceMapping copy = new ResourceMapping();
+    copy.setInstance(this.getInstance());
+    copy.setResource(this.getResource());
+    for (ResourceMapping subMapping : getResourceMappingList()) {
+      copy.addResourceMapping(subMapping.deepCopy());
+    }
+    return copy;
+  }
+
+  /**
+   * @return a deep copy of the solution
+   */
+  public Solution Solution.deepCopy() {
+
+    Solution copy = new Solution(getModel(), new List<>());
+
+    for (Assignment assignment : this.getAssignments()) {
+      Assignment clone = assignment.deepCopy();
+      copy.addAssignment(clone);
+    }
+
+    return copy;
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/solution/Navigation.jrag b/jastadd-mquat-base/src/main/jastadd/solution/Navigation.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..73e90f2678cda5a7e77106a13629b6a96a27fbe9
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solution/Navigation.jrag
@@ -0,0 +1,16 @@
+aspect Navigation {
+
+  // upwards search ====================================================================================================
+
+  //--- containingComponentMapping ---//
+
+  inh ComponentMapping Assignment.containingComponentMapping();
+  eq ComponentMapping.getAssignment().containingComponentMapping() = this;
+  eq Solution.getAssignment(int i).containingComponentMapping() = null;
+
+  //--- containingAssignment ---//
+
+  inh Assignment ComponentMapping.containingAssignment();
+  eq Assignment.getComponentMapping(int i).containingAssignment() = this;
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/solution/Printing.jrag b/jastadd-mquat-base/src/main/jastadd/solution/Printing.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..98b56750128dbd2f6f6ef2ca7befe6de922ba01c
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solution/Printing.jrag
@@ -0,0 +1,56 @@
+aspect Printing {
+
+  public MquatString Solution.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append("solution {").lb().ind();
+    for (Assignment assignment : getAssignmentList()) {
+      result.append(assignment.print(settings, indentationLevel + 1)).lb();
+    }
+    return result.und().lb().append("}").lb();
+  }
+
+  public MquatString Assignment.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    if (getTopLevel()) {
+      result.append(getRequest() == null ? "<no request>" : getRequest().name());
+    } // otherwise the instance name was already printed
+    result.append(" -> ")
+        .append(getImplementation() == null ? "<no impl>" : getImplementation().name())
+        .append(" {").lb().ind();
+    result.append(getResourceMapping().print(settings, indentationLevel + 1));
+    for (ComponentMapping entry : getComponentMappingList()) {
+      result.append(entry.print(settings, indentationLevel + 1));
+    }
+    result.und().lb().append("}");
+
+    return result;
+  }
+
+  public MquatString ResourceMapping.print(MquatWriteSettings settings, int indentationLevel) {
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getInstance() == null ? "<no instance>" : getInstance().name())
+        .append(" -> ").append((getResource() == null) ? "<no resource>" : getResource().name());
+    if (getNumResourceMapping() > 0) {
+      result.append(" {").lb().ind();
+      for (ResourceMapping subMapping : getResourceMappingList()) {
+        result.append(subMapping.print(settings, indentationLevel));
+      }
+      result.und().append("}").lb();
+    } else {
+      result.lb();
+    }
+    return result;
+  }
+
+  public MquatString ComponentMapping.print(MquatWriteSettings settings, int indentationLevel){
+    MquatString result = new MquatString(settings, indentationLevel);
+    result.append(getInstance() == null ? "<no instance>" : getInstance().name());
+    result.append((getAssignment() == null) ? "<no assignment>" : getAssignment().print(settings, indentationLevel));
+    return result.lb();
+  }
+
+  public String Assignment.name() {
+    return "Assignment@" + Integer.toHexString(hashCode());
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/solution/Solution.ast b/jastadd-mquat-base/src/main/jastadd/solution/Solution.ast
new file mode 100644
index 0000000000000000000000000000000000000000..7ed1c9b6d0e62f64a7e19b917234507d1ba5a48c
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solution/Solution.ast
@@ -0,0 +1,4 @@
+Solution ::= <Model:Root> Assignment* ;
+Assignment ::= <TopLevel:boolean> <Request:Request> <Implementation:Implementation> ResourceMapping ComponentMapping* ;
+ResourceMapping ::= <Instance:Instance> <Resource:Resource> ResourceMapping* ;
+ComponentMapping ::= <Instance:Instance> Assignment ;
diff --git a/jastadd-mquat-base/src/main/jastadd/solution/Traversal.jrag b/jastadd-mquat-base/src/main/jastadd/solution/Traversal.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..418c3b796de0d5699077cd15a17e90005070f2ea
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solution/Traversal.jrag
@@ -0,0 +1,55 @@
+aspect Traversal {
+
+  uncache Assignment.mappedAssignment(Instance instance);
+  syn Assignment Assignment.mappedAssignment(Instance instance) {
+    for (ComponentMapping mapping : getComponentMappingList()) {
+      if (mapping.getInstance() == instance) {
+        return mapping.getAssignment();
+      }
+    }
+    return null;
+  }
+
+  uncache Assignment.mappedResource(Instance instance);
+  syn Resource Assignment.mappedResource(Instance instance) {
+    return getResourceMapping().mappedResource(instance);
+  }
+
+  syn Resource ResourceMapping.mappedResource(Instance instance) {
+    if (this.getInstance() == instance) {
+      return this.getResource();
+    } else {
+      for (ResourceMapping subMapping : this.getResourceMappingList()) {
+        Resource result = subMapping.mappedResource(instance);
+        if (result != null) {
+          return result;
+        }
+      }
+      return null;
+    }
+  }
+
+  syn java.util.List<Assignment> Assignment.allAssignments() {
+    ArrayList<Assignment> allAssignments = new ArrayList<>();
+    allAssignments.add(this);
+    for (ComponentMapping mapping : getComponentMappingList()) {
+      allAssignments.addAll(mapping.getAssignment().allAssignments());
+    }
+    return Collections.unmodifiableList(allAssignments);
+  }
+
+  // everything related to solution must not be cached
+  uncache Solution.allAssignments();
+  syn java.util.List<Assignment> Solution.allAssignments() {
+    ArrayList<Assignment> allAssignments = new ArrayList<>();
+    for (Assignment assignment : getAssignments()) {
+      allAssignments.addAll(assignment.allAssignments());
+    }
+    return Collections.unmodifiableList(allAssignments);
+  }
+
+  syn Resource Assignment.getResource() {
+    return getResourceMapping().getResource();
+  }
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd b/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..b90d02da241730ed555ba145c1080a64fd72023c
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd
@@ -0,0 +1,40 @@
+aspect Helpers {
+
+  public static void Clause.populateResourceMapping(ResourceMapping mapping, ResourceRequirement requirement, Resource resource) {
+
+    for (ResourceRequirement subRequirement : requirement.getResourceRequirementList()) {
+      int fittingResourceCount = 0;
+      for (int currentInstance = 0; currentInstance < subRequirement.getNumInstance(); currentInstance++) {
+        Instance instance = subRequirement.getInstance(currentInstance);
+        for (int currentResource = 0; currentResource < resource.getNumSubResource(); currentResource++) {
+          Resource subResource = resource.getSubResource(currentResource);
+          if (subResource.getType().getRef() == subRequirement.getResourceTypeRef().getRef()) {
+            if (currentInstance == fittingResourceCount) {
+              ResourceMapping newMapping = new ResourceMapping(instance, subResource, new de.tudresden.inf.st.mquat.jastadd.model.List<>());
+              mapping.addResourceMapping(newMapping);
+              populateResourceMapping(newMapping, subRequirement, subResource);
+              fittingResourceCount++;
+            }
+            currentInstance++;
+          }
+        }
+      }
+    }
+  }
+
+  uncache Clause.simpleAssignment(Request request, Resource resource);
+  syn Assignment Clause.simpleAssignment(Request request, Resource resource) {
+    Assignment assignment = new Assignment();
+    assignment.setRequest(request);
+    Implementation impl = containingImplementation();
+    if (impl != null) {
+      assignment.setImplementation(impl);
+
+      ResourceMapping mapping=new ResourceMapping(impl.getResourceRequirement().getInstance(0),resource,new de.tudresden.inf.st.mquat.jastadd.model.List<>());
+      populateResourceMapping(mapping,impl.getResourceRequirement(),resource);
+      assignment.setResourceMapping(mapping);
+    }
+    return assignment;
+  }
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.ast b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.ast
new file mode 100644
index 0000000000000000000000000000000000000000..c40187e7b15a5072f1d717ad2ee42e115b7b69e9
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.ast
@@ -0,0 +1,18 @@
+ILP ::= IlpObjective IlpConstraint* IlpBound* IlpVariable* <Info:IlpVarInfo> ;
+TimedOutILP:ILP ::= <Reason:String> ;
+
+// objective kind is either minimize or maximize
+IlpObjective ::= <Kind:IlpObjectiveKind> IlpLeftHandSide ;
+
+IlpConstraint ::= <Name:String> IlpLeftHandSide <ClauseComparator:ClauseComparator> <RightHandSide:double> ;
+
+IlpBound ::= <Ref:IlpVariable> <Type:IlpBoundType> ;
+
+IlpVariable ::= <Name:String> <Request:Request> <Impl:Implementation> ;
+IlpAllResourcesVariable:IlpVariable ;
+IlpMappingVariable:IlpVariable ::= <Resource:Resource> ;
+
+// sum of terms
+IlpLeftHandSide ::= IlpTerm* ;
+
+IlpTerm ::= <Value:double> <Ref:IlpVariable> ;
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jadd b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..11e842dc3c9862c617afc16cacb9136178615775
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jadd
@@ -0,0 +1,97 @@
+aspect ILP {
+
+  public static String Root.ILP_TIMEOUT_VALUE = "de.tudresden.inf.st.mquat.solving.ilp.timeoutValue";
+  public static String Root.ILP_TIMEOUT_UNIT = "de.tudresden.inf.st.mquat.solving.ilp.timeoutUnit";
+
+  public enum IlpObjectiveKind {
+    MINIMIZE,
+    MAXIMIZE
+  }
+
+  public enum IlpBoundType {
+    BINARY,
+    ZERO,
+    GREATER_EQUAL_ZERO
+  }
+
+  public class IlpString {
+    StringBuilder buffer;
+
+    public IlpString() {
+      this.buffer = new StringBuilder();
+    }
+
+    public IlpString lb() {
+      this.buffer.append('\n');
+      return this;
+    }
+
+    public IlpString append(Object o) {
+      buffer.append(o);
+      return this;
+    }
+
+    public IlpString append(final IlpString s) {
+      this.buffer.append(s.getBuffer());
+      return this;
+    }
+
+    public StringBuilder getBuffer() {
+      return buffer;
+    }
+
+    public String toString() {
+      return buffer.toString();
+    }
+  }
+
+  public class IlpVarInfo {
+    public java.util.Map<String, IlpVariable> vars;
+    public java.util.Map<Resource, IlpConstraint> resourceConstraints;
+    public java.util.Set<IlpVariable> illegal;
+
+    public IlpVarInfo() {
+      vars = new java.util.TreeMap<>();
+      resourceConstraints = new java.util.HashMap<>();
+      illegal = new java.util.HashSet<>();
+    }
+
+    public IlpVariable getIlpVariable(Request request, Implementation impl, Resource resource) {
+      String varName = request.getIlpName() + "#" + impl.getIlpName() + "#" + resource.getIlpName();
+      IlpVariable result = vars.get(varName);
+      IlpConstraint resourceConstraint = resourceConstraints.get(resource);
+      if (resourceConstraint == null) {
+        resourceConstraint = new IlpConstraint("one_on_" + resource.getIlpName(), new IlpLeftHandSide(),
+            ClauseComparator.LE, 1);
+        resourceConstraints.put(resource, resourceConstraint);
+      }
+      if (result == null) {
+        result = new IlpMappingVariable(varName, request, impl, resource);
+        vars.put(varName, result);
+        resourceConstraint.getIlpLeftHandSide().addIlpTerm(new IlpTerm(1, result));
+      }
+      return result;
+    }
+
+    public void setIllegal(Request request, Implementation impl, Resource resource) {
+      illegal.add(getIlpVariable(request, impl, resource));
+    }
+
+    public IlpVariable getIlpVariable(Request request, Implementation impl) {
+      String varName = request.getIlpName() + "#" + impl.getIlpName();
+      IlpVariable result = vars.get(varName);
+      if (result == null) {
+        result = new IlpAllResourcesVariable(varName, request, impl);
+        vars.put(varName, result);
+      }
+      return result;
+    }
+  }
+
+  private static double Root.makeNegative(double value) {
+    return value == 0.0 || value == -0.0 ? 0.0 : -1.0 * value;
+  }
+
+  static java.util.regex.Pattern ASTNode.ilpSearchRegex = java.util.regex.Pattern.compile("[.\\-+*/]");
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jrag b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..e7ca0cd3e1aded4e97612b3b3d6ecff6eeb492d5
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jrag
@@ -0,0 +1,198 @@
+aspect ILP {
+
+  /**
+   * checks if an IlpVariable is a mapping variable
+   */
+  syn boolean IlpVariable.isMappingVariable() = false;
+  eq IlpMappingVariable.isMappingVariable() = true;
+
+  /**
+   * @return itself if it is a mapping variable, otherwise null
+   */
+  syn IlpMappingVariable IlpVariable.asMappingVariable() = null;
+  eq IlpMappingVariable.asMappingVariable() = this;
+
+  /**
+   * @return the name without the '_' characters
+   */
+  syn String ModelElement.getIlpName() = ilpSearchRegex.matcher(name()).replaceAll("_");
+  syn String Request.getIlpName()      = ilpSearchRegex.matcher(name()).replaceAll("_");
+
+  //--- ilpTimeout ---//
+
+  uncache Root.ilpTimeout(String reason);
+  syn TimedOutILP Root.ilpTimeout(String reason) {
+    TimedOutILP result = new TimedOutILP();
+    result.setReason(reason);
+    return result;
+  }
+
+  //--- hasTimeout ---//
+
+  syn boolean ILP.hasTimeout() = false;
+  eq TimedOutILP.hasTimeout() = true;
+
+  //--- timeoutReason ---//
+
+  syn String ILP.timeoutReason() = null;
+  eq TimedOutILP.timeoutReason() = getReason();
+
+
+  /**
+   * the non-terminal attribute to compute the ILP subtree
+   */
+  syn ILP Root.getILP() {
+    de.tudresden.inf.st.mquat.utils.StopWatch stopWatch = de.tudresden.inf.st.mquat.utils.StopWatch.start();
+//    StopWatch stopWatch = StopWatch.start();
+    long timeoutValue = (long) de.tudresden.inf.st.mquat.utils.StaticSettings.get(ILP_TIMEOUT_VALUE);
+    java.util.concurrent.TimeUnit timeoutUnit = (java.util.concurrent.TimeUnit) de.tudresden.inf.st.mquat.utils.StaticSettings.get(ILP_TIMEOUT_UNIT);
+    long timeoutNanos = timeoutUnit.toNanos(timeoutValue);
+
+    ILP result = new ILP();
+    IlpVarInfo info = new IlpVarInfo();
+
+    IlpObjective objective = new IlpObjective();
+    objective.setKind(IlpObjectiveKind.MINIMIZE);
+    IlpLeftHandSide olhs = new IlpLeftHandSide();
+    objective.setIlpLeftHandSide(olhs);
+    result.setIlpObjective(objective);
+    for (Request request : this.getRequestList()) {
+      for (Component comp : request.relevantComponents()) {
+        IlpLeftHandSide oneCompLhs = new IlpLeftHandSide();
+        for (Implementation impl : comp.getImplementationList()) {
+          if (stopWatch.time() > timeoutNanos) {
+            return ilpTimeout("Timeout in implementation " + impl.name());
+          }
+          oneCompLhs.addIlpTerm(new IlpTerm(1, info.getIlpVariable(request, impl)));
+          IlpLeftHandSide oneImplLhs = new IlpLeftHandSide();
+
+          // #1 Objective function
+          for (Resource resource : this.getHardwareModel().getResourceList()) {
+            // r1#c2#i3#hw4
+            IlpTerm term = new IlpTerm();
+            IlpVariable var = info.getIlpVariable(request, impl, resource);
+            term.setRef(var);
+            Clause providingObjectiveClause = impl.findFirstProvidingClause(getObjective().getPropertyRef().getRef());
+            if (providingObjectiveClause != null) {
+              term.setValue(providingObjectiveClause.evalUsing(request, resource));
+            } else {
+              term.setValue(0);
+            }
+            olhs.addIlpTerm(term);
+            oneImplLhs.addIlpTerm(new IlpTerm(1, var));
+          }
+          // 2.3 NFP-Negotiation: Requirements to other components
+          for (Clause reqClause : impl.requirementClauses()) {
+            if (stopWatch.time() > timeoutNanos) {
+              return ilpTimeout("Timeout in NFP-Negotiation");
+            }
+            Designator designator = reqClause.getDesignator();
+            IlpLeftHandSide reqLhs = new IlpLeftHandSide();
+            if (designator.isSoftwareDesignator()) {
+              for (Tuple<Implementation, Clause> tuple : reqClause.providingClausesOfRequiredComponent()) {
+                Implementation providingImpl = tuple.getKey();
+                Clause providingClause = tuple.getValue();
+                for (Resource resource : this.getHardwareModel().getResourceList()) {
+                  reqLhs.addIlpTerm(new IlpTerm(providingClause.evalUsing(request, resource),
+                      info.getIlpVariable(request, providingImpl, resource)));
+                }
+              }
+              for (Resource resource : this.getHardwareModel().getResourceList()) {
+                // we always use negative eval-value to get the required value on the right side (literally)
+                reqLhs.addIlpTerm(new IlpTerm(makeNegative(reqClause.evalUsing(request, resource)),
+                    info.getIlpVariable(request, impl, resource)));
+              }
+              result.addIlpConstraint(new IlpConstraint(
+                  request.getIlpName() + "_" + impl.getIlpName() + "_reqs_" +
+                      designator.asSoftwareDesignator().getPropertyRef().getRef().getIlpName() + "_from_" +
+                      designator.asSoftwareDesignator().getInstanceRef().getRef().referringComponent().getIlpName(),
+                  reqLhs, reqClause.getClauseComparator(), 0));
+            } else {
+              for (Resource resource : this.getHardwareModel().getResourceList()) {
+                // check if constraint is fulfilled, otherwise remember this illegal combination
+                if (!reqClause.checkUsing(request, resource)) {
+                  info.setIllegal(request, impl, resource);
+                }
+              }
+            }
+          }
+
+          // 2.2 Architecture constraints: One impl/resource and request
+          oneImplLhs.addIlpTerm(new IlpTerm(-1, info.getIlpVariable(request, impl)));
+          result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_single_" + impl.getIlpName(),
+              oneImplLhs, ClauseComparator.EQ, 0));
+          // 2.3 NFP-Negotiation: Use implementations of required components
+          for (ComponentRequirement req : impl.getComponentRequirementList()) {
+            IlpLeftHandSide reqImplLhs = new IlpLeftHandSide();
+            for (Implementation reqImpl : req.getComponentRef().getRef().getImplementationList()) {
+              reqImplLhs.addIlpTerm(new IlpTerm(1, info.getIlpVariable(request, reqImpl)));
+            }
+            reqImplLhs.addIlpTerm(new IlpTerm(-1, info.getIlpVariable(request, impl)));
+            result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_" + impl.getIlpName() +
+                "_req_" + req.getComponentRef().getRef().getIlpName(),
+                reqImplLhs, ClauseComparator.GE, 0));
+          }
+        }
+        // 2.2 Architecture constraints: One impl per component and request
+        result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_opc_" + comp.getIlpName(),
+            oneCompLhs, ClauseComparator.LE, 1));
+      }
+      // 2.1.a Request constraints: Target component (i.e., use one of its implementations)
+      IlpLeftHandSide targetLhs = new IlpLeftHandSide();
+      for (Implementation impl : request.getTarget().getRef().getImplementationList()) {
+        IlpVariable var = info.getIlpVariable(request, impl);
+        targetLhs.addIlpTerm(new IlpTerm(1, var));
+      }
+      result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_target", targetLhs, ClauseComparator.EQ, 1));
+      // 2.1.b Request constraints: Required NFPs of target component
+      for (Clause requiredClause : request.getConstraintList()) {
+        IlpLeftHandSide reqLhs = new IlpLeftHandSide();
+        Property requiredProperty = requiredClause.getDesignator().asSoftwareDesignator().getPropertyRef().getRef();
+        for(Implementation impl : request.getTarget().getRef().getImplementationList()) {
+          for (Resource resource : this.getHardwareModel().getResources()) {
+            Clause providingClause = impl.findFirstProvidingClause(requiredProperty);
+            if (providingClause != null) {
+              IlpVariable var = info.getIlpVariable(request, impl, resource);
+              reqLhs.addIlpTerm(new IlpTerm(providingClause.evalUsing(request, resource), var));
+            }
+          }
+        }
+        result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_req_" + requiredProperty.getIlpName(),
+            reqLhs, requiredClause.getClauseComparator(),
+            requiredClause.evalUsing(request, null)));
+      }
+    }
+    if (stopWatch.time() > timeoutNanos) {
+      return ilpTimeout("Timeout after constraint creation");
+    }
+    /*
+    #2 Constraints
+    #2.1 Request constraints (requiredNFPs)
+    #2.2 Architecture constraints (One SW on one HW, Only one mode/configuration per impl and per SW)
+    #2.3 NFP-negotiation (Satisfy requirements from SW to both SW and HW)
+    */
+
+    // 2.2 Architecture constraints: Only one config per hardware resource
+    for (IlpConstraint constraint : info.resourceConstraints.values()) {
+      result.addIlpConstraint(constraint);
+    }
+
+    // Generals
+    for (IlpVariable var : info.vars.values()) {
+      result.addIlpVariable(var);
+    }
+
+    // Bounds (all binary except illegal which are zero)
+    info.vars.values().removeAll(info.illegal);
+    for (IlpVariable var : info.vars.values()) {
+      // TODO uncomment addIlpBound line. Comment out to not clutter output for the moment.
+      result.addIlpBound(new IlpBound(var, IlpBoundType.BINARY));
+    }
+    for (IlpVariable var : info.illegal) {
+      result.addIlpBound(new IlpBound(var, IlpBoundType.ZERO));
+    }
+    result.setInfo(info);
+    return result;
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILPPrinting.jrag b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILPPrinting.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..d8a980bc0add96f61fa466136dc116d54b0e1f58
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILPPrinting.jrag
@@ -0,0 +1,74 @@
+aspect ILPPrinting {
+
+  syn IlpString ILP.printIlp() {
+    IlpString result = new IlpString();
+    result.append(getIlpObjective().printIlp()).lb();
+    result.append("Subject To").lb();
+    for (IlpConstraint c : getIlpConstraintList()) {
+      result.append(c.printIlp()).lb();
+    }
+    result.append("Bounds").lb();
+    for (IlpBound b : getIlpBoundList()) {
+      result.append(b.printIlp()).lb();
+    }
+    // TODO check if "Generals" is always correct
+    result.append("Generals").lb();
+    for (IlpVariable v : getIlpVariableList()) {
+      result.append(v.getName()).append(" ");
+    }
+    return result.lb().append("End").lb();
+  }
+
+  syn IlpString IlpObjective.printIlp() {
+    IlpString result = new IlpString();
+    switch(getKind()) {
+      case MAXIMIZE: result.append("Maximize"); break;
+      case MINIMIZE: result.append("Minimize"); break;
+    }
+    return result.lb().append(getIlpLeftHandSide().printIlp());
+  }
+
+  syn IlpString IlpConstraint.printIlp() {
+    IlpString result = new IlpString();
+    result.append(getName()).append(": ").append(getIlpLeftHandSide().printIlp()).append(" ");
+    switch (getClauseComparator()) {
+      case LT: result.append("<"); break;
+      case LE: result.append("<="); break;
+      case EQ: result.append("="); break;
+      case NE: result.append("!="); break;
+      case GE: result.append(">="); break;
+      case GT: result.append(">"); break;
+    }
+    return result.append(" ").append(getRightHandSide());
+  }
+
+  syn IlpString IlpBound.printIlp() {
+    IlpString result = new IlpString();
+    switch(getType()) {
+      case BINARY: result.append("0 <= ").append(getRef().getName()).append(" <= 1"); break;
+      case ZERO: result.append(getRef().getName()).append(" = 0"); break;
+      case GREATER_EQUAL_ZERO: result.append("0 <= ").append(getRef().getName()); break;
+      default: logger.error("Unknown IlpBound type {}", getType().toString());
+    }
+    return result;
+  }
+
+  syn IlpString IlpLeftHandSide.printIlp() {
+    IlpString result = new IlpString();
+    for (IlpTerm t : getIlpTermList()) {
+      if (t.getValue() >= 0) {
+        result.append(" +");
+      } else {
+        result.append(" ");
+      }
+      if (t.getValue() == -1) {
+        result.append("-");
+      } else if (t.getValue() != 1) {
+        result.append(t.getValue());
+      }
+      result.append(" ").append(t.getRef().getName());
+    }
+    return result;
+  }
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/Printing.jrag b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/Printing.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..0c099510277df60de2b8b7f7d6dfaaf87e9bfa6b
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/Printing.jrag
@@ -0,0 +1,8 @@
+aspect Printing {
+
+  eq ILP.print(MquatWriteSettings settings, int indentationLevel) {
+    // ILP should not be printed normally
+    return new MquatString(settings, indentationLevel);
+  }
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/simple/Construction.jadd b/jastadd-mquat-base/src/main/jastadd/solvers/simple/Construction.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..0fc4ba6291e4278a0e4e68a808ab93973faff876
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/simple/Construction.jadd
@@ -0,0 +1,56 @@
+aspect Construction {
+
+  /**
+   * Create a solution with no assignments and every resource in the model marked as free in the solution
+   *
+   * @param model the model to base the solution on
+   * @return a newly created solution, with not assignments
+   */
+  public static Solution Solution.emptySolutionOf(Root model) {
+    return new Solution(model,new List<>());
+  }
+
+  /**
+   * creates an assignment for the model given by the solution within it is called
+   *
+   * @param request
+   * @param component
+   * @return
+   */
+  public Assignment Solution.createSoftwareAssignment(Request request, Component component, boolean topLevel) {
+    Assignment assignment = new Assignment();
+    assignment.setRequest(request);
+    assignment.setTopLevel(topLevel);
+
+    // ignore resources here
+
+    // find the first impl
+    Implementation implementation = component.getImplementation(0);
+    assignment.setImplementation(implementation);
+
+    for (ComponentRequirement requirement : implementation.getComponentRequirementList()) {
+      for (Instance instance : requirement.getInstanceList()) {
+        assignment.addComponentMapping(new ComponentMapping(instance, createSoftwareAssignment(request, requirement.getComponentRef().getRef(), false)));
+      }
+    }
+
+    for (Instance instance : implementation.getResourceRequirement().getInstanceList()) {
+      assignment.setResourceMapping(new ResourceMapping(instance, null, new List<>()));
+    }
+
+    return assignment;
+  }
+
+  public static Solution Solution.createSoftwareSolution(Root model) {
+    Solution solution = new Solution();
+
+    solution.setModel(model);
+
+    for (Request request : model.getRequests()) {
+      solution.addAssignment(solution.createSoftwareAssignment(request, request.getTarget().getRef(), true));
+    }
+
+    return solution;
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/simple/Flushing.jadd b/jastadd-mquat-base/src/main/jastadd/solvers/simple/Flushing.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..9a0972daa9f5bffbfdbfd724752f6debd9f34748
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/simple/Flushing.jadd
@@ -0,0 +1,14 @@
+aspect Flushing {
+
+  // /**
+  //  * required for jastadd with caching
+  //  */
+  // public void Assignment.flushAssignmentUpwards() {
+  //   if (this.getParent() instanceof Assignment) {
+  //     Assignment parent = (Assignment) this.getParent();
+  //     parent.flushAssignmentUpwards();
+  //   }
+  //   flushCache();
+  // }
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/simple/Iterator.jadd b/jastadd-mquat-base/src/main/jastadd/solvers/simple/Iterator.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..bd4096d332fb1b5c1f53a4e19ed048313452eb35
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/simple/Iterator.jadd
@@ -0,0 +1,143 @@
+/**
+ *
+ */
+aspect Iterator {
+
+  /**
+   * Changes the solution to the next one (which may well be invalid)
+   *
+   * @return true, iff a new assignment could be found
+   */
+  public boolean Solution.nextSoftwareAssignment() {
+    return nextSoftwareAssignment(0);
+  }
+
+  private boolean Solution.nextSoftwareAssignment(int start) {
+
+    // try to get a next from the rest
+    if (start == this.getNumAssignment()) {
+      // if there is no rest, return false
+      return false;
+    } else if (nextSoftwareAssignment(start + 1)) {
+      // if this succeeds, return true
+      return true;
+    } else {
+
+      boolean nextResult = nextSoftwareAssignment(this.getAssignment(start));
+
+      if (!nextResult) {
+        // reset the rest
+        for (int i = start; i < this.getNumAssignment(); i++) {
+          Assignment oldAssignment = this.getAssignment(i);
+          Assignment newAssignment = createSoftwareAssignment(oldAssignment.getRequest(), oldAssignment.getRequest().getTarget().getRef(), oldAssignment.getTopLevel());
+          this.setAssignment(newAssignment, i);
+        }
+      } else {
+        for (int i = start + 1; i < this.getNumAssignment(); i++) {
+          Assignment oldAssignment = this.getAssignment(i);
+          Assignment newAssignment = createSoftwareAssignment(oldAssignment.getRequest(), oldAssignment.getRequest().getTarget().getRef(), oldAssignment.getTopLevel());
+          this.setAssignment(newAssignment, i);
+        }
+        // no need to flush, because only new assignments were added
+      }
+      return nextResult;
+    }
+  }
+
+  public boolean Solution.nextSoftwareAssignment(Assignment assignment) {
+
+    java.util.List<Instance> componentInstanceList = new ArrayList<>();
+    for (ComponentMapping mapping : assignment.getComponentMappingList()) {
+      componentInstanceList.add(mapping.getInstance());
+    }
+
+    boolean nextResult = nextSoftwareAssignment(assignment, componentInstanceList, 0);
+
+    if (!nextResult) {
+      for (int i = 0; i < assignment.getNumComponentMapping(); i++) {
+        Component requiredComponent = componentInstanceList.get(i).referringComponent();
+        Assignment newAssignment = this.createSoftwareAssignment(assignment.getRequest(), requiredComponent, false);
+        assignment.updateComponentMapping(componentInstanceList.get(i), newAssignment);
+      }
+      // no need to flush, this is done in the method call
+      return nextLocalSoftwareAssignment(assignment);
+    } else {
+      // // FLUSH
+      // assignment.flushTreeCache();
+      // assignment.flushAssignmentUpwards();
+      return true;
+    }
+  }
+
+  public boolean Solution.nextSoftwareAssignment(Assignment assignment, java.util.List<Instance> requiredInstances, int start) {
+
+    // try to get a next from the rest
+    if (start == assignment.getNumComponentMapping()) {
+      return false;
+    } else if (start < assignment.getNumComponentMapping() && nextSoftwareAssignment(assignment, requiredInstances, start + 1)) {
+      return true;
+    } else {
+      boolean nextResult = nextSoftwareAssignment(assignment.mappedAssignment(requiredInstances.get(start)));
+
+      if (!nextResult) {
+        // reset the rest
+        for (int i = start; i < assignment.getNumComponentMapping(); i++) {
+          Component requiredComponent = requiredInstances.get(i).referringComponent();
+          Assignment newAssignment = this.createSoftwareAssignment(assignment.getRequest(), requiredComponent, false);
+          assignment.updateComponentMapping(requiredInstances.get(i), newAssignment);
+        }
+      } else {
+        for (int i = start + 1; i < assignment.getNumComponentMapping(); i++) {
+          Component requiredComponent = requiredInstances.get(i).referringComponent();
+          Assignment newAssignment = this.createSoftwareAssignment(assignment.getRequest(), requiredComponent, false);
+          assignment.updateComponentMapping(requiredInstances.get(i), newAssignment);
+        }
+      }
+      // // FLUSH
+      // assignment.flushCache();
+      return nextResult;
+    }
+  }
+
+
+  private boolean Solution.nextLocalSoftwareAssignment(Assignment assignment) {
+
+    // then, look at a successor implementation
+    int pip = assignment.getImplementation().posInParent();
+    if (pip < assignment.getImplementation().containingComponent().getNumImplementation() - 1) {
+      // pick the first implementation
+      Implementation newImplementation = assignment.getImplementation().containingComponent().getImplementation(pip + 1);
+      assignment.setImplementation(newImplementation);
+
+      // the resourceRequirementAssignments change (even though just the keys are set.)
+      assignment.setResourceMapping(new ResourceMapping(newImplementation.getResourceRequirement().getInstance(0), null, new List<>()));
+
+      // the componentRequirementAssignments change!
+      assignment.setComponentMappingList(new List<>());
+      for (ComponentRequirement componentRequirement : newImplementation.getComponentRequirementList()) {
+        Component requiredComponent = componentRequirement.getComponentRef().getRef();
+        for (Instance instance : componentRequirement.getInstanceList()) {
+          assignment.addComponentMapping(new ComponentMapping(instance, createSoftwareAssignment(assignment.getRequest(), requiredComponent, false)));
+        }
+      }
+
+      // // FLUSH
+      // assignment.flushTreeCache();
+      // assignment.flushAssignmentUpwards();
+      return true;
+    }
+
+    return false;
+  }
+
+  public void Assignment.updateComponentMapping(Instance instance, Assignment assignment) {
+    for (ComponentMapping mapping : getComponentMappingList()) {
+      if (mapping.getInstance() == instance) {
+        mapping.setAssignment(assignment);
+        return;
+      }
+    }
+    addComponentMapping(new ComponentMapping(instance, assignment));
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/simple/Traversal.jadd b/jastadd-mquat-base/src/main/jastadd/solvers/simple/Traversal.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..a3d1151e14845d431cf979cfa0d2784ce9ac2484
--- /dev/null
+++ b/jastadd-mquat-base/src/main/jastadd/solvers/simple/Traversal.jadd
@@ -0,0 +1,72 @@
+aspect Traversal {
+
+  /**
+   * @return an iterator over all assignments in the solution
+   */
+  public Iterator<Assignment> Solution.assignmentIterator() {
+    return new Iterator<Assignment>() {
+
+      private Stack<Iterator<Assignment>> iteratorStack = new Stack<>();
+      {
+        iteratorStack.push(getAssignments().iterator());
+      }
+
+      @Override
+      public boolean hasNext() {
+        return !iteratorStack.isEmpty() && iteratorStack.peek().hasNext();
+      }
+
+      @Override
+      public Assignment next() {
+
+        // find current iterator
+        Iterator<Assignment> currentIterator = iteratorStack.peek();
+
+        if (currentIterator != null && currentIterator.hasNext()) {
+          Assignment currentAssignment = currentIterator.next();
+          Iterator<Assignment> nextIterator = currentAssignment.componentMappingIterator();
+          iteratorStack.push(nextIterator);
+
+          currentIterator = nextIterator;
+          while (currentIterator != null && !currentIterator.hasNext()) {
+            iteratorStack.pop();
+            currentIterator = iteratorStack.isEmpty() ? null : iteratorStack.peek();
+          }
+
+          return currentAssignment;
+        }
+
+        throw new NoSuchElementException();
+      }
+
+    };
+  }
+
+  /**
+   * @return an iterator over all component mappings of an assignment
+   */
+  public Iterator<Assignment> Assignment.componentMappingIterator() {
+    return new Iterator<Assignment>() {
+
+      private int index = 0;
+
+      @Override
+      public boolean hasNext() {
+        return index < getNumComponentMapping();
+      }
+
+      @Override
+      public Assignment next() {
+        if (hasNext()) {
+          Assignment result = getComponentMapping(index).getAssignment();
+          index++;
+          return result;
+        } else {
+          throw new NoSuchElementException();
+        }
+      }
+
+    };
+  }
+
+}
\ No newline at end of file
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/Main.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..82b6ee51045ce82dd00d4f2cdcb7bf856db49b8b
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/Main.java
@@ -0,0 +1,151 @@
+package de.tudresden.inf.st.mquat;
+
+import beaver.Parser;
+import de.tudresden.inf.st.mquat.deserializer.ASTNodeDeserializer;
+import de.tudresden.inf.st.mquat.generator.*;
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import de.tudresden.inf.st.mquat.jastadd.parser.MquatParser;
+import de.tudresden.inf.st.mquat.jastadd.scanner.MquatScanner;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.*;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Scanner;
+
+/**
+ * Main test entry point for jastadd-mquat.
+ * Created by rschoene on 11/01/17.
+ */
+@SuppressWarnings("unused")
+public class Main {
+
+  public static final ScenarioDescription SCENARIO_DESCRIPTION = new ScenarioDescription(2, 2, 0, 0, 0, 3, 2, 16, 2, 2, 0);
+
+  private static File getAbsoluteFileForLoading(String fileName) throws FileNotFoundException {
+    URL expUrl = Main.class.getClassLoader().getResource(fileName);
+    File file;
+    if (expUrl != null) {
+      file = new File(expUrl.getFile());
+    } else {
+      file = new File(fileName);
+    }
+    if (!file.exists()) {
+      throw new FileNotFoundException("Could not find file " + fileName);
+    }
+    return file;
+  }
+
+  private static Root load(String fileName) throws IOException, Parser.Exception {
+    File file = getAbsoluteFileForLoading(fileName);
+    if (fileName.endsWith(".json")) {
+      System.out.println("Loading JSON file '" + fileName + "'.");
+      return ASTNodeDeserializer.read(file);
+    } else {
+      System.out.println("Loading expression DSL file '" + fileName + "'.");
+      FileReader reader = new FileReader(file);
+      MquatScanner scanner = new MquatScanner(reader);
+      MquatParser parser = new MquatParser();
+      Root result = (Root) parser.parse(scanner);
+      parser.resolveReferences();
+      return result;
+    }
+  }
+
+  /**
+   * Print the node, and stores the output in a file.
+   * The file is created and truncated first, if needed.
+   * @param node     the node to print
+   * @param settings how to print the node (can be <code>null</code> if node is an ILP
+   * @param fileName where to store the output
+   */
+  public static void write(ASTNode<?> node, MquatWriteSettings settings, String fileName)
+          throws IOException {
+    String output;
+    if (node instanceof ILP) {
+      output = ((ILP) node).printIlp().toString();
+    } else {
+      output = node.print(settings).toString();
+    }
+    Path path = Paths.get(fileName);
+    System.out.println("Writing " + node.getClass().getSimpleName() + " to " + path.toAbsolutePath());
+    try (BufferedWriter writer = Files.newBufferedWriter(
+            path, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
+      writer.write(output);
+    }
+  }
+
+  private static void printFromProcess(Process process) {
+    try (Scanner s = new Scanner(process.getInputStream())) {
+      System.out.println(s.useDelimiter("\\A").hasNext() ? s.next() : "");
+    }
+    try (Scanner s = new Scanner(process.getErrorStream())) {
+      System.err.println(s.useDelimiter("\\A").hasNext() ? s.next() : "");
+    }
+  }
+
+  // required for the DrAST debugger
+  public static Object DrAST_root_node;
+
+  public static Optional<Root> loadModel(String fileName) {
+    try {
+      Root root = load(fileName);
+      // required for the DrAST debugger
+      DrAST_root_node = root;
+      System.out.println(root.info());
+      return Optional.of(root);
+    } catch (IOException | Parser.Exception e) {
+      e.printStackTrace();
+    }
+    return Optional.empty();
+  }
+
+  private static void checkParsedModel(Root parsedModel, File originalFile, MquatWriteSettings settings)
+      throws IOException, InterruptedException {
+    if (parsedModel == null) {
+      System.err.println("Passed model is null. Parsing failed!");
+      return;
+    }
+    String parsedFileName = originalFile.getAbsolutePath().replace(".txt", "-parsed.txt");
+    write(parsedModel, settings, parsedFileName);
+    Process process = Runtime.getRuntime().exec(
+        "diff --ignore-trailing-space " + originalFile.getAbsolutePath() + " " + parsedFileName);
+    int returnCode = process.waitFor();
+    if (returnCode == 0) {
+      System.out.println("Models match!");
+    } else {
+      printFromProcess(process);
+    }
+  }
+
+  private static Root generateNewModel(MquatWriteSettings settings, boolean printModel) throws IOException {
+    ScenarioGenerator generator = new ScenarioGenerator(SCENARIO_DESCRIPTION);
+    Root generatedModel = generator.generate();
+    if (printModel) {
+      System.out.println("---");
+      System.out.println(generatedModel.print(settings));
+    }
+    generator.printInfo();
+    write(generatedModel, settings, "src/main/resources/model-0.txt");
+    return generatedModel;
+  }
+
+  public static void main(String[] args) throws Exception {
+    Logger logger = LogManager.getLogger(Main.class);
+    logger.info("Starting base.Main");
+//    String fileName = args.length > 0 ? args[0] : "model-handmade.txt";
+//    Optional<Root> parsedModel = loadModel(fileName);
+//    checkParsedModel(parsedModel.orElseThrow(RuntimeException::new), getAbsoluteFileForLoading(fileName), settings);
+    ExtensibleScenarioGenerator esg = new ExtensibleScenarioGenerator();
+    esg.setDescription(SCENARIO_DESCRIPTION);
+    esg.setSerializer(new LoggingSerializer());
+    esg.generateModel();
+  }
+}
+
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/MainCheck.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/MainCheck.java
new file mode 100644
index 0000000000000000000000000000000000000000..c3054f7c66258a4f2b660a1c4e8496e9df2d69ea
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/MainCheck.java
@@ -0,0 +1,48 @@
+package de.tudresden.inf.st.mquat;
+
+import beaver.Parser;
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import de.tudresden.inf.st.mquat.jastadd.scanner.MquatScanner;
+import de.tudresden.inf.st.mquat.utils.ParserUtils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+/**
+ * TODO: Add description.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class MainCheck {
+
+  public static void main(String[] args) {
+    System.out.println(Arrays.toString(args));
+    if (args.length != 2) {
+      printUsage();
+      System.exit(1);
+    }
+    String modelFileName = args[0];
+    String solutionFileName = args[1];
+    Solution solution;
+    try {
+      Root model = ParserUtils.load(modelFileName);
+      solution = ParserUtils.loadSolution(solutionFileName, model);
+    } catch (IOException | Parser.Exception e) {
+      e.printStackTrace();
+      return;
+    }
+    MquatString out = solution.print(new MquatWriteSettings(" "));
+    System.out.println(out);
+    boolean isValid = solution.isValid();
+    double objectiveValue = solution.computeObjective();
+    System.out.println("Solution valid: " + Boolean.toString(isValid));
+    System.out.println("Objective value: " + objectiveValue);
+  }
+
+  private static void printUsage() {
+    System.out.println("Error. Need to be called with two arguments: ModelFile and SolutionFile!");
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/data/TestGeneratorSettings.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/data/TestGeneratorSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..34a0ce7c035fc90b3c06530e1c71e8d42b795c9f
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/data/TestGeneratorSettings.java
@@ -0,0 +1,49 @@
+package de.tudresden.inf.st.mquat.data;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_DEFAULT)
+public class TestGeneratorSettings {
+
+  public Boolean verbose = null;
+
+  public Integer minTopLevelComponents = null;
+  public Integer maxTopLevelComponents = null;
+
+  public Integer minAvgNumImplSubComponents = null;
+  public Integer maxAvgNumImplSubComponents = null;
+
+  public Integer minImplSubComponentDerivation = null;
+  public Integer maxImplSubComponentDerivation = null;
+
+  public Integer minAvgNumCompSubComponents = null;
+  public Integer maxAvgNumCompSubComponents = null;
+
+  public Integer minCompSubComponentDerivation = null;
+  public Integer maxCompSubComponentDerivation = null;
+
+  public Integer minComponentDepth = null;
+  public Integer maxComponentDepth = null;
+
+  public Integer minNumImplementations = null;
+  public Integer maxNumImplementations = null;
+
+  public Integer minRequests = null;
+  public Integer maxRequests = null;
+  public Integer stepRequests = null;
+
+  public Integer minCpus = null;
+  public Integer maxCpus = null;
+
+  public Double minResourceRatio = null;
+  public Double maxResourceRatio = null;
+  public Double stepResourceRatio = null;
+
+  public Integer timeoutValue = null;
+  public String timeoutUnit = null;
+
+  public Integer seed = null;
+
+  public Integer total = null;
+  public boolean shouldExitOnWarnings = true;
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/deserializer/ASTNodeDeserializer.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/deserializer/ASTNodeDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..45e0a9d6fef985a7e81e99063a8333b11adcbed9
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/deserializer/ASTNodeDeserializer.java
@@ -0,0 +1,247 @@
+package de.tudresden.inf.st.mquat.deserializer;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import de.tudresden.inf.st.mquat.jastadd.model.ASTNode;
+import de.tudresden.inf.st.mquat.jastadd.model.List;
+import de.tudresden.inf.st.mquat.jastadd.model.Opt;
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+
+/**
+ * Deserialize JSON into an ASTNode.
+ * Created by jm on 5/15/17.
+ */
+public class ASTNodeDeserializer extends StdDeserializer<ASTNode> {
+
+  public ASTNodeDeserializer() {
+    this(null);
+  }
+
+  public ASTNodeDeserializer(Class<?> vc) {
+    super(vc);
+  }
+
+  public static Root read(File file) {
+    ObjectMapper mapper = new ObjectMapper();
+    SimpleModule module = new SimpleModule();
+    module.addDeserializer(ASTNode.class, new ASTNodeDeserializer());
+    mapper.registerModule(module);
+
+    try {
+      ASTNode readValue = mapper.readValue(file, ASTNode.class);
+
+      if (readValue instanceof Root) {
+        return (Root) readValue;
+      } else {
+        throw new RuntimeException("Could not read a complete model");
+      }
+
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+    throw new RuntimeException("Could not read the model file " + file.getName());
+  }
+
+  @Override
+  public ASTNode deserialize(JsonParser jp, DeserializationContext ctxt)
+    throws IOException {
+
+    JsonNode node = jp.getCodec().readTree(jp);
+
+    return (ASTNode) deserializeObject(node);
+  }
+
+  private Object deserializeObject(JsonNode node) {
+    if (node.isObject()) {
+      String kind = node.get("k").asText();
+      switch (kind) {
+        case "NT":
+          return deserializeNonterminal(node);
+        case "List":
+          return deserializeList(node);
+        case "Opt":
+          return deserializeOpt(node);
+        case "t":
+          return deserializeTerminal(node);
+        case "enum":
+          return deserializeEnum(node);
+        default:
+          throw new DeserializationException("cannot deserialize node of unknown kind " + kind);
+      }
+    } else {
+      throw new DeserializationException("cannot deserialize non-object node as object node!");
+    }
+  }
+
+  private ASTNode deserializeNonterminal(JsonNode node) {
+
+    final String packageName = "de.tudresden.inf.st.mquat.jastadd.ast";
+
+    // get the type we want to create
+    String type = node.get("t").asText();
+    Class<?> typeClass;
+    try {
+      typeClass = Class.forName(packageName + "." + type);
+    } catch (ClassNotFoundException e) {
+      throw new DeserializationException("Unable to find class of type " + type + " in package " + packageName, e);
+    }
+
+    // create the instance
+    ASTNode instance;
+    try {
+      instance = (ASTNode) (typeClass.getConstructor().newInstance());
+    } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+      throw new DeserializationException("Unable to construct a nonterminal of type " + typeClass.getCanonicalName(), e);
+    }
+
+    // call every setter we have a field for
+    Iterator<String> f = node.get("c").fieldNames();
+    while (f.hasNext()) {
+      String fieldName = f.next();
+
+      // serialize the parameter
+      Object parameter = deserializeObject(node.get("c").get(fieldName));
+
+      // find the setter to call
+      boolean isList = node.get("c").get(fieldName).get("k").asText().equals("List");
+      boolean isOpt = node.get("c").get(fieldName).get("k").asText().equals("Opt");
+      // ... by getting its name
+      String setterName = "set" + fieldName + (isList ? "List" : "") + (isOpt ? "Opt" : "");
+      // ... and its type
+      Class<?> setterType;
+      if (isList) {
+        setterType = List.class;
+      } else if (isOpt) {
+        setterType = Opt.class;
+      } else {
+        setterType = parameter.getClass();
+      }
+      Class<?> originalSettType = setterType;
+
+      // get the method
+      Method method = null;
+
+      while(setterType != null && method == null) {
+        try {
+          method = typeClass.getMethod(setterName, setterType);
+        } catch (NoSuchMethodException e1) {
+          try {
+            if (setterType.equals(Integer.class)) {
+              method = typeClass.getMethod(setterName, int.class);
+            } else if (setterType.equals(Double.class)) {
+              method = typeClass.getMethod(setterName, double.class);
+            } else if (setterType.equals(Long.class)) {
+              method = typeClass.getMethod(setterName, long.class);
+            } else if (setterType.equals(Character.class)) {
+              method = typeClass.getMethod(setterName, char.class);
+            } else if (setterType.equals(Boolean.class)) {
+              method = typeClass.getMethod(setterName, boolean.class);
+            } else if (setterType.equals(Float.class)) {
+              method = typeClass.getMethod(setterName, float.class);
+            }
+            setterType = setterType.getSuperclass();
+          } catch (NoSuchMethodException e2) {
+            throw new DeserializationException("Unable to set value of " + fieldName + " with setter " + setterName, e2);
+          }
+        }
+      }
+      if (method == null) {
+        throw new DeserializationException("Unable to set value of " + fieldName + " with setter " + setterName + " of type " + originalSettType.getSimpleName() + "!");
+      }
+
+      // invoke the method on the instance with the parameter
+      try {
+        method.invoke(instance, parameter);
+      } catch (IllegalAccessException | InvocationTargetException e) {
+        throw new DeserializationException("Unable to set value of " + fieldName + " with setter " + setterName, e);
+      }
+    }
+
+    // finally, return the instance
+    return instance;
+  }
+
+  private ASTNode deserializeOpt(JsonNode node) {
+    if (node.has("c")) {
+      // opts can only contain Nonterminals
+      ASTNode value = deserializeNonterminal(node.get("c"));
+      return new Opt<ASTNode>(value);
+
+    } else {
+      return new Opt();
+    }
+  }
+
+  private Object deserializeTerminal(JsonNode node) {
+    // get the type name
+    String typeName = node.get("t").asText();
+
+    // first try the builtin types
+    switch (typeName) {
+      case "int":
+      case "Integer":
+        return node.get("v").asInt();
+      case "float":
+      case "Float":
+        return (float) node.get("v").asDouble();
+      case "boolean":
+      case "Boolean":
+        return node.get("v").asBoolean();
+      case "double":
+      case "Double":
+        return node.get("v").asDouble();
+      case "String":
+        return node.get("v").asText();
+      case "long":
+      case "Long":
+        return node.get("v").asLong();
+      default:
+        throw new DeserializationException("cannot create object of type " + typeName);
+    }
+  }
+
+  private Enum deserializeEnum(JsonNode node) {
+    // get the type name
+    String typeName = node.get("t").asText();
+
+    Class<?> type;
+    try {
+      type = Class.forName(typeName);
+    } catch (ClassNotFoundException e) {
+      throw new DeserializationException("cannot create enum of type " + typeName, e);
+    }
+
+    Method valueOf;
+    try {
+      valueOf = type.getMethod("valueOf", String.class);
+    } catch (NoSuchMethodException e) {
+      throw new DeserializationException("cannot call valueOf() on enum of type " + typeName, e);
+    }
+    try {
+      return (Enum) valueOf.invoke(null, node.get("v").asText());
+    } catch (IllegalAccessException | InvocationTargetException e) {
+      throw new DeserializationException("cannot call valueOf() on enum of type " + typeName, e);
+    }
+  }
+
+  private List deserializeList(JsonNode node) {
+    List<ASTNode> list = new List<>();
+    Iterator<JsonNode> it = node.get("c").elements();
+    while (it.hasNext()) {
+      JsonNode child = it.next();
+      // lists can only contain Nonterminals
+      list.add(deserializeNonterminal(child));
+    }
+    return list;
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/deserializer/DeserializationException.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/deserializer/DeserializationException.java
new file mode 100644
index 0000000000000000000000000000000000000000..084f1b9d403b03b91684acec2c4d7953a36ed74f
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/deserializer/DeserializationException.java
@@ -0,0 +1,22 @@
+package de.tudresden.inf.st.mquat.deserializer;
+
+public class DeserializationException extends RuntimeException {
+  public DeserializationException() {
+  }
+
+  public DeserializationException(String message) {
+    super(message);
+  }
+
+  public DeserializationException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public DeserializationException(Throwable cause) {
+    super(cause);
+  }
+
+  public DeserializationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+    super(message, cause, enableSuppression, writableStackTrace);
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ExtensibleScenarioGenerator.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ExtensibleScenarioGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b0bf8c2b21aa5032406c93851ec3eb2977af26d
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ExtensibleScenarioGenerator.java
@@ -0,0 +1,197 @@
+package de.tudresden.inf.st.mquat.generator;
+
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Generator for scenarios delegating the work to {@link ScenarioGenerator} and using a {@link ModelSerializer} to build custom models.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class ExtensibleScenarioGenerator {
+
+  private ModelSerializer serializer;
+  private ScenarioGenerator delegatee;
+
+  public ExtensibleScenarioGenerator() {
+    // empty
+  }
+
+  public ExtensibleScenarioGenerator(ModelSerializer serializer, ScenarioDescription description) {
+    setSerializer(serializer);
+    setDescription(description);
+  }
+
+  public void setSerializer(ModelSerializer serializer) {
+    this.serializer = serializer;
+  }
+
+  public void setDescription(ScenarioDescription description) {
+    this.delegatee = new ScenarioGenerator(description);
+  }
+
+  public void generateModel() throws Exception {
+    Objects.requireNonNull(serializer, "Serializer must be set!");
+    Objects.requireNonNull(delegatee, "Description must be set!");
+    serializer.initModel();
+    constructModel();
+    serializer.persistModel();
+  }
+
+  private void constructModel() {
+    Root model = delegatee.generate();
+    Map<ASTNode, Object> vertices = new HashMap<>();
+
+    // hwmodel
+    HardwareModel hwModel = model.getHardwareModel();
+    for (Property property : hwModel.getPropertyList()) {
+      vertices.put(property, serializer.createProperty(property));
+    }
+
+    for (ResourceType resourceType : hwModel.getResourceTypeList()) {
+      serializeResourceType(resourceType, vertices);
+    }
+
+    for (Resource resource : hwModel.getResourceList()) {
+      serializeResource(resource, vertices);
+    }
+    hwModel = null;
+
+    // swmodel
+    SoftwareModel swModel = model.getSoftwareModel();
+    for (MetaParameter mp : swModel.getMetaParameterList()) {
+      vertices.put(mp, serializer.createMetaParameter(mp));
+    }
+
+    for (Property property : swModel.getPropertyList()) {
+      vertices.put(property, serializer.createProperty(property));
+    }
+
+    for (Component component : swModel.getComponentList()) {
+      Object serializedComponent = serializer.createComponent(component);
+      vertices.put(component, serializedComponent);
+      for (Property property : component.getPropertyList()) {
+        vertices.put(property, serializer.createProperty(property));
+      }
+      for (PropertyRef propertyRef : component.getPropertyRefList()) {
+        serializer.createEdge("PropertyRef", serializedComponent, vertices.get(propertyRef.getRef()));
+      }
+    }
+
+    for (Implementation impl : model.allImplementations()) {
+      vertices.put(impl, serializer.createImplementation(impl));
+      for (ComponentRequirement cRequirement : impl.getComponentRequirementList()) {
+        Object serializedReq = serializer.createComponentRequirement();
+        serializer.createEdge("Component", serializedReq, vertices.get(cRequirement.getComponentRef().getRef()));
+        for (Instance instance : cRequirement.getInstanceList()) {
+          serializer.createEdge("Instance", serializedReq, serializer.createInstance(instance));
+        }
+      }
+      ResourceRequirement rRequirement = impl.getResourceRequirement();
+      Object serializedReq = serializer.createResourceRequirement();
+      serializer.createEdge("ResourceType", serializedReq, vertices.get(rRequirement.getResourceTypeRef().getRef()));
+      for (Instance instance : rRequirement.getInstanceList()) {
+        serializer.createEdge("Instance", serializedReq, serializer.createInstance(instance));
+      }
+      for (Clause clause : impl.getClauseList()) {
+        serializeClause(clause, vertices);
+      }
+    }
+
+    // requests
+    for (Request request : model.getRequestList()) {
+      Object serializedRequest = serializer.createRequest(request);
+      for (MetaParameterAssignment mpa : request.getMetaParameterAssignmentList()) {
+        serializer.createEdge("MetaParameter", serializer.createMetaParameterAssignment(), vertices.get(mpa.getMetaParameterRef().getRef()));
+      }
+      serializer.createEdge("Target", serializedRequest, vertices.get(request.getTarget().getRef()));
+      for (Clause clause : request.getConstraintList()) {
+        serializeClause(clause, vertices);
+      }
+    }
+
+    serializer.createEdge("Property", serializer.createObjective(model.getObjective()), model.getObjective().getPropertyRef().getRef());
+  }
+
+  private void serializeClause(Clause clause, Map<ASTNode, Object> vertices) {
+    Object serializedClause = serializer.createClause(clause);
+    serializer.createEdge("Designator", serializedClause, serializeDesignator(clause.getDesignator(), vertices));
+    serializer.createEdge("Expression", serializedClause, serializeExpression(clause.getExpression(), vertices));
+//    return serializedClause;
+  }
+
+  private Object serializeDesignator(Designator designator, Map<ASTNode, Object> vertices) {
+    Object serializedDesignator = serializer.createDesignator(designator);
+
+    // special handling for subclass
+    if (designator.isSoftwareDesignator()) {
+      SoftwareDesignator softwareDesignator = (SoftwareDesignator) designator;
+      serializer.createEdge("Property", serializedDesignator, vertices.get(softwareDesignator.getPropertyRef()));
+      if (softwareDesignator.hasInstanceRef()) {
+        serializer.createEdge("Instance", serializedDesignator, vertices.get(softwareDesignator.getInstanceRef().getRef()));
+      }
+    }
+
+    if (designator instanceof PropertyResourceDesignator) {
+      PropertyResourceDesignator propertyResourceDesignator = (PropertyResourceDesignator) designator;
+      serializer.createEdge("Property", serializedDesignator, vertices.get(propertyResourceDesignator.getPropertyRef()));
+      serializer.createEdge("Instance", serializedDesignator, vertices.get(propertyResourceDesignator.getInstanceRef().getRef()));
+    }
+
+    if (designator instanceof MetaParameterDesignator) {
+      serializer.createEdge("MetaParameter", serializedDesignator, vertices.get(((MetaParameterDesignator) designator).getMetaParameterRef().getRef()));
+    }
+
+    return serializedDesignator;
+  }
+
+  private Object serializeExpression(Expression expression, Map<ASTNode, Object> vertices) {
+    if (expression instanceof BinaryExpression) {
+      Object serializedExpression = serializer.createExpression(expression);
+      BinaryExpression binaryExpression = (BinaryExpression) expression;
+      Object left = serializer.createExpression(binaryExpression.getLeft());
+      Object right = serializer.createExpression(binaryExpression.getRight());
+      serializer.createEdge("Left", serializedExpression, left);
+      serializer.createEdge("Right", serializedExpression, right);
+      return serializedExpression;
+    } else if (expression instanceof Designator){
+      return serializeDesignator((Designator) expression, vertices);
+    } else if (expression instanceof LiteralExpression) {
+      return serializer.createLiteralExpression((LiteralExpression) expression);
+    } else {
+      throw new UnsupportedOperationException("Can not serialize " + expression);
+    }
+  }
+
+  private void serializeResourceType(ResourceType resourceType, Map<ASTNode, Object> vertices) {
+    Object serializedResourceType = serializer.createResourceType(resourceType);
+    vertices.put(resourceType, serializedResourceType);
+    for (Property property : resourceType.getPropertyList()) {
+      vertices.put(property, serializer.createProperty(property));
+    }
+    for (ResourceType subType : resourceType.getSubTypeList()) {
+      serializeResourceType(subType, vertices);
+    }
+    for (PropertyRef propertyRef : resourceType.getPropertyRefList()) {
+      serializer.createEdge("PropertyRef", serializedResourceType, vertices.get(propertyRef.getRef()));
+    }
+  }
+
+  private void serializeResource(Resource resource, Map<ASTNode, Object> vertices) {
+    Object serializedResource = serializer.createResource(resource);
+    vertices.put(resource, serializedResource);
+    for (CurrentResourceValue crv : resource.getCurrentResourceValueList()) {
+      Object serializedCrv = serializer.createCurrentResourceValue(crv);
+      vertices.put(crv, serializedCrv);
+      serializer.createEdge("PropertyRef", serializedCrv, vertices.get(crv.getPropertyRef().getRef()));
+    }
+    serializer.createEdge("Type", serializedResource, vertices.get(resource.getType().getRef()));
+    for (Resource subRes : resource.getSubResourceList()) {
+      serializeResource(subRes, vertices);
+    }
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/LoggingSerializer.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/LoggingSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9feff1f5cd0cb62c7f496e748995ec9caf45b9f
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/LoggingSerializer.java
@@ -0,0 +1,37 @@
+package de.tudresden.inf.st.mquat.generator;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.Map;
+
+/**
+ * Simple serializer logging out new nodes to a logger.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class LoggingSerializer extends ModelSerializer {
+
+  private Logger logger = LogManager.getLogger(LoggingSerializer.class);
+
+  @Override
+  public void initModel() {
+    logger.info("InitModel");
+  }
+
+  @Override
+  public void persistModel() {
+    logger.info("PersistModel");
+  }
+
+  @Override
+  protected Object createVertex(long id, String type, Map<String, ?> attributes) {
+    logger.info("CreateVertex (id={}, type={} attributes={})", id, type, attributes);
+    return id;
+  }
+
+  @Override
+  protected void createEdge(String label, Object from, Object to) {
+    logger.info("CreateEdge (label={}) from {} to {}", label, from, to);
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ModelSerializer.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ModelSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..809eebc1e97633535a8aab6b9b503ce684fafd7f
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ModelSerializer.java
@@ -0,0 +1,127 @@
+package de.tudresden.inf.st.mquat.generator;
+
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import de.tudresden.inf.st.mquat.utils.MapCreator;
+
+import java.util.Map;
+
+import static de.tudresden.inf.st.mquat.utils.MapCreator.e;
+
+/**
+ * Customized creation of models.
+ *
+ * @author rschoene - Initial contribution
+ */
+public abstract class ModelSerializer {
+
+  private long id;
+
+  public ModelSerializer() {
+    id = 0;
+  }
+
+  protected long getId() {
+    return id;
+  }
+
+  public abstract void initModel();
+
+  public abstract void persistModel();
+
+  public Object createProperty(Property property) {
+    return createVertex("Property", MapCreator.of(
+        e("Name", property.getName()),
+        e("Unit", property.getUnit())));
+  }
+
+  public Object createResourceType(ResourceType resourceType) {
+    return createVertex("ResourceType", MapCreator.of(
+        e("Name", resourceType.getName()),
+        e("Container", resourceType.getContainer())));
+  }
+
+  public Object createResource(Resource resource) {
+    return createVertex("Resource", MapCreator.of(
+        e("Name", resource.getName())));
+  }
+
+  public Object createCurrentResourceValue(CurrentResourceValue crv) {
+    return createVertex("CurrentResourceValue", MapCreator.of(
+        e("Value", crv.getValue().evalAsDouble())));
+  }
+
+  public Object createMetaParameter(MetaParameter metaParameter) {
+    return createVertex("MetaParameter", MapCreator.of(
+        e("Name", metaParameter.getName())));
+  }
+
+  public Object createComponent(Component component) {
+    return createVertex("Component", MapCreator.of(
+        e("Name", component.getName())));
+  }
+
+  public Object createImplementation(Implementation implementation) {
+    return createVertex("Implementation", MapCreator.of(
+        e("Name", implementation.getName())));
+  }
+
+  public Object createComponentRequirement() {
+    return createVertex("ComponentRequirement", MapCreator.of());
+  }
+
+  public Object createResourceRequirement() {
+    return createVertex("ResourceRequirement", MapCreator.of());
+  }
+
+  public Object createInstance(Instance instance) {
+    return createVertex("Instance", MapCreator.of(
+        e("Name", instance.getName())));
+  }
+
+  public Object createClause(Clause Clause) {
+    return createVertex("Clause", MapCreator.of(
+        e("ClauseType", Clause.getClauseType()),
+        e("ClauseComparator", Clause.getClauseComparator())));
+  }
+
+  public Object createDesignator(Designator designator) {
+    Object result = createVertex(designator.getClass().getSimpleName(), MapCreator.of());
+    if (designator instanceof QualifiedNameDesignator) {
+      throw new RuntimeException("Should not exist anymore: " + designator);
+    }
+    return result;
+  }
+
+  public Object createExpression(Expression expression) {
+    return createVertex(expression.getClass().getSimpleName(), MapCreator.of());
+  }
+
+  public Object createLiteralExpression(LiteralExpression expression) {
+    return createVertex("RealLiteralExpression", MapCreator.of(
+        e("Value", expression.getValue())));
+  }
+
+  public Object createRequest(Request request) {
+    return createVertex("Request", MapCreator.of(
+        e("Name", request.getName())));
+  }
+
+  public Object createMetaParameterAssignment() {
+    return createVertex("MetaParameterAssignment", MapCreator.of());
+  }
+
+  public Object createObjective(Objective objective) {
+    return createVertex("Objective", MapCreator.of(
+        e("Agg", objective.getAgg())));
+  }
+
+  // TODO add and use parent parameter
+  public final Object createVertex(final String type, final Map<String, ?> attributes) {
+    return createVertex(id++, type, attributes);
+  }
+
+  protected abstract Object createVertex(long id, String type, Map<String, ?> attributes);
+
+  protected abstract void createEdge(String label, Object from, Object to);
+
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ScenarioDescription.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ScenarioDescription.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e476cc4648e1cefdcbea580e86d5936c268a0d5
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ScenarioDescription.java
@@ -0,0 +1,49 @@
+package de.tudresden.inf.st.mquat.generator;
+
+/**
+ * A class to contain all scenario parameter for the problem domain
+ *
+ * @author rschoene - Initial contribution
+ */
+public class ScenarioDescription {
+  public final long seed;
+  public final int avgNumImplSubComponents;
+  public final int implSubComponentStdDerivation;
+  public final int avgNumCompSubComponents;
+  public final int compSubComponentStdDerivation;
+  public final int numImplementations;
+  public final double excessComputeResourceRatio;
+  public final int numRequests;
+  public final int numTopLevelComponents;
+  public final int componentDepth;
+  public final int numCpus;
+
+  /**
+   * A class to contain all scenario parameter for the problem domain
+   *
+   * @param numTopLevelComponents          the amount of components that are used in requests
+   * @param avgNumImplSubComponents        the average number of required components each implementation in every level except the last
+   * @param implSubComponentStdDerivation  the standard derivation of the average number of components for an implementation
+   * @param avgNumCompSubComponents        the average number of required components each component in every level except the last
+   * @param compSubComponentStdDerivation  the standard derivation of the average number of components for a component
+   * @param componentDepth                 the depth of the required component tree
+   * @param numImplementations             the amount of numImplementations for each component
+   * @param excessComputeResourceRatio     the factor of how many more compute nodes there are than required
+   * @param numRequests                    the amount of requests
+   * @param numCpus                        the number of CPUs per component
+   * @param seed                           the random seed used to get the numbers
+   */
+  public ScenarioDescription(int numTopLevelComponents, int avgNumImplSubComponents, int implSubComponentStdDerivation, int avgNumCompSubComponents, int compSubComponentStdDerivation, int componentDepth, int numImplementations, double excessComputeResourceRatio, int numRequests, int numCpus, long seed) {
+    this.numTopLevelComponents = numTopLevelComponents;
+    this.avgNumImplSubComponents = avgNumImplSubComponents;
+    this.implSubComponentStdDerivation = implSubComponentStdDerivation;
+    this.avgNumCompSubComponents = avgNumCompSubComponents;
+    this.compSubComponentStdDerivation = compSubComponentStdDerivation;
+    this.numImplementations = numImplementations;
+    this.componentDepth = componentDepth;
+    this.excessComputeResourceRatio = excessComputeResourceRatio;
+    this.numRequests = numRequests;
+    this.numCpus = numCpus;
+    this.seed = seed;
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ScenarioGenerator.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ScenarioGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..6588645ffe48cdb1d1b5c7a498f0cbfa25f674b6
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/generator/ScenarioGenerator.java
@@ -0,0 +1,689 @@
+package de.tudresden.inf.st.mquat.generator;
+
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Random;
+
+public class ScenarioGenerator {
+
+  // ranges for random variables
+  private static final int cpu_freq_min = 500;
+  private static final int cpu_freq_max = 3000;
+  private static final int total_ram_min = 500;
+  private static final int total_ram_max = 16000;
+  private static final int total_disk_min = 500;
+  private static final int total_disk_max = 16000;
+  private static final int latency_min = 1;
+  private static final int latency_max = 1000;
+  private static final int throughput_min = 10;
+  private static final int throughput_max = 100000;
+  private static final int request_size_min = 1;
+  private static final int request_size_max = 1000;
+  private static final int quality_min = 0;
+  private static final int quality_max = 100;
+  private final ScenarioDescription description;
+  private final Logger logger;
+  private Solution initialSolution;
+  private Random random;
+  private int resourceCounter = 0;
+
+  /**
+   * A class to generate scalable scenarios for the Optaplanner domain
+   *
+   * @param description the configuration
+   */
+  public ScenarioGenerator(ScenarioDescription description) {
+    this.description = description;
+    this.logger = LogManager.getLogger(ScenarioGenerator.class);
+    random = new Random();
+  }
+
+  public Solution getInitialSolution() {
+    return initialSolution;
+  }
+
+//  private double getAverageComponentTreeSize() {
+//    // (N^L-1) / (N-1)
+//    return (Math.pow(getAvgNumSubComponents(), getComponentDepth()) - 1) / (getAvgNumSubComponents() - 1);
+//  }
+
+  private int nextRandomInt(int from, int to) {
+    return from + random.nextInt(to - from + 1);
+  }
+
+  private int nextRandomGaussianInt(double mean, double derivation) {
+    if (Math.round(derivation) == 0) {
+      return (int) Math.round(mean);
+    }
+    double result;
+    do {
+      result = random.nextGaussian() * derivation + mean;
+    } while (result < 0);
+    return (int) Math.round(result);
+  }
+
+  public int getNumTopLevelComponents() {
+    return description.numTopLevelComponents;
+  }
+
+  public int getAvgNumImplSubComponents() {
+    return description.avgNumImplSubComponents;
+  }
+
+  public int getImplSubComponentStdDerivation() {
+    return description.implSubComponentStdDerivation;
+  }
+
+  public int getAvgNumCompSubComponents() {
+    return description.avgNumCompSubComponents;
+  }
+
+  public int getCompSubComponentStdDerivation() {
+    return description.compSubComponentStdDerivation;
+  }
+
+  public int getNumImplementations() {
+    return description.numImplementations;
+  }
+
+//  public int getNumModes() {
+//    return description.numModes;
+//  }
+
+  public double getExcessResourceRatio() {
+    return description.excessComputeResourceRatio;
+  }
+
+  public int getNumRequests() {
+    return description.numRequests;
+  }
+
+  public int getComponentDepth() {
+    return description.componentDepth;
+  }
+
+  public int getNumCpus() {
+    return description.numCpus;
+  }
+
+  public long getSeed() {
+    return description.seed;
+  }
+
+  public void printInfo() {
+//    logger.info("Scenario ID:                                 {}", getId());
+    logger.info("Number of top-level components:              {}", getNumTopLevelComponents());
+    logger.info("Average number of impl sub-components:       {}", getAvgNumImplSubComponents());
+    logger.info("Standard derivation of impl sub-components:  {}", getImplSubComponentStdDerivation());
+    logger.info("Average number of comp sub-components:       {}", getAvgNumCompSubComponents());
+    logger.info("Standard derivation of comp sub-components:  {}", getCompSubComponentStdDerivation());
+    logger.info("Component tree depth:                        {}", getComponentDepth());
+    logger.info("Number of implementations per component:     {}", getNumImplementations());
+    logger.info("Excess compute resource ratio:               {}", getExcessResourceRatio());
+    logger.info("Number cpus per compute resource:            {}", getNumCpus());
+//    logger.info("Minimum number of required resources:        {}", getAverageComponentTreeSize() * getNumRequests());
+    logger.info("Number of requests:                          {}", getNumRequests());
+    logger.info("Seed:                                        {}", getSeed());
+//    logger.info("Total number of configurations:              {}", getAverageComponentTreeSize() * getNumImplementations() * getNumModes() * getNumTopLevelComponents());
+  }
+
+  /**
+   * generates the Jastadd model with the given seed of the object
+   *
+   * @return a Jastadd model with one guaranteed solution
+   */
+  public Root generate() {
+
+    // reset the random seed to ensure reproducibility
+    random.setSeed(getSeed());
+
+    // generate the overall structure of the model
+    Root root = new Root();
+    HardwareModel hardwareModel = Root.createSimpleHardwareModel();
+    root.setHardwareModel(hardwareModel);
+    SoftwareModel softwareModel = new SoftwareModel();
+    root.setSoftwareModel(softwareModel);
+
+    // create the meta parameters
+    MetaParameter sizeMetaParameter = new MetaParameter(new Name("size"));
+    softwareModel.addMetaParameter(sizeMetaParameter);
+
+//    Property[] nfp = new Property[getNumNfp()];
+//    softwareModel.setPropertyList(new List<>());
+//    for (int i=0; i < getNumNfp(); i++) {
+//      nfp[i] = new Property(new Name("nfp" + String.valueOf(i)), "", PropertyKind.DERIVED);
+//      softwareModel.addProperty(nfp[i]);
+//    }
+
+    // add two nonfunctional properties energy and quality
+    Property energyProperty = new Property(new Name("energy"), "J");
+    Property qualityProperty = new Property(new Name("quality"), "%");
+    softwareModel.addProperty(energyProperty);
+    softwareModel.addProperty(qualityProperty);
+
+    // create the top-level components
+    Component[] components = new Component[getNumTopLevelComponents()];
+    for (int currentTopLevelComponent = 0; currentTopLevelComponent < getNumTopLevelComponents(); currentTopLevelComponent++) {
+      Component component = createComponent(root, String.valueOf(currentTopLevelComponent), getComponentDepth());
+      components[currentTopLevelComponent] = component;
+    }
+
+    // create the requests
+    for (int i = 0; i < getNumRequests(); i++) {
+      int requestSize = nextRandomInt(request_size_min, request_size_max);
+      Request request = new Request();
+      request.addMetaParameterAssignment(new MetaParameterAssignment(sizeMetaParameter.createRef(), new LiteralExpression(requestSize)));
+      request.setTarget(components[i % getNumTopLevelComponents()].createRef());
+
+      // add some constraints
+      Clause qualityClause = new Clause(
+          ClauseType.REQUIRING,
+          new SoftwareDesignator(
+              new Opt<>(),
+              qualityProperty.createRef()
+          ),
+          ClauseComparator.GE,
+          new LiteralExpression(nextRandomInt(quality_min, quality_max))
+      );
+      request.addConstraint(qualityClause);
+
+      root.addRequest(request);
+
+    }
+
+    Objective objective = new Objective(energyProperty.createRef(), PropertyAggregation.SUM);
+    root.setObjective(objective);
+
+    // we need to make sure the rewrites do not result in faulty caches! HELP US, RACR!
+    root.flushTreeCache();
+    this.initialSolution = sanitize(root);
+
+    root.flushTreeCache();
+
+    // generate the excess resources
+    if (getExcessResourceRatio() < 1) {
+      throw new RuntimeException("Cannot generate a model with less resources than are required by the guaranteed solution!");
+    }
+    long totalResources = Math.round(getExcessResourceRatio() * hardwareModel.getNumResource());
+    for (long i = hardwareModel.getNumResource() + 1; i <= totalResources; i++) {
+      hardwareModel.addResource(createResource(root));
+    }
+
+    // shuffle the resources
+    java.util.List<Resource> resourceJavaList = new ArrayList<>(root.getHardwareModel().getResourceList().asJavaCollection());
+    root.getHardwareModel().setResourceList(new List<>());
+    Collections.shuffle(resourceJavaList, random);
+    for (Resource resource : resourceJavaList) {
+      root.getHardwareModel().addResource(resource);
+    }
+    root.flushTreeCache();
+
+    return root;
+  }
+
+  private Resource createResource(Root model) {
+    int i = resourceCounter;
+    resourceCounter++;
+
+    HardwareModel hardwareModel = model.getHardwareModel();
+
+    ResourceType type = hardwareModel.computeResourceType();
+    ResourceType cpuType = hardwareModel.cpuType();
+    ResourceType ramType = hardwareModel.ramType();
+    ResourceType diskType = hardwareModel.diskType();
+    ResourceType networkType = hardwareModel.networkType();
+
+    Property frequency = cpuType.findPropertyByName("frequency");
+    Property load = cpuType.findPropertyByName("load");
+    Property total = ramType.findPropertyByName("total");
+    Property free = ramType.findPropertyByName("free");
+    Property throughput = networkType.findPropertyByName("throughput");
+    Property latency = networkType.findPropertyByName("latency");
+
+    // create a new resource
+    Resource resource = new Resource(new Name("resource" + String.valueOf(i)), type.createRef(), new List<>(), new List<>());
+    // add subresources
+    // there are multiple cpus
+    for (int numCpu = 0; numCpu < getNumCpus(); numCpu++) {
+      Resource cpu1 = new Resource(new Name("cpu" + String.valueOf(i) + "_" + String.valueOf(numCpu)), cpuType.createRef(), new List<>(), new List<>());
+      int currentFrequency = nextRandomInt(cpu_freq_min, cpu_freq_max);
+      cpu1.addCurrentResourceValue(new CurrentResourceValue(frequency.createRef(), new LiteralExpression(currentFrequency)));
+      cpu1.addCurrentResourceValue(new CurrentResourceValue(load.createRef(), new LiteralExpression(0)));
+      resource.addSubResource(cpu1);
+    }
+    Resource ram1 = new Resource(new Name("ram" + String.valueOf(i)), ramType.createRef(), new List<>(), new List<>());
+    int currentRam = nextRandomInt(total_ram_min, total_ram_max);
+    ram1.addCurrentResourceValue(new CurrentResourceValue(total.createRef(), new LiteralExpression(currentRam)));
+    ram1.addCurrentResourceValue(new CurrentResourceValue(free.createRef(), new LiteralExpression(currentRam)));
+    resource.addSubResource(ram1);
+    Resource disk1 = new Resource(new Name("disk" + String.valueOf(i)), diskType.createRef(), new List<>(), new List<>());
+    int currentDisk = nextRandomInt(total_disk_min, total_disk_max);
+    disk1.addCurrentResourceValue(new CurrentResourceValue(total.createRef(), new LiteralExpression(currentDisk)));
+    disk1.addCurrentResourceValue(new CurrentResourceValue(free.createRef(), new LiteralExpression(currentDisk)));
+    resource.addSubResource(disk1);
+    Resource network1 = new Resource(new Name("network" + String.valueOf(i)), networkType.createRef(), new List<>(), new List<>());
+    int currentThroughput = nextRandomInt(throughput_min, throughput_max);
+    int currentLatency = nextRandomInt(latency_min, latency_max);
+    network1.addCurrentResourceValue(new CurrentResourceValue(latency.createRef(), new LiteralExpression(currentLatency)));
+    network1.addCurrentResourceValue(new CurrentResourceValue(throughput.createRef(), new LiteralExpression(currentThroughput)));
+    resource.addSubResource(network1);
+    return resource;
+  }
+
+  /**
+   * creates a component and adds it to the given model.
+   *
+   * @param model       The model all (recursively) created components are added to
+   * @param componentId the component id, something like "1_2_3"
+   * @param depth       the depth of the component subtree
+   * @return the directy created component. This is required for dependency tracking in recursive calls.
+   */
+  private Component createComponent(Root model, String componentId, int depth) {
+    Component component = new Component();
+    component.setName(new Name("component_" + componentId));
+    model.getSoftwareModel().addComponent(component);
+
+    // get the ResourceTypes we need
+    ResourceType cpu = model.getHardwareModel().findResourceTypeByName("ComputeNode").findSubResourceTypeByName("CPU");
+    ResourceType ram = model.getHardwareModel().findResourceTypeByName("ComputeNode").findSubResourceTypeByName("RAM");
+    ResourceType disk = model.getHardwareModel().findResourceTypeByName("ComputeNode").findSubResourceTypeByName("DISK");
+    ResourceType network = model.getHardwareModel().findResourceTypeByName("ComputeNode").findSubResourceTypeByName("NETWORK");
+
+    // get the properties we need
+    assert cpu != null;
+    assert ram != null;
+    assert network != null;
+    assert disk != null;
+
+    Property frequency = cpu.findPropertyByName("frequency");
+    Property total = ram.findPropertyByName("total");
+    Property throughput = network.findPropertyByName("throughput");
+    Property quality = model.getSoftwareModel().findPropertyByName("quality");
+    Property energy = model.getSoftwareModel().findPropertyByName("energy");
+//    Property flops = model.getHardwareModel().getResourceType(0).getPropertyByName("flops");
+
+    component.addPropertyRef(quality.createRef());
+    component.addPropertyRef(energy.createRef());
+
+    // create the component requirements
+//    java.util.List<Clause> clauseList = new java.util.ArrayList<>();
+//    java.util.List<ComponentRequirement> componentRequirementList = new java.util.ArrayList<>();
+    java.util.List<Component> componentList = new java.util.ArrayList<>();
+
+    // if the component has a depth above one, it has references to two sub-components
+    if (depth > 1) {
+      for (int currentSubComponent = 0; currentSubComponent < nextRandomGaussianInt(getAvgNumCompSubComponents(), getCompSubComponentStdDerivation());
+           currentSubComponent++) {
+
+        // recursive call
+        Component subComponent = createComponent(model,
+            componentId + "c" + currentSubComponent, depth - 1);
+
+        componentList.add(subComponent);
+
+//        // an instance is needed, otherwise no requirements can be properly written
+//        Instance componentInstance = new Instance(new Name("the_" + subComponent.getName().getName()));
+//
+//        ComponentRequirement requirement = new ComponentRequirement();
+//        requirement.setComponentRef(subComponent.createRef());
+//        requirement.addInstance(componentInstance);
+//
+//        // add required quality clause to implementation
+//        Clause qualityClause = new Clause();
+//        qualityClause.setDesignator(new SoftwareDesignator(new Opt<>(componentInstance.createRef()), quality.createRef()));
+//        qualityClause.setClauseType(ClauseType.REQUIRING);
+//        qualityClause.setClauseComparator(ClauseComparator.GE);
+//        int randQuality = nextRandomInt(quality_min, quality_max);
+//        qualityClause.setExpression(new LiteralExpression(randQuality));
+//        clauseList.add(qualityClause);
+//
+//        componentRequirementList.add(requirement);
+      }
+    }
+
+    for (int currentImplementation = 0; currentImplementation < getNumImplementations(); currentImplementation++) {
+      Implementation implementation = new Implementation();
+
+      if (depth > 1) {
+        for (int currentSubComponent = 0; currentSubComponent < nextRandomGaussianInt(getAvgNumCompSubComponents(), getCompSubComponentStdDerivation());
+             currentSubComponent++) {
+          Component subComponent = componentList.get(currentSubComponent);
+          // an instance is needed, otherwise no requirements can be properly written
+          Instance componentInstance = new Instance(new Name("the_" + subComponent.getName().getName()));
+
+          ComponentRequirement requirement = new ComponentRequirement();
+          requirement.setComponentRef(subComponent.createRef());
+          requirement.addInstance(componentInstance);
+
+          // add required quality clause to implementation
+          Clause qualityClause = new Clause();
+          qualityClause.setDesignator(new SoftwareDesignator(new Opt<>(componentInstance.createRef()), quality.createRef()));
+          qualityClause.setClauseType(ClauseType.REQUIRING);
+          qualityClause.setClauseComparator(ClauseComparator.GE);
+          int randQuality = nextRandomInt(quality_min, quality_max);
+          qualityClause.setExpression(new LiteralExpression(randQuality));
+          implementation.addClause(qualityClause);
+
+          implementation.addComponentRequirement(requirement);
+        }
+      }
+
+      String implementationId = componentId + "i" + currentImplementation;
+      implementation.setName(new Name("implementation_" + implementationId));
+
+
+      // add the compute resource requirement
+      ResourceRequirement computeReqirement = new ResourceRequirement();
+      computeReqirement.setResourceTypeRef(model.getHardwareModel().getResourceType(0).createRef());
+      Instance computeInstance = new Instance(new Name("compute_resource_0"));
+      computeReqirement.addInstance(computeInstance);
+      implementation.setResourceRequirement(computeReqirement);
+
+      // there are multiple cpus possible
+      Instance[] cpuInstances = new Instance[getNumCpus()];
+      ResourceRequirement cpuRequirement = new ResourceRequirement();
+      cpuRequirement.setResourceTypeRef(cpu.createRef());
+      for (int numCpu = 0; numCpu < getNumCpus(); numCpu++) {
+        Instance cpuInstance = new Instance(new Name("cpu_" + numCpu));
+        cpuRequirement.addInstance(cpuInstance);
+        cpuInstances[numCpu] = cpuInstance;
+      }
+      computeReqirement.addResourceRequirement(cpuRequirement);
+      ResourceRequirement ramRequirement = new ResourceRequirement();
+      ramRequirement.setResourceTypeRef(ram.createRef());
+      Instance ram1 = new Instance(new Name("ram_1"));
+      ramRequirement.addInstance(ram1);
+      computeReqirement.addResourceRequirement(ramRequirement);
+      ResourceRequirement diskRequirement = new ResourceRequirement();
+      diskRequirement.setResourceTypeRef(disk.createRef());
+      Instance disk1 = new Instance(new Name("disk_1"));
+      diskRequirement.addInstance(disk1);
+      computeReqirement.addResourceRequirement(diskRequirement);
+      ResourceRequirement networkRequirement = new ResourceRequirement();
+      networkRequirement.setResourceTypeRef(network.createRef());
+      Instance network1 = new Instance(new Name("network_1"));
+      networkRequirement.addInstance(network1);
+      computeReqirement.addResourceRequirement(networkRequirement);
+
+      component.addImplementation(implementation);
+
+      // if the implementation has a depth above one, it has references to two sub-components
+      if (depth > 1) {
+        for (int currentSubComponent = 0; currentSubComponent < nextRandomGaussianInt(getAvgNumImplSubComponents(), getImplSubComponentStdDerivation());
+             currentSubComponent++) {
+          ComponentRequirement requirement = new ComponentRequirement();
+
+          // recursive call
+          Component subComponent = createComponent(model,
+              componentId + "i" + currentImplementation + "_" + currentSubComponent, depth - 1);
+
+          requirement.setComponentRef(subComponent.createRef());
+
+          // an instance is needed, otherwise no requirements can be properly written
+          Instance componentInstance = new Instance(new Name("the_" + subComponent.getName().getName()));
+          requirement.addInstance(componentInstance);
+
+          // add required quality clause to implementation
+          Clause qualityClause = new Clause();
+          qualityClause.setDesignator(new SoftwareDesignator(new Opt<>(componentInstance.createRef()), quality.createRef()));
+          qualityClause.setClauseType(ClauseType.REQUIRING);
+          qualityClause.setClauseComparator(ClauseComparator.GE);
+          int randQuality = nextRandomInt(quality_min, quality_max);
+          qualityClause.setExpression(new LiteralExpression(randQuality));
+          implementation.addClause(qualityClause);
+
+          implementation.addComponentRequirement(requirement);
+        }
+      }
+
+      int randFreq = nextRandomInt(cpu_freq_min, cpu_freq_max);
+      int randRam = nextRandomInt(total_ram_min, total_ram_max);
+      int randDisk = nextRandomInt(total_disk_min, total_disk_max);
+      int randThroughput = nextRandomInt(throughput_min, throughput_max);
+      int randQuality = nextRandomInt(quality_min, quality_max);
+
+      // add the requiring hardware clauses
+      // there are multiple cpus possible
+      for (int numCpu = 0; numCpu < getNumCpus(); numCpu++) {
+        Clause cpuClause = new Clause(
+            ClauseType.REQUIRING,
+            new PropertyResourceDesignator(cpuInstances[numCpu].createRef(), frequency.createRef()),
+            ClauseComparator.GE,
+            new LiteralExpression(randFreq)
+        );
+        implementation.addClause(cpuClause);
+      }
+      Clause ramClause = new Clause(
+          ClauseType.REQUIRING,
+          new PropertyResourceDesignator(ram1.createRef(), total.createRef()),
+          ClauseComparator.GE,
+          new LiteralExpression(randRam)
+      );
+      implementation.addClause(ramClause);
+      Clause diskClause = new Clause(
+          ClauseType.REQUIRING,
+          new PropertyResourceDesignator(disk1.createRef(), total.createRef()),
+          ClauseComparator.GE, new LiteralExpression(randDisk)
+      );
+      implementation.addClause(diskClause);
+      Clause networkClause = new Clause(
+          ClauseType.REQUIRING,
+          new PropertyResourceDesignator(network1.createRef(), throughput.createRef()),
+          ClauseComparator.GE,
+          new LiteralExpression(randThroughput)
+      );
+      implementation.addClause(networkClause);
+
+      // add flops provision clause
+
+      // build an expression adding all cpu frequencies
+      Expression cpuExpression = new PropertyResourceDesignator(cpuInstances[0].createRef(), frequency.createRef());
+      for (int currentCpu = 1; currentCpu < getNumCpus(); currentCpu++) {
+        cpuExpression = new AddExpression(
+            cpuExpression,
+            new PropertyResourceDesignator(cpuInstances[currentCpu].createRef(), frequency.createRef())
+        );
+      }
+
+
+//        Clause flopsClause = new Clause(
+//            ClauseType.PROVIDING,
+//            new SoftwareDesignator(new Opt<>(), flops.createRef()),
+//            // new PropertyResourceDesignator(computeInstance.createRef(), flops.createRef()),
+//            ClauseComparator.EQ,
+//            cpuExpression
+//        );
+//        configuration.addClause(flopsClause);
+
+      // add the providing software clauses
+      Clause qualityClause = new Clause(
+          ClauseType.PROVIDING,
+          new SoftwareDesignator(new Opt<>(), quality.createRef()),
+          ClauseComparator.EQ,
+          new LiteralExpression(randQuality)
+      );
+      implementation.addClause(qualityClause);
+      // return 0.1*size^2 - 0.3*cpu.frequency
+      double factor1 = Math.round(random.nextDouble() * 100) / 100d;
+      double factor2 = Math.round(random.nextDouble() * 100) / 100d;
+      MetaParameterRef sizeRef = model.getSoftwareModel().getMetaParameter(0).createRef();
+      Clause energyClause = new Clause(
+          ClauseType.PROVIDING,
+          new SoftwareDesignator(new Opt<>(), energy.createRef()),
+          ClauseComparator.EQ,
+          new AddExpression(
+              new MultExpression(
+                  new LiteralExpression(factor1),
+                  new PowerExpression(
+                      new MetaParameterDesignator(sizeRef),
+                      new LiteralExpression(2)
+                  )
+              ),
+              new MultExpression(
+                  new LiteralExpression(factor2),
+                  cpuExpression
+              )
+          )
+      );
+      implementation.addClause(energyClause);
+
+    }
+
+    return component;
+  }
+
+  private Solution sanitize(Root model) {
+    Solution solution = new Solution();
+    solution.setModel(model);
+
+    for (Request request : model.getRequests()) {
+
+      // get the size of the request
+      int quality = (int) request.getConstraintValueByName("quality");
+
+      // fix the tree for the given request
+      sanitize(request, request.getTarget().getRef(), quality, solution, true);
+    }
+
+    return solution;
+  }
+
+  private Assignment sanitize(Request request, Component component, int quality, Solution solution, boolean isTopLevel) {
+
+    Root model = solution.getModel();
+
+    ResourceType computeType = model.getHardwareModel().getResourceType(0);
+    ResourceType cpuType = model.getHardwareModel().getResourceType(0).findSubResourceTypeByName("CPU");
+    ResourceType ramType = model.getHardwareModel().getResourceType(0).findSubResourceTypeByName("RAM");
+    ResourceType diskType = model.getHardwareModel().getResourceType(0).findSubResourceTypeByName("DISK");
+    ResourceType networkType = model.getHardwareModel().getResourceType(0).findSubResourceTypeByName("NETWORK");
+
+    Assignment currentAssignment = new Assignment();
+    currentAssignment.setTopLevel(isTopLevel);
+    currentAssignment.setRequest(request);
+
+    // pick an arbitrary implementation
+    Implementation implementation = component.getImplementation(random.nextInt(component.getNumImplementation()));
+    currentAssignment.setImplementation(implementation);
+
+
+    // add a new resource to allocate the current component to
+    Resource resource = createResource(model);
+    model.getHardwareModel().addResource(resource);
+    currentAssignment.setResourceMapping(new ResourceMapping(currentAssignment.getImplementation().getResourceRequirement().getInstance(0), resource, new List<>()));
+
+    // do the recursive assignment of dependent components
+    for (ComponentRequirement componentRequirement : implementation.getComponentRequirementList()) {
+      for (Instance requiredInstance : componentRequirement.getInstanceList()) {
+        int newQualityValue = 0;
+
+        // find the clause in the implementation that references the instance get the quality from it
+        for (Clause clause : implementation.getClauseList()) {
+          if (clause.isRequiringClause()) {
+            if (clause.getDesignator().isSoftwareDesignator()) {
+              if (clause.getDesignator().asSoftwareDesignator().getInstanceRef().getRef() == requiredInstance) {
+                newQualityValue = (int) clause.getExpression().evalAsDouble();
+              }
+            }
+          }
+        }
+        Assignment assignmentReference = sanitize(request, componentRequirement.getComponentRef().getRef(), newQualityValue, solution, false);
+        currentAssignment.addComponentMapping(new ComponentMapping(requiredInstance, assignmentReference));
+      }
+    }
+
+    // set the provided quality of the configuration
+    for (Clause clause : implementation.getClauseList()) {
+      if (clause.isProvidingClause()
+          && clause.getDesignator().simpleName().equals("quality")) {
+        if (logger.isTraceEnabled()) {
+          logger.trace("set quality value from {} to {}", clause.getExpression().evalAsDouble(), quality);
+        }
+        clause.setExpression(new LiteralExpression(Math.max((int) clause.getExpression().evalAsDouble(), quality)));
+      }
+    }
+
+    // get the hardware requirements
+    Instance computeInstance = null;
+    ResourceRequirement rr = implementation.getResourceRequirement();
+    if (rr.getResourceTypeRef().getRef().equals(computeType)) {
+      computeInstance = rr.getInstance(0);
+    }
+
+
+    int frequencyValue[] = new int[getNumCpus()];
+    Instance cpuInstance[] = new Instance[getNumCpus()];
+    for (int currentCPU = 0; currentCPU < getNumCpus(); currentCPU++) {
+      frequencyValue[currentCPU] = (int) implementation.getRequiringClauseValue(cpuType, "frequency") + 1;
+      cpuInstance[currentCPU] = implementation.getRequiringClauseInstance(cpuType, "frequency", currentCPU);
+    }
+
+    int totalRamValue = (int) implementation.getRequiringClauseValue(ramType, "total") + 1;
+    Instance ramInstance = implementation.getRequiringClauseInstance(ramType, "total");
+    int totalDiskValue = (int) implementation.getRequiringClauseValue(diskType, "total") + 1;
+    Instance diskInstance = implementation.getRequiringClauseInstance(diskType, "total");
+    int networkThroughputValue = (int) implementation.getRequiringClauseValue(networkType, "throughput") + 1;
+    Instance networkInstance = implementation.getRequiringClauseInstance(networkType, "throughput");
+
+    // put the compute resource into the assignment
+    ResourceMapping computeResourceMapping = new ResourceMapping();
+    computeResourceMapping.setInstance(computeInstance);
+    computeResourceMapping.setResource(resource);
+    currentAssignment.setResourceMapping(computeResourceMapping);
+
+    // set the values
+    int currentCpu = 0;
+    for (Resource sub : resource.getSubResourceList()) {
+      if (sub.getType().getRef().equals(cpuType)) {
+        for (CurrentResourceValue value : sub.getCurrentResourceValueList()) {
+          if (value.getPropertyRef().getRef().getName().getName().equals("frequency")) {
+            computeResourceMapping.addResourceMapping(new ResourceMapping(cpuInstance[currentCpu], sub, new List<>()));
+            if (logger.isTraceEnabled()) {
+              logger.trace("set frequency value from {} to {}", value.getValue().evalAsDouble(), frequencyValue[currentCpu]);
+            }
+            value.setValue(new LiteralExpression(frequencyValue[currentCpu]));
+            currentCpu++;
+          }
+        }
+      } else if (sub.getType().getRef().equals(ramType)) {
+        setTotalStorageValue(computeResourceMapping, totalRamValue, ramInstance, sub);
+        computeResourceMapping.addResourceMapping(new ResourceMapping(ramInstance, sub, new List<>()));
+      } else if (sub.getType().getRef().equals(diskType)) {
+        setTotalStorageValue(computeResourceMapping, totalDiskValue, diskInstance, sub);
+        computeResourceMapping.addResourceMapping(new ResourceMapping(diskInstance, sub, new List<>()));
+      } else if (sub.getType().getRef().equals(networkType)) {
+        for (CurrentResourceValue value : sub.getCurrentResourceValueList()) {
+          if (value.getPropertyRef().getRef().getName().getName().equals("throughput")) {
+            computeResourceMapping.addResourceMapping(new ResourceMapping(networkInstance, sub, new List<>()));
+            if (logger.isTraceEnabled()) {
+              logger.trace("set throughput value from {} to {}", value.getValue().evalAsDouble(), networkThroughputValue);
+            }
+            value.setValue(new LiteralExpression(networkThroughputValue));
+          }
+        }
+      }
+    }
+
+    // finally, add the current assignment if it is a top-level assignment
+    if (isTopLevel) {
+      solution.addAssignment(currentAssignment);
+    }
+    return currentAssignment;
+
+  }
+
+  private void setTotalStorageValue(ResourceMapping computeResourceMapping, int totalStorageValue, Instance storageInstance, Resource sub) {
+    for (CurrentResourceValue value : sub.getCurrentResourceValueList()) {
+      String resourceName = value.getPropertyRef().getRef().getName().getName();
+      if (resourceName.equals("total") || resourceName.equals("free")) {
+        value.setValue(new LiteralExpression(totalStorageValue));
+      }
+    }
+  }
+
+
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/jastadd/model/Tuple.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/jastadd/model/Tuple.java
new file mode 100644
index 0000000000000000000000000000000000000000..4df2d7d2f7e21c965e6157a1580bb3953d2d1a14
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/jastadd/model/Tuple.java
@@ -0,0 +1,21 @@
+package de.tudresden.inf.st.mquat.jastadd.model;
+
+import java.util.AbstractMap;
+
+public class Tuple<T1, T2> extends AbstractMap.SimpleEntry<T1, T2> {
+  public Tuple(T1 firstElement, T2 secondElement) {
+    super(firstElement, secondElement);
+  }
+
+  public static <T1, T2> Tuple<T1, T2> of(T1 firstElement, T2 secondElement) {
+    return new Tuple<>(firstElement, secondElement);
+  }
+
+  public T1 getFirstElement() {
+    return getKey();
+  }
+
+  public T2 getSecondElement() {
+    return getValue();
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/parser/MquatParserHelper.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/parser/MquatParserHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a15ceb83dd396a4c5fe7bd6605ce90c36625602
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/parser/MquatParserHelper.java
@@ -0,0 +1,167 @@
+package de.tudresden.inf.st.mquat.parser;
+
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Resolving names while parsing model and solution files.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class MquatParserHelper {
+
+  private Logger logger = LogManager.getLogger(MquatParserHelper.class);
+  // create new fields for references
+  public Map<String, Instance> instanceMap = new HashMap<>();
+  public Map<String, Component> componentMap = new HashMap<>();
+  public Map<String, Property> propertyMap = new HashMap<>();
+  public Map<String, ResourceType> resourceTypeMap = new HashMap<>();
+  public Map<String, MetaParameter> metaParameterMap = new HashMap<>();
+  public java.util.List<InstanceRef> instanceRefList = new ArrayList<>();
+  public java.util.List<ComponentRef> componentRefList = new ArrayList<>();
+  public java.util.List<PropertyRef> propertyRefList = new ArrayList<>();
+  public java.util.List<ResourceTypeRef> resourceTypeRefList = new ArrayList<>();
+  public java.util.List<MetaParameterRef> metaParameterRefList = new ArrayList<>();
+
+  // references to be resolved for solution
+  // assignment -> (requestName|instanceName, implName)
+  public Map<Assignment, Tuple<String, String>> assignmentTerminals = new HashMap<>();
+  // resource mapping -> (instanceName, resourceName)
+  public Map<ResourceMapping, Tuple<String, String>> resourceMappingTerminals = new HashMap<>();
+  public Solution unfinishedSolution;
+
+  interface RefToName<RefType> {
+    String getName(RefType ref);
+  }
+  interface SetRef<RefType, RealType> {
+    void setRef(RefType ref, RealType resolved);
+  }
+
+  private <RefType, RealType> void resolve(
+      java.util.List<RefType> refList,
+      Map<String, RealType> refMap,
+      RefToName<RefType> rtn,
+      SetRef<RefType, RealType> sr) {
+    for (RefType ref : refList) {
+      RealType resolved = refMap.get(rtn.getName(ref));
+      if (resolved == null) {
+        logger.warn("reference in {} '{}' cannot be resolved",
+            ref.getClass().getSimpleName(), rtn.getName(ref));
+      }
+      sr.setRef(ref, resolved);
+    }
+  }
+
+  /**
+   * Post processing step after parsing a model, to resolve all references within the model.
+   * @throws java.util.NoSuchElementException if a reference can not be resolved
+   */
+  public void resolveReferences() {
+    resolve(instanceRefList, instanceMap, ref -> ref.getName().getName(), InstanceRef::setRef);
+    resolve(componentRefList, componentMap, ref -> ref.getName().getName(), ComponentRef::setRef);
+    resolve(propertyRefList, propertyMap, ref -> ref.getName().getName(), PropertyRef::setRef);
+    resolve(resourceTypeRefList, resourceTypeMap, ref -> ref.getName().getName(), ResourceTypeRef::setRef);
+    resolve(metaParameterRefList, metaParameterMap, ref -> ref.getName().getName(), MetaParameterRef::setRef);
+  }
+
+  private void resolveResourceMappingOf(Assignment assignment) {
+    ResourceMapping rm = assignment.getResourceMapping();
+    Implementation impl = assignment.getImplementation();
+    Tuple<String, String> tuple = resourceMappingTerminals.get(rm);
+    // first name in tuple is instance name
+    // resolve instance using implementation of assignment
+    Instance instance = impl.findInstanceByName(tuple.getFirstElement());
+    rm.setInstance(instance);
+    // second name in tuple is resource name
+    // resolve top-level resource using model
+    Resource container = impl.root().findResourceByName(tuple.getSecondElement());
+    rm.setResource(container);
+    ResourceRequirement rr = instance.containingResourceRequirement();
+    for (ResourceMapping subResMapping : rm.getResourceMappingList()) {
+      resolveSubResourceMapping(subResMapping, container, rr);
+    }
+  }
+
+  private void resolveSubResourceMapping(ResourceMapping rm, Resource container, ResourceRequirement rr) {
+    // resolve sub-resource using the top-level resource, and the corresponding resource requirement
+    Tuple<String, String> tuple = resourceMappingTerminals.get(rm);
+    // first name in tuple is instance name
+    Instance instance = rr.findInstanceByName(tuple.getFirstElement());
+    rm.setInstance(instance);
+    // second name in tuple is resource name
+    Resource resource = container.findResourceByName(tuple.getSecondElement());
+    rm.setResource(resource);
+    if (rm.getNumResourceMapping() > 0) {
+      ResourceRequirement subResReq = instance.containingResourceRequirement();
+      for (ResourceMapping subResMapping : rm.getResourceMappingList()) {
+        resolveSubResourceMapping(subResMapping, resource, subResReq);
+      }
+    }
+  }
+
+  /**
+   * Post processing step after parsing a solution, to resolve all references.
+   * @param model the model to resolve the references
+   * @throws RuntimeException if assignments are malformed
+   * @throws java.util.NoSuchElementException if a reference can not be resolved
+   */
+  public void resolveSolutionReferencesWith(Root model) {
+    this.unfinishedSolution.setModel(model);
+    // first set request names for all top-level assignments
+    for (Assignment assignment : unfinishedSolution.getAssignmentList()) {
+      Tuple<String, String> value = assignmentTerminals.get(assignment);
+      // first name in value is request name
+      Request request = model.findRequestByName(value.getFirstElement());
+      assignment.setRequest(request);
+      // second name in value is impl name
+      Implementation impl = model.findImplementationByName(value.getSecondElement());
+      assignment.setImplementation(impl);
+      resolveResourceMappingOf(assignment);
+    }
+    // now iterate over nested assignments, i.e., non-top-level
+    for (Map.Entry<Assignment, Tuple<String, String>> entry : assignmentTerminals.entrySet()) {
+      Assignment assignment = entry.getKey();
+      if (assignment.getTopLevel()) {
+        continue;
+      }
+      Request request = null;
+      Assignment parentAssignment = assignment;  // start with this assignment
+      java.util.List<Assignment> assignmentsWithoutRequest = new java.util.ArrayList<>();
+      assignmentsWithoutRequest.add(assignment);
+      while (request == null) {
+        ComponentMapping cm = parentAssignment.containingComponentMapping();
+        if (cm == null) {
+          throw new RuntimeException("Assignment has no parent");
+        }
+        parentAssignment = cm.containingAssignment();
+        if (parentAssignment == null) {
+          // should never happen
+          throw new RuntimeException("ComponentMapping has no parent");
+        }
+        request = parentAssignment.getRequest();
+        if (request == null) {
+          assignmentsWithoutRequest.add(parentAssignment);
+        }
+      }
+      // set request for all assignments found "on the way up"
+      for (Assignment assignmentWithoutRequest : assignmentsWithoutRequest) {
+        assignmentWithoutRequest.setRequest(request);
+      }
+      // first name in value is name of instance, set it for component mapping
+      ComponentMapping cm = assignment.containingComponentMapping();
+      // to find correct instance, we need to start at implementation of parentAssignment
+      parentAssignment = cm.containingAssignment();
+      cm.setInstance(parentAssignment.getImplementation().findInstanceByName(entry.getValue().getFirstElement()));
+      // second name in value is name of impl
+      Implementation impl = model.findImplementationByName(entry.getValue().getSecondElement());
+      assignment.setImplementation(impl);
+      resolveResourceMappingOf(assignment);
+    }
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/ASTNodeSerializer.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/ASTNodeSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe5d1ecd8da12d33e5de05445fc06f1b355c1e90
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/ASTNodeSerializer.java
@@ -0,0 +1,59 @@
+package de.tudresden.inf.st.mquat.serializer;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import de.tudresden.inf.st.mquat.jastadd.model.ASTNode;
+import de.tudresden.inf.st.mquat.jastadd.model.ASTNodeAnnotation;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class ASTNodeSerializer extends StdSerializer<ASTNode> {
+
+  public ASTNodeSerializer() {
+    this(null);
+  }
+
+  public ASTNodeSerializer(Class<ASTNode> t) {
+    super(t);
+  }
+
+  @Override
+  public void serialize(
+    ASTNode value, JsonGenerator jgen, SerializerProvider provider)
+    throws IOException {
+
+    jgen.writeStartObject();
+    jgen.writeStringField("k", "NT");
+    jgen.writeStringField("t", value.getClass().getSimpleName());
+    jgen.writeObjectFieldStart("c");
+    for (Method m : value.getClass().getMethods()) {
+      try {
+        if (m.getAnnotation(ASTNodeAnnotation.Child.class) != null) {
+          jgen.writeFieldName(m.getAnnotation(ASTNodeAnnotation.Child.class).name());
+          provider.defaultSerializeValue(m.invoke(value), jgen);
+        } else if (m.getAnnotation(ASTNodeAnnotation.Token.class) != null) {
+          jgen.writeFieldName(m.getAnnotation(ASTNodeAnnotation.Token.class).name());
+          jgen.writeStartObject();
+          jgen.writeStringField("k", m.getReturnType().isEnum() ? "enum" : "t");
+          jgen.writeStringField("t", m.getReturnType().getName());
+          jgen.writeFieldName("v");
+          provider.defaultSerializeValue(m.invoke(value), jgen);
+          jgen.writeEndObject();
+        } else if (m.getAnnotation(ASTNodeAnnotation.ListChild.class) != null) {
+          jgen.writeFieldName(m.getAnnotation(ASTNodeAnnotation.ListChild.class).name());
+          provider.defaultSerializeValue(m.invoke(value), jgen);
+        } else if (m.getAnnotation(ASTNodeAnnotation.OptChild.class) != null) {
+          jgen.writeFieldName(m.getAnnotation(ASTNodeAnnotation.OptChild.class).name());
+          provider.defaultSerializeValue(m.invoke(value), jgen);
+        }
+      } catch (IllegalAccessException | InvocationTargetException e) {
+        e.printStackTrace();
+      }
+    }
+    jgen.writeEndObject();
+    jgen.writeEndObject();
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/JsonSerializer.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/JsonSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a6e35af6d3f9ec7fe2656de9b36c9462f3f1696
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/JsonSerializer.java
@@ -0,0 +1,34 @@
+package de.tudresden.inf.st.mquat.serializer;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import de.tudresden.inf.st.mquat.jastadd.model.ASTNode;
+import de.tudresden.inf.st.mquat.jastadd.model.List;
+import de.tudresden.inf.st.mquat.jastadd.model.Opt;
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+
+import java.io.File;
+import java.io.IOException;
+
+public class JsonSerializer {
+
+  public static void write(Root r, String fileName) {
+    ObjectMapper mapper = new ObjectMapper();
+    mapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
+    mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+    SimpleModule module = new SimpleModule();
+    module.addSerializer(ASTNode.class, new ASTNodeSerializer());
+    module.addSerializer(List.class, new ListSerializer());
+    module.addSerializer(Opt.class, new OptSerializer());
+    mapper.registerModule(module);
+
+    try {
+      mapper.writeValue(new File(fileName), r);
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/ListSerializer.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/ListSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..7051dd9124d3a5b481d2e05ebfe90bc4be2cf7ed
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/ListSerializer.java
@@ -0,0 +1,36 @@
+package de.tudresden.inf.st.mquat.serializer;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import de.tudresden.inf.st.mquat.jastadd.model.ASTNode;
+import de.tudresden.inf.st.mquat.jastadd.model.List;
+
+import java.io.IOException;
+
+public class ListSerializer extends StdSerializer<List> {
+
+  public ListSerializer() {
+    this(null);
+  }
+
+  public ListSerializer(Class<List> t) {
+    super(t);
+  }
+
+  @Override
+  public void serialize(
+    List value, JsonGenerator jgen, SerializerProvider provider)
+    throws IOException {
+
+    jgen.writeStartObject();
+    jgen.writeStringField("k", "List");
+    jgen.writeArrayFieldStart("c");
+    // unchecked cast, because otherwise class clash when adding serializer
+    for (ASTNode child : ((List<ASTNode>) value).astChildren()) {
+      provider.defaultSerializeValue(child, jgen);
+    }
+    jgen.writeEndArray();
+    jgen.writeEndObject();
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/OptSerializer.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/OptSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..979f20c51f2dfec5fe9c76932300090826b78543
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/serializer/OptSerializer.java
@@ -0,0 +1,37 @@
+package de.tudresden.inf.st.mquat.serializer;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import de.tudresden.inf.st.mquat.jastadd.model.ASTNode;
+import de.tudresden.inf.st.mquat.jastadd.model.Opt;
+
+import java.io.IOException;
+
+public class OptSerializer extends StdSerializer<Opt> {
+
+  public OptSerializer() {
+    this(null);
+  }
+
+  public OptSerializer(Class<Opt> t) {
+    super(t);
+  }
+
+  @Override
+  public void serialize(
+    Opt value, JsonGenerator jgen, SerializerProvider provider)
+    throws IOException {
+
+    jgen.writeStartObject();
+    jgen.writeStringField("k", "Opt");
+    if (value.getNumChild() > 0) {
+      jgen.writeFieldName("c");
+      // unchecked cast, because otherwise class clash when adding serializer
+      for (ASTNode child : ((Opt<ASTNode>) value).astChildren()) {
+        provider.defaultSerializeValue(child, jgen);
+      }
+    }
+    jgen.writeEndObject();
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/LoggingProxyForStdOut.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/LoggingProxyForStdOut.java
new file mode 100644
index 0000000000000000000000000000000000000000..818012ce5bc583b6cd71d45dae7279a56864e2dd
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/LoggingProxyForStdOut.java
@@ -0,0 +1,37 @@
+package de.tudresden.inf.st.mquat.utils;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Logger;
+
+import java.io.PrintStream;
+
+public class LoggingProxyForStdOut extends PrintStream {
+
+  private final PrintStream formerOut;
+  private final Logger logger;
+  private final Level logLevel;
+
+  public LoggingProxyForStdOut(Logger logger, Level logLevel) {
+    super(System.out);
+    this.formerOut = System.out;
+    this.logger = logger;
+    this.logLevel = logLevel;
+    System.setOut(this);
+  }
+
+  @Override
+  public void print(final String x) {
+    logger.log(logLevel, x);
+  }
+
+  @Override
+  public void println(String x) {
+    logger.log(logLevel, x);
+  }
+
+  @Override
+  public void close() {
+    System.setOut(formerOut);
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/MapCreator.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/MapCreator.java
new file mode 100644
index 0000000000000000000000000000000000000000..07d456c7ee440700a69b3da1ffea1ebe7c911548
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/MapCreator.java
@@ -0,0 +1,30 @@
+package de.tudresden.inf.st.mquat.utils;
+
+import java.util.AbstractMap;
+import java.util.Collections;
+import java.util.Map;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Helper class to create immutable maps.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class MapCreator {
+
+  public static <K, V> Map.Entry<K, V> e(K key, V value) {
+    return new AbstractMap.SimpleEntry<>(key, value);
+  }
+
+  private static <K, V> Collector<Map.Entry<K, V>, ?, Map<K, V>> entriesToMap() {
+        return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue);
+    }
+
+  @SafeVarargs
+  public static <K, V> Map<K, V> of(Map.Entry<K, V>... entries) {
+    return Collections.unmodifiableMap(Stream.of(entries)
+        .collect(entriesToMap()));
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/ParserUtils.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/ParserUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5388256a9921d534b3af7a79440aafc27bbc700
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/ParserUtils.java
@@ -0,0 +1,104 @@
+package de.tudresden.inf.st.mquat.utils;
+
+import beaver.Parser;
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+import de.tudresden.inf.st.mquat.jastadd.model.Solution;
+import de.tudresden.inf.st.mquat.jastadd.parser.MquatParser;
+import de.tudresden.inf.st.mquat.jastadd.scanner.MquatScanner;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Objects;
+
+/**
+ * Utility methods involving scanner and parser of the models.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class ParserUtils {
+
+  /**
+   * Loads a model in a local file with the given path.
+   * @param fileName path to the file, either absolute, or relative to the current directory
+   * @return the parsed model
+   * @throws IOException if the file could not be found, or opened
+   * @throws Parser.Exception if the file contains a malformed model
+   */
+  public static Root load(String fileName) throws IOException, Parser.Exception {
+    return load(fileName, null);
+  }
+
+  /**
+   * Loads a model in a file with the given path.
+   * Resolving of relative paths depends on the value of clazz.
+   * @param fileName  path to the file, either absolute, or relative.
+   * @param clazz     {@code null} to search relative to current directory, otherwise search relative to resources location of given class
+   * @return the parsed model
+   * @throws IOException if the file could not be found, or opened
+   * @throws Parser.Exception if the file contains a malformed model
+   */
+  public static Root load(String fileName, Class<?> clazz) throws IOException, Parser.Exception {
+    System.out.println("Loading model DSL file '" + fileName + "'.");
+    Reader reader = clazz == null ? getLocalReaderFor(fileName) : getClassReaderFor(fileName, clazz);
+    MquatScanner scanner = new MquatScanner(reader);
+    MquatParser parser = new MquatParser();
+    Root result = (Root) parser.parse(scanner);
+    parser.resolveReferences();
+    reader.close();
+    return result;
+  }
+
+  /**
+   * Loads a solution in a local file with the given path.
+   * @param fileName  path to the file, either absolute, or relative to the current directory
+   * @param model     the referenced model
+   * @return the parsed solution
+   * @throws IOException if the file could not be found, or opened
+   * @throws Parser.Exception if the file contains a malformed model
+   */
+  public static Solution loadSolution(String fileName, Root model) throws IOException, Parser.Exception {
+    return loadSolution(fileName, model, null);
+  }
+
+  /**
+   * Loads a solution in a file with the given path.
+   * Resolving of relative paths depends on the value of clazz.
+   * @param fileName  path to the file, either absolute, or relative
+   * @param model     the referenced model
+   * @param clazz     {@code null} to search relative to current directory, otherwise search relative to resources location of given class
+   * @return the parsed solution
+   * @throws IOException if the file could not be found, or opened
+   * @throws Parser.Exception if the file contains a malformed model
+   */
+  public static Solution loadSolution(String fileName, Root model, Class<?> clazz) throws IOException, Parser.Exception {
+    System.out.println("Loading solution DSL file '" + fileName + "'.");
+    Reader reader = clazz == null ? getLocalReaderFor(fileName) : getClassReaderFor(fileName, clazz);
+    MquatScanner scanner = new MquatScanner(reader);
+    MquatParser parser = new MquatParser();
+    Solution result = (Solution) parser.parse(scanner, MquatParser.AltGoals.solution);
+    parser.resolveSolutionReferencesWith(model);
+    reader.close();
+    return result;
+  }
+
+  private static Reader getClassReaderFor(String fileName, Class<?> clazz) throws IOException {
+    URL url = clazz.getClassLoader().getResource(fileName);
+    return new BufferedReader(new InputStreamReader(
+        Objects.requireNonNull(url, "Could not open file " + fileName)
+            .openStream()));
+  }
+
+  private static Reader getLocalReaderFor(String fileName) throws IOException {
+    try {
+      return Files.newBufferedReader(Paths.get(fileName));
+    } catch (IOException e) {
+      System.out.println("Error. Searching at" + Paths.get(fileName).toAbsolutePath());
+      throw e;
+    }
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/ScenarioGeneratorConsumer.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/ScenarioGeneratorConsumer.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b815879b94745bca6d0b10ce2ab3b346ea16993
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/ScenarioGeneratorConsumer.java
@@ -0,0 +1,13 @@
+package de.tudresden.inf.st.mquat.utils;
+
+import de.tudresden.inf.st.mquat.generator.ScenarioGenerator;
+
+public interface ScenarioGeneratorConsumer {
+  /**
+   * Do something with the scenario generator. Return whether to move on with further generation.
+   * @param gen    the generator to work with
+   * @param testId the current number of test
+   * @return <code>false</code> to stop generation, <code>true</code> to move on
+   */
+  boolean run(ScenarioGenerator gen, int testId);
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/StaticSettings.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/StaticSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..32ecd9f8575107401bdb8e62605a4e5e6ef75d2c
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/StaticSettings.java
@@ -0,0 +1,35 @@
+package de.tudresden.inf.st.mquat.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Settings specific to solvers using attributes.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class StaticSettings {
+
+  private static StaticSettings theInstance;
+  private Map<String, Object> values;
+
+  private StaticSettings() {
+    values = new HashMap<>();
+  }
+
+  public static StaticSettings getInstance() {
+    if (theInstance == null) {
+      theInstance = new StaticSettings();
+    }
+    return theInstance;
+  }
+
+  public static void put(String key, Object value) {
+    getInstance().values.put(key, value);
+  }
+
+  public static Object get(String key) {
+    return getInstance().values.get(key);
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/StopWatch.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/StopWatch.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5cd7604cba85dea9b75fdf79c30689a02106359
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/StopWatch.java
@@ -0,0 +1,42 @@
+package de.tudresden.inf.st.mquat.utils;
+
+import java.util.concurrent.TimeUnit;
+
+public class StopWatch {
+  private long starts;
+
+  /**
+   * Starts a measurement.
+   * @return a new StopWatch
+   */
+  public static StopWatch start() {
+    return new StopWatch();
+  }
+
+  private StopWatch() {
+    reset();
+  }
+
+  /**
+   * Restarts the measurement.
+   */
+  public StopWatch reset() {
+    starts = System.nanoTime();
+    return this;
+  }
+
+  /**
+   * @return elapsed time in nanoseconds
+   */
+  public long time() {
+    long ends = System.nanoTime();
+    return ends - starts;
+  }
+
+  /**
+   * @return elapsed time in the given TimeUnit
+   */
+  public long time(TimeUnit unit) {
+    return unit.convert(time(), TimeUnit.NANOSECONDS);
+  }
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/TestGenerator.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/TestGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..2eaad7e15d00fa3c24b91f10f2ff611aca7efc31
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/TestGenerator.java
@@ -0,0 +1,169 @@
+package de.tudresden.inf.st.mquat.utils;
+
+import de.tudresden.inf.st.mquat.data.TestGeneratorSettings;
+import de.tudresden.inf.st.mquat.generator.ScenarioDescription;
+import de.tudresden.inf.st.mquat.generator.ScenarioGenerator;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * Creates a number of ScenarioGenerators by iterating the range of each parameter.
+ */
+public class TestGenerator {
+  private TestGeneratorSettings settings;
+
+  private Logger logger;
+
+  public TestGenerator() {
+    logger = LogManager.getLogger(TestGenerator.class);
+  }
+
+  public TestGenerator(TestGeneratorSettings settings) {
+    this();
+    setSettings(settings);
+  }
+
+  public int generateScenarioGenerator(ScenarioGeneratorConsumer consumer) {
+    if (hasWarnings() && settings.shouldExitOnWarnings) {
+      logger.error("Exiting because of previous warnings.");
+      return 0;
+    }
+    int testId = 0;
+    for (int tlc = settings.minTopLevelComponents; tlc <= settings.maxTopLevelComponents; tlc++) {
+      for (int iac = settings.minAvgNumImplSubComponents; iac <= settings.maxAvgNumImplSubComponents; iac++) {
+        for (int isd = settings.minImplSubComponentDerivation; isd <= settings.maxImplSubComponentDerivation; isd++) {
+          for (int cac = settings.minAvgNumCompSubComponents; cac <= settings.maxAvgNumCompSubComponents; cac++) {
+            for (int csd = settings.minCompSubComponentDerivation; csd <= settings.maxCompSubComponentDerivation; csd++) {
+              for (int dep = settings.minComponentDepth; dep <= settings.maxComponentDepth; dep++) {
+                for (int imp = settings.minNumImplementations; imp <= settings.maxNumImplementations; imp++) {
+                  for (double res = settings.minResourceRatio; res <= settings.maxResourceRatio; res += settings.stepResourceRatio) {
+                    for (int req = settings.minRequests; req <= settings.maxRequests; req += settings.stepRequests) {
+                      for (int cpu = settings.minCpus; cpu <= settings.maxCpus; cpu++) {
+                        if (settings.verbose) {
+                          logger.debug(
+                              "Test " + testId + " with tlc=" + tlc
+                                  + ", iac=" + iac
+                                  + ", isd=" + isd
+                                  + ", cac=" + cac
+                                  + ", csd=" + csd
+                                  + ", dep=" + dep
+                                  + ", imp=" + imp
+//                                      + ", mod=" + mod
+                                  + ", res=" + res
+//                                      + ", nfp=" + nfp
+                                  + ", req=" + req
+                                  + ", cpu=" + cpu
+                                  + ", seed=" + settings.seed);
+                        }
+                        ScenarioGenerator generator = new ScenarioGenerator(new ScenarioDescription(
+                            tlc, iac, isd, cac, csd, dep, imp, res, req, cpu, settings.seed));
+                        if (!consumer.run(generator, testId++)) {
+                          return testId;
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    return testId;
+  }
+
+  public void setSettings(TestGeneratorSettings settings) {
+    this.settings = settings;
+  }
+
+  public int getExpectedModelCount() {
+    return (settings.maxTopLevelComponents + 1 - settings.minTopLevelComponents) *
+        (settings.maxAvgNumImplSubComponents + 1 - settings.minAvgNumImplSubComponents) *
+        (settings.maxImplSubComponentDerivation + 1 - settings.minImplSubComponentDerivation) *
+        (settings.maxAvgNumCompSubComponents + 1 - settings.minAvgNumCompSubComponents) *
+        (settings.maxCompSubComponentDerivation + 1 - settings.minCompSubComponentDerivation) *
+        (settings.maxComponentDepth + 1 - settings.minComponentDepth) *
+        (settings.maxNumImplementations + 1 - settings.minNumImplementations) *
+        (settings.maxCpus + 1 - settings.minCpus) *
+        (int) ((settings.maxResourceRatio - settings.minResourceRatio) / settings.stepResourceRatio + 1) *
+        (int) ((settings.maxRequests - settings.minRequests) / 1.0 * settings.stepRequests + 1);
+  }
+
+  /**
+   * Checks all given parameters w.r.t. their validity, e.g., whether min &lt; max, or min &gt; max if step &lt; 0
+   * @return whether the this generator has wrong parameters
+   */
+  private boolean hasWarnings() {
+    boolean hasWarnings = false;
+    if (settings.minTopLevelComponents > settings.maxTopLevelComponents) {
+      logger.warn("minTopLevelComponents ({}) is greater than its max counterpart ({})!",
+          settings.minTopLevelComponents, settings.maxTopLevelComponents);
+      hasWarnings = true;
+    }
+
+    if (settings.minAvgNumImplSubComponents > settings.maxAvgNumImplSubComponents) {
+      logger.warn("minAvgNumImplSubComponents ({}) is greater than its max counterpart ({})!",
+          settings.minAvgNumImplSubComponents, settings.maxAvgNumImplSubComponents);
+      hasWarnings = true;
+    }
+
+    if (settings.minImplSubComponentDerivation > settings.maxImplSubComponentDerivation) {
+      logger.warn("minImplSubComponentDerivation ({}) is greater than its max counterpart ({})!",
+          settings.minImplSubComponentDerivation, settings.maxImplSubComponentDerivation);
+      hasWarnings = true;
+    }
+
+    if (settings.minAvgNumCompSubComponents > settings.maxAvgNumCompSubComponents) {
+      logger.warn("minAvgNumCompSubComponents ({}) is greater than its max counterpart ({})!",
+          settings.minAvgNumCompSubComponents, settings.maxAvgNumCompSubComponents);
+      hasWarnings = true;
+    }
+
+    if (settings.minCompSubComponentDerivation > settings.maxCompSubComponentDerivation) {
+      logger.warn("minCompSubComponentDerivation ({}) is greater than its max counterpart ({})!",
+          settings.minCompSubComponentDerivation, settings.maxCompSubComponentDerivation);
+      hasWarnings = true;
+    }
+
+    if (settings.minComponentDepth > settings.maxComponentDepth) {
+      logger.warn("minComponentDepth ({}) is greater than its max counterpart ({})!",
+          settings.minComponentDepth, settings.maxComponentDepth);
+      hasWarnings = true;
+    }
+
+    if (settings.minNumImplementations > settings.maxNumImplementations) {
+      logger.warn("minNumImplementations ({}) is greater than its max counterpart ({})!",
+          settings.minNumImplementations, settings.maxNumImplementations);
+      hasWarnings = true;
+    }
+
+    if (settings.minResourceRatio > settings.maxResourceRatio && settings.stepResourceRatio >= 0) {
+      logger.warn("minResourceRatio ({}) is greater than its max counterpart ({}) with step = {}!",
+          settings.minResourceRatio, settings.maxResourceRatio, settings.stepResourceRatio);
+      hasWarnings = true;
+    } else if (settings.minResourceRatio > settings.maxResourceRatio && settings.stepResourceRatio >= 0) {
+      logger.warn("minResourceRatio ({}) is smaller than its max counterpart ({}) with step = {}!",
+          settings.minResourceRatio, settings.maxResourceRatio, settings.stepResourceRatio);
+      hasWarnings = true;
+    }
+
+    if (settings.minCpus > settings.maxCpus) {
+      logger.warn("maxCpu ({}) is greater than its max counterpart ({})!",
+          settings.minCpus, settings.maxCpus);
+      hasWarnings = true;
+    }
+
+    if (settings.minRequests > settings.maxRequests && settings.stepRequests >= 0) {
+      logger.warn("minRequests ({}) is greater than its max counterpart ({}) with step = {}!",
+          settings.minRequests, settings.maxRequests, settings.stepRequests);
+      hasWarnings = true;
+    } else if (settings.minRequests < settings.maxRequests && settings.stepRequests <= 0) {
+      logger.warn("minRequests ({}) is smaller than its max counterpart ({}) with step = {}!",
+          settings.minRequests, settings.maxRequests, settings.stepRequests);
+      hasWarnings = true;
+    }
+    return hasWarnings;
+  }
+
+}
diff --git a/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/TestUtils.java b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/TestUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa6c370165ba9c68871b5ff8e922472cb6a3c58a
--- /dev/null
+++ b/jastadd-mquat-base/src/main/java/de/tudresden/inf/st/mquat/utils/TestUtils.java
@@ -0,0 +1,9 @@
+package de.tudresden.inf.st.mquat.utils;
+
+public class TestUtils {
+
+  public static boolean shouldTestLongRunning() {
+    return Boolean.valueOf(System.getProperty(
+        "de.tudresden.inf.st.mquat.longRunningTest", Boolean.FALSE.toString()));
+  }
+}
diff --git a/jastadd-mquat-base/src/main/resources/log4j2.xml b/jastadd-mquat-base/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0594576fac98ba859e411597c90c8e3d989378bd
--- /dev/null
+++ b/jastadd-mquat-base/src/main/resources/log4j2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration>
+    <Appenders>
+        <Console name="Console">
+            <PatternLayout pattern="%highlight{%d{HH:mm:ss.SSS} %-5level} %c{1.} - %msg%n"/>
+        </Console>
+        <RollingFile name="RollingFile" fileName="logs/jastadd-mquat.log"
+                    filePattern="logs/jastadd-mquat-%i.log">
+            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n"/>
+            <Policies>
+                <OnStartupTriggeringPolicy/>
+            </Policies>
+            <DefaultRolloverStrategy max="20"/>
+        </RollingFile>
+    </Appenders>
+    <Loggers>
+        <Root level="debug">
+            <AppenderRef ref="Console"/>
+            <AppenderRef ref="RollingFile"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/jastadd-mquat-base/src/main/resources/model-handmade.txt b/jastadd-mquat-base/src/main/resources/model-handmade.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c16884f0ef143504b0971f7465ff936eac10d1e6
--- /dev/null
+++ b/jastadd-mquat-base/src/main/resources/model-handmade.txt
@@ -0,0 +1,297 @@
+
+container resource type ComputeNode {
+    resource type CPU {
+        static property frequency [Hz]
+        runtime property load [%]
+    }
+    resource type RAM {
+        using property total
+        using property free
+    }
+    resource type DISK {
+        using property total
+        using property free
+    }
+    resource type NETWORK {
+        static property latency [ms]
+        static property throughput [kB/s]
+    }
+    derived property flops [ops/s]
+    runtime property STATE []
+}
+resource resource0:ComputeNode {
+    resource cpu0_0:CPU {
+        frequency = 2930
+        load = 0
+    }
+    resource cpu0_1:CPU {
+        frequency = 2930
+        load = 0
+    }
+    resource cpu0_2:CPU {
+        frequency = 2930
+        load = 0
+    }
+    resource cpu0_3:CPU {
+        frequency = 2930
+        load = 0
+    }
+    resource ram0:RAM {
+        total = 10596
+        free = 12709
+    }
+    resource disk0:DISK {
+        total = 3421
+        free = 6238
+    }
+    resource network0:NETWORK {
+        latency = 762
+        throughput = 22003
+    }
+}
+
+meta size
+
+static property total [MB]
+runtime property free [MB]
+runtime property energy [J]
+runtime property quality [%]
+
+component component_0 {
+    contract implementation_0i0 {
+        requires component the_component_0i0_0 of type component_0i0_0
+        requires component the_component_0i0_1 of type component_0i0_1
+        requires resource compute_resource_0 of type ComputeNode
+        requires resource cpu_0 of type CPU
+        requires resource cpu_1 of type CPU
+        requires resource cpu_2 of type CPU
+        requires resource cpu_3 of type CPU
+        requires resource ram_1 of type RAM
+        requires resource disk_1 of type DISK
+        requires resource network_1 of type NETWORK
+        requiring the_component_0i0_0.quality >= 95
+        requiring the_component_0i0_1.quality >= 86
+
+        mode configuration_0i0m0 {
+            requiring cpu_0.frequency >= 2159
+            requiring cpu_1.frequency >= 2159
+            requiring cpu_2.frequency >= 2159
+            requiring cpu_3.frequency >= 2159
+            requiring ram_1.total >= 11005
+            requiring disk_1.total >= 13482
+            requiring network_1.throughput >= 76460
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 90
+            providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+        }
+        mode configuration_0i0m1 {
+            requiring cpu_0.frequency >= 2929
+            requiring cpu_1.frequency >= 2929
+            requiring cpu_2.frequency >= 2929
+            requiring cpu_3.frequency >= 2929
+            requiring ram_1.total >= 10595
+            requiring disk_1.total >= 3420
+            requiring network_1.throughput >= 22002
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 35
+            providing energy = ((0.11*(size^2))+(0.94*compute_resource_0.flops))
+        }
+    }
+    contract implementation_0i1 {
+        requires component the_component_0i1_0 of type component_0i1_0
+        requires component the_component_0i1_1 of type component_0i1_1
+        requires resource compute_resource_0 of type ComputeNode
+        requires resource cpu_0 of type CPU
+        requires resource cpu_1 of type CPU
+        requires resource cpu_2 of type CPU
+        requires resource cpu_3 of type CPU
+        requires resource ram_1 of type RAM
+        requires resource disk_1 of type DISK
+        requires resource network_1 of type NETWORK
+        requiring the_component_0i1_0.quality >= 72
+        requiring the_component_0i1_1.quality >= 30
+
+        mode configuration_0i1m0 {
+            requiring cpu_0.frequency >= 2289
+            requiring cpu_1.frequency >= 2289
+            requiring cpu_2.frequency >= 2289
+            requiring cpu_3.frequency >= 2289
+            requiring ram_1.total >= 14825
+            requiring disk_1.total >= 6315
+            requiring network_1.throughput >= 52125
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 10
+            providing energy = ((0.17*(size^2))+(0.78*compute_resource_0.flops))
+        }
+        mode configuration_0i1m1 {
+            requiring cpu_0.frequency >= 1888
+            requiring cpu_1.frequency >= 1888
+            requiring cpu_2.frequency >= 1888
+            requiring cpu_3.frequency >= 1888
+            requiring ram_1.total >= 4782
+            requiring disk_1.total >= 5972
+            requiring network_1.throughput >= 45852
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 1
+            providing energy = ((0.25*(size^2))+(0.44*compute_resource_0.flops))
+        }
+    }
+}
+
+component component_0i0_0 {
+    contract implementation_0i0_0i0 {
+        requires resource compute_resource_0 of type ComputeNode
+        requires resource cpu_0 of type CPU
+        requires resource cpu_1 of type CPU
+        requires resource cpu_2 of type CPU
+        requires resource cpu_3 of type CPU
+        requires resource ram_1 of type RAM
+        requires resource disk_1 of type DISK
+        requires resource network_1 of type NETWORK
+
+        mode configuration_0i0_0i0m0 {
+            requiring cpu_0.frequency >= 2847
+            requiring cpu_1.frequency >= 2847
+            requiring cpu_2.frequency >= 2847
+            requiring cpu_3.frequency >= 2847
+            requiring ram_1.total >= 1009
+            requiring disk_1.total >= 13412
+            requiring network_1.throughput >= 10042
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 2
+            providing energy = ((0.28*(size^2))+(0.96*compute_resource_0.flops))
+        }
+        mode configuration_0i0_0i0m1 {
+            requiring cpu_0.frequency >= 1901
+            requiring cpu_1.frequency >= 1901
+            requiring cpu_2.frequency >= 1901
+            requiring cpu_3.frequency >= 1901
+            requiring ram_1.total >= 15803
+            requiring disk_1.total >= 4106
+            requiring network_1.throughput >= 58977
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 95
+            providing energy = ((0.24*(size^2))+(0.39*compute_resource_0.flops))
+        }
+    }
+}
+
+component component_0i0_1 {
+    contract implementation_0i0_1i0 {
+        requires resource compute_resource_0 of type ComputeNode
+        requires resource cpu_0 of type CPU
+        requires resource cpu_1 of type CPU
+        requires resource cpu_2 of type CPU
+        requires resource cpu_3 of type CPU
+        requires resource ram_1 of type RAM
+        requires resource disk_1 of type DISK
+        requires resource network_1 of type NETWORK
+
+        mode configuration_0i0_1i0m0 {
+            requiring cpu_0.frequency >= 1968
+            requiring cpu_1.frequency >= 1968
+            requiring cpu_2.frequency >= 1968
+            requiring cpu_3.frequency >= 1968
+            requiring ram_1.total >= 2057
+            requiring disk_1.total >= 9579
+            requiring network_1.throughput >= 64854
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 60
+            providing energy = ((0.45*(size^2))+(0.34*compute_resource_0.flops))
+        }
+        mode configuration_0i0_1i0m1 {
+            requiring cpu_0.frequency >= 2573
+            requiring cpu_1.frequency >= 2573
+            requiring cpu_2.frequency >= 2573
+            requiring cpu_3.frequency >= 2573
+            requiring ram_1.total >= 7208
+            requiring disk_1.total >= 8109
+            requiring network_1.throughput >= 10366
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 52
+            providing energy = ((0.02*(size^2))+(0.71*compute_resource_0.flops))
+        }
+    }
+}
+
+component component_0i1_0 {
+    contract implementation_0i1_0i0 {
+        requires resource compute_resource_0 of type ComputeNode
+        requires resource cpu_0 of type CPU
+        requires resource cpu_1 of type CPU
+        requires resource cpu_2 of type CPU
+        requires resource cpu_3 of type CPU
+        requires resource ram_1 of type RAM
+        requires resource disk_1 of type DISK
+        requires resource network_1 of type NETWORK
+
+        mode configuration_0i1_0i0m0 {
+            requiring cpu_0.frequency >= 2540
+            requiring cpu_1.frequency >= 2540
+            requiring cpu_2.frequency >= 2540
+            requiring cpu_3.frequency >= 2540
+            requiring ram_1.total >= 5708
+            requiring disk_1.total >= 11314
+            requiring network_1.throughput >= 87018
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 36
+            providing energy = ((0.77*(size^2))+(0.8*compute_resource_0.flops))
+        }
+        mode configuration_0i1_0i0m1 {
+            requiring cpu_0.frequency >= 2303
+            requiring cpu_1.frequency >= 2303
+            requiring cpu_2.frequency >= 2303
+            requiring cpu_3.frequency >= 2303
+            requiring ram_1.total >= 13297
+            requiring disk_1.total >= 15689
+            requiring network_1.throughput >= 2820
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 54
+            providing energy = ((0.21*(size^2))+(0.92*compute_resource_0.flops))
+        }
+    }
+}
+
+component component_0i1_1 {
+    contract implementation_0i1_1i0 {
+        requires resource compute_resource_0 of type ComputeNode
+        requires resource cpu_0 of type CPU
+        requires resource cpu_1 of type CPU
+        requires resource cpu_2 of type CPU
+        requires resource cpu_3 of type CPU
+        requires resource ram_1 of type RAM
+        requires resource disk_1 of type DISK
+        requires resource network_1 of type NETWORK
+
+        mode configuration_0i1_1i0m0 {
+            requiring cpu_0.frequency >= 1941
+            requiring cpu_1.frequency >= 1941
+            requiring cpu_2.frequency >= 1941
+            requiring cpu_3.frequency >= 1941
+            requiring ram_1.total >= 6327
+            requiring disk_1.total >= 6875
+            requiring network_1.throughput >= 99879
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 6
+            providing energy = ((0.67*(size^2))+(0.4*compute_resource_0.flops))
+        }
+        mode configuration_0i1_1i0m1 {
+            requiring cpu_0.frequency >= 2896
+            requiring cpu_1.frequency >= 2896
+            requiring cpu_2.frequency >= 2896
+            requiring cpu_3.frequency >= 2896
+            requiring ram_1.total >= 15404
+            requiring disk_1.total >= 4378
+            requiring network_1.throughput >= 94766
+            providing compute_resource_0.flops = (((cpu_0.frequency+cpu_1.frequency)+cpu_2.frequency)+cpu_3.frequency)
+            providing quality = 27
+            providing energy = ((0.47*(size^2))+(0.11*compute_resource_0.flops))
+        }
+    }
+}
+
+request component_0 {
+    meta size = 6
+    requiring quality >= 35
+}
+minimize sum(energy)
diff --git a/jastadd-mquat-base/src/main/resources/vision-contract.txt b/jastadd-mquat-base/src/main/resources/vision-contract.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b1e552c79482f441bbcb7f0f616e51d7e9f93506
--- /dev/null
+++ b/jastadd-mquat-base/src/main/resources/vision-contract.txt
@@ -0,0 +1,29 @@
+
+resource CPU1 : CPU {
+
+}
+
+restype
+
+component MYCOMPONENT {
+contract ImageViewer {
+    parameter cores
+	// requires 2 components Analyzer // version 1 for multiple components
+	requires resources CPU1, CPU2 of type CPU // version 2 for multiple components
+	requires CPU1.frequency >= 200
+	requires CPU1.parent = CPU2.parent
+	provides accuracy >= 0.5
+	provides refreshRate > 300
+	provides imageWidth > 800 // ignored for brevity
+	provides imageHeight > 600 // ignored for brevity
+	mode twoCores cores = 2, quality = * {
+		requires Analyzer1.accuracy > 0.5
+		requires Analyzer2.accuracy >= Analyzer1.accuracy + CPU1.frequency
+		requires Analyzer2.refreshRate > 400
+		// the following clause can not (and also should not be possible to) be modelled
+		// requires Analyzer1.accuracy + Analyzer2.accuracy < this.accuracy + CPU1.frequency --> this should not be possible, right?
+		requires CPU1.frequency > 450 // gets combined with outer constraint, i.e., overrides it
+		provides accuracy > 0.6 // gets combined with outer constraint, i.e., overrides it
+	}
+}
+}
diff --git a/jastadd-mquat-base/src/test/java/de/tudresden/inf/st/mquat/GeneratorTest.java b/jastadd-mquat-base/src/test/java/de/tudresden/inf/st/mquat/GeneratorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1ed2b7d0bde999ab2d9884ea8030de4a7367f00
--- /dev/null
+++ b/jastadd-mquat-base/src/test/java/de/tudresden/inf/st/mquat/GeneratorTest.java
@@ -0,0 +1,40 @@
+package de.tudresden.inf.st.mquat;
+
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+import de.tudresden.inf.st.mquat.jastadd.model.Solution;
+import de.tudresden.inf.st.mquat.utils.TestGenerator;
+import de.tudresden.inf.st.mquat.utils.TestUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.*;
+
+public class GeneratorTest {
+
+  private static Logger logger;
+
+  @BeforeClass
+  public static void initLogger() {
+    Assume.assumeTrue(TestUtils.shouldTestLongRunning());
+    logger = LogManager.getLogger(GeneratorTest.class);
+  }
+
+  @Test
+  public void testGenerator() {
+    long startTime = System.nanoTime();
+
+    TestGenerator testGenerator = new TestGenerator();
+    int total = testGenerator.generateScenarioGenerator((generator, testId) -> {
+      Root model = generator.generate();
+      Solution solution = generator.getInitialSolution();
+      logger.debug(testId + " " + model.description() + " has " + solution.allAssignments().size() + " assignments.");
+      Assert.assertTrue(solution.isValid());
+      return true;
+    });
+
+    long endTime = System.nanoTime();
+    double totalTimeInSec = (endTime - startTime) / 1000000000d;
+    double testsPerSec = (total + 1) / totalTimeInSec;
+    logger.info("Testing speed was " + testsPerSec + " tests/sec.");
+  }
+
+}
diff --git a/jastadd-mquat-benchmark/.gitignore b/jastadd-mquat-benchmark/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..1e56a258612142072018a8a834f283ae1144d64b
--- /dev/null
+++ b/jastadd-mquat-benchmark/.gitignore
@@ -0,0 +1,2 @@
+build/
+src/main/resources/local-benchmark-settings.json
diff --git a/jastadd-mquat-benchmark/README.md b/jastadd-mquat-benchmark/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..fe61fc68502158eca828d774aead22159e770e79
--- /dev/null
+++ b/jastadd-mquat-benchmark/README.md
@@ -0,0 +1,40 @@
+# Setting up a benchmark
+
+The default settings file is found in `src/main/resources/benchmark-settings.json`.
+**However**, to change values, a separate file `src/main/resources/local-benchmark-settings.json` should be used.
+This file is not under version control on purpose to allow local changes.
+
+There, the following things can be specified. Listed are keys, possible prefixes (min, max, step) and some explanations.
+
+- kind: either `incremental` for IncrementalBenchmark, or `basic` for Benchmark
+- path: result path
+- filePattern: pattern for result name, must contain one `%s` replaced by a timestamp
+- solvers: a list of solvers to use (identified by their name)
+- logLevel: level of logging (from Log4j) set for the package of each used solver
+- basic
+  - TopLevelComponents (min, max)
+  - AvgNumSubComponents (min, max)
+  - SubComponentDerivation (min, max)
+  - NumImplementations (min, max)
+  - NumModes (min, max)
+  - Cpus (min, max)
+  - Requests  (min, max, step) 
+  - ResourceRatio  (min, max, step)
+  - timeoutValue: value for timeout
+  - timeoutUnit: unit for timeout
+  - seed: input for random generator
+  - total: total number of runs (useful to test the settings, but not run the full benchmark)
+- incremental
+  - requestsToChange
+  - percentToChange
+
+As an example, to set the minimum number of top level components to 5, the following entry is needed:
+
+```json
+{
+  "kind": "normal",
+  "basic": {
+    "minTopLevelComponents": 5
+  }
+}
+```
diff --git a/jastadd-mquat-benchmark/build.gradle b/jastadd-mquat-benchmark/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..eaafbc051d26d58a19aed720a692799fa8d99ab0
--- /dev/null
+++ b/jastadd-mquat-benchmark/build.gradle
@@ -0,0 +1,38 @@
+
+apply plugin: 'java'
+
+sourceCompatibility = 1.8
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    compile project(':jastadd-mquat-base')
+    compile project(':jastadd-mquat-solver')
+    compile project(':jastadd-mquat-solver-ilp')
+    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'
+    testCompile group: 'junit', name: 'junit', version: '4.12'
+}
+
+task benchmarkCustom(type: JavaExec, dependsOn: assemble) {
+    group "application"
+    classpath = sourceSets.test.runtimeClasspath
+    main = 'de.tudresden.inf.st.mquat.benchmark.CustomBenchmarkMain'
+    systemProperty "java.library.path", project.glpkPath
+    jvmArgs("-XX:+UnlockCommercialFeatures", "-XX:+FlightRecorder", "-XX:StartFlightRecording=settings=profile", "-XX:FlightRecorderOptions=defaultrecording=true,dumponexit=true,dumponexitpath=results/fr", "-Xverify:none")
+}
+
+task benchmarkFull(type: JavaExec, dependsOn: assemble) {
+    group "application"
+    classpath = sourceSets.test.runtimeClasspath
+    main = 'de.tudresden.inf.st.mquat.benchmark.FullBenchmarkMain'
+    systemProperty "java.library.path", project.glpkPath
+//    jvmArgs("-Xmx=4096m")
+    if (project.hasProperty("scenario")) {
+        args(scenario.split(','))
+    }
+//    jvmArgs("-XX:+UnlockCommercialFeatures", "-XX:+FlightRecorder", "-XX:StartFlightRecording=settings=profile", "-XX:FlightRecorderOptions=defaultrecording=true,dumponexit=true,dumponexitpath=results/fr", "-Xverify:none")
+}
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-10-15-44-09.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-10-15-44-09.csv
new file mode 100644
index 0000000000000000000000000000000000000000..431245877d8b9029bf3d9f815248fb68399ff06a
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-10-15-44-09.csv
@@ -0,0 +1,16 @@
+topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,modelGeneration,ilpGeneration,ilpSolving,initialObjective,ilpObjective
+1,1,1,1,1,2,1,1,0,1,0,26,0,0,0.0,0.0
+1,1,1,1,1,2,1,1,25,1,0,7,82,131,2668443.7099999995,2020737.26
+1,1,1,1,1,2,1,1,50,1,0,7,63,171,4241926.700000002,3228965.0
+1,1,1,1,1,2,1,1,75,1,0,6,109,60321,7021993.930000003,5459681.98
+1,1,1,1,1,2,1,1,100,1,0,8,189,525,9159741.290000001,7181905.64
+1,1,1,2,1,2,1,1,0,1,0,1,0,0,0.0,0.0
+1,1,1,2,1,2,1,1,25,1,0,2,82,107,6209612.91,4534688.64
+1,1,1,2,1,2,1,1,50,1,0,2,281,510,1.4405934880000006E7,1.042163198E7
+1,1,1,2,1,2,1,1,75,1,0,7,562,1115,2.6732370939999983E7,1.865061939E7
+1,1,1,2,1,2,1,1,100,1,0,7,1134,2910,3.5270170789999954E7,2.571826968E7
+1,1,1,3,1,2,1,1,0,1,0,0,0,0,0.0,0.0
+1,1,1,3,1,2,1,1,25,1,0,2,68,90,7423021.679999999,4073910.15
+1,1,1,3,1,2,1,1,50,1,0,2,239,392,1.9320319169999994E7,1.099436497E7
+1,1,1,3,1,2,1,1,75,1,0,4,680,975,2.928928794999999E7,1.701516569E7
+1,1,1,3,1,2,1,1,100,1,0,5,1059,61834,4.2870849489999995E7,2.389607656E7
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-10-15-44-09.csv.html b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-10-15-44-09.csv.html
new file mode 100644
index 0000000000000000000000000000000000000000..ecb5d110db9df275d305d179c5ac10de9fc61f21
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-10-15-44-09.csv.html
@@ -0,0 +1,18 @@
+<table>
+<tr><th>topLevelComponents</th><th>avgSubComponents</th><th>subComponentStdDerivation</th><th>componentDepth</th><th>implementations</th><th>modes</th><th>computeResources</th><th>nonfunctionalProperties</th><th>requests</th><th>cpus</th><th>seed</th><th>modelGeneration</th><th>ilpGeneration</th><th>ilpSolving</th><th>initialObjective</th><th>ilpObjective</th></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>1</td><td>0</td><td>1</td><td>0</td><td>26</td><td>0</td><td>0</td><td>0.0</td><td>0.0</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>1</td><td>25</td><td>1</td><td>0</td><td>7</td><td>82</td><td>131</td><td>2668443.7099999995</td><td>2020737.26</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>1</td><td>50</td><td>1</td><td>0</td><td>7</td><td>63</td><td>171</td><td>4241926.700000002</td><td>3228965.0</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>1</td><td>75</td><td>1</td><td>0</td><td>6</td><td>109</td><td>60321</td><td>7021993.930000003</td><td>5459681.98</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>1</td><td>100</td><td>1</td><td>0</td><td>8</td><td>189</td><td>525</td><td>9159741.290000001</td><td>7181905.64</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>2</td><td>1</td><td>1</td><td>0</td><td>1</td><td>0</td><td>1</td><td>0</td><td>0</td><td>0.0</td><td>0.0</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>2</td><td>1</td><td>1</td><td>25</td><td>1</td><td>0</td><td>2</td><td>82</td><td>107</td><td>6209612.91</td><td>4534688.64</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>2</td><td>1</td><td>1</td><td>50</td><td>1</td><td>0</td><td>2</td><td>281</td><td>510</td><td>1.4405934880000006E7</td><td>1.042163198E7</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>2</td><td>1</td><td>1</td><td>75</td><td>1</td><td>0</td><td>7</td><td>562</td><td>1115</td><td>2.6732370939999983E7</td><td>1.865061939E7</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>2</td><td>1</td><td>1</td><td>100</td><td>1</td><td>0</td><td>7</td><td>1134</td><td>2910</td><td>3.5270170789999954E7</td><td>2.571826968E7</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>3</td><td>1</td><td>2</td><td>1</td><td>1</td><td>0</td><td>1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0.0</td><td>0.0</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>3</td><td>1</td><td>2</td><td>1</td><td>1</td><td>25</td><td>1</td><td>0</td><td>2</td><td>68</td><td>90</td><td>7423021.679999999</td><td>4073910.15</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>3</td><td>1</td><td>2</td><td>1</td><td>1</td><td>50</td><td>1</td><td>0</td><td>2</td><td>239</td><td>392</td><td>1.9320319169999994E7</td><td>1.099436497E7</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>3</td><td>1</td><td>2</td><td>1</td><td>1</td><td>75</td><td>1</td><td>0</td><td>4</td><td>680</td><td>975</td><td>2.928928794999999E7</td><td>1.701516569E7</td></tr>
+<tr><td>1</td><td>1</td><td>1</td><td>3</td><td>1</td><td>2</td><td>1</td><td>1</td><td>100</td><td>1</td><td>0</td><td>5</td><td>1059</td><td>61834</td><td>4.2870849489999995E7</td><td>2.389607656E7</td></tr>
+</table>
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-14-21.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-14-21.csv
new file mode 100644
index 0000000000000000000000000000000000000000..93f7ddede2137ed42195f2e2589eafee72853bc7
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-14-21.csv
@@ -0,0 +1,2 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-directGeneration,ilp-directSolving,,ilp-externalValid,ilp-directValidinitialObjective,ilp-externalObjective,ilp-directObjective
+2018-01-12-15-14-21,1,1,1,1,1,2,1,1,0,1,0,24,0,0,true,0,0,true,0.0,0.0,0.0
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-19-24.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-19-24.csv
new file mode 100644
index 0000000000000000000000000000000000000000..d3c701f89405cd40944fabcaf87fee73ea9a71e0
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-19-24.csv
@@ -0,0 +1,4 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-directGeneration,ilp-directSolving,,ilp-externalValid,ilp-directValidinitialObjective,ilp-externalObjective,ilp-directObjective
+2018-01-12-15-19-24,1,1,1,1,1,2,1,1,0,1,0,25,0,0,true,0,0,true,0.0,0.0,0.0
+2018-01-12-15-19-24,1,1,1,1,1,2,1,1,25,1,0,10,74,115,true,53,0,true,2668443.71,2020737.26,2020737.26
+2018-01-12-15-19-25,1,1,1,1,1,2,1,1,50,1,0,12,80,146,true,82,0,true,4241926.700000001,3228965.0,3228965.0000000005
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-26-31.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-26-31.csv
new file mode 100644
index 0000000000000000000000000000000000000000..598b69fc3bdae1dcfed85936a5013df45dcb8ce3
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-26-31.csv
@@ -0,0 +1,4 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-directGeneration,ilp-directSolving,,ilp-externalValid,ilp-directValidinitialObjective,ilp-externalObjective,ilp-directObjective
+2018-01-12-15-26-31,1,1,1,1,1,2,1,1,0,1,0,31,0,0,true,0,0,true,0.0,0.0,0.0
+2018-01-12-15-26-31,1,1,1,1,1,2,1,1,25,1,0,12,88,124,true,54,0,true,2668443.7100000004,2020737.26,2020737.26
+2018-01-12-15-26-33,1,1,1,1,1,2,1,1,50,1,0,35,79,231,true,69,0,true,4241926.700000002,3228965.0,3228965.0000000005
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-35-38.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-35-38.csv
new file mode 100644
index 0000000000000000000000000000000000000000..fbf3efb761763201449740d9d1951e11fa911835
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-15-35-38.csv
@@ -0,0 +1,4 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-directGeneration,ilp-directSolving,,ilp-externalValid,ilp-directValidinitialObjective,ilp-externalObjective,ilp-directObjective
+2018-01-12-15-35-38,1,1,1,1,1,2,1,1,0,1,0,26,0,0,true,0,0,true,0.0,0.0,0.0
+2018-01-12-15-35-38,1,1,1,1,1,2,1,1,25,1,0,9,86,122,true,50,0,true,2668443.71,2020737.26,2020737.2600000005
+2018-01-12-15-35-39,1,1,1,1,1,2,1,1,50,1,0,6,57,142,true,79,0,true,4241926.700000001,3228965.0,3228965.0000000014
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-16-47-31.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-16-47-31.csv
new file mode 100644
index 0000000000000000000000000000000000000000..48c65c85dc83074b46d12b47e14b2642ba412248
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-12-16-47-31.csv
@@ -0,0 +1,4 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-directGeneration,ilp-directSolving,,ilp-externalValid,ilp-directValidinitialObjective,ilp-externalObjective,ilp-directObjective
+2018-01-12-16-47-31,1,1,1,1,1,2,1,1,0,1,0,27,0,0,true,0,0,true,0.0,0.0,0.0
+2018-01-12-16-47-31,1,1,1,1,1,2,1,1,25,1,0,8,89,137,true,62,0,true,2668443.71,2020737.26,2020737.2600000005
+2018-01-12-16-47-32,1,1,1,1,1,2,1,1,50,1,0,14,79,180,true,63,0,true,4241926.7,3228965.0,3228965.0
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-09-56-57.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-09-56-57.csv
new file mode 100644
index 0000000000000000000000000000000000000000..2098bda39c7e92ec76ac56b7c3373d91c078a741
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-09-56-57.csv
@@ -0,0 +1,16 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-externalValid,initialObjective,ilp-externalObjective
+2018-01-15-09-56-57,1,1,1,1,1,2,1,1,0,1,0,24,0,0,true,0.0,0.0
+2018-01-15-09-56-57,1,1,1,1,1,2,1,1,25,1,0,8,71,166,true,2668443.71,2020737.26
+2018-01-15-09-56-57,1,1,1,1,1,2,1,1,50,1,0,6,58,217,true,4241926.700000001,3228965.0
+2018-01-15-09-57-01,1,1,1,1,1,2,1,1,75,1,0,7,123,60311,true,7021993.930000001,5459681.98
+2018-01-15-09-58-09,1,1,1,1,1,2,1,1,100,1,0,6,180,421,true,9159741.290000003,7181905.64
+2018-01-15-09-58-30,1,1,1,2,1,2,1,1,0,1,0,1,0,0,true,0.0,0.0
+2018-01-15-09-58-30,1,1,1,2,1,2,1,1,25,1,0,2,89,110,true,6209612.910000001,4534688.64
+2018-01-15-09-58-34,1,1,1,2,1,2,1,1,50,1,0,4,556,841,true,1.4405934880000008E7,1.042163198E7
+2018-01-15-09-59-01,1,1,1,2,1,2,1,1,75,1,0,6,552,1048,true,2.6732370939999975E7,1.865061939E7
+2018-01-15-10-00-34,1,1,1,2,1,2,1,1,100,1,0,8,1042,2310,true,3.527017078999998E7,2.571826968E7
+2018-01-15-10-04-45,1,1,1,3,1,2,1,1,0,1,0,0,0,0,true,0.0,0.0
+2018-01-15-10-04-45,1,1,1,3,1,2,1,1,25,1,0,2,63,86,true,7423021.680000001,4073910.15
+2018-01-15-10-04-48,1,1,1,3,1,2,1,1,50,1,0,1,235,375,true,1.9320319170000006E7,1.099436497E7
+2018-01-15-10-05-13,1,1,1,3,1,2,1,1,75,1,0,4,873,1261,true,2.9289287949999996E7,1.701516569E7
+2018-01-15-10-06-41,1,1,1,3,1,2,1,1,100,1,0,4,1046,61773,true,4.287084948999997E7,2.389607656E7
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-10-57-58.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-10-57-58.csv
new file mode 100644
index 0000000000000000000000000000000000000000..85f9f51c0480e6b3656c4b179e51ffd7b4fb39c5
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-10-57-58.csv
@@ -0,0 +1,16 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-externalValid,initialObjective,ilp-externalObjective
+2018-01-15-10-57-58,1,1,0,1,1,2,40,1,0,1,0,1,1,2,30,0,0,true,0.0,0.0
+2018-01-15-10-57-58,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,124,152,true,3754269.869999999,2809811.2
+2018-01-15-10-57-59,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,51,139,true,8614715.24,6382704.29
+2018-01-15-10-58-02,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,116,305,true,1.1206278750000004E7,7289379.27
+2018-01-15-10-58-10,1,1,0,1,1,2,40,1,100,1,0,1,1,2,5,194,407,true,1.4461749410000004E7,9440690.9
+2018-01-15-10-58-29,1,1,0,2,1,2,40,1,0,1,0,2,2,4,1,0,0,true,0.0,0.0
+2018-01-15-10-58-29,1,1,0,2,1,2,40,1,25,1,0,2,2,4,2,99,115,true,4660419.600000002,2402332.35
+2018-01-15-10-58-33,1,1,0,2,1,2,40,1,50,1,0,2,2,4,3,249,552,true,1.1654015820000006E7,6165636.19
+2018-01-15-10-58-58,1,1,0,2,1,2,40,1,75,1,0,2,2,4,8,546,1171,true,1.3830861550000008E7,7487402.99
+2018-01-15-11-00-25,1,1,0,2,1,2,40,1,100,1,0,2,2,4,5,1031,1749,true,1.8353526140000004E7,9967414.22
+2018-01-15-11-04-07,1,1,0,3,1,2,40,1,0,1,0,3,3,6,1,0,0,true,0.0,0.0
+2018-01-15-11-04-07,1,1,0,3,1,2,40,1,25,1,0,3,3,6,3,219,206,true,1.1553344309999999E7,8121836.9
+2018-01-15-11-04-18,1,1,0,3,1,2,40,1,50,1,0,3,3,6,2,738,1167,true,2.8331707599999998E7,2.143625945E7
+2018-01-15-11-05-53,1,1,0,3,1,2,40,1,75,1,0,3,3,6,7,1429,2379,true,3.367488789999999E7,2.413993455E7
+2018-01-15-11-11-36,1,1,0,3,1,2,40,1,100,1,0,3,3,6,6,2973,4977,true,4.374915701E7,3.133061251E7
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-04-45.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-04-45.csv
new file mode 100644
index 0000000000000000000000000000000000000000..073c7506a69b823b8b9b428231957dea8a1eca55
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-04-45.csv
@@ -0,0 +1,2 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-externalValid,initialObjective,ilp-externalObjective
+2018-01-15-15-04-46,1,1,0,1,1,2,40,1,0,1,0,1,1,2,28,0,0,true,0.0,0.0
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-05-16.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-05-16.csv
new file mode 100644
index 0000000000000000000000000000000000000000..a8639ef00eaef7f2d0548ee21f289f0a810e6974
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-05-16.csv
@@ -0,0 +1,2 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-externalValid,initialObjective,ilp-externalObjective
+2018-01-15-15-05-16,1,1,0,1,1,2,40,1,0,1,0,1,1,2,27,0,0,true,0.0,0.0
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-05-40.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-05-40.csv
new file mode 100644
index 0000000000000000000000000000000000000000..a014cd98ac632d684d70323bf20a818f91e96f69
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-05-40.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-externalValid,initialObjective,ilp-externalObjective
+2018-01-15-15-05-40,1,1,0,1,1,2,40,1,0,1,0,1,1,2,36,0,0,true,0.0,0.0
+2018-01-15-15-05-40,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,100,166,true,3754269.8699999996,2809811.2
+2018-01-15-15-05-41,1,1,0,1,1,2,40,1,50,1,0,1,1,2,15,82,237,true,8614715.240000002,6382704.29
+2018-01-15-15-05-45,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,109,323,true,1.120627875E7,7289379.27
+2018-01-15-15-05-55,1,1,0,1,1,2,40,1,100,1,0,1,1,2,5,258,544,true,1.4461749410000006E7,9440690.9
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-20-56.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-20-56.csv
new file mode 100644
index 0000000000000000000000000000000000000000..4d761ace2556f0981d63c4f83d5d93d1002c9ccc
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-20-56.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-externalValid,initialObjective,ilp-externalObjective
+2018-01-15-15-20-56,1,1,0,1,1,2,40,1,0,1,0,1,1,2,24,0,0,true,0.0,0.0
+2018-01-15-15-20-56,1,1,0,1,1,2,40,1,25,1,0,1,1,2,8,110,140,true,3754269.8699999996,2809811.2
+2018-01-15-15-20-58,1,1,0,1,1,2,40,1,50,1,0,1,1,2,30,123,380,true,8614715.24,6382704.29
+2018-01-15-15-21-02,1,1,0,1,1,2,40,1,75,1,0,1,1,2,4,116,299,true,1.1206278750000002E7,7289379.27
+2018-01-15-15-21-11,1,1,0,1,1,2,40,1,100,1,0,1,1,2,4,192,430,true,1.4461749410000006E7,9440690.9
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-25-31.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-25-31.csv
new file mode 100644
index 0000000000000000000000000000000000000000..122bc9b7e75794c1972a8993779fb197e9974095
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-25-31.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-externalValid,initialObjective,ilp-externalObjective
+2018-01-15-15-25-31,1,1,0,1,1,2,40,1,0,1,0,1,1,2,49,0,0,true,0.0,0.0
+2018-01-15-15-25-31,1,1,0,1,1,2,40,1,25,1,0,1,1,2,25,385,180,true,3754269.8699999996,2809811.2
+2018-01-15-15-25-32,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,74,138,true,8614715.240000002,6382704.29
+2018-01-15-15-25-35,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,103,299,true,1.1206278750000002E7,7289379.27
+2018-01-15-15-25-43,1,1,0,1,1,2,40,1,100,1,0,1,1,2,4,175,431,true,1.4461749410000002E7,9440690.9
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-30-27.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-30-27.csv
new file mode 100644
index 0000000000000000000000000000000000000000..0b5579e6162b9164b32b5601fa78f012fe477386
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-30-27.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-externalValid,initialObjective,ilp-externalObjective
+2018-01-15-15-30-27,1,1,0,1,1,2,40,1,0,1,0,1,1,2,61,0,0,true,0.0,0.0
+2018-01-15-15-30-27,1,1,0,1,1,2,40,1,25,1,0,1,1,2,25,262,197,true,3754269.8699999996,2809811.2
+2018-01-15-15-30-29,1,1,0,1,1,2,40,1,50,1,0,1,1,2,4,47,165,true,8614715.240000002,6382704.29
+2018-01-15-15-30-31,1,1,0,1,1,2,40,1,75,1,0,1,1,2,4,100,290,true,1.1206278750000002E7,7289379.27
+2018-01-15-15-30-39,1,1,0,1,1,2,40,1,100,1,0,1,1,2,5,181,402,true,1.4461749410000002E7,9440690.9
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-37-35.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-37-35.csv
new file mode 100644
index 0000000000000000000000000000000000000000..7f0f1bef1085e1e5926ed49f030fa07b50b1d934
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-15-15-37-35.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration,ilp-externalSolving,ilp-externalValid,initialObjective,ilp-externalObjective
+2018-01-15-15-37-35,1,1,0,1,1,2,40,1,0,1,0,1,1,2,27,0,0,true,0.0,0.0
+2018-01-15-15-37-35,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,134,169,true,3754269.8699999987,2809811.2
+2018-01-15-15-37-37,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,50,136,true,8614715.24,6382704.29
+2018-01-15-15-37-39,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,126,338,true,1.1206278750000004E7,7289379.27
+2018-01-15-15-37-48,1,1,0,1,1,2,40,1,100,1,0,1,1,2,3,188,422,true,1.4461749410000011E7,9440690.9
diff --git a/jastadd-mquat-benchmark/old-results/benchmark-2018-01-19-13-42-26.csv b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-19-13-42-26.csv
new file mode 100644
index 0000000000000000000000000000000000000000..73b59b7879dfa1ea020648d11b682c7698fb9e95
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/benchmark-2018-01-19-13-42-26.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,ilp-externalGen,ilp-externalSolved,ilp-externalValid,ilp-externalTimeOut,ilp-directGen,ilp-directSolved,ilp-directValid,ilp-directTimeOut,simpleSolved,simpleValid,simpleTimeOut,mh-naiveGen,mh-naiveSolved,mh-naiveValid,mh-naiveTimeOut,initObj,ilp-externalObj,ilp-directObj,simpleObj,mh-naiveObj
+2018-01-19-13-42-26,1,1,0,1,3,2,1.0,1,0,1,0,1,3,6,32,0,0,true,false,0,0,true,false,0,true,false,9,0,true,false,0.0,0.0,0.0,0.0,0.0
+2018-01-19-13-42-26,1,1,0,1,3,2,1.0,1,1,1,0,1,3,6,4,11,29,true,false,2,12,true,false,1,true,false,0,0,false,false,5707.990000000001,5707.99,5707.990000000001,5707.990000000001,-44193.0
+2018-01-19-13-42-32,1,1,0,1,3,2,1.0,1,2,1,0,1,3,6,1,3,18,true,false,2,3,true,false,6,true,false,0,0,false,false,128796.79,128796.79,128796.79,128796.79,-380368.0
+2018-01-19-13-42-37,1,1,0,1,3,2,1.0,1,3,1,0,1,3,6,1,3,20,true,false,3,5,true,false,10,true,false,0,0,false,false,305746.44999999995,305746.45,305746.45,305746.44999999995,-388455.0
+2018-01-19-13-42-42,1,1,0,1,3,2,1.0,1,4,1,0,1,3,6,0,4,24,true,false,4,6,true,false,29,true,false,0,0,false,false,155750.37,109479.6,109479.59999999999,109479.59999999999,-548381.0
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-12936-id-0-2018_01_16_09_40_57.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-12936-id-0-2018_01_16_09_40_57.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..32247b28b0f398319b4530eea0ed6f8fa1f20ed4
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-12936-id-0-2018_01_16_09_40_57.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-13273-id-0-2018_01_16_09_44_49.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-13273-id-0-2018_01_16_09_44_49.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..2931d18307827143050f4fdca8df2ffa4b2ddee6
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-13273-id-0-2018_01_16_09_44_49.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-13399-id-0-2018_01_16_09_46_03.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-13399-id-0-2018_01_16_09_46_03.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..c06a529561831ebf044ab1a41239dcb70034be59
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-13399-id-0-2018_01_16_09_46_03.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-13929-id-0-2018_01_16_09_53_29.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-13929-id-0-2018_01_16_09_53_29.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..658c620070cfa473b43846cb52196129ea34b491
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-13929-id-0-2018_01_16_09_53_29.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-14053-id-0-2018_01_16_09_54_58.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-14053-id-0-2018_01_16_09_54_58.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..914b8d26a6f35a0f49c7b0b82d15510d447c6389
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-14053-id-0-2018_01_16_09_54_58.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-15549-id-0-2018_01_16_10_21_13.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-15549-id-0-2018_01_16_10_21_13.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..2cd9862d2e1af3e8cbbd638ae770ee550393793d
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-15549-id-0-2018_01_16_10_21_13.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-15725-id-0-2018_01_16_10_22_46.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-15725-id-0-2018_01_16_10_22_46.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..a94f296854546126343b8c4674c30f848e4f8fd5
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-15725-id-0-2018_01_16_10_22_46.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-16103-id-0-2018_01_16_10_30_05.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-16103-id-0-2018_01_16_10_30_05.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..13153210d545d477e643b6b566a177aa2401a5e2
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-16103-id-0-2018_01_16_10_30_05.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-16312-id-0-2018_01_16_10_32_20.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-16312-id-0-2018_01_16_10_32_20.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..6235a964bafe18329097d9b3f1640b9340515f87
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-16312-id-0-2018_01_16_10_32_20.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-16665-id-0-2018_01_16_10_42_02.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-16665-id-0-2018_01_16_10_42_02.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..f0f5cdfd8d109b1a838f70452a51fd58d37efd3b
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-16665-id-0-2018_01_16_10_42_02.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-17153-id-0-2018_01_16_10_52_10.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-17153-id-0-2018_01_16_10_52_10.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..353f2746f776410d861960fb418775547a3e6b5e
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-17153-id-0-2018_01_16_10_52_10.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-17652-id-0-2018_01_16_10_58_50.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-17652-id-0-2018_01_16_10_58_50.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..ecb1fcddd018c91b023a4e5f7659d1db9beb7b1c
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-17652-id-0-2018_01_16_10_58_50.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-19585-id-0-2018_01_18_16_17_27.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-19585-id-0-2018_01_18_16_17_27.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..d54e1cceca3d21dda717a6700b9b55811d45e506
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-19585-id-0-2018_01_18_16_17_27.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-21065-id-0-2018_01_18_16_38_52.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-21065-id-0-2018_01_18_16_38_52.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..d968541362ed6e4157611d735f82cd74b1f1a969
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-21065-id-0-2018_01_18_16_38_52.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-21281-id-0-2018_01_17_10_54_02.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-21281-id-0-2018_01_17_10_54_02.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..5627c65532963b9a6b38db005b02bb8ad00ddafb
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-21281-id-0-2018_01_17_10_54_02.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-21384-id-0-2018_01_17_10_55_04.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-21384-id-0-2018_01_17_10_55_04.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..2bce544112884d9698d757bc1c8e0b9354c088d5
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-21384-id-0-2018_01_17_10_55_04.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-21546-id-0-2018_01_17_10_57_05.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-21546-id-0-2018_01_17_10_57_05.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..b27058590a0eb8eac22f6d0c5c0be6276fdc4376
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-21546-id-0-2018_01_17_10_57_05.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-22267-id-0-2018_01_16_12_15_58.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-22267-id-0-2018_01_16_12_15_58.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..2cf0c9f908b2143cfdb65ddc8c4f9787f2db6afa
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-22267-id-0-2018_01_16_12_15_58.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-22524-id-0-2018_01_16_12_19_48.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-22524-id-0-2018_01_16_12_19_48.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..9abd96646206b12e35d79dcb299460c199ec6b00
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-22524-id-0-2018_01_16_12_19_48.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-26593-id-0-2018_01_16_13_56_39.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-26593-id-0-2018_01_16_13_56_39.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..d9fa079f1bda7185ae872dcc9a01bd30faea8655
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-26593-id-0-2018_01_16_13_56_39.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-26782-id-0-2018_01_16_14_00_27.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-26782-id-0-2018_01_16_14_00_27.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..75495b5d2c0f5380d7968405fccccf0581427206
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-26782-id-0-2018_01_16_14_00_27.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/hotspot-pid-32178-id-0-2018_01_15_15_38_07.jfr b/jastadd-mquat-benchmark/old-results/hotspot-pid-32178-id-0-2018_01_15_15_38_07.jfr
new file mode 100644
index 0000000000000000000000000000000000000000..85034b759a88ecb9ed8e97e1b064a4cf37ca421e
Binary files /dev/null and b/jastadd-mquat-benchmark/old-results/hotspot-pid-32178-id-0-2018_01_15_15_38_07.jfr differ
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-40-49.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-40-49.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8e289cbb1a93a21f5108c3f98a3a391fe8ffdfe2
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-40-49.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGenerationStart,ilp-externalSolvingStart,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidStart,ilp-externalValidHard,ilp-externalValidEasy,initialObjective,ilp-externalObjectiveStart,ilp-externalObjectiveHard,ilp-externalObjectiveEasy
+2018-01-16-09-40-49,1,1,0,1,1,2,40,1,0,1,0,1,1,2,28,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0
+2018-01-16-09-40-49,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,140,295,true,36,155,true,27,136,true,3754269.8699999996,2809811.2,2809811.2,2809811.2
+2018-01-16-09-40-50,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,65,264,true,81,260,true,72,261,true,8614715.240000002,6382704.29,6382704.29,6382704.29
+2018-01-16-09-40-51,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,118,509,true,164,548,true,165,577,true,1.1206278750000004E7,7289379.27,7289379.27,7289379.27
+2018-01-16-09-40-53,1,1,0,1,1,2,40,1,100,1,0,1,1,2,6,204,907,true,309,887,true,206,752,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-44-41.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-44-41.csv
new file mode 100644
index 0000000000000000000000000000000000000000..cb9d753bc4c5acf5ba5640fda9feae31795c6924
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-44-41.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGenerationStart,ilp-externalSolvingStart,ilp-externalValidStart,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,initialObjective,ilp-externalObjectiveStart,ilp-externalObjectiveHard,ilp-externalObjectiveEasy
+2018-01-16-09-44-41,1,1,0,1,1,2,40,1,0,1,0,1,1,2,29,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0
+2018-01-16-09-44-41,1,1,0,1,1,2,40,1,25,1,0,1,1,2,11,122,279,true,49,185,true,38,145,true,3754269.8699999996,2809811.2,2809811.2,2809811.2
+2018-01-16-09-44-42,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,86,331,true,69,250,true,104,277,true,8614715.240000002,6382704.29,6382704.29,6382704.29
+2018-01-16-09-44-43,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,140,505,true,146,739,true,193,579,true,1.1206278750000004E7,7289379.27,7289379.27,7289379.27
+2018-01-16-09-44-45,1,1,0,1,1,2,40,1,100,1,0,1,1,2,6,288,949,true,267,789,true,216,772,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-45-51.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-45-51.csv
new file mode 100644
index 0000000000000000000000000000000000000000..6d0a3fd3433f10cc25ba0a9b36597c4c353498a4
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-45-51.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGenerationStart,ilp-externalSolvingStart,ilp-externalValidStart,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGenerationStart,ilp-directSolvingStart,ilp-directValidStart,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjectiveStart,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjectiveStart,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-09-45-51,1,1,0,1,1,2,40,1,0,1,0,1,1,2,34,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-09-45-51,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,158,280,true,43,197,true,50,159,true,48,149,true,42,88,true,47,78,true,3754269.869999999,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2
+2018-01-16-09-45-52,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,99,250,true,68,291,true,77,243,true,51,272,true,130,295,true,103,217,true,8614715.24,6382704.29,6382704.29,6382704.29,6382704.290000001,6382704.290000001,6382704.290000001
+2018-01-16-09-45-54,1,1,0,1,1,2,40,1,75,1,0,1,1,2,8,263,582,true,110,520,true,112,427,true,141,319,true,170,344,true,124,291,true,1.1206278750000002E7,7289379.27,7289379.27,7289379.27,7289379.270000001,7289379.270000001,7289379.270000001
+2018-01-16-09-45-58,1,1,0,1,1,2,40,1,100,1,0,1,1,2,6,217,831,true,216,846,true,265,928,true,189,484,true,273,448,true,281,447,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-54-45.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-54-45.csv
new file mode 100644
index 0000000000000000000000000000000000000000..02b42c54391adcc8fcd1cd5f6c366793d3e4a9f1
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-09-54-45.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-09-54-45,1,1,0,1,1,2,40,1,0,1,0,1,1,2,29,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-09-54-45,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,118,276,true,46,191,true,31,131,true,20,93,true,36,72,true,82,111,true,3754269.869999999,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2
+2018-01-16-09-54-46,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,68,300,true,66,323,true,50,197,true,68,184,true,89,253,true,168,281,true,8614715.24,6382704.29,6382704.29,6382704.29,6382704.290000001,6382704.290000001,6382704.290000001
+2018-01-16-09-54-48,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,272,605,true,138,526,true,103,440,true,126,339,true,232,355,true,148,316,true,1.1206278750000002E7,7289379.27,7289379.27,7289379.27,7289379.270000001,7289379.270000001,7289379.270000001
+2018-01-16-09-54-52,1,1,0,1,1,2,40,1,100,1,0,1,1,2,6,210,813,true,207,860,true,288,950,true,210,488,true,218,486,true,280,460,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-21-00.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-21-00.csv
new file mode 100644
index 0000000000000000000000000000000000000000..0861eca6f9190333cda258a9c32c25721131923a
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-21-00.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-10-21-00,1,1,0,1,1,2,40,1,0,1,0,1,1,2,39,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-10-21-00,1,1,0,1,1,2,40,1,25,1,0,1,1,2,10,155,375,true,38,145,true,43,151,true,27,110,true,21,69,true,56,78,true,3754269.8699999996,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2
+2018-01-16-10-21-02,1,1,0,1,1,2,40,1,50,1,0,1,1,2,15,93,260,true,93,211,true,48,222,true,46,139,true,77,265,true,126,185,true,8614715.240000004,6382704.29,6382704.29,6382704.29,6382704.290000001,6382704.290000001,6382704.290000001
+2018-01-16-10-21-04,1,1,0,1,1,2,40,1,75,1,0,1,1,2,23,264,531,true,170,664,true,112,477,true,150,455,true,255,393,true,190,306,true,1.1206278750000002E7,7289379.27,7289379.27,7289379.27,7289379.270000001,7289379.270000001,7289379.270000001
+2018-01-16-10-21-08,1,1,0,1,1,2,40,1,100,1,0,1,1,2,6,198,756,true,239,762,true,185,859,true,179,462,true,248,451,true,236,465,true,1.4461749410000002E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-22-36.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-22-36.csv
new file mode 100644
index 0000000000000000000000000000000000000000..15ff47f4cb8fdb07c4627af65387b40dba020055
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-22-36.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-10-22-36,1,1,0,1,1,2,40,1,0,1,0,1,1,2,36,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-10-22-36,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,133,264,true,36,163,true,23,107,true,34,53,true,23,38,true,32,39,true,3754269.8699999996,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2
+2018-01-16-10-22-37,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,58,267,true,49,270,true,45,187,true,46,91,true,56,101,true,59,79,true,8614715.240000002,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29
+2018-01-16-10-22-38,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,170,534,true,127,505,true,102,426,true,171,258,true,273,318,true,150,175,true,1.1206278749999996E7,7289379.27,7289379.27,7289379.27,7289379.270000001,7289379.270000001,7289379.270000001
+2018-01-16-10-22-41,1,1,0,1,1,2,40,1,100,1,0,1,1,2,7,199,803,true,202,833,true,255,786,true,178,311,true,194,317,true,208,310,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-29-55.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-29-55.csv
new file mode 100644
index 0000000000000000000000000000000000000000..4c06b2d9c050bcff951cd05b8be5e4224ccac516
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-29-55.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-10-29-55,1,1,0,1,1,2,40,1,0,1,0,1,1,2,36,5,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-10-29-55,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,5,20,132,299,true,40,137,true,21,116,true,35,64,true,23,42,true,35,40,true,3754269.8699999996,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2
+2018-01-16-10-29-56,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,5,20,65,233,true,47,290,true,60,208,true,44,82,true,49,99,true,49,69,true,8614715.240000002,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29
+2018-01-16-10-29-57,1,1,0,1,1,2,40,1,75,1,0,1,1,2,3,5,20,156,547,true,105,532,true,178,487,true,117,231,true,160,321,true,174,174,true,1.1206278749999996E7,7289379.27,7289379.27,7289379.27,7289379.270000001,7289379.270000001,7289379.270000001
+2018-01-16-10-30-00,1,1,0,1,1,2,40,1,100,1,0,1,1,2,4,5,20,187,806,true,184,798,true,252,776,true,178,310,true,190,309,true,209,309,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-32-10.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-32-10.csv
new file mode 100644
index 0000000000000000000000000000000000000000..04fe37a65d980b52da5c955edfc91f75593da9cb
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-32-10.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-10-32-10,1,1,0,1,1,2,40,1,0,1,0,1,1,2,33,15,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-10-32-10,1,1,0,1,1,2,40,1,25,1,0,1,1,2,10,15,20,185,243,true,25,144,true,37,136,true,32,64,true,20,40,true,26,56,true,3754269.8699999996,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2
+2018-01-16-10-32-11,1,1,0,1,1,2,40,1,50,1,0,1,1,2,6,15,20,75,261,true,51,233,true,87,212,true,43,74,true,55,94,true,72,102,true,8614715.240000002,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29
+2018-01-16-10-32-12,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,15,20,125,574,true,95,403,true,119,420,true,133,182,true,141,245,true,175,167,true,1.1206278749999996E7,7289379.27,7289379.27,7289379.27,7289379.270000001,7289379.270000001,7289379.270000001
+2018-01-16-10-32-15,1,1,0,1,1,2,40,1,100,1,0,1,1,2,5,15,20,191,782,true,184,752,true,211,890,true,175,309,true,187,307,true,190,345,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-41-51.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-41-51.csv
new file mode 100644
index 0000000000000000000000000000000000000000..3f898ab538c796f5d1952e9e507c94203c40005c
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-41-51.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-10-41-51,1,1,0,1,1,2,40,1,0,1,0,1,1,2,32,100,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-10-41-51,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,100,20,129,284,true,45,157,true,37,120,true,25,47,true,24,40,true,32,36,true,3754269.8699999996,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2
+2018-01-16-10-41-52,1,1,0,1,1,2,40,1,50,1,0,1,1,2,10,100,20,59,249,true,46,257,true,47,189,true,47,88,true,55,114,true,79,119,true,8614715.240000002,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29
+2018-01-16-10-41-54,1,1,0,1,1,2,40,1,75,1,0,1,1,2,19,100,20,198,539,true,104,504,true,144,496,true,177,272,true,249,248,true,167,189,true,1.1206278749999996E7,7289379.27,7289379.27,7289379.27,7289379.270000001,7289379.270000001,7289379.270000001
+2018-01-16-10-41-57,1,1,0,1,1,2,40,1,100,1,0,1,1,2,4,100,20,207,821,true,189,809,true,262,786,true,178,310,true,190,316,true,205,311,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-52-00.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-52-00.csv
new file mode 100644
index 0000000000000000000000000000000000000000..947aa246c2c9348d4f74ad9dbfd69c5c7de82797
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-52-00.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-10-52-00,1,1,0,1,1,2,40,1,0,1,0,1,1,2,29,100,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-10-52-00,1,1,0,1,1,2,40,1,25,1,0,1,1,2,8,100,20,128,272,true,36,164,true,23,130,true,34,68,true,25,42,true,40,38,true,3754269.8699999996,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2,2809811.2
+2018-01-16-10-52-01,1,1,0,1,1,2,40,1,50,1,0,1,1,2,3,100,20,62,237,true,48,298,true,50,216,true,44,83,true,59,89,true,57,99,true,8614715.240000002,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29,6382704.29
+2018-01-16-10-52-03,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,100,20,154,554,true,103,463,true,114,435,true,120,217,true,151,206,true,104,176,true,1.1206278749999996E7,7289379.27,7289379.27,7289379.27,7289379.270000001,7289379.270000001,7289379.270000001
+2018-01-16-10-52-05,1,1,0,1,1,2,40,1,100,1,0,1,1,2,5,100,20,210,822,true,203,808,true,258,792,true,183,313,true,185,312,true,198,317,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-58-41.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-58-41.csv
new file mode 100644
index 0000000000000000000000000000000000000000..951a38bb3239535fd0dda76a756ca3f618d64c1d
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-10-58-41.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-10-58-41,1,1,0,1,1,2,40,1,0,1,0,1,1,2,28,100,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-10-58-41,1,1,0,1,1,2,40,1,25,1,0,1,1,2,8,100,20,108,241,false,29,159,true,34,106,false,-1,-1,false,-1,-1,false,-1,-1,false,3754269.8699999996,0.0,2809811.2,0.0,0.0,0.0,0.0
+2018-01-16-10-58-42,1,1,0,1,1,2,40,1,50,1,0,1,1,2,11,100,20,67,270,false,69,283,true,55,215,false,-1,-1,false,-1,-1,false,-1,-1,false,8614715.240000002,0.0,6250091.81,0.0,0.0,0.0,0.0
+2018-01-16-10-58-43,1,1,0,1,1,2,40,1,75,1,0,1,1,2,5,100,20,166,492,false,110,508,true,118,414,false,-1,-1,false,-1,-1,false,-1,-1,false,1.1206278750000002E7,0.0,7279772.4,0.0,0.0,0.0,0.0
+2018-01-16-10-58-46,1,1,0,1,1,2,40,1,100,1,0,1,1,2,5,100,20,210,792,false,196,841,true,261,746,false,-1,-1,false,-1,-1,false,-1,-1,false,1.4461749410000004E7,0.0,9440690.9,0.0,0.0,0.0,0.0
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-12-15-47.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-12-15-47.csv
new file mode 100644
index 0000000000000000000000000000000000000000..5f8a3c9b2a459064c39bf96cea6b2360c4ebd0eb
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-12-15-47.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-12-15-47,1,1,0,1,1,2,40,1,0,1,0,1,1,2,29,100,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-12-15-47,1,1,0,1,1,2,40,1,25,1,0,1,1,2,10,100,20,164,281,true,52,180,true,36,185,true,39,71,true,47,71,true,55,83,true,3754269.8699999996,2809811.2,2809811.2,2809811.2,2809811.1999999997,2809811.1999999997,2809811.2
+2018-01-16-12-15-48,1,1,0,1,1,2,40,1,50,1,0,1,1,2,5,100,20,98,260,true,89,307,true,72,221,true,46,107,true,96,172,true,58,84,true,8614715.240000002,6250091.81,6250091.81,6250091.81,6250091.810000001,6250091.810000001,6250091.810000001
+2018-01-16-12-15-50,1,1,0,1,1,2,40,1,75,1,0,1,1,2,6,100,20,188,580,true,105,480,true,195,481,true,181,221,true,178,347,true,130,227,true,1.1206278749999996E7,7279772.4,7279772.4,7279772.4,7279772.400000001,7279772.400000001,7279772.400000001
+2018-01-16-12-15-53,1,1,0,1,1,2,40,1,100,1,0,1,1,2,6,100,20,204,863,true,233,778,true,258,871,true,190,325,true,220,320,true,204,327,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-12-19-37.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-12-19-37.csv
new file mode 100644
index 0000000000000000000000000000000000000000..ce9d3697ee89b3bedc689afd18270913553d59b5
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-12-19-37.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-12-19-37,1,1,0,1,1,2,40,1,0,1,0,1,1,2,30,100,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-12-19-37,1,1,0,1,1,2,40,1,25,1,0,1,1,2,9,100,20,159,272,true,45,171,true,27,132,true,38,46,true,25,48,true,27,59,true,3754269.8699999996,2809811.2,2809811.2,2809811.2,2809811.1999999997,2809811.1999999997,2809811.2
+2018-01-16-12-19-38,1,1,0,1,1,2,40,1,50,1,0,1,1,2,6,100,20,61,240,true,63,261,true,90,219,true,53,87,true,57,144,true,71,118,true,8614715.240000002,6250091.81,6250091.81,6250091.81,6250091.810000001,6250091.810000001,6250091.810000001
+2018-01-16-12-19-40,1,1,0,1,1,2,40,1,75,1,0,1,1,2,6,100,20,172,585,true,113,489,true,183,423,true,134,266,true,188,302,true,184,190,true,1.1206278749999996E7,7279772.4,7279772.4,7279772.4,7279772.400000001,7279772.400000001,7279772.400000001
+2018-01-16-12-19-43,1,1,0,1,1,2,40,1,100,1,0,1,1,2,8,100,20,198,804,true,190,766,true,262,866,true,178,316,true,189,310,true,184,328,true,1.4461749410000008E7,9440690.9,9440690.9,9440690.9,9440690.900000004,9440690.900000004,9440690.900000004
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-13-56-06.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-13-56-06.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8b81f9866aceec9432c7e29e131bb4c570478897
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-13-56-06.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-13-56-06,1,1,0,1,3,2,40,1,0,1,0,1,3,6,33,100,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-13-56-06,1,1,0,1,3,2,40,1,25,1,0,1,3,6,9,100,20,338,544,true,68,335,true,64,315,true,144,163,true,63,124,true,112,130,true,3798531.44,2509547.62,2509547.62,2509547.62,2509547.62,2509547.62,2509547.62
+2018-01-16-13-56-09,1,1,0,1,3,2,40,1,50,1,0,1,3,6,12,100,20,201,821,true,164,644,true,170,747,true,194,703,true,161,719,true,190,761,true,8982037.919999998,5464938.59,5548427.75,5406579.61,5395088.479999999,5406579.610000001,5395088.4799999995
+2018-01-16-13-56-14,1,1,0,1,3,2,40,1,75,1,0,1,3,6,4,100,20,367,1560,true,341,1590,true,340,1384,true,355,656,true,476,650,true,362,607,true,1.1645878680000002E7,7882095.92,7882095.92,7882095.92,7882095.919999997,7882095.919999997,7882095.919999997
+2018-01-16-13-56-23,1,1,0,1,3,2,40,1,100,1,0,1,3,6,5,100,20,655,3028,true,621,2679,true,622,2944,true,629,1123,true,710,1114,true,731,1097,true,1.4230622959999999E7,9257569.34,9257569.34,9257569.34,9257569.34,9257569.34,9257569.34
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-13-59-45.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-13-59-45.csv
new file mode 100644
index 0000000000000000000000000000000000000000..9d9ea8644a1bfc6d630d53158065c9e080dfa701
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-16-13-59-45.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-16-13-59-45,1,1,0,1,3,2,40,1,0,1,0,1,3,6,37,100,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-16-13-59-45,1,1,0,1,3,2,40,1,25,1,0,1,3,6,10,100,20,275,525,true,85,349,true,112,396,true,64,105,true,123,83,true,63,107,true,3798531.4400000004,2509547.62,2509547.62,2509547.62,2509547.6200000006,2509547.6200000006,2509547.620000001
+2018-01-16-13-59-47,1,1,0,1,3,2,40,1,50,1,0,1,3,6,3,100,20,246,741,true,175,703,true,165,743,true,210,2154,true,142,8545,true,145,538,true,8982037.919999998,5464938.59,5548427.75,5406579.61,5464938.589999999,5548427.75,5406579.609999999
+2018-01-16-14-00-02,1,1,0,1,3,2,40,1,75,1,0,1,3,6,4,100,20,402,1419,true,407,1312,true,367,1351,true,401,716,true,397,1008,true,363,702,true,1.164587868E7,7882095.92,7882095.92,7882095.92,7882095.919999997,7882095.919999999,7882095.919999996
+2018-01-16-14-00-11,1,1,0,1,3,2,40,1,100,1,0,1,3,6,2,100,20,746,2919,true,708,2955,true,680,3065,true,638,1109,true,699,1118,true,698,1069,true,1.423062296E7,9257569.34,9257569.34,9257569.34,9257569.339999996,9257569.339999998,9257569.34
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-17-10-56-22.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-17-10-56-22.csv
new file mode 100644
index 0000000000000000000000000000000000000000..2edf4c4e74277d4a6ca460f1ac750b409e9db2a0
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-17-10-56-22.csv
@@ -0,0 +1,6 @@
+timestamp,topLevelComponents,avgSubComponents,subComponentStdDerivation,componentDepth,implementations,modes,computeResources,nonfunctionalProperties,requests,cpus,seed,genComponents,genImplementations,genConfigurations,modelGeneration,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy
+2018-01-17-10-56-22,1,1,0,1,3,2,40,1,0,1,0,1,3,6,35,100,20,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0,0,true,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-17-10-56-22,1,1,0,1,3,2,40,1,25,1,0,1,3,6,9,100,20,252,563,true,116,358,true,64,314,true,117,105,true,69,125,true,105,106,true,3798531.4399999995,2509547.62,2509547.62,2509547.62,2509547.6200000006,2509547.6200000006,2509547.620000001
+2018-01-17-10-56-24,1,1,0,1,3,2,40,1,50,1,0,1,3,6,5,100,20,197,785,true,158,762,true,154,786,true,174,2364,true,156,10378,true,198,706,true,8982037.920000002,5464938.59,5548427.75,5406579.61,5464938.59,5548427.749999998,5406579.61
+2018-01-17-10-56-41,1,1,0,1,3,2,40,1,75,1,0,1,3,6,3,100,20,362,1648,true,365,1576,true,346,1383,true,362,589,true,405,651,true,353,675,true,1.1645878679999998E7,7882095.92,7882095.92,7882095.92,7882095.919999998,7882095.919999999,7882095.919999997
+2018-01-17-10-56-50,1,1,0,1,3,2,40,1,100,1,0,1,3,6,5,100,20,655,2918,true,624,2522,true,654,2502,true,680,1119,true,635,1089,true,633,1133,true,1.4230622959999999E7,9257569.34,9257569.34,9257569.34,9257569.339999998,9257569.339999998,9257569.339999996
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-18-16-17-23.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-18-16-17-23.csv
new file mode 100644
index 0000000000000000000000000000000000000000..380029b651d902e656c7ee7b1646b8994278b8b9
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-18-16-17-23.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGeneration0,ilp-externalSolving0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenerationHard,ilp-externalSolvingHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenerationEasy,ilp-externalSolvingEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGeneration0,ilp-directSolving0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenerationHard,ilp-directSolvingHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenerationEasy,ilp-directSolvingEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolving0,simpleValid0,simpleTimeOut0,simpleSolvingHard,simpleValidHard,simpleTimeOutHard,simpleSolvingEasy,simpleValidEasy,simpleTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy
+2018-01-18-16-17-23,1,1,0,1,3,2,40,1,0,1,0,1,3,6,32,100,20,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-18-16-17-23,1,1,0,1,3,2,40,1,1,1,0,1,3,6,16,100,20,62,101,true,false,9,44,true,false,17,27,true,false,6,34,true,false,6,8,true,false,5,9,true,false,5,true,false,3,true,false,7,true,false,345548.75,131274.92,131274.92,131274.92,131274.91999999998,131274.91999999998,131274.91999999998,131274.92,131274.92,131274.92
+2018-01-18-16-17-23,1,1,0,1,3,2,40,1,2,1,0,1,3,6,1,100,20,17,62,true,false,20,61,true,false,10,43,true,false,12,18,true,false,13,50,true,false,23,58,true,false,16,true,false,18,true,false,19,true,false,580734.28,361218.02,361218.02,296864.57,361218.02,361218.02,296864.56999999995,361218.02,361218.02,296864.57
+2018-01-18-16-17-24,1,1,0,1,3,2,40,1,3,1,0,1,3,6,1,100,20,41,70,true,false,20,63,true,false,24,48,true,false,12,18,true,false,15,19,true,false,8,11,true,false,57,true,false,43,true,false,64,true,false,693341.58,367752.27,367752.27,302788.86,367752.26999999996,367752.26999999996,302788.8599999999,367752.26999999996,367752.26999999996,302788.86
+2018-01-18-16-17-24,1,1,0,1,3,2,40,1,4,1,0,1,3,6,1,100,20,21,103,true,false,30,58,true,false,13,42,true,false,27,19,true,false,27,26,true,false,21,12,true,false,1207,true,false,707,true,false,866,true,false,801741.8099999999,459241.98,459241.98,459241.98,459241.98,459241.98,459241.98,459241.98,459241.98,459241.98
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-18-16-38-48.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-18-16-38-48.csv
new file mode 100644
index 0000000000000000000000000000000000000000..792ecf28a15f15c3377f52506645a72809fd05f4
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-18-16-38-48.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy
+2018-01-18-16-38-48,1,1,0,1,3,2,40,1,0,1,0,1,3,6,36,100,20,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-18-16-38-48,1,1,0,1,3,2,40,1,1,1,0,1,3,6,5,100,20,46,135,true,false,10,60,true,false,7,33,true,false,6,19,true,false,5,7,true,false,5,7,true,false,4,true,false,3,true,false,2,true,false,345548.75,131274.92,131274.92,131274.92,131274.91999999998,131274.91999999998,131274.91999999998,131274.92,131274.92,131274.92
+2018-01-18-16-38-48,1,1,0,1,3,2,40,1,2,1,0,1,3,6,1,100,20,11,42,true,false,12,47,true,false,7,36,true,false,10,17,true,false,10,15,true,false,8,16,true,false,8,true,false,8,true,false,11,true,false,580734.28,361218.02,361218.02,296864.57,361218.02,361218.02,296864.56999999995,361218.02,361218.02,296864.57
+2018-01-18-16-38-49,1,1,0,1,3,2,40,1,3,1,0,1,3,6,1,100,20,28,55,true,false,12,47,true,false,11,74,true,false,11,18,true,false,13,15,true,false,7,11,true,false,49,true,false,37,true,false,70,true,false,693341.58,367752.27,367752.27,302788.86,367752.26999999996,367752.26999999996,302788.8599999999,367752.26999999996,367752.26999999996,302788.86
+2018-01-18-16-38-49,1,1,0,1,3,2,40,1,4,1,0,1,3,6,1,100,20,28,69,true,false,33,61,true,false,30,60,true,false,16,22,true,false,15,24,true,false,13,30,true,false,1174,true,false,589,true,false,822,true,false,801741.8099999999,459241.98,459241.98,459241.98,459241.98,459241.98,459241.98,459241.98,459241.98,459241.98
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-13-55-30.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-13-55-30.csv
new file mode 100644
index 0000000000000000000000000000000000000000..e0a71ed86d8a9b7c81b4d08b7823f575b8b8492d
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-13-55-30.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
+2018-01-19-13-55-30,1,1,0,1,3,2,1.0,1,0,1,0,1,3,6,27,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,5,0,true,false,0,0,true,false,0,0,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-19-13-55-30,1,1,0,1,3,2,1.0,1,1,1,0,1,3,6,3,100,25,8,38,true,false,2,11,true,false,1,7,true,false,1,14,true,false,0,4,true,false,1,3,true,false,2,true,false,1,true,false,1,true,false,0,0,false,false,0,0,true,false,0,0,false,false,5707.990000000001,5707.99,5707.99,5707.99,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,-5707.0,-5707.0,-17455.0
+2018-01-19-13-55-45,1,1,0,1,3,2,1.0,1,2,1,0,1,3,6,0,100,25,1,11,true,false,2,14,true,false,1,11,true,false,1,3,true,false,5,3,true,false,1,2,true,false,7,true,false,4,true,false,3,true,false,0,0,false,false,0,0,false,false,0,0,false,false,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,-406855.0,-151820.0,-325456.0
+2018-01-19-13-56-00,1,1,0,1,3,2,1.0,1,3,1,0,1,3,6,0,100,25,2,23,true,false,9,16,true,false,2,35,true,false,2,11,true,false,2,2,true,false,4,2,true,false,9,true,false,6,true,false,6,true,false,0,0,false,false,0,0,false,false,0,0,false,false,305746.44999999995,305746.45,305746.45,305746.45,305746.45,305746.45,305746.45,305746.44999999995,305746.44999999995,305746.44999999995,-194354.0,-361607.0,-335866.0
+2018-01-19-13-56-15,1,1,0,1,3,2,1.0,1,4,1,0,1,3,6,0,100,25,2,14,true,false,3,14,true,false,1,21,true,false,2,4,true,false,2,5,true,false,3,4,true,false,85,true,false,36,true,false,68,true,false,0,0,false,false,0,0,false,false,0,0,false,false,155750.37,75180.08,109479.6,75180.08,75180.08,109479.59999999999,75180.08,75180.08,109479.59999999999,75180.08,-179125.0,-188436.0,-213464.0
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-15-55-54.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-15-55-54.csv
new file mode 100644
index 0000000000000000000000000000000000000000..e6eec3da8ba9fd09c7a421d01dc2f93c0e5278ed
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-15-55-54.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
+2018-01-19-15-55-54,1,1,0,1,3,2,1.0,1,0,1,0,1,3,6,25,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,5,0,true,false,0,0,true,false,0,0,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-19-15-55-55,1,1,0,1,3,2,1.0,1,1,1,0,1,3,6,3,100,25,12,34,true,false,2,10,true,false,1,10,true,false,1,14,true,false,1,1,true,false,0,1,true,false,3,true,false,1,true,false,1,true,false,0,0,true,false,0,0,false,false,0,0,false,false,5707.990000000001,5707.99,5707.99,5707.99,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,-5707.0,-44193.0,-17455.0
+2018-01-19-15-56-10,1,1,0,1,3,2,1.0,1,2,1,0,1,3,6,0,100,25,2,12,true,false,1,14,true,false,1,16,true,false,2,3,true,false,1,3,true,false,1,3,true,false,8,true,false,6,true,false,3,true,false,0,0,false,false,0,0,false,false,0,0,false,false,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,-400601.0,-380368.0,-131587.0
+2018-01-19-15-56-25,1,1,0,1,3,2,1.0,1,3,1,0,1,3,6,0,100,25,2,21,true,false,2,12,true,false,1,27,true,false,2,4,true,false,2,3,true,false,2,3,true,false,9,true,false,8,true,false,7,true,false,0,0,false,false,0,0,false,false,0,0,false,false,305746.44999999995,305746.45,305746.45,305746.45,305746.45,305746.45,305746.45,305746.44999999995,305746.44999999995,305746.44999999995,-161894.0,-93429.0,-93429.0
+2018-01-19-15-56-40,1,1,0,1,3,2,1.0,1,4,1,0,1,3,6,0,100,25,2,24,true,false,4,12,true,false,2,13,true,false,3,4,true,false,2,5,true,false,2,13,true,false,67,true,false,33,true,false,81,true,false,0,0,false,false,0,0,false,false,0,0,false,false,155750.37,75180.08,109479.6,75180.08,75180.08,109479.59999999999,75180.08,75180.08,109479.59999999999,75180.08,-251521.0,-210789.0,-147844.0
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-17-10-30.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-17-10-30.csv
new file mode 100644
index 0000000000000000000000000000000000000000..0370837d2b5be4b8203ed677902f1eb13ab130a3
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-17-10-30.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
+2018-01-19-17-10-30,1,1,0,1,3,2,1.0,1,0,1,0,1,3,6,31,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,7,0,true,false,0,0,true,false,0,0,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-19-17-10-30,1,1,0,1,3,2,1.0,1,1,1,0,1,3,6,7,100,25,12,39,true,false,2,10,true,false,2,6,true,false,0,10,true,false,0,1,true,false,1,2,true,false,2,true,false,1,true,false,1,true,false,0,0,false,false,0,0,true,false,0,0,false,false,5707.990000000001,5707.99,5707.99,5707.99,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,-44193.0,-5707.0,-5707.0
+2018-01-19-17-11-30,1,1,0,1,3,2,1.0,1,2,1,0,1,3,6,0,100,25,1,7,true,false,1,13,true,false,1,12,true,false,1,5,true,false,1,3,true,false,1,3,true,false,5,true,false,3,true,false,3,true,false,0,0,false,false,0,0,false,false,0,0,false,false,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,-74085.0,-377577.0,-154035.0
+2018-01-19-17-12-31,1,1,0,1,3,2,1.0,1,3,1,0,1,3,6,0,100,25,2,16,true,false,4,14,true,false,2,14,true,false,2,2,true,false,2,3,true,false,1,3,true,false,7,true,false,6,true,false,6,true,false,0,0,false,false,0,0,false,false,0,0,false,false,305746.44999999995,305746.45,305746.45,305746.45,305746.45,305746.45,305746.45,305746.44999999995,305746.44999999995,305746.44999999995,-319188.0,-73438.0,-161894.0
+2018-01-19-17-13-31,1,1,0,1,3,2,1.0,1,4,1,0,1,3,6,1,100,25,3,18,true,false,2,15,true,false,2,12,true,false,2,4,true,false,2,4,true,false,2,5,true,false,110,true,false,62,true,false,98,true,false,0,0,false,false,0,0,false,false,0,0,false,false,155750.37,75180.08,109479.6,75180.08,75180.08,109479.59999999999,75180.08,75180.08,109479.59999999999,75180.08,-209585.0,-538480.0,-432826.0
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-17-50-04.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-17-50-04.csv
new file mode 100644
index 0000000000000000000000000000000000000000..5f6f6ff433d7c44cff20ece2efea6cc0a8c83f37
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-17-50-04.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
+2018-01-19-17-50-04,1,1,0,1,3,2,1.0,1,0,1,0,1,3,6,26,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,6,31,true,false,0,2,true,false,0,1,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-19-17-50-04,1,1,0,1,3,2,1.0,1,1,1,0,1,3,6,6,100,25,11,35,true,false,1,10,true,false,2,6,true,false,9,2,true,false,2,1,true,false,2,0,true,false,2,true,false,1,true,false,1,true,false,0,20007,false,false,1,20001,false,false,0,20001,false,false,5707.990000000001,5707.99,5707.99,5707.99,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,37422.0,17455.0,44193.0
+2018-01-19-17-51-04,1,1,0,1,3,2,1.0,1,2,1,0,1,3,6,0,100,25,2,13,true,false,1,14,true,false,1,12,true,false,2,4,true,false,2,1,true,false,2,0,true,false,6,true,false,4,true,false,3,true,false,0,20000,false,false,0,20000,false,false,0,20000,false,false,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,42126.0,325456.0,131587.0
+2018-01-19-17-52-04,1,1,0,1,3,2,1.0,1,3,1,0,1,3,6,1,100,25,2,11,true,false,2,14,true,false,1,12,true,false,4,1,true,false,2,0,true,false,2,0,true,false,8,true,false,6,true,false,5,true,false,0,20000,false,false,0,20000,false,false,0,20000,false,false,305746.44999999995,305746.45,305746.45,305746.45,305746.45,305746.45,305746.45,305746.44999999995,305746.44999999995,305746.44999999995,93429.0,319188.0,414196.0
+2018-01-19-17-53-05,1,1,0,1,3,2,1.0,1,4,1,0,1,3,6,0,100,25,2,12,true,false,2,12,true,false,2,13,true,false,8,4,true,false,4,2,true,false,3,1,true,false,66,true,false,30,true,false,77,true,false,0,20000,false,false,0,20001,false,false,0,20000,false,false,155750.37,75180.08,109479.6,75180.08,75180.08,109479.59999999999,75180.08,75180.08,109479.59999999999,75180.08,304857.0,417131.0,501766.0
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-26-59.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-26-59.csv
new file mode 100644
index 0000000000000000000000000000000000000000..56297880ee13704de0acfa38e4b8b0638728f4e5
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-26-59.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
+2018-01-19-18-26-59,1,1,0,1,3,2,1.5,1,0,1,0,1,3,6,37,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,5,26,true,false,0,1,true,false,0,0,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-19-18-27-00,1,1,0,1,3,2,1.5,1,1,1,0,1,3,6,3,100,25,11,37,true,false,5,12,true,false,1,10,true,false,11,2,true,false,0,0,true,false,0,0,true,false,2,true,false,1,true,false,2,true,false,0,20007,false,false,0,20001,false,false,0,20000,false,false,5707.990000000001,5707.99,5707.99,5707.99,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,37422.0,37422.0,44457.0
+2018-01-19-18-28-00,1,1,0,1,3,2,1.5,1,2,1,0,1,3,6,0,100,25,1,11,true,false,2,19,true,false,2,16,true,false,3,3,true,false,2,1,true,false,2,2,true,false,7,true,false,5,true,false,3,true,false,0,20000,false,false,0,20000,false,false,0,20001,false,false,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,51061.0,316713.0,54109.0
+2018-01-19-18-29-00,1,1,0,1,3,2,1.5,1,3,1,0,1,3,6,0,100,25,3,19,true,false,3,16,true,false,2,13,true,false,5,0,true,false,5,0,true,false,4,0,true,false,8,true,false,6,true,false,5,true,false,0,20001,false,false,0,20001,false,false,0,20000,false,false,305746.44999999995,305746.45,305746.45,305746.45,305746.45,305746.45,305746.45,305746.44999999995,305746.44999999995,305746.44999999995,347410.0,186710.0,420915.0
+2018-01-19-18-30-00,1,1,0,1,3,2,1.5,1,4,1,0,1,3,6,0,100,25,2,13,true,false,5,19,true,false,3,10,true,false,9,0,true,false,6,0,true,false,4,0,true,false,107,true,false,42,true,false,83,true,false,0,20001,false,false,0,20000,false,false,0,20000,false,false,155750.37,75180.08,109479.6,75180.08,75180.08,109479.59999999999,75180.08,75180.08,109479.59999999999,75180.08,102415.0,184056.0,189970.0
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-32-07.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-32-07.csv
new file mode 100644
index 0000000000000000000000000000000000000000..bc57606707aa5532d7bd272902084bafa2cf9c9e
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-32-07.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
+2018-01-19-18-32-07,1,1,0,1,3,2,1.5,1,0,1,0,1,3,6,30,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,5,22,true,false,0,1,true,false,0,1,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-19-18-32-07,1,1,0,1,3,2,1.5,1,1,1,0,1,3,6,7,100,25,13,44,true,false,2,12,true,false,2,12,true,false,10,2,true,false,1,0,true,false,1,0,true,false,4,true,false,1,true,false,1,true,false,0,60001,false,false,0,59999,false,false,0,59999,false,false,5707.990000000001,5707.99,5707.99,5707.99,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,44457.0,5707.0,37422.0
+2018-01-19-18-35-08,1,1,0,1,3,2,1.5,1,2,1,0,1,3,6,0,100,25,1,18,true,false,3,21,true,false,3,13,true,false,4,1,true,false,4,1,true,false,3,1,true,false,13,true,false,8,true,false,7,true,false,0,59999,false,false,0,59999,false,false,0,59999,false,false,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,406855.0,158074.0,51061.0
+2018-01-19-18-38-08,1,1,0,1,3,2,1.5,1,3,1,0,1,3,6,1,100,25,3,23,true,false,3,16,true,false,2,14,true,false,5,1,true,false,5,1,true,false,5,4,true,false,8,true,false,6,true,false,6,true,false,0,59999,false,false,0,59999,false,false,0,60000,false,false,305746.44999999995,305746.45,305746.45,305746.45,305746.45,305746.45,305746.45,305746.44999999995,305746.44999999995,305746.44999999995,368326.0,172513.0,93243.0
+2018-01-19-18-41-08,1,1,0,1,3,2,1.5,1,4,1,0,1,3,6,0,100,25,2,13,true,false,3,16,true,false,2,12,true,false,4,0,true,false,4,0,true,false,5,1,true,false,100,true,false,40,true,false,73,true,false,0,59999,false,false,0,60000,false,false,0,59999,false,false,155750.37,75180.08,109479.6,75180.08,75180.08,109479.59999999999,75180.08,75180.08,109479.59999999999,75180.08,227780.0,219105.0,483999.0
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-46-49.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-46-49.csv
new file mode 100644
index 0000000000000000000000000000000000000000..182a6e01afd7a39c49f9da3e315cb0d62ea85335
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-46-49.csv
@@ -0,0 +1,2 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
+2018-01-19-18-46-49,1,1,0,1,3,2,1.5,1,0,1,0,1,3,6,26,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,7,25,true,false,0,1,true,false,0,1,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
diff --git a/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-48-23.csv b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-48-23.csv
new file mode 100644
index 0000000000000000000000000000000000000000..73dee14e37b946df4ef2be96366412a7701c2206
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/inc-benchmark-2018-01-19-18-48-23.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
+2018-01-19-18-48-23,1,1,0,1,3,2,1.5,1,0,1,0,1,3,6,28,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,5,28,true,false,0,3,true,false,0,1,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-19-18-48-23,1,1,0,1,3,2,1.5,1,1,1,0,1,3,6,6,100,25,16,37,true,false,3,10,true,false,2,7,true,false,12,4,true,false,2,0,true,false,0,0,true,false,2,true,false,3,true,false,2,true,false,0,10000,false,false,0,9999,false,false,0,9999,false,false,5707.990000000001,5707.99,5707.99,5707.99,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.0,37422.0,5707.0
+2018-01-19-18-48-53,1,1,0,1,3,2,1.5,1,2,1,0,1,3,6,2,100,25,2,12,true,false,2,15,true,false,2,12,true,false,3,2,true,false,3,1,true,false,3,1,true,false,8,true,false,8,true,false,4,true,false,0,10000,false,false,0,10000,false,false,0,10000,false,false,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,316713.0,74277.0,42126.0
+2018-01-19-18-49-24,1,1,0,1,3,2,1.5,1,3,1,0,1,3,6,0,100,25,2,20,true,false,5,20,true,false,2,15,true,false,5,0,true,false,5,0,true,false,5,0,true,false,8,true,false,6,true,false,5,true,false,0,10000,false,false,0,9999,false,false,0,10000,false,false,305746.44999999995,305746.45,305746.45,305746.45,305746.45,305746.45,305746.45,305746.44999999995,305746.44999999995,305746.44999999995,99967.0,93243.0,93243.0
+2018-01-19-18-49-54,1,1,0,1,3,2,1.5,1,4,1,0,1,3,6,0,100,25,2,13,true,false,2,11,true,false,2,9,true,false,4,0,true,false,4,0,true,false,5,0,true,false,104,true,false,51,true,false,88,true,false,0,9999,false,false,0,9999,false,false,0,9999,false,false,155750.37,75180.08,109479.6,75180.08,75180.08,109479.59999999999,75180.08,75180.08,109479.59999999999,75180.08,301861.0,460829.0,193712.0
diff --git a/jastadd-mquat-benchmark/old-results/incremental/benchmark-2018-01-22-14-50-16.csv b/jastadd-mquat-benchmark/old-results/incremental/benchmark-2018-01-22-14-50-16.csv
new file mode 100644
index 0000000000000000000000000000000000000000..d5ccc5e84ad1b6d9d5ddba1e9f79495d84691320
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/incremental/benchmark-2018-01-22-14-50-16.csv
@@ -0,0 +1 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
diff --git a/jastadd-mquat-benchmark/old-results/incremental/benchmark-2018-01-22-14-56-31.csv b/jastadd-mquat-benchmark/old-results/incremental/benchmark-2018-01-22-14-56-31.csv
new file mode 100644
index 0000000000000000000000000000000000000000..28cb1b79bb635f9ea8c2fd9641afa6bb401ce6a4
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/incremental/benchmark-2018-01-22-14-56-31.csv
@@ -0,0 +1,3 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,initialObjective,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy
+2018-01-22-14-56-31,1,1,0,1,3,2,1.5,1,0,1,0,1,3,6,22,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,true,false,0,true,false,0,true,false,8,30,true,false,0,1,true,false,0,1,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-22-14-56-31,1,1,0,1,3,2,1.5,1,1,1,0,1,3,6,5,100,25,11,36,true,false,2,9,true,false,2,10,true,false,15,3,true,false,2,0,true,false,2,0,true,false,3,true,false,3,true,false,3,true,false,0,10000,false,false,0,9999,false,false,0,10000,false,false,5707.990000000001,5707.99,5707.99,5707.99,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,44457.0,44457.0,37422.0
diff --git a/jastadd-mquat-benchmark/old-results/incremental/benchmark-2018-01-22-15-09-17.csv b/jastadd-mquat-benchmark/old-results/incremental/benchmark-2018-01-22-15-09-17.csv
new file mode 100644
index 0000000000000000000000000000000000000000..d9986d0f8c91d00ae72cc559fec4af8fc24522e2
--- /dev/null
+++ b/jastadd-mquat-benchmark/old-results/incremental/benchmark-2018-01-22-15-09-17.csv
@@ -0,0 +1,6 @@
+when,tlc,asc,std,dep,bi,bm,res,nfp,req,cpu,seed,comp,impl,conf,gen,reqToChange,percentToChange,ilp-directGen0,ilp-directSolved0,ilp-directValid0,ilp-directTimeOut0,ilp-directGenHard,ilp-directSolvedHard,ilp-directValidHard,ilp-directTimeOutHard,ilp-directGenEasy,ilp-directSolvedEasy,ilp-directValidEasy,ilp-directTimeOutEasy,ilp-externalGen0,ilp-externalSolved0,ilp-externalValid0,ilp-externalTimeOut0,ilp-externalGenHard,ilp-externalSolvedHard,ilp-externalValidHard,ilp-externalTimeOutHard,ilp-externalGenEasy,ilp-externalSolvedEasy,ilp-externalValidEasy,ilp-externalTimeOutEasy,mh-naiveGen0,mh-naiveSolved0,mh-naiveValid0,mh-naiveTimeOut0,mh-naiveGenHard,mh-naiveSolvedHard,mh-naiveValidHard,mh-naiveTimeOutHard,mh-naiveGenEasy,mh-naiveSolvedEasy,mh-naiveValidEasy,mh-naiveTimeOutEasy,simpleSolved0,simpleValid0,simpleTimeOut0,simpleSolvedHard,simpleValidHard,simpleTimeOutHard,simpleSolvedEasy,simpleValidEasy,simpleTimeOutEasy,initialObjective,ilp-directObjective0,ilp-directObjectiveHard,ilp-directObjectiveEasy,ilp-externalObjective0,ilp-externalObjectiveHard,ilp-externalObjectiveEasy,mh-naiveObjective0,mh-naiveObjectiveHard,mh-naiveObjectiveEasy,simpleObjective0,simpleObjectiveHard,simpleObjectiveEasy
+2018-01-22-15-09-17,1,1,0,1,3,2,1.5,1,0,1,0,1,3,6,25,100,25,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,0,0,true,false,6,22,true,false,0,1,true,false,0,1,true,false,0,true,false,0,true,false,0,true,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+2018-01-22-15-09-17,1,1,0,1,3,2,1.5,1,1,1,0,1,3,6,11,100,25,27,3,true,false,7,2,true,false,4,3,true,false,2,34,true,false,2,8,true,false,1,6,true,false,0,10001,false,false,0,9999,false,false,0,10000,false,false,1,true,false,2,true,false,2,true,false,5707.990000000001,5707.990000000001,5707.990000000001,5707.990000000001,5707.99,5707.99,5707.99,44457.0,37422.0,17455.0,5707.990000000001,5707.990000000001,5707.990000000001
+2018-01-22-15-09-47,1,1,0,1,3,2,1.5,1,2,1,0,1,3,6,1,100,25,3,2,true,false,4,2,true,false,3,0,true,false,1,15,true,false,2,14,true,false,1,12,true,false,0,10000,false,false,0,10000,false,false,2,10000,false,false,5,true,false,4,true,false,3,true,false,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.79,128796.0,131844.0,142566.0,128796.79,128796.79,128796.79
+2018-01-22-15-10-17,1,1,0,1,3,2,1.5,1,3,1,0,1,3,6,0,100,25,6,0,true,false,6,0,true,false,5,0,true,false,2,21,true,false,2,16,true,false,2,15,true,false,0,10000,false,false,0,9999,false,false,0,9999,false,false,7,true,false,6,true,false,5,true,false,305746.44999999995,305746.45,305746.45,305746.45,305746.45,305746.45,305746.45,427639.0,193429.0,160784.0,305746.44999999995,305746.44999999995,305746.44999999995
+2018-01-22-15-10-47,1,1,0,1,3,2,1.5,1,4,1,0,1,3,6,0,100,25,7,0,true,false,5,0,true,false,6,0,true,false,3,21,true,false,4,17,true,false,3,20,true,false,0,9999,false,false,0,10000,false,false,0,9999,false,false,53,true,false,25,true,false,54,true,false,155750.37,75180.08,109479.59999999999,75180.08,75180.08,109479.6,75180.08,218606.0,292426.0,178276.0,75180.08,109479.59999999999,75180.08
diff --git a/jastadd-mquat-benchmark/results/.gitignore b/jastadd-mquat-benchmark/results/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..4da2c52ba7cf6cff45a5ef64dd0a3f1c4522826b
--- /dev/null
+++ b/jastadd-mquat-benchmark/results/.gitignore
@@ -0,0 +1,5 @@
+*
+!.gitignore
+!jastadd-mquat-plots.ipynb
+!to-html.sh
+!fr
diff --git a/jastadd-mquat-benchmark/results/fr/.gitignore b/jastadd-mquat-benchmark/results/fr/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d6b7ef32c8478a48c3994dcadc86837f4371184d
--- /dev/null
+++ b/jastadd-mquat-benchmark/results/fr/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/jastadd-mquat-benchmark/results/jastadd-mquat-plots.ipynb b/jastadd-mquat-benchmark/results/jastadd-mquat-plots.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..bdded81c25a5d39aa085864df26a9dcf08a78e29
--- /dev/null
+++ b/jastadd-mquat-benchmark/results/jastadd-mquat-plots.ipynb
@@ -0,0 +1,461 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Requirement already satisfied: numpy in /home/rschoene/.local/lib/python3.6/site-packages\r\n",
+      "Requirement already satisfied: pandas in /home/rschoene/.local/lib/python3.6/site-packages\r\n",
+      "Requirement already satisfied: scipy in /home/rschoene/.local/lib/python3.6/site-packages\r\n",
+      "Requirement already satisfied: matplotlib in /home/rschoene/.local/lib/python3.6/site-packages\r\n",
+      "Requirement already satisfied: python-dateutil>=2 in /home/rschoene/.local/lib/python3.6/site-packages (from pandas)\r\n",
+      "Requirement already satisfied: pytz>=2011k in /usr/lib/python3.6/site-packages (from pandas)\r\n",
+      "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/lib/python3.6/site-packages (from matplotlib)\r\n",
+      "Requirement already satisfied: cycler>=0.10 in /home/rschoene/.local/lib/python3.6/site-packages (from matplotlib)\r\n",
+      "Requirement already satisfied: six>=1.10 in /usr/lib/python3.6/site-packages (from matplotlib)\r\n"
+     ]
+    }
+   ],
+   "source": [
+    "!pip3 install --user numpy pandas scipy matplotlib\n",
+    "import pandas as pd\n",
+    "import numpy as np\n",
+    "import scipy as sp\n",
+    "import matplotlib.pyplot as plt\n",
+    "from matplotlib import colors as mcolors\n",
+    "# import plotly.plotly as py\n",
+    "# import plotly.figure_factory as ff\n",
+    "# from plotly.graph_objs import *"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "%matplotlib inline"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['ILP (Direct)', 'ILP (External)', 'Simple']"
+      ]
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "def toLabel(name):\n",
+    "    if '-' in name:\n",
+    "        tokens = name.split('-')\n",
+    "        return '{} ({})'.format(tokens[0].upper(), tokens[1].title())\n",
+    "    else:\n",
+    "        return name.title()\n",
+    "\n",
+    "[toLabel(n) for n in ['ilp-direct', 'ilp-external', 'simple']]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "bar_width = 0.2\n",
+    "solver_names = ['ilp-direct', 'ilp-external', 'simple', 'mh-naive']\n",
+    "patterns = ['❌', '❌', '✔', '➖']\n",
+    "colors = [c[4:] for c in (sorted(mcolors.TABLEAU_COLORS.keys())) if 'dark'+c[4:] in mcolors.CSS4_COLORS]\n",
+    "colors.reverse()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def load(name, show_head=False):\n",
+    "    data = pd.read_csv(name)\n",
+    "    data['name'] = data.comp.astype(str).str.cat(\n",
+    "        [data.impl.astype(str),\n",
+    "         data.conf.astype(str),\n",
+    "         data.req.astype(str)], sep='-')\n",
+    "    if show_head:\n",
+    "        data.head()\n",
+    "    return data"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def add_gen_and_solve(ax, index, i, solver_name, df, suffix, printStatus=True):\n",
+    "    pattern_index = 2 * df.get(solver_name + 'Valid' + suffix) + df.get(solver_name + 'TimeOut' + suffix)\n",
+    "    genTimes = df.get(solver_name + 'Gen' + suffix)\n",
+    "    if genTimes is not None:\n",
+    "        ax.bar(index + i * bar_width, genTimes, bar_width,\n",
+    "                #label=toLabel(solver_name) + \"[GEN]\",\n",
+    "                color='dark' + colors[i])\n",
+    "    solvTimes = df.get(solver_name + 'Solved' + suffix)\n",
+    "    solvBars = None\n",
+    "    if solvTimes is not None:\n",
+    "        solvBars = ax.bar(index + i * bar_width, solvTimes, bar_width,\n",
+    "                label=toLabel(solver_name),\n",
+    "                bottom=genTimes,\n",
+    "                color=colors[i])\n",
+    "    if printStatus and solvBars is not None:\n",
+    "        for rect, pi in zip(solvBars, pattern_index):\n",
+    "            height = rect.get_height()\n",
+    "            #print(rect.get_y(), height)\n",
+    "            ax.text(rect.get_x() + rect.get_width() / 2, max(5, rect.get_y() + height),\n",
+    "                     patterns[pi], fontname='symbola', \n",
+    "                     ha='center', va='bottom', color=colors[i])\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {
+    "scrolled": false
+   },
+   "outputs": [],
+   "source": [
+    "def create_single(name, suffix='Hard'):\n",
+    "    fig = plt.figure()\n",
+    "    ax = fig.add_subplot(111)\n",
+    "    data = load(name)\n",
+    "    index = np.arange(len(data.name))\n",
+    "    for i, solver_name in enumerate(solver_names):\n",
+    "        add_gen_and_solve(ax, index, i, solver_name, data, suffix, False)\n",
+    "\n",
+    "    plt.xticks(rotation=90)\n",
+    "    plt.title(\"Solving time for hard problem\")\n",
+    "    plt.xlabel('Comp-Impl-Config-Request')\n",
+    "    plt.ylabel('Solving time [ms]')\n",
+    "    plt.yscale(\"log\")\n",
+    "\n",
+    "    plt.xticks(index + bar_width / len(solver_names), data.name.astype(str))\n",
+    "    plt.legend()\n",
+    "    plt.tight_layout()\n",
+    "    plt.show()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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51NBtbRi6dSpE4cddljtDb5mZi1RlhVUJV2DyudxG5nOOeccJkyYAMB9993HCSecwMMPP8z06dMZN24cgwYNYtGiRSxatIiRI0cyePBgPvvZz9aOgn7uuefy4x//mNGjR/OjH/2I8ePH8/Wvf53hw4ez8847M2nSpNp9HX/88QwePJg99tiD6667rsH8HH/88Vx//fX5vh1mZrUq/xpUiWvO4zZqRkAH2GOPPbj++uu59NJLGTJkCLvvvjs//elP+fOf/8yBBx7Isccey+jRo2sHpD3ssMO46qqr2HXXXXnsscf4zne+wz//+U8Ali1bxm233cb222/P+PHjmT9/PrNnz2bVqlUMGDCAb3/723Ts2JEpU6bQq1cv1qxZw7777svRRx9Nr1696uRxzz33bHDUCjOz5irLCqoS5PO4jYZGQO/WrRtXX301hxxyCOPHj6dfv34bpbV69WoefvjhOkMsffjhh7Xzo0ePpkOHDrWvR40aRefOnencuTNbbbUVb775Jn379mXSpEnceuutACxdupRXXnllowqqQ4cOdOrUiVWrVtGzZ8/c3xAzs3pcQRVJazxuo8azzz7LFltswZtvvtng+g0bNvCpT32qduTy+rp161bndefOnWvnO3TowPr167nvvvu45557eOSRR+jWrRsHHnhgnUou04cffkiXLl1yyruZWWMqv4JqYbfwzAf11R/0tZCyPW4j02uvvcYVV1zBXXfdxamnnspRRx3FtttuW+exGZttthk77bQTt9xyCyeddBIRwTPPPMM+++yTc35WrlzJFltsQbdu3Zg/fz5PPvlkg9utWLGCLbfcko4dO+actplZQ8qyk0Q5ae3HbdR0Mx80aBAffvghZ5xxBpdffjlbb701V1xxBePGjWPt2rWcfPLJTJw4kX333ZdFixZx/fXXc+2117LPPvuwxx57cNtttzXrOEaOHMn69evZfffd+clPfsJ+++3X4HZ+NIeZtZaybEFJOgY4pn///sXOSoPa8nEb99xzD5C09Pbee2/uvfdeunTpwkEHHbRRN/M777xzo/grr7yyzuvx48fXeZ356I477rijdj6zZfnqq6/Wzt9www1cdtllWY/NzCwXZdmCKqcHFrZEKTxuoznWrVvH8ccfz2677VbsrJhZBSjLFlR7UQqP22iOTp06cdpppxU7G2ZWIcqyBWVmZpXP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\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f5bf56050b8>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "create_single('incremental/handcrafted-benchmark-1.csv')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def make_plot(name, df, ax, solver_names=solver_names, suffix='Hard'):\n",
+    "    index = np.arange(len(df.name))\n",
+    "    for i, solver_name in enumerate(solver_names):\n",
+    "        add_gen_and_solve(ax, index, i, solver_name, df, suffix)\n",
+    "        ax.set_title(name)\n",
+    "\n",
+    "    plt.sca(ax)\n",
+    "    plt.yscale(\"log\")\n",
+    "    plt.xticks(rotation=90)\n",
+    "    plt.xticks(index + bar_width / len(solver_names), list(df.name))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {
+    "scrolled": false
+   },
+   "outputs": [],
+   "source": [
+    "def create_row(name):\n",
+    "    data = load(name)\n",
+    "    groupByReq = data.groupby('req')\n",
+    "    nrDifferentRequests = len(groupByReq)\n",
+    "    print (nrDifferentRequests)\n",
+    "\n",
+    "    fig, axs = plt.subplots(1, nrDifferentRequests, sharey=True)\n",
+    "    plt.suptitle(\"Solving time for hard problem\", fontsize=16)\n",
+    "    #fig.autofmt_xdate()\n",
+    "    #print (axs)\n",
+    "    for (name, df), ax in zip(groupByReq, axs.flatten()):\n",
+    "        #print (df['ilp-externalSolvedHard'])\n",
+    "        make_plot('req=' + str(name), df, ax, ['ilp-external'])\n",
+    "\n",
+    "    ## Create shared axes title\n",
+    "    fig.add_subplot(111, frameon=False)\n",
+    "    # hide tick and tick label of the big axes\n",
+    "    plt.tick_params(labelcolor='none', top='off', bottom='off', left='off', right='off')\n",
+    "    plt.grid(False)\n",
+    "    plt.xlabel(\"Comp-Impl-Config-Request\", labelpad=50)\n",
+    "    plt.ylabel(\"Solving time [ms]\")\n",
+    "\n",
+    "    plt.show()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "4\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f5bf32e3898>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "create_row('incremental/handcrafted-benchmark-1.csv')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def make_plot_in_grid(name, df, ax, suffix, solver_names=solver_names):\n",
+    "    index = np.arange(len(df.name))\n",
+    "    for i, solver_name in enumerate(solver_names):\n",
+    "        add_gen_and_solve(ax, index, i, solver_name, df, suffix)\n",
+    "        ax.set_title(name, visible=name is not None)\n",
+    "\n",
+    "    plt.sca(ax)\n",
+    "    plt.yscale(\"log\")\n",
+    "    plt.xticks(index + bar_width / len(solver_names), list(df.conf))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def create_grid_plot(name, suffix='Hard'):\n",
+    "    data = load(name)\n",
+    "    groupByResRat = data.groupby('res')\n",
+    "    nrDifferentRatios = len(groupByResRat)\n",
+    "    nrDifferentRequests = len(data.req.unique())\n",
+    "    print (\"nrDifferentRequests:\", nrDifferentRequests, \"nrDifferentRatios:\", nrDifferentRatios)\n",
+    "\n",
+    "    fig, axs = plt.subplots(nrDifferentRatios, nrDifferentRequests, sharey=True, figsize=(12, 12))\n",
+    "    plt.suptitle(\"Solving time for hard problem\", fontsize=16)\n",
+    "\n",
+    "    #print (axs)\n",
+    "    firstResRatio = True\n",
+    "    for (resRatio, df), axs_res_ratio in zip(groupByResRat, axs):\n",
+    "        lastAx = axs_res_ratio[-1]\n",
+    "        lastAx.set_ylabel('rr=' + str(resRatio), rotation=0)\n",
+    "        #lastAx.yaxis.set_label_position(\"right\")\n",
+    "        lastAx.yaxis.set_label_coords(1.3,0.5)\n",
+    "        #print (resRatio)\n",
+    "        for (reqNumber, df_inner), ax in zip(df.groupby('req'), axs_res_ratio):\n",
+    "            name = 'req=' + str(reqNumber) if firstResRatio else None\n",
+    "            #print (name)\n",
+    "            make_plot_in_grid(name, df_inner, ax, suffix, solver_names=['ilp-external', 'ilp-direct', 'simple'])\n",
+    "        firstResRatio = False\n",
+    "\n",
+    "    ## general settings\n",
+    "    ## create another subplot for the big axes (solving time, configurations)\n",
+    "    fig.add_subplot(111, frameon=False)\n",
+    "    ## hide tick and tick label of the big axes\n",
+    "    plt.tick_params(labelcolor='none', top='off', bottom='off', left='off', right='off')\n",
+    "    plt.grid(False)\n",
+    "    plt.xlabel(\"Configurations\", labelpad=0)\n",
+    "    plt.ylabel(\"Solving time [ms]\", labelpad=20)\n",
+    "\n",
+    "    ## tight layout make title worse at the moment\n",
+    "    #plt.tight_layout()\n",
+    "    #plt.subplots_adjust(top=0.85, left=0.85)\n",
+    "    plt.show()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "nrDifferentRequests: 4 nrDifferentRatios: 2\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxwAAAMMCAYAAADZ0aGTAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAAIABJREFUeJzs3Xu8XXldH/zPl0yADHESZYBUTTLAMDHWJoiXijWEeHxaVGLtRUUrQvV5ptWH2tri7VGLivdLrXS8EG8DYr2jMjZogiZGajDMKAoaY4KQAgblNhFQiITf88faYQ6HnJN9krPO2pf3+/Xar332Pmvv/f3t853M/uzfb61VrbUAAAD04UFDFwAAAMwugQMAAOiNwAEAAPRG4AAAAHojcAAAAL0ROAAAgN4IHMCKqupzq+pEVf11Vf1dVZ2vql+tqqdcx3PdXVWvX6/H3ajR2P/zVe5/clW1qnryetd0NVX1MVX121X1N6O6PrfH13p9Vb2or+cf4/Un6r1Pxn9PhupjgKEJHMCyquork/xKkrNJvizJZyf5ttGvP30dS3lukn+xjq93xecm+ZDAkeQPkjxxdD0J/luSxyT5/HR1/c6w5QDAA24augBgoj07ya+21r5s0X2/neTHqmrdvrBorb12vV5rHK21v0nyiqHrWGR3khOttd9Yiyerqoe01t67Fs/l9QEwwwGs5COSvPlqv2itvX/x7ar65Kp6WVW9q6reXVW/VVWfvNwTV9VDqurtVfXfrvK7zx8tm/n40e0PWopSVbeNfv/vqupbq+pCVd1fVfdU1Ucvea6bq+pHqupto9p+pao+dfT4Z65Q391JnpHko0bbtis1XG1ZT1Udr6qXV9VTqupVo+Vnf1hV/7iqbqqq7xjV+fbReB52lTq/u6peV1WXRtffsFKwu1JHktuSPP1KnYt+/5SqOjmq5eJoKdyuJc9xpe6Do3rfm+QrlnvNRY97WlWdHv2t762qT1vy+0+qql+qqjeOXv/M6D3YNO7rV9Ujqup/jpaK3V9VL0yy9Vq1jR579+i1P7WqXllV7xktffoPS7Z75uh9e1JV/WJV3Z/k9xf9/our6o9Gj39rVf10Vf2DZV7z/6mqc6Nt/6CqDoxR5zX/7ov67XOr6vmjHrq/qv57VW0YvdcvH/0t/qSq/tk47xHAejHDAazkVJJnVNVfJPm11tqfX22jqtqTbhnPnyZ5ZpKW5OuS/E5VfUpr7Y+WPqa19t6q+oUkX1hVX91au7zo109P8prW2h9eo76vT/J7Sb40ySOTfH+SFyV58qJtDiX5vCTfnOTeJAtJfuYaz5t0y7gekeSTknzO6L5rfet9e5LvTfLtSd6V5HuSvGR0uSnde7N7tM1fJ/maJKmqm5L8ZpKPHb3uq5N8SpJvShf6/ssyr3dladdLkrxy9NiMnvMpSf5XuhmpL0iyOcm3Jnl5VT2+tfamRc9zR5LnjR7/F0nefo1x7kuya1Tfe0aP+/Wquq21dv9omx1JXpXk7iTvTPIPk/zXdEu/nrbk+ZZ7/Rcn2Zvk/0u3rO8LkvyPa9S22C1Jfj7Jdyc5N3rd51XVO1trdy/Z9meS/GySf53R/xur6s4kzx89x9cn+cgk35HkH1fVE1pr71r0+Ccn+YQk35CuT742yUuram9r7czViruOv/t/T/eefEGSJyX5xiQbknxGup560+i+F1fVztbaW8d5kwB611pzcXFxueol3QfBP04XIFqSt6b7UPZPl2z3S0nuT7J10X23pPvg+OJF992d5PWLbv+T0fP+s0X3PSLJ3yf5mhUed9vocceX1PHs0f0fObq9K8n7Fz/X6P7njbZ75jXGf3eSN17l/iePHv/kRfcdH9X9mEX3fc5ou5ctefyLk7xu0e2nj7Z70pLtviHJpSSPvEadb0xy95L77k33If2mRfc9elTjf1tS9/uTPH7Mnnh9knck+fBF933iqP4vWuYxle5D/BePXuvh13r9JP/X6DmftuT+ly5971f4213t8UeTnE9So9vPHG33A0u225Dkr5IcW3L/p422/8ol78mlJNsX3fdh6fr/p1fo47H+7ov67SeXbPcHo/s/bdF9e0b3PWOcv6eLi4vLelwsqQKW1boZjY9Psj/dt/avSrfz9m9W1Tcu2vRJSX69PfDtdlq3n8NLRo9d7vn/d5LXpvvgdcXT0i33HGcW4vCS268eXe8YXf/jdB92f3HJdr80xnNfjz9vrf3Fott/Nrr+zSXb/VmSj66qGt1+SroPwb83Wn510+jb7yNJNqb71ntso+VaT0jy86219125v7X2uiT/Ox/6N3l9a+1Vq3iJk621dyy6vfR9T1XdMloq9Np03/j/fZKfTvf3eNwYr//EJJeT/PKS+39uFXUu9/gdST5qyf2/suT2rnSzZh/Uh621l6f7Wy19D1/RWnvDou3emW6G6Ykr1Lfav/tLl9z+syTvHtW0+L4k2b7C6wKsK0uqgBW1bqnTidElVfWRSX4jyXOq6odGHzw/IsmFqzz8zUk+/Bov8aIkz66qh7XW3p0ufPx2++AlP8tZuvTnypKnh46ur6y1/+sl2/3VGM99Pd6x5PalFe6/Kd236O9L98F2Z7oP5Vfz8FXW8eHpPtgv9zfZueS+q223kg9631u3PC554H1Pkp9Kt9Tnv6YLqu9O8slJfmjJdsu9/j9I8o7W2tL3ZDV/u5Ue/1HpZoaWq+EjVqjtzYt+v1Jdf5UPDTaLrfbvfrU+un/xHa21S1f5WwAMSuAAVqW19pdV9eNJfjDdN9Wn0n0A3XaVzbflQz8kLfXTSZ6T5F9W1e+n22fiGWtU7pUPi49M8rpF9z9qjZ5/rbwtXX2fv8zvX7/K53tHumU1y/1Nlga1dpXtrltVPTTJP0/yza21H1x0/z9a5iFXe/0LST68qjYuCQ2r+dut9PilgXZpDVfeo+Xew/uW3He1uh51lddZbK3/7gATyZIqYFnLHY0nyceMrq8cwep3knxWVX3Yosd+WJKD6dboL6t1h7z9vXQzG09P9034i6+/6g9yKt0Hyc9bcv/S28t5b5JN19zqxv1GuiUw72qt3XuVy6p2/h3NFN2X5POqasOV+6tqZ5JPzTX+JmvgIelmb5Z+c//MVTzHydFz/Ksl9y/d4Xwlyz3+/2TlIJAkZ9LNUHzQ61XVp6ablTi+ZPtPqarti7b7sHTnrTm5wmus6d8dYFKZ4QBW8pqqelm6fSVel25H8M9K8u+T/EJr7f+Mtntukqcm+a2q+u50H/K/NsnN6Y6MdC0/nW6pzT9K8ivtg4/+c91aa39WVf8zyXNHhxm9L90JCw+ONnn/sg/u/GmSj6iqL0+3E/Z7WmuvvsZjrsfPJPm36d6/70/yR0kenOSx6XY8/9zW2t+u8jm/Kd0+BL9eVT+c7ihV35LkYrqjefWmtXaxql6R5L9U1YV0Bxv40qy8vGjpcxytqpcneX5V3ZoHjlL1caso5Z1JvmfR478w3TKvZ7bWVpzVaa1drqr/Onr9F6Vb+vdR6fZlOpvkJ5c85K+SHKmqb84DR6l6WBYdOewq+vi7A0wcgQNYyTekCxjfmm55yOUkf57ukLf//cpGrbU/ru6cFN+e5AXp9h94RZL97SqHxL2Kn0+3RGtbuvCxlu5M98Hza9J9mPvtJP9vkl9P9+F7JT+ebsfd70h3/ofz6Y6QtaZaa38/OnfC143qfXS6mZ7XpgsNl1Z4+HLP+RtV9dnplqv9wug5jqc7YtdfrlHpK/nCJD+SLkj+3aiG/5jufR/Xv0x3RLHvTNd7L0nyrCS/Oubj/ybdDMUPpguzf5XkP7bWXjDOg1trh6rqb5N8dZJfS3eo48Pp3sN3L9n8d9K9v9+R5KPThdXPbMscSnr0/Gv+dweYRHWNL3kAZk5VPTvdOTJuWzRLwwyp7sSNn9Fa++hrbQtAv8xwADOtqp6abhnOq9ItodqX7nwdvyBsAED/BA5g1r0zyeemW7bysHQ7Cz8v3VIjAKBnllQBAAC9cVhcAACgNwIHAADQG4EDAADojcABAAD0RuAAAAB6I3AAAAC9ETgAAIDeCBwAAEBvBA4AAKA3AgcAANAbgQMAAOiNwAEAAPRG4AAAAHojcAAAAL0ROAAAgN4IHAAAQG8EDgAAoDcCBwAA0BuBAwAA6I3AAQAA9EbgAAAAeiNwAAAAvRE4AACA3ggcAABAbwQOAACgNwIHAADQG4EDAADojcABAAD0RuAAAAB6I3AAAAC9ETgAAIDeCBwAAEBvBA4AAKA3AgcAANAbgQMAAOiNwAEAAPRG4AAAAHojcAAAAL0ROAAAgN4IHAAAQG8EDgAAoDcCBwAA0BuBAwAA6I3AAQAA9EbgAAAAeiNwAAAAvRE4AACA3ggcAABAbwQOAACgNwIHAADQG4EDAADojcABAAD0RuAAAAB6I3AAAAC9ETgAAIDeCBwAAEBvBA5uSFU9q6rurar3VtXdQ9cD46iqh1TVT1TV+ap6Z1W9qqo+c+i6YBxV9aKqulBVf1NVf15V//fQNcG4qupxVfWeqnrR0LWwfgSOGVVVN63TS/1lkm9L8pPr9HrMuHXq3ZuSvCHJ/iRbknxjkl+oqtvW4bWZUev47+53JrmttXZLks9J8m1V9Qnr9NrMmHXs2yt+KMkr1/k1GZjAMUOq6vVV9bVV9cdJ3l1VO6rql6vqLVX1uqr6ykXbbqqqu6vqHVX1p1X11VX1xtW+Zmvtxa21X03ytrUcC/NlvXu3tfbu1to3t9Ze31p7f2vt15O8LokPbazKQP/u/klr7b1Xbo4uj12bETEPhujb0XM9Lcn9SX5rjYbClFjvVEv/vjDJZyd5e5ITSX5tdN9HJ3lZVZ1prf1mkuek+x/UY5M8LMlLFz9JVf16kk9b5jVe3lp7aj/lM8cG692qelSSO5L8ydoMhTmz7r1bVT+c5JlJNiX5wySH13A8zId17duquiXJtyb59CSWAc4ZMxyz53mttTck+bgkj2itfWtr7VJr7S+S/FiSp422+/wk395ae/to++ctfpLW2lNba1uXuQgb9GGQ3q2qjUl+JskLWmt/1usImVXr3rutta9I8mFJ9iV5cZL3BlZnvfv2uUl+orV2XbMjTDczHLPnDaPrnUk+sqruX/S7DUl+d/TzRy7aNknOr0NtsJJ1792qelCSn05yKcmzrvd5mHuD/LvbWruc5OVV9cVJvjxLPgjCNaxb31bV45N8RpKPv446mQECx+xpo+s3JHlda+1xy2x3Icn2PLCEZMfiX1bVS9N9c3Y1v9tac0Qf1tq69m5VVZKfSPKoJJ/VWvv7G6id+Tb0v7s3xT4crN569u2Tk9yW5P90//Rmc5INVfWxrbUnXO8AmB4Cx+w6leSdVfW16b71upRkd5JNrbVXJvmFJF9fVb+fbk3mf1j84HEDxejoFjel+zZkQ1U9NMn7WmvvW7ORMG/WpXeT/MjoeT+jtfZ3a1U8c6333q2qR6ZbA//rSf4u3bfGXzi6wPVYj39zDyX5uUW3n50ugHz5DVfPVLAPx4waTbU/Ncnj0x19561JfjzdIUCT5FvSTYu+LsmRdMtKrsc3pvuf3tcl+eLRz9943YUz99ajd6tqZ5J/N3qNN1fVu0aXf3PjI2BerdO/uy3dh7Q3JnlHku9L8p9aay+5oeKZW+vRt621v22tvfnKJcm7kryntfaWNRgCU6Baa9feiplXVU9O8qLW2kcPXQusht5lWuldppG+5XqY4QAAAHojcAAAAL2xpAoAAOiNGQ4AAKA3c3dY3FtvvbXddtttQ5fBlLvvvvve2lp7xHq+pt7lRulbppXeZVoN0buTaO4Cx2233ZZ777136DKYclW17mdm17vcKH3LtNK7TKshencSWVIFAAD0RuAAAAB6I3AAAAC9ETgAAIDezE3gqKqDVXXo4sWLQ5cCq6J3mUb6lmmld2HtzU3gaK3d01q7c8uWLUOXAquid5lG+pZppXdh7c1N4AAAANafwAEAAPRG4AAAAHojcAAAAL0ROAAAgN4IHAAAQG8EDgAAoDdzEzicyIdppXeZRvqWaaV3Ye3NTeBwIh+mld5lGulbppXehbU3N4EDAABYfwIHAADQG4EDAADojcABAAD0RuAAAMbX2tAVAFNG4AAAxnP+fLJ3b3Ly5NCVAFNE4AAAru3s2WTfvuTSpWT37qGrAaaIwAEAfLALF5L9+x+YyTh9urudJEeOJFu3DlcbMHXmJnA4cyjTSu8yjfTtlDt0KDlxIjl1Knn1q7uwcfly8rKXJTt2DF1dr/QurL25CRzOHMq00rtMI3075TZu7K7vuis5cKALG0ePJnfcMWxd60Dvwtqbm8ABAIxp27bu+ty5ZMOG5NixZM+eYWsCptZNQxcAAEyYhYVk+/ZupuPw4WTXrqErAqaYwAEAfLCdO5MzZ7qfN20athZg6gkcAMADqsbbzgkAgTHZhwMAAOiNwAEAAPRG4AAAAHojcAAAAL0ROAAAgN4IHAAAQG/mJnBU1cGqOnTx4sWhS4FV0btMI33LtNK7sPbmJnC01u5prd25ZcuWoUuBVdG7TCN9y7TSu7D25iZwAABMozZDJ1k0lvkkcAAATKjz95/P3h/dm5NvODl0KTfMWOaXwAEAMIHOvu1s9v3Uvly6fCm7H7F76HJuiLHMN4EDAGBgF955Ifvv3v+Bb8xPv+V09t+9P0ly5OlHsvWhW4csb1WMhaVuGroAAIB5d+i+Qzlx/kROvelUNj94cxZeuJCqyvEvOZ4dW3YMXd6qGAtLmeEAABjYxg0bkyR3vfKuHHjBgVxul3P06Udzx8PvGLiy1TMWlhI4AAAGtm3ztiTJubefy4YHbcixZxzLnkftGbiq62MsLGVJFcAQWkuqhq4CmBALj17I9lu2Z+OGjTn8RYez69ZdQ5d03YyFpQQOgPV2/nxy8GDy/OcnT3zi0NUAE2Dn1p0586wzSZJNGzcNXM2NMRaWEjgA1tPZs8nCQnLzzcluh1MEHjBLH2iNhcUEDoC+XLiQPO1pyXd9VzeTcfp0FzZuuik5ciTZ6nCKc8MSOlZQ3zJeb7TnTP6ZrY2Fq7HTOEBfDh1KTpxITp1KXv3qZP/+5PLl5GUvS3Y4nOLcOH8+2bs3OemMxMB8mpvAUVUHq+rQxYsXhy4FVkXvTrGN3eEUc9ddyYEDXdg4ejS5Y/YPp6hvR86eTfbtSy5dsoRuSuhdWHtzEzhaa/e01u7csmXL0KXAqujdKbatO5xizp1LNmxIjh1L9szH4RTnsm8vXOhmsa7MZJw+3d1OLKGbInPZu9Az+3AA9GVhIdm+vZvpOHw42eVwijNt8RK6zZu7v39Vcvy4JXTAXBM4APqyc2dypjucYjY5ysnMW7yE7rnP7XYUP3ZsLpbQAaxE4ADow7hHJGqObjIzFi+he+Qju/115mQJHcBKBA4AWAuW0AFclcABAGvBEjqAqxI4AGCtCBoAH0LgAIAbZZ8dgGXNzXk4AACA9SdwAAAAvRE4AACA3ggcAABAbwQOAACgNwIHAADQG4EDAADojcABAAD0Zm4CR1UdrKpDFy9eHLoUWBW9yzTSt0wrvTvDnHhzMHMTOFpr97TW7tyyZcvQpcCq6F2mkb5lWundGXX+fLJ3b3Ly5NCVzKW5CRwAAMyhs2eTffuSS5eS3buHrmYuCRwAAMyGCxeS/fsfmMk4fbq7nSRHjiRbtw5X2xy7aegCAABgTRw6lJw4kZw6lWzenCwsJFXJ8ePJjh1DVze3zHAw/ewEBgAkycaN3fVddyUHDiSXLydHjyZ33DFsXXNO4GC62QkMALhi27bu+ty5ZMOG5NixZM+eYWvCkiqm2Nmz3VTpzTfbCWxetNZNjQPA1SwsJNu3dzMdhw8nu3YNXRExw8G0sBMYZrMAuJadO5MzZ5LXvEbYmCBmOJgOdgKbb2azABjXpk1DV8ASZjiYDnYCmx9mswC4HlXjXVh3ZjiYDot3AnvkI7uwYSew2WQ2CwBmihkOpsOVncAe85juw6iwMbvMZgHATDHDwXS4shNYYm3mrDObBQAzReBgsq1mraUTAM4GhzQEgJkicACTxWwWAMwUgQOYPIIGAMwMgQOYHOMuobN8DgCmhqNUAQAAvRE4AACA3ggcAABAbwQOAACgN3MTOKrqYFUdunjx4tClwKroXaaRvmVa6V1Ye3MTOFpr97TW7tyyZcvQpcCq6F2mkb5lWuldWHtzEzgAAID1J3AAAAC9ETgAmExO8AgwEwQOACbP+fPJ3r3JyZNDVwLADRI4AJgsZ88m+/Ylly4lu3cPXQ0AN0jgAGA4Fy4k+/c/MJNx+nR3O0mOHEm2bh2uNsDSRtaEwAHAcA4dSk6cSE6dSl796i5sXL6cvOxlyY4dQ1cH883SRtaIwAHAcDZu7K7vuis5cKALG0ePJnfcMWxdMO8sbWQNCRzzyhQpMAm2beuuz51LNmxIjh1L9uwZtiaYN5Y20jOBYx6ZIgUmxcJCsn178pjHdEurhA1Yf5Y20rObhi6AdXb2bPc/+JtvNkUKDG/nzuTMme7nTZuGrQXm1eKljc99brcK4tgxSxtZM2Y4ZpkpUmAabNokbMCQLG2kZ2Y4ZtniKdLNm7uZjark+HFTpMDwqsbbzj5n0K8rSxs3bkwOH0527Rq6ImaMwDHLTJECANdiaSM9s6RqlpkiBQDGYWkjPTLDMctMkQIAK7G0kXUgcMwyU6QAAAxM4Jh1ggYAAAMSOGaVKVIAACaAncYBAIDeCBwAAEBvBA4AAKA3AgcAANAbgQMAAOiNwAEAAPRG4AAAAHojcAAAAL0ROAAAgN4IHAAAQG/mJnBU1cGqOnTx4sWhS4FV0btMI33LtNK7sPbmJnC01u5prd25ZcuWoUuBVdG7TCN9y7TSu7D25iZwwFxrbegKAIA5JXDArDt/Ptm7Nzl5cuhKAIA5JHDALDt7Ntm3L7l0Kdm9e+hqAIA5JHDArLhwIdm//4GZjNOnu9tJcuRIsnXrcLUBAHPrpqELANbIoUPJiRPJqVPJ5s3JwkJSlRw/nuzYMXR1AMCcMsMBs2Ljxu76rruSAweSy5eTo0eTO+4Yti4AYK4JHDArtm3rrs+dSzZsSI4dS/bsGbYmAGDuWVIFs2JhIdm+vZvpOHw42bVr6IoAAAQOmBk7dyZnznQ/b9o0bC0AACMCB8wSQQMAmDACB0y7qvG3dcZxAGCd2WkcAADojcABAAD0RuAAAAB6I3AAAAC9ETgAAIDeCBwAAECq6mOq6mRVvbeqnr3CdndX1euq6lWjy+NXel6HxQUAgBlTVZWkWmvvH93e0Fq7fI2HvT3JVyb53DFe4qtba780Ti1mOAAAYAZU1W1VdaaqXpjkNUkuV9X3V9UfJXnitR7fWvvr1tork/z9WtYlcAAAwOx4XJIfbq39w9Ht32+t7W2tvbyqfmDRMqjFl6+7jtf59qr649FzPmSlDS2pAgCA2XG+tfaK0c+Xk/zylV+01r5qjV7j65O8OcmDkxxK8rVJvnW5jQWO1WgtqRq6CgBgkvm8wLDevejn9yzeb6OqfiDJgas85udaa9817gu01i6MfnxvVf1UkmV3ME8sqRrf+fPJ3r3JyZNDVwIATCqfF5hgrbWvaq09/iqXscNGklTVPxhdV7odzF+z0vYCxzjOnk327UsuXUp27x66GgBgEvm8wJSrqm1V9cYk/znJN1bVG6vqltHvDlfVR442/ZmqenWSVye5Ncm3rfS8AsdSFy4k+/c/8M3E6dPd7SQ5ciTZunW42gCAyeDzAhOotfb61trHLbq9eZWPf3Nr7aNba7e01raOfv6b0e8+q7X2l6OfP7219o9aax/XWvvi1tq7Vnpe+3AsdehQcuJEcupUsnlzsrDQrcM8fjzZsWPo6gCASeDzAozNDMdSGzd213fdlRw4kFy+nBw9mtxxx7B1AQCTw+cFGJvAsdS2bd31uXPJhg3JsWPJnj3D1gQATBafF2BsllQttbCQbN/efXNx+HCya9fQFQEAk8bnBRibwLHUzp3JmTPdz5s2DVsLADCZfF6AsQkcV+MfDgDgWnxegLEIHIuNe1bQ1vqtAwCYXD4vwKrYaRwAAOiNwAEAAPRG4AAAAHojcAAAAL0ROAAAgN4IHAAAQG8EDgAAoDcCBwAA0BuBAwAA6I3AAQAA9EbgAAAAeiNwAAAAvRE4AACA3ggcAABAbwQOAACgN1MdOKrqMVX1E1X1S0PXAgAAfKiJCxxV9ZNV9ddV9Zol9z+lqs5U1bmq+rokaa39RWvty4apFAAAuJaJCxxJ7k7ylMV3VNWGJD+U5DOTfGySL6yqj13/0gAAgNWYuMDRWjuR5O1L7v7kJOdGMxqXkvxckn++7sUBAACrMnGBYxkfleQNi26/MclHVdXDq+pHk3x8VX39cg+uqjur6t6quvctb3lL37XCmtG7TCN9y7TSu9CPaQkcV9Vae1tr7d+31h7bWvvOFbY71Fr7xNbaJz7iEY9YzxLhhuhdppG+ZVrpXejHtASONyXZvuj2R4/uAwAAJti0BI5XJnlcVT26qh6c5GlJXjJwTQAAwDVMXOCoqp9NcjLJrqp6Y1V9WWvtfUmeleQ3k5xO8guttT8Zsk4AAODabhq6gKVaa1+4zP2Hkxxe53IAAIAbMHEzHAAAwOwQOIBVa60NXcKaMRYA6NfcBI6qOlhVhy5evDh0KbAqk9a75+8/n70/ujcn33By6FJumLH0Z9L6Fsald2HtzU3gaK3d01q7c8uWLUOXAqsySb179m1ns++n9uXS5UvZ/YjdQ5dzQ4ylX5PUt7AaehfW3twEDmB1LrzzQvbfvf8D35iffsvp7L97f5LkyNOPZOtDtw5Z3qoYCwAMZ+KOUgVMhkP3HcqJ8ydy6k2nsvnBm7PwwoVUVY5/yfHs2LJj6PJWxVgAYDhmOICr2rhhY5LkrlfelQMvOJDL7XKOPv1o7nj4HQNXtnrGAgDDETiAq9q2eVuS5Nzbz2XDgzbk2DOOZc+j9gxc1fUxFgAYjiVVwFUtPHoh22/Zno0bNubwFx3Orlt3DV3SdTMWABiOwAFc1c6tO3PmWWeSJJs2bhq4mhtjLAAwHIEDWNYsfaA1FgAYxtwEjqpQenG9AAAgAElEQVQ6mOTg7bffPnQpsCpD9G59S421XXvO5J/Z2liG4d9cppXehbU3NzuNO5EP00rvMo30LdNK78Lam5vAAQAArD+BAwAA6I3AAQAA9EbgAAAAeiNwAAAAvRE4AACA3ggcAABAbwQOAACgN3MTOKrqYFUdunjx4tClwKroXaaRvmVa6V1Ye3MTOJw5lGmld5lG+pZppXdh7c1N4ACA1trQJayZWRnLrIwDWJ7AAcBcOH//+ez90b05+YaTQ5dyw2ZlLLMyDmBlAgcAM+/s285m30/ty6XLl7L7EbuHLueGzMpYZmUcwLUJHADMlAvvvJD9d+//wLfmp99yOvvv3p8kOfL0I9n60K1DlrcqszKWWRkHcH1uGroAAFhLh+47lBPnT+TUm05l84M3Z+GFC6mqHP+S49mxZcfQ5a3KrIxlVsYBXB8zHADMlI0bNiZJ7nrlXTnwggO53C7n6NOP5o6H3zFwZas3K2OZlXEA10fgAGCmbNu8LUly7u3nsuFBG3LsGcey51F7Bq7q+szKWGZlHMD1saQKgJmy8OiFbL9lezZu2JjDX3Q4u27dNXRJ121WxjIr4wCuj8ABwEzZuXVnzjzrTJJk08ZNA1dzY2ZlLLMyDuD6CBwAzJxZ+lA7K2OZlXEAqzc3gaOqDiY5ePvttw9dCqyK3mUaDdG39S019rbtOZN9dutxxzLp40imbyz+zYW1Nzc7jbfW7mmt3blly5ahS4FV0btMI33LtNK7sPbmJnAAAADrT+AAAAB6I3D0oY23DrWNud2gjGW+zNLYjWV+zNL7YyzzZZbeI2NhBQLHWnv3+eSle5O3nFxxs/P3n8/eH92bk29YebtBGct8GfM9mgrGMj9m6f0xlvkyS++RsXANAsda+puzydF9yfsvJVt2L7vZ2bedzb6f2pdLly9l9yOW325QxrKOBU6AMd+jqWAs82OW3h9jmS+z9B4ZC2MQOK7X311IXrb/gQR88XTyW/u7nw8cSR68NUly4Z0Xsv/u/R/4xvz0W05n/93ddkeefiRbH7p13Uv/EMYymWPpy5jv0VQwlvkxS++PscyXWXqPjIXrNDfn4Vhz5w4lf30iedupZOPm5LcWkqpk4XjysB0f2OzQfYdy4vyJnHrTqWx+8OYsvHAhVZXjX3I8O7bsWP7515OxTOZY+jLmezQVjGV+zNL7YyzzZZbeI2PhOpnhuF4P2thd//ldyW8dSNrl5MDR5JY7PmizjRu67e565V058IIDudwu5+jTj+aOh9+x9BmHYyyTOZa+jPkeTQVjmR+z9P4Yy3yZpffIWLhOAsf1eui27vpd55LakCwcSz58z4dstm1zt925t5/LhgdtyLFnHMueR33odoMylskcS1/GfI+mgrHMj1l6f4xlvszSe2QsXCdLqq7XtoXk5u1dQn7y4eSWXVfdbOHRC9l+y/Zs3LAxh7/ocHbdevXtBmUskzmWvoz5Hk0FY5kfs/T+GMt8maX3yFi4TgLH9XrYzuSpZ7qfb9q07GY7t+7MmWd1223auPx2gzKW9ahscoz5Hk0FY5kfs/T+GMt8maX3yFi4TgLHjRizQafiA62xzJdZ+sfVWObHLL0/xjJfZuk9Mhauw9wEjqo6mOTg7bffPnQpsCp6l2k0Tt9+35jP9ezvrzWpqU/GMjv8mwtrb252Gm+t3dNau3PLli1DlwKroneZRvqWaaV3Ye3NTeAAAADWn8ABAAD0RuAAAAB6I3AAAAC9ETgAAIDeCBwAAEBvBA4AAKA3AgcAANAbgQMAAOiNwAEAAPRG4AAAAHojcAAAAL0ROAAAgN4IHAAAQG8EDgAAoDc3DV3Aeqmqg0kO3n777UOXAquypr37P+vGn2MSzMo4ktkayyL+zWVarWnvfv8M/fdtLNyAuZnhaK3d01q7c8uWLUOXAquid5lG+pZppXdh7c1N4AAAANafwAEAAPRG4AAAAHojcAAAAL0ROAAAgN4IHAAAQG8EDgAAoDcCBwAA0BuBAwAA6I3AAQAA9EbgAAAAeiNwAAAAvRE4AACA3ggcAABAbwQOAACgNwIHAADQG4EDAADojcABAAD0RuAAAAB6I3AAAAC9uWnoAtZLVR1McvD2229fdpvvG/O5nj3ua35LjbVde04b8xnHNytjGXccyeSP5XqN07tju3DjTzERZmUcyWyNZZE17VtYR3oX1t7czHC01u5prd25ZcuWoUuBVdG7TCN9y7TSu7D25iZwAAAA60/gAAAAeiNwAAAAvRE4AACA3ggcAABAbwQOAACgNwIHAADQG4EDAADojcABAAD0RuAAAAB6I3AAAAC9ETgAAIDeCBwAAEBvBA4AAKA3AgcAANAbgQMAAOjNTcv9oqr+5RiPf09r7fAa1gMAAMyQZQNHkh9L8mtJaoVtnpRE4AAAAK5qpcDx0tbal6704Kp60RrXAwAAzJBl9+ForX3xtR48zjYAAMD8uuZO41X1eVX1YaOfv6mqXlxVT+i/NAAAYNqNc5Sqb2qtvbOqPi3JQpKfSPIj/ZYFAADMgnECx+XR9WcnOdRa+19JHtxfSQAAwKwYJ3C8qaqen+QLkhyuqoeM+TgAAGDOjRMcPj/Jbyb5Z621+5N8RJKv7rUqAABgJqx0WNwkSWvtb6vqWJLti3YWf2u/ZQEAALPgmoGjqp6b5JlJXpukje5uST69v7IAAIBZcM3AkW5J1WNba5f6LgYAAJgt4+zD8ZokW/suBAAAmD3VWlt5g6pPTPJr6YLHe6/c31r7nH5LW1tVdTDJwXRH2zp7nU9za2Zn/xVjuTE7W2uPWI8X0rsfwliu37T1bTI7f+9ZGUfi39xx+HtPppnu3Uk2TuD4kyTPT/LqJO+/cn9r7Xf6LW3yVNW9rbVPHLqOtWAs82WW3iNjmS+z8h7NyjiS2RpLX2bpPTIW1sI4+3D8bWvteb1XAgAAzJxxAsfvVtV3JnlJPnhJ1R/0VhUAADATxgkcHz+6/pRF983rYXEPDV3AGjKW+TJL75GxzJdZeY9mZRzJbI2lL7P0HhkLN+ya+3AAAABcr2UPi1tVT73Wg8fZBgAAmF8rnYfje6vq46vqCctdknzHehU6tKraWlW/VFV/VlWnq+qJQ9c0rqr6yar666p6zaL7vnc0lj+uql+pqqk418oyY3l8Vb2iql5VVfdW1ScPWeMk0beTQd+unt6dDHp39fTuZNC7k2XZJVVVdTzdvhoreXtr7V+tdVGTqKpekOR3W2s/XlUPTnJza+3+oesaR1U9Kcm7krywtfZxo/v+aZLfbq29r6q+O0laa187YJljWWYsR5L8QGvtpVX1WUm+prX25AHLnBj6djLo29XTu5NB766e3p0MeneyLLvTuD/AA6pqS5InJXlmkrTWLiW5NGRNq9FaO1FVty2578iim69I8q/Xs6brdbWxpAvGt4x+3pLkL9ezpkmlbyeHvl0dvTs59O7q6N3JoXcnyzhHqSJ5dJK3JPmpqtqb5L4k/7G19u5hy1ozX5rk54cu4gb8pyS/WVXfl26Z4KcOXM+k0LeTTd8uT+9ONr27PL072fTuQFbah4MH3JTkCUl+pLX28UneneTrhi1pbVTVNyR5X5KfGbqWG/DlSb6qtbY9yVcl+YmB65kU+nay6dvl6d3JpneXp3cnm94diMAxnjcmeWNr7fdHt38p3T8oU62qnpnkqUn+TZvu4yM/I8mLRz//YhI7gXX07WTTt8vTu5NN7y5P7042vTuQawaOqrq5qr6pqn5sdPtxNWeHw22tvTnJG6pq1+iuhSR/OmBJN6yqnpLka5J8Tmvtb4eu5wb9ZZL9o58/PcnZAWuZGPp24unbZejdiad3l6F3J57eHcg1T/xXVT+fbg3il7TWPq6qbk7ye621x69HgZOiqh6f5MeTPDjJXyT5t621dwxb1Xiq6meTPDnJrUn+Kslzknx9kockedtos1e01v79IAWuwjJjOZPkB9NNZb8nyVe01u4bqsZJom8ng75dPb07GfTu6undyaB3J8s4gePe1tonVtUfjtYjpqr+qLW2d10qBAAAptY4+3BcqqpNGZ2To6oem+S9vVYFAADMhHEOi/ucJL+RZHtV/UySf5LR8aUBAABWcs0lVUlSVQ9P8ilJKt3avbf2XRgAADD9xg0ce5LclkUzIq21Fy/7AAAAgIyxpKqqfjLJniR/kuT9o7tbHjiOMQAAwFWNc5SqP22tfew61QMAAMyQcY5SdbKqBA4AAGDVxpnh2J/kJUnenO5wuJWktdb29F8eAAAwzcYJHOeS/Ockr84D+3CktXa+39IAAIBpN855ON7SWntJ75UAAAAzZ5wZjh9OsjXJPVl0hnGHxQUAAK5lnBmOTemCxj9ddJ/D4gIAANc01on/AAAArseyMxxV9TWtte+pqv+Rbkbjg7TWvrLXygAAgKm30pKq06Pre9ejEAAAYPYsGzhaa/eMfvzb1tovLv5dVX1er1UBAAAzYZyjVP1Ba+0J17oPAABgqZX24fjMJJ+V5KOq6nmLfnVLkvf1XRgAADD9VtqH4y/T7b/xOUnuW3T/O5N8VZ9FAQAAs2GcJVUbW2t/v071AAAAM8R5OAAAgN48aOgCAACA2SVwAAAAvVlpp/EkSVXdkw890/jFdDuUP7+19p4+CgMAAKbfODMcf5HkXUl+bHT5m3RHqrpjdBsAAOCqxjlK1Stba590tfuq6k9aa/+w1woBAICpNc4Mx+aq2nHlxujnzaObl3qpCgAAmAnX3IcjyX9J8vKqem2SSvLoJF9RVQ9L8oI+iwMAAKbbWOfhqKqHJPmY0c0zdhQHAADGMW7g+NQkt2XRjEhr7YX9lQUAAMyCcQ6L+9NJHpvkVUkuj+5uSQQOAABgReMcpep0ko9t40yFAAAALDLOUapek2Rb34UAAACzZ5yjVN2a5E+r6lSS9165s7X2Ob1VBQAAzIRxAsc3910EAAAwm8Y6ShUAAMD1WHaGo6pe3lr7tKp6Z7qjUn3gV0laa+2W3qsDAACmmhkOAACgN9c8SlVVPa+qnrgexQAAALNlnMPi3pfkm6rqtVX1fVX1iX0XBQAAzIaxl1RV1Uck+VdJnpZkR2vtcX0WBgAATL9xZjiuuD3JxyTZmeTP+ikHAACYJdec4aiq70nyL5K8NsnPJ/mV1tr961AbAAAw5cY58d9rkzyxtfbWvotZD7feemu77bbbhi6DKXffffe9tbX2iPV8Tb3LjdK3TCu9y7Qaoncn0Urn4XjC6MdXJtlRVTsW/7619gd9FtaX2267Lffee+/QZTDlqur8er+m3uVG6Vumld5lWg3Ru5NopRmO71/hdy3Jp69xLQAAwIxZNnC01g6sZyEAAMDsueY+HFW1McmXJ3nS6K7jSZ7fWvv7HusCAABmwDiHxf2RJJ+Q5IdHl08Y3TdVqupgVR26ePHi0KXAquhdppG+nWFjnr9rWuldWHvjBI5Paq09o7X226PLv03ySX0XttZaa/e01u7csmXL0KXAquhdppG+nVHnzyd79yYnTw5dSW/0Lqy9cQLH5ap67JUbVfWYJJf7KwkAmDhnzyb79iWXLiW7dw9dDTBFxgkcX53kWFUdr6rfSfLbSf5Lv2UBAIO5cCHZv/+BmYzTp7vbSXLkSLJ163C1AVPnmjuNt9Z+q6oel2TX6K4zrbX39lsWADCYQ4eSEyeSU6eSzZuThYWkKjl+PNmx45oPB1hs2RmOqvqkqtqWJKOA8fgkz03yvVX1EetUHwCw3jZu7K7vuis5cCC5fDk5ejS5445h6wKm0kpLqp6f5FKSVNWTknxXkhcmuZjkUP+lAQCD2Latuz53LtmwITl2LNmzZ9iagKm10pKqDa21t49+/oIkh1prv5zkl6vqVf2XBgAMYmEh2b69m+k4fDjZtevajwFYxoqBo6puaq29L8lCkjvHfBwAMM127kzOnOl+3rRp2FqAqbfSkqqfTfI7VfVrSf4uye8mSVXdnm5Z1VRxIh+mld5lGunbKVbVXW6+ubtcub30MqP0Lqy9ZQNHa+3b0x3+9u4kn9baB04t+qAk/6H/0taWE/kwrfQu00jfMq30Lqy9FZdGtdZecZX7/ry/cgAAgFkyzon/AAAArovAAQAA9EbgAAAAeiNwAAAAvRE4AACA3ggcAABAbwQOAACgNwIHwBA+cC5VAJhtcxM4qupgVR26ePHi0KXAqujdGXT+fLJ3b3Ly5NCV9EbfMq30Lqy9uQkcrbV7Wmt3btmyZehSYFX07ow5ezbZty+5dCnZvXvoanqjb5lWehfW3twEDoB1d+FCsn//AzMZp093t5PkyJFk69bhagOAdXLT0AUAzKxDh5ITJ5JTp5LNm5OFhaQqOX482bFj6OoAYF2Y4QDoy8aN3fVddyUHDiSXLydHjyZ33DFsXQCwjgQOgL5s29ZdnzuXbNiQHDuW7NkzbE0AsM4sqQLoy8JCsn17N9Nx+HCya9fQFQHAuhM4APqyc2dy5kz386ZNw9YCAAMROAD6JGiQdCd6rBq6CoBB2IcDoA9V412YfXNwokeAlQgcANCXOTnRI8BK5iZwVNXBqjp08eLFoUuBVdG7TKO57FsnepwJc9m70LO5CRyttXtaa3du2bJl6FJgVfQu02gu+3bxiR5f/eoubFy+nLzsZU70OEXmsnehZ3MTOACgV070CHBVAgcArAUneqQnrbWhS1gzxjKfBA4AWAtXTvT4mMd0S6uEDdbA+fvPZ++P7s3JN0z/Uc6MZX45DwcArAUnemSNnX3b2Sy8cCE3b7w5ux8x3Uc5m4ixrNH5cCZiLFPGDAcArJVNm4QNrsuFd17I/rv3f+Ab89NvOZ39d3dHOTvy9CPZ+tDpOcrZRI7lOs+HM5FjmUJmOADgRo37rak13yzj0H2HcuL8iZx606lsfvDmLLxwIVWV419yPDu2TNdRziZuLGfPdkseb7551efDmbixTCkzHEw//wMHYMpt3NAd5eyuV96VAy84kMvtco4+/WjuePj0HeVs0LGs8flwZunvMiSBg+l2nVOkADBJtm3ujnJ27u3nsuFBG3LsGcey51HTeeCBQceyxufDmaW/y5AsqWJ63cAUKQBMkoVHL2T7LduzccPGHP6iw9l1666hS7pug45l8flwnvvcbhXEsWPXfT6cWfq7DEngYDpcuJA87WnJd31X8sQndlOkCwvJTTdd1xQpAEySnVt35syzuqOcbdo43QceGHQsi8+H88hHdiffvIFDVM/S32VIAgfTYfEU6ebNXdioSo4fv64pUgCYNLP0gXawsVw5H87Gjcnhw8muG5+RmKW/y1AEDqbDGk+RAsCkqG8Z7yhn7TmTf5CUwceyhufDGXwsM2RudhqvqoNVdejixYtDl8L1WDxFumFDFzbm5Cy+epdppG+ZVnp3ilV1l5tv7i5Xbi+9sO7mJnC01u5prd25ZcuWoUvhelyZIn3MY7qlVXMSNhK9y3TSt0wrvQtrz5IqpsMaTpECALB+BA6mh6ABADB1BA4m22rWWjrj+OxrzfpbAJgyc7MPBzDlnFUeAKaSwAFMvrNnk337kkuXnFUeAKaMwAFMlgsXkv37H5jJOH26u504qzwATCH7cACTxVnlAWCmmOEAJsvis8ofOJBcvpwcPeqs8gAwpQQOYLLM8VnlAWAWWVIFTJYrZ5XfuDE5fDjZtWvoigCAGyBwAJPFWeUBYKYIHMDkETQAYGYIHMDkGPcs4s4qDwBTw07jAABAbwQOAACgN3MTOKrqYFUdunjx4tClwKroXaaRvmVa6V1Ye3MTOFpr97TW7tyyZcvQpcCq6F2mkb5lWuldWHtzEzgAAID1J3AAAHB1jgrIGhA4AAD4UOfPJ3v3JidPDl0JU07gmFe+sQAAlnP2bLJvX3LpUrJ799DVMOUEjnnkGwsA4IoLF5L9+x/4XHD6dHc7SY4cSbZuHa42ZoIzjc+bs2eThYXk5pt9YwEAJIcOJSdOJKdOJZs3d58TqpLjx5MdO4aujhlghmOW+cYCALiWjRu767vuSg4cSC5fTo4eTe64Y9i6mBlmOGaZbywAgGvZtq27PncueeQju7CxZ8+wNTFTzHDMMt9YAADXsrCQbN+ePOYx3ReVwgZrzAzHLPONBQBwLTt3JmfOdD9v2jRsLcwkgWOWXfnGYuPG5PDhZNeuoSsCACaRoEGPBI5Z5hsLYJq11u13BvRn3P/GnL+LG2Afjlm3aZOwAUwf5wsCmBkCx6yqGu8CMGmc4RhgpggcAAzH+YIAZp59OAAYjvMFAcw8MxwADMf5ggBmnsABwHAWny9ow4bk2DHnCwKYMZZUATAc5wsCmHkCBwDDcb4ggJk3N0uqqupgVR26ePHi0KXAquhdptFYfXvl8Nw339xdHL6bCeDfXFh7cxM4Wmv3tNbu3LJly9ClwKroXaaRvmVa6V1Ye3MTOAAAgPUncAAAAL0ROAAAgN4IHAAAQG8EDgAAoDcCBwAA0BuBAwAA6I3AAQAA9EbgAAAAeiNwAAAAvRE4AACA3ggcAABAbwQOmAetDV0BADCnBA6YdefPJ3v3JidPDl0JADCHBA6YZWfPJvv2JZcuJbt3D10NADCHBA6YFRcuJPv3PzCTcfp0dztJjhxJtm4drjYAYG7dNHQBwBo5dCg5cSI5dSrZvDlZWEiqkuPHkx07hq4OAJhTZjhgVmzc2F3fdVdy4EBy+XJy9Ghyxx3D1gUAzDWBA2bFtm3d9blzyYYNybFjyZ49w9YEAMw9S6pgViwsJNu3dzMdhw8nu3YNXREAgMABM2PnzuTMme7nTZuGrQUAYETggFkiaAAAE0bggGlXNf62zjgOAKwzO40DAAC9ETgAAIDeCBwAAEBvBA4AAKA3AgcAANAbgWM1HOEHALgWnxfggwgc4zp/Ptm7Nzl5cuhKAIBJ5fMCfIi5CRxVdbCqDl28eHH1Dz57Ntm3L7l0Kdm9e+2LgxXcUO/CQPQt08rnBVh7cxM4Wmv3tNbu3LJly8obXriQ7N//wDcTp093t5PkyJFk69Z+C4Ulxu5dmCD6lmnl8wKsPWcaX+rQoeTEieT/b+/+Y+2s7/uAvz+YSyDxuJ4CC1EwDq1jF8YwSVm0dHEc7+YPttZts1ajTQWk6Ya6iKmLVlWpJjXKsi1rmmhqylbkpYmha5O1bJlK5S641MxLAxhQCSVxXdxoFlCaUCgkYc1o3O/+uIfs1vja59x7n/ucH6+XZN1znvOc53w+Xz5cnfd9zo/Dh5ONG5OFhcVvcr777uSSS/quDgAYB54vwNBm5gzH0ObmFn/efHOye3dy4kRy4ECybVu/dQEA48PzBRiawHGyiy5a/HnsWLJhQ3LwYHLllf3WBACMF88XYGheUnWyhYVk8+bFv1zs359s3953RQDAuPF8AYYmcJxsy5bk6NHFy+ed128tAMB48nwBhiZwnIpfHADAmXi+AEMROJaqGm4/3yAKALPL8wUYiTeNAwAAnRE4AACAzggcAABAZwQOAACgMwIHAADQGYEDAADojMABAAB0RuAAAAA6I3AAAACdETgAAIBU1fdV1cNV9VBVPVBVb15mv++sqt+vqmNV9dGqqtMdV+AAAIApU4vOWnJ9wxB3uyvJjtbaVUneleRjy+z3i0n+SZLXDf5dc7qDChwAADAFquq1VXW0qm5L8kiSE1X1kar6fJI3nen+rbWvt9ba4OorkrST96mqVyc5v7V272Df25J8/+mOe/aojQAAAGPrdUluaK3dW1UtyX2ttX+RJFX175PsPsV9PtVa+3eDfd6e5INJ/kaS7z7Fvq9J8viS648Pti1L4AAAgOlxvLV27+DyiST/9cUbWmvvOdOdW2ufTvLpqnpLkg8kedtqCxI4AABgejy/5PI3WmsnXrwyzBmOF7XWDlXVt1XVBa21P11y0xNJLl5y/eLBtmUJHAAAMAPOdIajqrYm+aPWWquqNyR5WZKnTzrGk1X11ar6O0nuS3J9kl843XEFDgAAIEl+IMn1VfUXSf48ybUvvom8qh4afHpVkrw7yb4k5yX5rcG/ZQkcAAAwBVpr/zvJFUuubxzx/j+b5GeXue2qJZcfWPo4Z+JjcQEAgM4IHAAAQGcEDgAAoDMCBwAA0BmBAwAA6IzAAQAAdEbgAAAAOiNwAAAAnRE4AACAzggcAABAZwQOAACgMwIHAADQGYEDAADojMABAAB0RuAAAAA6I3AAAACdETgAAIDOCBwAAEBnBA4AAKAzAgcAANAZgQMAAOiMwAEAAHRmogNHVX1bVf1SVd3edy0AAMBLjV3gqKqPV9VXquqRk7ZfU1VHq+pYVb03SVprX2qt/Vg/lQIAAGcydoEjyb4k1yzdUFUbkvyHJH8/yeVJfriqLl//0gAAgFGMXeBorR1K8sxJm9+Y5NjgjMYLST6V5PvWvTgAAGAkYxc4lvGaJI8tuf54ktdU1Sur6pYkr6+qn17uzlV1Y1U9UFUPPPXUU13XCmvG7DKJzC2TyuxCNyYlcJxSa+3p1tqPt9a+vbX2wdPst7e1dnVr7eoLL7xwPUuEVTG7TCJzy6Qyu9CNSQkcTyTZvOT6xYNtAADAGJuUwHF/ktdV1aVVdU6SH0ryGz3XBAAAnMHYBY6q+mSSe5Jsr6rHq+rHWmvfTHJTks8kOZLk11prX+izTgAA4MzO7ruAk7XWfniZ7fuT7F/ncgAAgFUYuzMcAADA9BA4gJG11vouYc3oBQC6NTOBo6r2VNXe5557ru9SYCTjNrvHnz2eHbfsyD2P3dN3Kauml+6M29zCsMwurL2ZCRyttTtaazfOz8/3XQqMZJxm99GnH83OT+zMCydeyGUXXtZ3Oauil26N09zCKMwurL2ZCRzAaJ782pPZtW/Xt/5ifuSpI9m1b1eS5M7r7symczf1Wd5I9AIA/Rm7T6kCxsPeB/fm0PFDOfzE4Ww8Z2MWbltIVeXu6+/OJfOX9F3eSPQCABy5lLMAAA5iSURBVP1xhgM4pbkNc0mSm++/Obtv3Z0T7UQOXHcg2165refKRqcXAOiPwAGc0kUbL0qSHHvmWDactSEHbziYK191Zc9VrYxeAKA/XlIFnNLCpQvZfP7mzG2Yy/537M/2C7b3XdKK6QUA+iNwAKe0ZdOWHL3paJLkvLnzeq5mdfQCAP0ROIBlTdMTWr0AQD9mJnBU1Z4ke7Zu3dp3KTCSPma33l9D7dfeN/7fbK2Xfvidy6Qyu7D2ZuZN477Ih0lldplE5pZJZXZh7c1M4AAAANafwAEAAHRG4AAAADojcAAAAJ0ROAAAgM4IHAAAQGcEDgAAoDMCBwAA0JmZCRxVtaeq9j733HN9lwIjMbtMInPLpDK7sPZmJnD45lAmldllEplbJpXZhbU3M4EDAFprfZewZqall2npA1iewAHATDj+7PHsuGVH7nnsnr5LWbVp6WVa+gBOT+AAYOo9+vSj2fmJnXnhxAu57MLL+i5nVaall2npAzgzgQOAqfLk157Mrn27vvVX8yNPHcmufbuSJHded2c2nbupz/JGMi29TEsfwMqc3XcBALCW9j64N4eOH8rhJw5n4zkbs3DbQqoqd19/dy6Zv6Tv8kYyLb1MSx/AyjjDAcBUmdswlyS5+f6bs/vW3TnRTuTAdQey7ZXbeq5sdNPSy7T0AayMwAHAVLlo40VJkmPPHMuGszbk4A0Hc+Wrruy5qpWZll6mpQ9gZbykCoCpsnDpQjafvzlzG+ay/x37s/2C7X2XtGLT0su09AGsjMABwFTZsmlLjt50NEly3tx5PVezOtPSy7T0AayMwAHA1JmmJ7XT0su09AGMbmYCR1XtSbJn69atfZcCIzG7TKI+5rbeX0Pv29433t9uPWwv495HMnm9+J0La29m3jTeWrujtXbj/Px836XASMwuk8jcMqnMLqy9mQkcAADA+hM4AACAzggcXWjDvQ61Dblfr/QyW6apd73MjmlaH73MlmlaI71wGgLHWnv+ePJbO5Kn7jntbsefPZ4dt+zIPY+dfr9e6WW2DLlGE0Evs2Oa1kcvs2Wa1kgvnIHAsZa++mhyYGfyly8k85ctu9ujTz+anZ/YmRdOvJDLLlx+v17pZR0LHANDrtFE0MvsmKb10ctsmaY10gtDEDhW6s+fTH571/9PwM8dSe7atXh5953JOZuSJE9+7cns2rfrW38xP/LUkezat7jfndfdmU3nblr30l9CL+PZS1eGXKOJoJfZMU3ro5fZMk1rpBdWaGa+h2PNHdubfOVQ8vThZG5jctdCUpUs3J284pJv7bb3wb05dPxQDj9xOBvP2ZiF2xZSVbn7+rtzyfwlyx9/PellPHvpypBrNBH0MjumaX30MlumaY30wgo5w7FSZ80t/vzDm5O7diftRLL7QHL+tr+y29yGxf1uvv/m7L51d060Ezlw3YFse+W2k4/YH72MZy9dGXKNJoJeZsc0rY9eZss0rZFeWCGBY6XOvWjx59ePJbUhWTiY/PUrX7LbRRsX9zv2zLFsOGtDDt5wMFe+6qX79Uov49lLV4Zco4mgl9kxTeujl9kyTWukF1bIS6pW6qKF5OWbFxPyW/cn528/5W4Lly5k8/mbM7dhLvvfsT/bLzj1fr3Sy3j20pUh12gi6GV2TNP66GW2TNMa6YUVEjhW6hVbku85unj57POW3W3Lpi05etPifufNLb9fr/SyHpWNjyHXaCLoZXZM0/roZbZM0xrphRUSOFZjyAGdiCe0epkt0/TLVS+zY5rWRy+zZZrWSC+swMwEjqrak2TP1q1b+y4FRmJ2mUTDzO2HhzzWT36k1qSmLullevidC2tvZt403lq7o7V24/z8fN+lwEjMLpPI3DKpzC6svZkJHAAAwPoTOAAAgM4IHAAAQGcEDgAAoDMCBwAA0BmBAwAA6IzAAQAAdEbgAAAAOiNwAAAAnRE4AACAzggcAABAZwQOAACgMwIHAADQGYEDAADojMABAAB05uy+C1gvVbUnyZ6tW7f2XQqMZE1n91dr9ccYB9PSRzJdvSzhdy6Tak1n9yNT9P+3XliFmTnD0Vq7o7V24/z8fN+lwEjMLpPI3DKpzC6svZkJHAAAwPoTOAAAgM4IHAAAQGcEDgAAoDMCBwAA0BmBAwAA6IzAAQAAdEbgAAAAOiNwAAAAnRE4AACAzggcAABAZwQOAACgMwIHAADQGYEDAADojMABAAB0RuAAAAA6I3AAAACdETgAAIDOCBwAAEBnBA4AAKAzZ/ddwHqpqj1J9mzdunXZfT485LF+ctjHfH8NtV97XxvyiMObll6G7SMZ/15WapjZHdqTqz/EWJiWPpLp6mWJNZ1bWEdmF9bezJzhaK3d0Vq7cX5+vu9SYCRml0lkbplUZhfW3swEDgAAYP0JHAAAQGcEDgAAoDMCBwAA0BmBAwAA6IzAAQAAdEbgAAAAOiNwAAAAnRE4AACAzggcAABAZwQOAACgMwIHAADQGYEDAADojMABAAB0RuAAAAA6I3AAAACdETgAAIDOCBwAAEBnBA4AAKAzAgcAANAZgQMAAOiMwAEAAHRG4AAAADojcAAAAJ0ROAAAgM4IHAAAQGcEDgAAoDMCBwAA0BmBAwAA6Ey11vquYV1U1Z4ke5Jcm+TRFR7mgiR/umZF9Usvq7OltXbhejyQ2X0JvazcpM1tMj3/vaelj8Tv3GH47z2epnp2x9nMBI61UFUPtNau7ruOtaCX2TJNa6SX2TItazQtfSTT1UtXpmmN9MJa8JIqAACgMwIHAADQGYFjNHv7LmAN6WW2TNMa6WW2TMsaTUsfyXT10pVpWiO9sGrewwEAAHTGGQ4AAKAzAseQqmpTVd1eVX9QVUeq6k191zSsqvp4VX2lqh5Zsu3nBr08XFWfrqpNfdY4rGV6uaqq7q2qh6rqgap6Y581jhNzOx7M7ejM7ngwu6Mzu+PB7I4XgWN4P5/kf7TWviPJjiRHeq5nFPuSXHPStgNJrmitXZnkD5P89HoXtUL78tJePpTk/a21q5L8zOA6i8zteNgXczsqszse9sXsjsrsjod9MbtjQ+AYQlXNJ3lLkl9KktbaC621Z/utanittUNJnjlp252ttW8Ort6b5OJ1L2wFTtVLkpbk/MHl+SR/vK5FjSlzOz7M7WjM7vgwu6Mxu+PD7I6Xs/suYEJcmuSpJJ+oqh1JHkzyE6215/sta828K8l/6buIVfjnST5TVR/OYoj+rp7rGRfmdryZ2+WZ3fFmdpdndseb2e2JMxzDOTvJG5L8Ymvt9UmeT/LefktaG1X1L5N8M8mv9F3LKvzTJO9prW1O8p4M/rKEuR1z5nZ5Zne8md3lmd3xZnZ7InAM5/Ekj7fW7htcvz2Lv1AmWlW9M8n3JPmRNtmfj3xDkv82uPzrSbwJbJG5HW/mdnlmd7yZ3eWZ3fFmdnsicAyhtfYnSR6rqu2DTQtJvthjSatWVdck+akk39ta+z9917NKf5xk1+Dy30vyaI+1jA1zO/bM7TLM7tgzu8swu2PP7PbEF/8NqaquSvKxJOck+VKSH22t/Vm/VQ2nqj6Z5K1JLkjy5STvy+KnTLwsydOD3e5trf14LwWOYJlejmbxU0HOTvKNJO9urT3YV43jxNyOB3M7OrM7Hszu6MzueDC740XgAAAAOuMlVQAAQGcEDoAxVVUXVdWnquqPqurBqtpfVdtWcJydVfWFwbfrvqaqbu+i3pMe86qq+gdLrn9vVU3Fp/UAMBovqQIYQ1VVST6X5NbW2i2DbTuSnN9a+18jHuuWJJ9trf3nNa7x7CVfCHbybe9McnVr7aa1fEwAJo8zHADjaXeSv3gxbCRJa+3zST5bVT9XVY9U1e9X1bVJUlVvraq7q+r2qvqDqvqVWvSPk/yjJB8YbHttVT0yuM/Lq+rXquqLVfXpqrqvqq4e3Pb1Fx+3qn6wqvYNLu+rqluq6r4kH6qqN1bVPVX1e1X1uaraXlXnJPlXSa4dnFW5tqreWVU3D47x2qr6nap6uKruqqpLlhz7o4PjfKmqfnCw/dVVdWhwrEeqamfXiw/A2vFN4wDj6Yosfkvxyf5hkquS7Mjip6/cX1WHBre9PsnfzOJHP/5ukr/bWvtYVb05yW+21m6vqtcuOda7k/xZa+3yqroiyUND1nZxku9qrZ2oqvOT7GytfbOq3pbk37bWfqCqfiZLznAMzni86BeyeObm1qp6V5KPJvn+wW2vTvLmJN+R5Dey+D0G70jymdbav6mqDUlePmSdAIwBgQNgsrw5ySdbayeSfLmq/meSv53kq0kOt9YeT5KqeijJa5N89gzH+vkkaa09UlUPD1nDrw8eP0nmk9xaVa9L0pLMDXH/N2UxOCXJLyf50JLb/ntr7S+TfLGqXjXYdn+Sj1fV3OD2YYMRAGPAS6oAxtMXknzniPf5v0sun8jq/qi09A1+55502/NLLn8gycHW2hVJ9pxi31Et7aGSpLV2KMlbkjyRZF9VXb/KxwBgHQkcAOPpd5K8rKpufHFDVV2Z5NksvjdiQ1VdmMUn4odX+Bi/m8X3d6SqLk/yt5bc9uWquqyqzkry9tMcYz6LQSBJ3rlk+9eS/LVl7vO5JD80uPwjSU77Jviq2pLky621/5TFL1R7w+n2B2C8CBwAY6gtfoTg25O8bfCxuF9I8sEkv5rk4SSfz2Io+anW2p+s8GH+Y5ILq+qLSf51Fs+qPDe47b1JfjOL4eDJ0xzjQ0k+WFW/l796RuVgkstffNP4Sff5Z0l+dPASruuS/MQZ6nxrks8PHuPaDF4GBsBk8LG4ADNq8AbsudbaN6rq25P8dpLtrbUXei4NgCniTeMAs+vlSQ4O3oxdSd4tbACw1pzhAAAAOuM9HAAAQGcEDgAAoDMCBwAA0BmBAwAA6IzAAQAAdEbgAAAAOvP/AEOf/jw+uI/iAAAAAElFTkSuQmCC\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f5bf2eb2748>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "create_grid_plot('incremental/handcrafted-benchmark-1.csv')"
+   ]
+  },
+  {
+   "cell_type": "raw",
+   "metadata": {},
+   "source": [
+    "create_grid_plot('incremental/benchmark-2018-01-23-12-33-59.csv')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "metadata": {
+    "scrolled": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "nrDifferentRequests: 5 nrDifferentRatios: 8\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f5bf301dc88>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "create_grid_plot('http://141.76.65.44:8080/jastadd-mquat-benchmark/results/basic/benchmark-2018-01-24-16-18-58.csv', suffix='')"
+   ]
+  },
+  {
+   "cell_type": "raw",
+   "metadata": {
+    "scrolled": false
+   },
+   "source": [
+    "hpattern = ['x', 'x', '', '/']\n",
+    "\n",
+    "def create_single_hatched(name, solver_names=solver_names, fromIncremental=True):\n",
+    "    data = load(name)\n",
+    "    suffix = 'Hard' if fromIncremental else ''\n",
+    "    index = np.arange(len(data.name))\n",
+    "    for i, solver_name in enumerate(solver_names):\n",
+    "        hpattern_index = 2 * data.get(solver_name + 'Valid' + suffix) + data.get(solver_name + 'TimeOut' + suffix)\n",
+    "        print (solver_name, suffix, [hpattern[pi] for pi in hpattern_index])\n",
+    "        genTimes = data.get(solver_name + 'Gen' + suffix)\n",
+    "        if genTimes is not None:\n",
+    "            plt.bar(index + i * bar_width, genTimes, bar_width,\n",
+    "                    label=toLabel(solver_name) + \"[GEN]\",\n",
+    "                    color='dark' + colors[i],\n",
+    "                    hatch='/',\n",
+    "                    #edgecolor='black'\n",
+    "                   )\n",
+    "        solvTimes = data.get(solver_name + 'Solved' + suffix)\n",
+    "        if solvTimes is not None:\n",
+    "            plt.bar(index + i * bar_width, solvTimes, bar_width,\n",
+    "                    label=toLabel(solver_name),\n",
+    "                    bottom=genTimes,\n",
+    "                    color=colors[i],\n",
+    "                    hatch='/',\n",
+    "                   )\n",
+    "\n",
+    "    plt.xticks(rotation=90)\n",
+    "    plt.title(\"Solving time for hard problem\")\n",
+    "    plt.xlabel('Comp-Impl-Config-Request')\n",
+    "    plt.ylabel('Solving time [ms]')\n",
+    "    plt.yscale(\"log\")\n",
+    "\n",
+    "    plt.xticks(index + bar_width / len(solver_names), data.name.astype(str))\n",
+    "    plt.legend()\n",
+    "    plt.tight_layout()\n",
+    "    plt.show()"
+   ]
+  },
+  {
+   "cell_type": "raw",
+   "metadata": {},
+   "source": [
+    "create_single_hatched('incremental/handcrafted-benchmark-hatched.csv',\n",
+    "                      solver_names=['ilp-external', 'ilp-direct', 'simple'],\n",
+    "                      fromIncremental=False)"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.6.3"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/jastadd-mquat-benchmark/results/to-html.sh b/jastadd-mquat-benchmark/results/to-html.sh
new file mode 100644
index 0000000000000000000000000000000000000000..023e4efb1792b257a15e8ff2a101d2389e806875
--- /dev/null
+++ b/jastadd-mquat-benchmark/results/to-html.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+[[ $# -ne 1 ]] && echo Usage: $0 [CSV_FN] && exit -1
+
+CSV_FN=$1
+HTML_FN="$CSV_FN.html"
+
+echo "<table>" > $HTML_FN
+head -n 1 $CSV_FN | \
+    sed -e 's/^/<tr><th>/' -e 's/,/<\/th><th>/g' -e 's/$/<\/th><\/tr>/' >> $HTML_FN
+tail -n +2 $CSV_FN | \
+    sed -e 's/^/<tr><td>/' -e 's/,/<\/td><td>/g' -e 's/$/<\/td><\/tr>/' >> $HTML_FN
+echo "</table>" >> $HTML_FN
+
+xdg-open $HTML_FN
diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/Benchmark.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/Benchmark.java
new file mode 100644
index 0000000000000000000000000000000000000000..6492b561b6facfe2d0917209c1b033fb1334dad6
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/Benchmark.java
@@ -0,0 +1,367 @@
+package de.tudresden.inf.st.mquat.benchmark;
+
+import de.tudresden.inf.st.mquat.data.TestGeneratorSettings;
+import de.tudresden.inf.st.mquat.benchmark.data.BenchmarkSettings;
+import de.tudresden.inf.st.mquat.generator.ScenarioGenerator;
+import de.tudresden.inf.st.mquat.jastadd.model.MquatString;
+import de.tudresden.inf.st.mquat.jastadd.model.MquatWriteSettings;
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+import de.tudresden.inf.st.mquat.jastadd.model.Solution;
+import de.tudresden.inf.st.mquat.solving.BenchmarkableSolver;
+import de.tudresden.inf.st.mquat.solving.SolvingException;
+import de.tudresden.inf.st.mquat.utils.StopWatch;
+import de.tudresden.inf.st.mquat.utils.TestGenerator;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.config.Configurator;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.file.*;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+import static de.tudresden.inf.st.mquat.utils.MapCreator.e;
+import static java.nio.file.Files.exists;
+
+@SuppressWarnings("WeakerAccess")
+public class Benchmark {
+
+  private static final char SEPARATOR = ',';
+  private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");
+
+  protected final List<BenchmarkableSolver> solvers;
+  private final Logger logger;
+
+  private String resultFilePattern = "benchmark-%s.csv";  // default
+  private boolean append = false;  // default
+  private long timeoutValue;
+  private TimeUnit timeoutUnit;
+  protected BenchmarkSettings settings;
+
+  public Benchmark() {
+    solvers = new ArrayList<>();
+    logger = LogManager.getLogger(this.getClass());
+    setTimeout(60, TimeUnit.SECONDS);  // default
+  }
+
+  public void setResultFilePattern(String resultFilePattern) {
+    this.setResultFilePattern(resultFilePattern, false);
+  }
+
+  public void setResultFilePattern(String resultFilePattern, boolean append) {
+    if (!append && !resultFilePattern.contains("%(date)s")) {
+      logger.warn("Ignoring (non-append) new file pattern lacking %(date)s part.");
+      return;
+    }
+    this.append = append;
+    this.resultFilePattern = resultFilePattern;
+  }
+
+  public void setTimeout(long timeoutValue, TimeUnit timeoutUnit) {
+    this.timeoutValue = timeoutValue;
+    this.timeoutUnit = timeoutUnit;
+    for (BenchmarkableSolver s : solvers) {
+      s.setTimeout(this.timeoutValue, this.timeoutUnit);
+    }
+  }
+
+  public void setSettings(BenchmarkSettings settings) {
+    this.settings = settings;
+    setResultFilePattern(settings.resultFilePattern);
+  }
+
+  public void addSolver(BenchmarkableSolver s) {
+    solvers.add(s);
+    Configurator.setLevel(s.getClass().getPackage().getName(), Level.toLevel(this.settings.logLevel));
+    s.setTimeout(this.timeoutValue, this.timeoutUnit);
+  }
+
+  protected StringBuilder createRow(ScenarioGenerator gen, int testId, Root model, long modelGeneration) {
+    StringBuilder sb = new StringBuilder(makeNow()).append(SEPARATOR);
+    return sb.append(testId).append(SEPARATOR)
+        .append(gen.getNumTopLevelComponents()).append(SEPARATOR)
+        .append(gen.getAvgNumImplSubComponents()).append(SEPARATOR)
+        .append(gen.getImplSubComponentStdDerivation()).append(SEPARATOR)
+        .append(gen.getAvgNumCompSubComponents()).append(SEPARATOR)
+        .append(gen.getCompSubComponentStdDerivation()).append(SEPARATOR)
+        .append(gen.getComponentDepth()).append(SEPARATOR)
+        .append(gen.getNumImplementations()).append(SEPARATOR)
+        .append(gen.getExcessResourceRatio()).append(SEPARATOR)
+        .append(gen.getNumRequests()).append(SEPARATOR)
+        .append(gen.getNumCpus()).append(SEPARATOR)
+        .append(gen.getSeed()).append(SEPARATOR)
+        .append(model.numComponents()).append(SEPARATOR)
+        .append(model.numImplementations()).append(SEPARATOR)
+        .append(modelGeneration).append(SEPARATOR)
+        .append(gen.getInitialSolution().computeObjective()).append(SEPARATOR);
+  }
+
+  private void writeHeader(BufferedWriter writer) throws IOException {
+    writer.append("when").append(SEPARATOR)
+        .append("id").append(SEPARATOR)  // testId
+        .append("tlc").append(SEPARATOR)  // topLevelComponents
+        .append("isc").append(SEPARATOR)  // avgImplSubComponents
+        .append("isd").append(SEPARATOR)  // implSubComponentStdDerivation
+        .append("csc").append(SEPARATOR)  // avgCompSubComponents
+        .append("csd").append(SEPARATOR)  // compSubComponentStdDerivation
+        .append("dep").append(SEPARATOR)  // componentDepth
+        .append("bi").append(SEPARATOR)  // implementations
+        .append("res").append(SEPARATOR)  // computeResources
+        .append("req").append(SEPARATOR)  // requests
+        .append("cpu").append(SEPARATOR)  // cpus
+        .append("seed").append(SEPARATOR)  // seed
+        .append("comp").append(SEPARATOR)  // genComponents
+        .append("impl").append(SEPARATOR)  // genImplementations
+        .append("gen").append(SEPARATOR)  // modelGeneration
+        .append("initObj").append(SEPARATOR)  // initial solution objective
+        .append("name").append(SEPARATOR);  // name of the solver
+    writeHeaderSolvers(writer);
+    writer.append('\n');
+  }
+
+  protected void writeHeaderSolvers(BufferedWriter writer) throws IOException {
+    writer.append("Gen").append(SEPARATOR)
+          .append("Solved").append(SEPARATOR)
+          .append("Obj").append(SEPARATOR)
+          .append("Valid").append(SEPARATOR)
+          .append("TimeOut");
+  }
+
+  /**
+   * Run the benchmark with added solvers, writing to the set solution path.
+   */
+  public void run() {
+    Objects.requireNonNull(settings, "Settings not set!");
+    if (solvers.isEmpty()) {
+      logger.warn("No solvers defined. Only model generation will be done.");
+    }
+    Path benchmarkPath = Paths.get(settings.path);
+    Path path, modelDirectory, solutionDirectory;
+    String start = makeNow();
+    try {
+      Path directory = benchmarkPath.resolve(getDirectory());
+      createDirIfNecessary(directory);
+      path = directory.resolve(stringFormat(resultFilePattern, e("date", start)));
+
+      modelDirectory = directory.resolve("models");
+      createDirIfNecessary(modelDirectory);
+
+      solutionDirectory = directory.resolve("solutions");
+      createDirIfNecessary(solutionDirectory);
+    } catch (IOException e) {
+      logger.catching(e);
+      logger.fatal("Could not resolve directory: {}/{}", benchmarkPath, getDirectory());
+      return;
+    }
+    AtomicInteger failCount = new AtomicInteger(5);
+    final boolean needHeader = !Files.exists(path);
+    try (BufferedWriter writer = openFile(path)) {
+      if (needHeader) {
+        writeHeader(writer);
+      }
+      TestGenerator testGen = new TestGenerator();
+      testGen.setSettings(settings.basic);
+      setTimeout(settings.basic.timeoutValue,
+          TimeUnit.valueOf(settings.basic.timeoutUnit));
+
+      // output a description of the benchmark
+      StringBuilder sb = new StringBuilder();
+      describe(sb, testGen);
+      logger.info(sb.toString());
+
+      AtomicInteger totalCount;
+      if (settings.basic.total != null && settings.basic.total > 0) {
+        totalCount = new AtomicInteger(settings.basic.total);
+      } else {
+        totalCount = null;
+      }
+      logger.info("Going to create {}{} models",
+          totalCount == null ? "" : totalCount.get() + " of ",
+          testGen.getExpectedModelCount());
+      testGen.generateScenarioGenerator((gen, testId) -> runScenario(
+          gen, testId, writer, path,
+          () -> modelDirectory.resolve(stringFormat(settings.modelFilePattern,
+              e("date", start), e("id", testId))),
+          s -> solutionDirectory.resolve(stringFormat(settings.solutionFilePattern,
+              e("date", start), e("solver", s.getName()), e("id", testId))),
+          failCount, totalCount));
+      logger.info("Results have been written to {}", path);
+    } catch (IOException e) {
+      logger.fatal("Could not create or write header to the benchmark file {}. {}. Exiting.",
+          path.toAbsolutePath(), e);
+    }
+  }
+
+  private String makeNow() {
+    return df.format(new Date());
+  }
+
+  private void createDirIfNecessary(Path directory) throws IOException {
+    if (!exists(directory)) {
+      Files.createDirectories(directory);
+    }
+  }
+
+  @SafeVarargs
+  private final String stringFormat(String pattern, Map.Entry<String, Object>... args) {
+    String result = pattern;
+    for (Map.Entry<String, Object> entry : args) {
+      result = result.replace("%(" + entry.getKey() + ")s", entry.getValue().toString());
+    }
+    return result;
+  }
+
+  private BufferedWriter openFile(Path path) throws IOException {
+    if (append) {
+      return Files.newBufferedWriter(path, StandardOpenOption.APPEND, StandardOpenOption.CREATE);
+    } else {
+      return Files.newBufferedWriter(path);
+    }
+  }
+
+  protected String getDirectory() {
+    return "basic";
+  }
+
+  protected boolean runScenario(ScenarioGenerator gen, int testId, BufferedWriter writer, Path path, ModelFilePattern mfp, SolutionFilePattern sfp, AtomicInteger failCount, AtomicInteger totalCount) {
+    logger.debug("Starting model generation");
+    StopWatch watch = StopWatch.start();
+    Root model = gen.generate();
+    logger.info("Model: {}", model.description());
+    long modelGeneration = watch.time(TimeUnit.MILLISECONDS);
+    saveModel(model, mfp.getModelPath());
+
+    for (BenchmarkableSolver s : solvers) {
+      // reset attribute values to have same start condition for all solvers
+      model.flushAttrCache();
+      StringBuilder sb = createRow(gen, testId, model, modelGeneration);
+      Solution solution = solveAndAppend(model, s, sb);
+      // write out solution
+      try (BufferedWriter solutionWriter = Files.newBufferedWriter(sfp.getSolutionPath(s))) {
+        MquatString out = solution.print(new MquatWriteSettings(" "));
+        solutionWriter.write(out.toString());
+      } catch (IOException e) {
+        logger.catching(e);
+      }
+      if (!writeOutResult(writer, path, failCount, sb)) return false;
+    }
+
+    return totalCount == null || totalCount.decrementAndGet() > 0;
+  }
+
+  private void saveModel(Root model, Path modelPath) {
+    try (BufferedWriter writer = Files.newBufferedWriter(modelPath)) {
+      MquatString out = model.print(new MquatWriteSettings(" "));
+      writer.write(out.toString());
+    } catch (IOException e) {
+      logger.catching(e);
+    }
+  }
+
+  /**
+   * Write out result. Return <code>true</code> if run should go on.
+   * @param writer    target to write out
+   * @param path      filename of target for error messages
+   * @param failCount number of failed writes so far
+   * @param sb        source to read from
+   * @return <code>true</code> if everything was ok, <code>false</code> upon error
+   */
+  protected boolean writeOutResult(BufferedWriter writer, Path path, AtomicInteger failCount, StringBuilder sb) {
+    try {
+      writer.append(sb.toString());
+      writer.flush();
+    } catch (IOException e) {
+      logger.error("Could not write to benchmark file " + path.toAbsolutePath(), e);
+      if (failCount.decrementAndGet() == 0) {
+        logger.fatal("Giving up to write to benchmark file.");
+        return false;
+      }
+    }
+    return true;
+  }
+
+  protected Solution solveAndAppend(Root model, BenchmarkableSolver s, StringBuilder sb) {
+    Solution result = null;
+    sb.append(s.getName()).append(SEPARATOR);
+    try {
+      logger.info("Calling solver '{}'", s.getName());
+      result = s.solve(model);
+      boolean validSolution = result.isValid();
+      sb.append(s.doesGeneration() ? s.getLastGenerationTime() : -1).append(SEPARATOR)
+          .append(s.getLastSolvingTime()).append(SEPARATOR)
+          .append(s.getLastObjective()).append(SEPARATOR)
+          .append(validSolution);
+      logger.debug("Solver {} found {} solution in {}{}ms{}",
+          s.getName(),
+          validSolution ? "a valid" : "NO",
+          s.doesGeneration() ? s.getLastGenerationTime() + " + " : "",
+          s.getLastSolvingTime(),
+          s.hadTimeout() ? " -> Timed out" : "");
+    } catch (SolvingException e) {
+      logger.catching(e);
+      sb.append(-1).append(SEPARATOR)  // generation time
+          .append(-1).append(SEPARATOR)  // solution time
+          .append(-1).append(SEPARATOR)  // objective
+          .append(false);  // valid
+    }
+    sb.append(SEPARATOR).append(s.hadTimeout())
+        .append("\n");
+    return result;
+  }
+
+  protected void describe(StringBuilder sb, TestGenerator testGen) {
+    sb.append(this.getClass().getSimpleName()).append(":\n");
+    sb.append("Timeout: ").append(this.timeoutValue).append(" ")
+        .append(this.timeoutUnit.toString().toLowerCase()).append('\n');
+    TestGeneratorSettings tgs = this.settings.basic;
+    append(sb, "TopLevelComponents", tgs.minTopLevelComponents, tgs.maxTopLevelComponents);
+    append(sb, "AvgNumImplSubComponents", tgs.minAvgNumImplSubComponents, tgs.maxAvgNumImplSubComponents);
+    append(sb, "ImplSubComponentDerivation", tgs.minImplSubComponentDerivation, tgs.maxImplSubComponentDerivation);
+    append(sb, "AvgNumCompSubComponents", tgs.minAvgNumCompSubComponents, tgs.maxAvgNumCompSubComponents);
+    append(sb, "CompSubComponentDerivation", tgs.minCompSubComponentDerivation, tgs.maxCompSubComponentDerivation);
+    append(sb, "ComponentDepth", tgs.minComponentDepth, tgs.maxComponentDepth);
+    append(sb, "NumImplementations", tgs.minNumImplementations, tgs.maxNumImplementations);
+    append(sb, "Requests", tgs.minRequests, tgs.maxRequests, tgs.stepRequests);
+    append(sb, "Cpus", tgs.minCpus, tgs.maxCpus);
+    append(sb, "ResourceRatio", tgs.minResourceRatio, tgs.maxResourceRatio, tgs.stepResourceRatio);
+    append(sb, "Seed", this.settings.basic.seed);
+    sb.append("Solvers: ").append(solvers.stream().map(Object::toString).collect(Collectors.joining(", ")))
+        .append('\n');
+  }
+
+  protected <T extends Number> void append(StringBuilder sb, String name, T value) {
+    append(sb, name, value, null, null);
+  }
+
+  protected <T extends Number> void append(StringBuilder sb, String name, T min, T max) {
+    append(sb, name, min, max, null);
+  }
+
+  protected <T extends Number> void append(StringBuilder sb, String name, T min, T max, T step) {
+    sb.append(name).append(": ");
+    if (max == null || min.equals(max)) {
+      sb.append(min);
+    } else {
+      sb.append("from ").append(min).append(" to ").append(max);
+      if (step != null) {
+        sb.append(" with step ").append(step);
+      }
+    }
+    sb.append('\n');
+  }
+
+  interface ModelFilePattern {
+    Path getModelPath();
+  }
+
+  interface SolutionFilePattern {
+    Path getSolutionPath(BenchmarkableSolver s);
+  }
+
+}
diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/CustomBenchmarkMain.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/CustomBenchmarkMain.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0d65fa9107cd80703ff1e4978dcb16bd63e4ad0
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/CustomBenchmarkMain.java
@@ -0,0 +1,44 @@
+package de.tudresden.inf.st.mquat.benchmark;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.tudresden.inf.st.mquat.benchmark.data.BenchmarkSettings;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.IOException;
+
+public class CustomBenchmarkMain {
+
+  private static Benchmark createFromConfig() {
+    Logger logger = LogManager.getLogger(CustomBenchmarkMain.class);
+    BenchmarkSettings settings, localSettings;
+    ObjectMapper mapper = Utils.getMapper();
+    try {
+      settings = Utils.readFromResource(mapper, "benchmark-settings.json", BenchmarkSettings.class);
+    } catch (IOException e) {
+      logger.catching(e);
+      throw new RuntimeException("Could not read settings! Exiting.", e);
+    }
+    try {
+      localSettings = Utils.readFromResource(mapper, "local-benchmark-settings.json", BenchmarkSettings.class);
+    } catch (IOException ignored) {
+      // use an empty local settings, no value will be changed
+      LogManager.getLogger(CustomBenchmarkMain.class).info("No local settings found, using default values.");
+      localSettings = new BenchmarkSettings();
+    }
+    settings.update(localSettings);
+    Benchmark result;
+    switch (settings.kind) {
+      case "normal": result = new Benchmark(); break;
+      default: throw new RuntimeException("Unknown benchmark kind: " + settings.kind);
+    }
+    result.setSettings(settings);
+    settings.solvers.forEach(solverName -> result.addSolver(SolverFactory.getSolverByName(solverName)));
+    return result;
+  }
+
+  public static void main(String[] args) {
+    Benchmark benchmark = createFromConfig();
+    benchmark.run();
+  }
+}
diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/FullBenchmarkMain.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/FullBenchmarkMain.java
new file mode 100644
index 0000000000000000000000000000000000000000..403d8b67547aecfbab31ff78770739d3504f1a83
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/FullBenchmarkMain.java
@@ -0,0 +1,104 @@
+package de.tudresden.inf.st.mquat.benchmark;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.tudresden.inf.st.mquat.data.TestGeneratorSettings;
+import de.tudresden.inf.st.mquat.benchmark.data.BenchmarkSettings;
+import de.tudresden.inf.st.mquat.benchmark.data.ScenarioData;
+import de.tudresden.inf.st.mquat.benchmark.data.ScenarioSettings;
+import de.tudresden.inf.st.mquat.solving.BenchmarkableSolver;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * Runs all defined scenarios using every solver defined.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class FullBenchmarkMain {
+
+  private static Logger logger = LogManager.getLogger(FullBenchmarkMain.class);
+
+  public static void main(String[] args) {
+    List<Benchmark> benchmarks = createFromConfig(args);
+    if (benchmarks == null || benchmarks.isEmpty()) {
+      logger.fatal("Could not create benchmarks. Exiting now.");
+      return;
+    }
+    benchmarks.forEach(Benchmark::run);
+  }
+
+  private static List<Benchmark> createFromConfig(String[] args) {
+    Logger logger = LogManager.getLogger(CustomBenchmarkMain.class);
+    ObjectMapper mapper = Utils.getMapper();
+    ScenarioSettings settings;
+    try {
+      settings = Utils.readFromResource(mapper, "scenarios.json", ScenarioSettings.class);
+    } catch (IOException e) {
+      logger.catching(e);
+      return null;
+    }
+    final List<Integer> allowedIds = Arrays.stream(args)
+        .map(FullBenchmarkMain::parseInt)
+        .filter(Objects::nonNull)
+        .collect(Collectors.toList());
+    final List<String> allowedNames = Arrays.asList(args);
+    final boolean takeAll = args.length == 0;
+    final List<BenchmarkableSolver> solvers = settings.solvers.stream()
+        .map(SolverFactory::getSolverByName).collect(Collectors.toList());
+    return settings.scenarios.stream()
+        .filter(data -> takeAll || allowedIds.contains(data.getId()) || allowedNames.contains(data.name))
+        .map(data -> new ScenarioBenchmark(from(settings, data), solvers, settings.repetitions))
+        .collect(Collectors.toList());
+  }
+
+  private static Integer parseInt(String s) {
+    try {
+      return Integer.parseInt(s);
+    } catch (NumberFormatException e) {
+      return null;
+    }
+  }
+
+  private static BenchmarkSettings from(ScenarioSettings settings, ScenarioData data) {
+    BenchmarkSettings result = new BenchmarkSettings();
+    result.kind = "normal";
+    String scenarioName = data.getId() + "_" + data.name;
+    result.resultFilePattern = scenarioName + ".csv";
+    result.modelFilePattern = scenarioName + ".txt";
+    result.solutionFilePattern = scenarioName + "-%(solver)s.txt";
+    result.logLevel = settings.logLevel;
+    result.path = settings.path;
+    result.solvers = settings.solvers;
+    TestGeneratorSettings tgs = new TestGeneratorSettings();
+    tgs.minTopLevelComponents = tgs.maxTopLevelComponents = 1;
+    tgs.minAvgNumImplSubComponents = tgs.maxAvgNumImplSubComponents = 0;
+    tgs.minImplSubComponentDerivation = tgs.maxImplSubComponentDerivation = 0;
+    tgs.minAvgNumCompSubComponents = tgs.maxAvgNumCompSubComponents = 2;
+    tgs.minCompSubComponentDerivation = tgs.maxCompSubComponentDerivation = 0;
+    tgs.minComponentDepth = data.depth;
+    tgs.maxComponentDepth = data.depth;
+    tgs.minNumImplementations = data.variants;
+    tgs.maxNumImplementations = data.variants;
+    tgs.minRequests = data.requests;
+    tgs.maxRequests = data.requests;
+    tgs.stepRequests = 1;
+    tgs.minCpus = tgs.maxCpus = 1;
+    tgs.minResourceRatio = data.resources;
+    tgs.maxResourceRatio = data.resources;
+    tgs.stepResourceRatio = 1.0;
+    tgs.timeoutValue = settings.timeoutValue;
+    tgs.timeoutUnit = settings.timeoutUnit;
+    tgs.seed = settings.seed;
+    tgs.total = settings.repetitions;
+    tgs.verbose = true;
+    result.updateBasic(tgs);
+    return result;
+  }
+
+}
diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/ScenarioBenchmark.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/ScenarioBenchmark.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c244cbba0e7f686b7ba5a2f7245ff5548e33c88
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/ScenarioBenchmark.java
@@ -0,0 +1,54 @@
+package de.tudresden.inf.st.mquat.benchmark;
+
+import de.tudresden.inf.st.mquat.benchmark.data.BenchmarkSettings;
+import de.tudresden.inf.st.mquat.generator.ScenarioGenerator;
+import de.tudresden.inf.st.mquat.solving.BenchmarkableSolver;
+import de.tudresden.inf.st.mquat.utils.TestGenerator;
+
+import java.io.BufferedWriter;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Benchmark running a predefined scenario.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class ScenarioBenchmark extends Benchmark {
+
+  private int repetitions;
+
+  public ScenarioBenchmark(BenchmarkSettings settings, List<BenchmarkableSolver> solvers, int repetitions) {
+    super();
+    this.repetitions = repetitions;
+    this.settings = settings;
+    setResultFilePattern(settings.resultFilePattern, true);
+    for (BenchmarkableSolver solver : solvers) {
+      addSolver(solver);
+    }
+  }
+
+  @Override
+  protected String getDirectory() {
+    return "scenarios";
+  }
+
+  @Override
+  protected boolean runScenario(ScenarioGenerator gen, int testId, BufferedWriter writer, Path path, ModelFilePattern mfp, SolutionFilePattern sfp, AtomicInteger failCount, AtomicInteger totalCount) {
+    for (int i = 0; i < this.repetitions; i++) {
+      if (!super.runScenario(gen, testId, writer, path, mfp, sfp, failCount, totalCount)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  protected void describe(StringBuilder sb, TestGenerator testGen) {
+    super.describe(sb, testGen);
+    append(sb, "Repetitions", this.repetitions);
+    sb.append("Result file: ").append(this.settings.resultFilePattern);
+  }
+}
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
new file mode 100644
index 0000000000000000000000000000000000000000..3a28cd527edf9480cafd5a88342d1fef2c6f6da7
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/SolverFactory.java
@@ -0,0 +1,42 @@
+package de.tudresden.inf.st.mquat.benchmark;
+
+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 java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Gathering point for all solvers.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class SolverFactory {
+
+  private static Map<String, BenchmarkableSolver> availableSolvers;
+
+  private static Map<String, BenchmarkableSolver> createAvailableSolversIfNeeded() {
+    if (availableSolvers == null) {
+      availableSolvers = Stream.of(
+          new ILPExternalSolver(),
+          new ILPDirectSolver(),
+          new SimpleSolver()
+      ).collect(Collectors.toMap(BenchmarkableSolver::getName, Function.identity()));
+    }
+    return availableSolvers;
+  }
+
+  /**
+   * Get a solver by its name. Returns <code>null</code> if no solver exists with this name.
+   * @param name the name of the solver to search for
+   * @return an instance of the solver, or <code>null</code>
+   */
+  public static BenchmarkableSolver getSolverByName(String name) {
+    return createAvailableSolversIfNeeded().get(name);
+  }
+
+}
diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/Utils.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/Utils.java
new file mode 100644
index 0000000000000000000000000000000000000000..791e011c4cd728fd166b2eb3a724292bcd55ef45
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/Utils.java
@@ -0,0 +1,44 @@
+package de.tudresden.inf.st.mquat.benchmark;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+public class Utils {
+
+  static ObjectMapper getMapper() {
+    ObjectMapper mapper = new ObjectMapper();
+    mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
+    return mapper;
+  }
+
+  private static File readFromResource(String filename) throws IOException {
+    URL basicSettingsURL = CustomBenchmarkMain.class.getClassLoader().getResource(filename);
+    if (basicSettingsURL == null) {
+      System.err.println();
+      throw new IOException("Could not access " + filename + ". Exiting.");
+    }
+    return new File(basicSettingsURL.getFile());
+  }
+
+  static <T> T readFromResource(ObjectMapper mapper, String filename, Class<T> clazz) throws IOException {
+    File basicSettingsFile = readFromResource(filename);
+    T result = null;
+    try {
+      result = mapper.readValue(basicSettingsFile, clazz);
+    } catch (Exception e) {
+      System.err.println("Could not load '" + filename + "'. Exiting.");
+      e.printStackTrace();
+      System.exit(2);
+    }
+    return result;
+  }
+
+  public static <T> T nonNullOrDefault(T newValue, T defaultValue) {
+    return newValue != null ? newValue : defaultValue;
+  }
+
+}
diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/data/BenchmarkSettings.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/data/BenchmarkSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..998df5e65a7327bb50a21a126eeec1a496d48ad4
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/data/BenchmarkSettings.java
@@ -0,0 +1,62 @@
+package de.tudresden.inf.st.mquat.benchmark.data;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import de.tudresden.inf.st.mquat.data.TestGeneratorSettings;
+
+import java.util.List;
+
+import static de.tudresden.inf.st.mquat.benchmark.Utils.nonNullOrDefault;
+
+@JsonInclude(JsonInclude.Include.NON_DEFAULT)
+public class BenchmarkSettings {
+
+  public String kind = null;
+  public String path = null;
+  public String resultFilePattern = null;
+  public String modelFilePattern = null;
+  public String solutionFilePattern = null;
+  public List<String> solvers = null;
+  public String logLevel = null;
+
+  public final TestGeneratorSettings basic = new TestGeneratorSettings();
+
+  public void update(BenchmarkSettings other) {
+    this.kind = nonNullOrDefault(other.kind, this.kind);
+    this.path = nonNullOrDefault(other.path, this.path);
+    this.resultFilePattern = nonNullOrDefault(other.resultFilePattern, this.resultFilePattern);
+    this.solvers = nonNullOrDefault(other.solvers, this.solvers);
+    this.logLevel = nonNullOrDefault(other.logLevel, this.logLevel);
+    updateBasic(other.basic);
+  }
+
+  public void updateBasic(TestGeneratorSettings other) {
+    basic.verbose = nonNullOrDefault(other.verbose, basic.verbose);
+    basic.minTopLevelComponents = nonNullOrDefault(other.minTopLevelComponents, basic.minTopLevelComponents);
+    basic.maxTopLevelComponents = nonNullOrDefault(other.maxTopLevelComponents, basic.maxTopLevelComponents);
+    basic.minAvgNumImplSubComponents = nonNullOrDefault(other.minAvgNumImplSubComponents, basic.minAvgNumImplSubComponents);
+    basic.maxAvgNumImplSubComponents = nonNullOrDefault(other.maxAvgNumImplSubComponents, basic.maxAvgNumImplSubComponents);
+    basic.minImplSubComponentDerivation = nonNullOrDefault(other.minImplSubComponentDerivation, basic.minImplSubComponentDerivation);
+    basic.maxImplSubComponentDerivation = nonNullOrDefault(other.maxImplSubComponentDerivation, basic.maxImplSubComponentDerivation);
+    basic.minAvgNumCompSubComponents = nonNullOrDefault(other.minAvgNumCompSubComponents, basic.minAvgNumCompSubComponents);
+    basic.maxAvgNumCompSubComponents = nonNullOrDefault(other.maxAvgNumCompSubComponents, basic.maxAvgNumCompSubComponents);
+    basic.minCompSubComponentDerivation = nonNullOrDefault(other.minCompSubComponentDerivation, basic.minCompSubComponentDerivation);
+    basic.maxCompSubComponentDerivation = nonNullOrDefault(other.maxCompSubComponentDerivation, basic.maxCompSubComponentDerivation);
+    basic.minComponentDepth = nonNullOrDefault(other.minComponentDepth, basic.minComponentDepth);
+    basic.maxComponentDepth = nonNullOrDefault(other.maxComponentDepth, basic.maxComponentDepth);
+    basic.minNumImplementations = nonNullOrDefault(other.minNumImplementations, basic.minNumImplementations);
+    basic.maxNumImplementations = nonNullOrDefault(other.maxNumImplementations, basic.maxNumImplementations);
+    basic.minRequests = nonNullOrDefault(other.minRequests, basic.minRequests);
+    basic.maxRequests = nonNullOrDefault(other.maxRequests, basic.maxRequests);
+    basic.stepRequests = nonNullOrDefault(other.stepRequests, basic.stepRequests);
+    basic.minCpus = nonNullOrDefault(other.minCpus, basic.minCpus);
+    basic.maxCpus = nonNullOrDefault(other.maxCpus, basic.maxCpus);
+    basic.minResourceRatio = nonNullOrDefault(other.minResourceRatio, basic.minResourceRatio);
+    basic.maxResourceRatio = nonNullOrDefault(other.maxResourceRatio, basic.maxResourceRatio);
+    basic.stepResourceRatio = nonNullOrDefault(other.stepResourceRatio, basic.stepResourceRatio);
+    basic.timeoutValue = nonNullOrDefault(other.timeoutValue, basic.timeoutValue);
+    basic.timeoutUnit = nonNullOrDefault(other.timeoutUnit, basic.timeoutUnit);
+    basic.seed = nonNullOrDefault(other.seed, basic.seed);
+    basic.total = nonNullOrDefault(other.total , basic.total);
+  }
+
+}
diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/data/ScenarioData.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/data/ScenarioData.java
new file mode 100644
index 0000000000000000000000000000000000000000..27262e145f825b0f398794d1d3b7ade64ea73e7e
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/data/ScenarioData.java
@@ -0,0 +1,26 @@
+package de.tudresden.inf.st.mquat.benchmark.data;
+
+/**
+ * Data describing a single scenario.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class ScenarioData {
+    private int id;
+    public String name = null;
+    public int variants;
+    public int requests;
+    public int depth;
+    public double resources;
+
+  public void setId(int id) {
+    this.id = id;
+    if (this.name == null) {
+      this.name = "<Scenario " + Integer.toString(this.id) + ">";
+    }
+  }
+
+  public int getId() {
+    return id;
+  }
+}
diff --git a/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/data/ScenarioSettings.java b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/data/ScenarioSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe785540707d9662fde203ea3efba31992951044
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/java/de/tudresden/inf/st/mquat/benchmark/data/ScenarioSettings.java
@@ -0,0 +1,19 @@
+package de.tudresden.inf.st.mquat.benchmark.data;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.logging.log4j.Level;
+
+import java.util.List;
+
+@JsonInclude(JsonInclude.Include.NON_DEFAULT)
+public class ScenarioSettings {
+
+  public String path;
+  public String logLevel = Level.WARN.name();
+  public List<String> solvers;
+  public int timeoutValue;
+  public String timeoutUnit;
+  public int seed;
+  public int repetitions = 1;
+  public List<ScenarioData> scenarios;
+}
diff --git a/jastadd-mquat-benchmark/src/main/resources/benchmark-settings.json b/jastadd-mquat-benchmark/src/main/resources/benchmark-settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..40efbacb2ab56eb2b9368ba6b1ae688a600a72e8
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/resources/benchmark-settings.json
@@ -0,0 +1,42 @@
+{
+  "kind": "normal",
+  "path": "results",
+  "resultFilePattern": "benchmark-%(date)s.csv",
+  "modelFilePattern": "model-%(date)s-%(id)s.txt",
+  "solutionFilePattern": "sol-%(date)s-%(id)s-%(solver)s.txt",
+  "solvers": [
+//    "ilp-direct",
+//    "ilp-external",
+//    "mh-naive",
+    "simple"
+  ],
+  "logLevel": "debug",
+  "basic": {
+    "verbose": true,
+    "minTopLevelComponents": 1,
+    "maxTopLevelComponents": 1,
+    "minAvgNumImplSubComponents": 1,
+    "maxAvgNumImplSubComponents": 1,
+    "minImplSubComponentDerivation": 0,
+    "maxImplSubComponentDerivation": 0,
+    "minAvgNumCompSubComponents": 0,
+    "maxAvgNumCompSubComponents": 0,
+    "minCompSubComponentDerivation": 0,
+    "maxCompSubComponentDerivation": 0,
+    "minComponentDepth": 3,
+    "maxComponentDepth": 3,
+    "minNumImplementations": 3,
+    "maxNumImplementations": 3,
+    "minRequests": 2,
+    "maxRequests": 3,
+    "stepRequests": 1,
+    "minCpus": 1,
+    "maxCpus": 1,
+    "minResourceRatio": 1.5,
+    "maxResourceRatio": 1.5,
+    "stepResourceRatio": 0.5,
+    "timeoutValue": 120,
+    "timeoutUnit": "SECONDS",
+    "seed": 0
+  }
+}
diff --git a/jastadd-mquat-benchmark/src/main/resources/scenarios.json b/jastadd-mquat-benchmark/src/main/resources/scenarios.json
new file mode 100644
index 0000000000000000000000000000000000000000..063ae60b4be994e626ba1976d697420184454f8f
--- /dev/null
+++ b/jastadd-mquat-benchmark/src/main/resources/scenarios.json
@@ -0,0 +1,119 @@
+{
+  "path": "results",
+  "logLevel": "info",
+  "solvers": [
+    "ilp-direct"
+//    "ilp-external",
+//    "simple"
+  ],
+  "timeoutValue": 15,
+  "timeoutUnit": "MINUTES",
+  "seed": 0,
+//  "repetitions": 10,
+  "scenarios": [
+    {
+      "id": 0,
+      "name": "trivial",
+      "variants": 1,
+      "requests": 1,
+      "depth": 1,
+      "resources": 1
+    },
+    {
+      "id": 1,
+      "name": "small",
+      "variants": 2,
+      "requests": 1,
+      "depth": 2,
+      "resources": 1.5
+    },
+    {
+      "id": 2,
+      "name": "medium",
+      "variants": 10,
+      "requests": 15,
+      "depth": 2,
+      "resources": 1.5
+    },
+    {
+      "id": 3,
+      "name": "large",
+      "variants": 20,
+      "requests": 20,
+      "depth": 2,
+      "resources": 1.5
+    },
+    {
+      "id": 4,
+      "name": "huge",
+      "variants": 50,
+      "requests": 50,
+      "depth": 2,
+      "resources": 1.5
+    },
+    {
+      "id": 5,
+      "name": "small-many-hw",
+      "variants": 2,
+      "requests": 1,
+      "depth": 2,
+      "resources": 5
+    },
+    {
+      "id": 6,
+      "name": "medium-many-hw",
+      "variants": 10,
+      "requests": 15,
+      "depth": 2,
+      "resources": 5
+    },
+    {
+      "id": 7,
+      "name": "large-many-hw",
+      "variants": 20,
+      "requests": 20,
+      "depth": 2,
+      "resources": 5
+    },
+    {
+      "id": 8,
+      "name": "huge-many-hw",
+      "variants": 50,
+      "requests": 50,
+      "depth": 2,
+      "resources": 5
+    },
+    {
+      "id": 9,
+      "name": "small-complex-sw",
+      "variants": 2,
+      "requests": 1,
+      "depth": 5,
+      "resources": 1.5
+    },
+    {
+      "id": 10,
+      "name": "medium-complex-sw",
+      "variants": 5,
+      "requests": 10,
+      "depth": 5,
+      "resources": 1.5
+    },
+    {
+      "id": 11,
+      "name": "large-complex-sw",
+      "variants": 10,
+      "requests": 20,
+      "depth": 5,
+      "resources": 1.5
+    },
+    {
+      "id": 12,
+      "name": "huge-complex-sw",
+      "variants": 20,
+      "requests": 50,
+      "depth": 5,
+      "resources": 1.5
+    }
+  ]
+}
diff --git a/jastadd-mquat-solver-ilp/.gitignore b/jastadd-mquat-solver-ilp/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..92cd68aedc8aa87cfae28c1f5485cfd008a84d0e
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/.gitignore
@@ -0,0 +1,4 @@
+build/
+src/main/resources/sample.lp
+src/main/resources/solution.txt
+src/main/resources/solution.txt.mr
diff --git a/jastadd-mquat-solver-ilp/build.gradle b/jastadd-mquat-solver-ilp/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..fcdb26bacaed33bbb4b969877546967edd1b4dc4
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/build.gradle
@@ -0,0 +1,32 @@
+
+apply plugin: 'java'
+apply plugin: 'application'
+
+sourceCompatibility = 1.8
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    testCompile group: 'junit', name: 'junit', version: '4.12'
+    compile group: 'org.gnu.glpk', name: 'glpk-java', version: '1.11.0'
+    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')
+    testCompile project(path: ':jastadd-mquat-solver', configuration: 'testArtifacts')
+}
+
+tasks.withType(Test) {
+    systemProperty "java.library.path", project.glpkPath
+}
+
+run {
+    mainClassName = 'de.tudresden.inf.st.mquat.solving.ilp.ILPMain'
+    standardInput = System.in
+    systemProperty "java.library.path", project.glpkPath
+    if (project.hasProperty("appArgs")) {
+        args Eval.me(appArgs)
+    }
+}
diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/AbstractILPSolver.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/AbstractILPSolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..0127a8d2af3f82479feea2c593d388085ac49c76
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/AbstractILPSolver.java
@@ -0,0 +1,171 @@
+package de.tudresden.inf.st.mquat.solving.ilp;
+
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import de.tudresden.inf.st.mquat.solving.BenchmarkableSolver;
+import de.tudresden.inf.st.mquat.solving.SolverUtils;
+import de.tudresden.inf.st.mquat.solving.SolvingException;
+import de.tudresden.inf.st.mquat.utils.StaticSettings;
+import de.tudresden.inf.st.mquat.utils.StopWatch;
+import org.apache.logging.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public abstract class AbstractILPSolver implements BenchmarkableSolver {
+
+  protected transient final Logger logger;
+  protected long lastGeneration;
+  protected long lastSolving;
+  protected long lastSolutionCreation;
+  protected double lastObjective;
+  protected transient long timeoutValue;
+  protected transient TimeUnit timeoutUnit;
+  protected transient long timeoutValueOriginal;
+  protected transient TimeUnit timeoutUnitOriginal;
+  protected long timeoutInSeconds;
+  protected boolean timedOut;
+  private boolean resetTimeOut;
+
+  /**
+   * Create a new, abstract solver with default settings.
+   * Defaults are:
+   * <ul>
+   *   <li>1 minute timeout</li>
+   * </ul>
+   * @param logger the logger to use
+   * @see ILPDirectSolver#setTimeout(long, TimeUnit)
+   */
+  public AbstractILPSolver(Logger logger) {
+    this.logger = logger;
+    this.resetTimeOut = false;
+    setTimeout(1, TimeUnit.MINUTES);
+    reset();
+  }
+
+  protected void cleanup(StopWatch watch) {
+    setTimeout(this.timeoutValueOriginal, this.timeoutUnitOriginal);
+    lastSolving = watch.time(TimeUnit.MILLISECONDS);
+    logger.debug("Solving took " + lastSolving + "ms.");
+  }
+
+  /**
+   * Reset times and the objective (i.e., all member fields beginning with "last").
+   */
+  protected void reset() {
+    this.lastGeneration = 0;
+    this.lastSolving = 0;
+    this.lastSolutionCreation = 0;
+    this.lastObjective = 0;
+    this.timedOut = false;
+  }
+
+  @Override
+  public synchronized Solution solve(Root model) throws SolvingException {
+    reset();
+    if (model.getNumRequest() == 0) {
+      return Solution.emptySolutionOf(model);
+    }
+
+    StopWatch watch = StopWatch.start();
+    final ILP ilp = model.getILP();
+    lastGeneration = watch.time(TimeUnit.MILLISECONDS);
+    logger.debug("ILP-Generation took {}ms.", lastGeneration);
+    if (ilp.hasTimeout()) {
+      logger.error("ILP-Generation exceeded timeout, message: '{}'", ilp.timeoutReason());
+      return Solution.emptySolutionOf(model);
+    }
+
+    if (ilp.getNumIlpVariable() != ilp.getNumIlpBound()) {
+      logger.warn("Different variable ({}) and bound ({}) count", ilp.getNumIlpVariable(), ilp.getNumIlpBound());
+    }
+
+    // temporary update timeout to the remaining time.
+    // calling cleanup will reset it to the original value
+    this.timeoutValueOriginal = this.timeoutValue;
+    this.timeoutUnitOriginal = this.timeoutUnit;
+    long nanosRemaining = this.timeoutUnit.toNanos(this.timeoutValue) - watch.time();
+    if (nanosRemaining < 0) {
+      logger.error("ILP-Generation actually timed out");
+      cleanup(watch);
+      return Solution.emptySolutionOf(model);
+    }
+    setTimeout(nanosRemaining, TimeUnit.NANOSECONDS);
+
+    List<IlpVariable> variablesSetToOne = new ArrayList<>();
+    watch.reset();
+
+    // call to abstract method
+    lastObjective = solve0(model, watch, variablesSetToOne);
+
+    cleanup(watch);
+    return populateSolution(variablesSetToOne, new ILPSolution(model));
+  }
+
+  /**
+   * Solves the model. The method <code>model.getILP()</code> was already called and can be assumed to be cached.
+   * @param model             the model to solve
+   * @param watch             a stop watch to be passed to cleanup if necessary
+   * @param variablesSetToOne the means of a solution, i.e., which variables are set to one
+   * @return the objective value
+   * @throws SolvingException if anything went wrong
+   */
+  protected abstract double solve0(Root model, StopWatch watch, List<IlpVariable> variablesSetToOne) throws SolvingException;
+
+  protected ILPSolution populateSolution(List<IlpVariable> variablesSetToOne, ILPSolution result) throws SolvingException {
+    List<Assignment> listOfAssignments = new ArrayList<>();
+    for (IlpVariable var : variablesSetToOne) {
+      logger.debug("Found, that {} = 1", var.getName());
+      if (var.isMappingVariable()) {
+        IlpMappingVariable mappingVar = var.asMappingVariable();
+        Assignment assignment = new Assignment();
+        assignment.setRequest(mappingVar.getRequest());
+        assignment.setImplementation(mappingVar.getImpl());
+        assignment.setResourceMapping(new ResourceMapping(assignment.getImplementation().getResourceRequirement().getInstance(0), mappingVar.getResource(), new de.tudresden.inf.st.mquat.jastadd.model.List<>()));
+        listOfAssignments.add(assignment);
+      }
+    }
+    lastSolutionCreation = SolverUtils.populateSolution(listOfAssignments, result, logger);
+    return result;
+  }
+
+  public AbstractILPSolver setTimeout(long timeoutValue, TimeUnit timeoutUnit) {
+    this.timeoutUnit = timeoutUnit;
+    this.timeoutValue = timeoutValue;
+    StaticSettings.put(Root.ILP_TIMEOUT_VALUE, timeoutValue);
+    StaticSettings.put(Root.ILP_TIMEOUT_UNIT, timeoutUnit);
+    recomputeTimeoutInSeconds();
+    return this;
+  }
+
+  protected void recomputeTimeoutInSeconds() {
+    this.timeoutInSeconds = timeoutUnit.toSeconds(timeoutValue);
+  }
+
+  @Override
+  public boolean doesGeneration() {
+    return true;
+  }
+
+  @Override
+  public long getLastGenerationTime() {
+    return lastGeneration;
+  }
+
+  @Override
+  public long getLastSolvingTime() {
+    return lastSolving + lastSolutionCreation;
+  }
+
+  @Override
+  public double getLastObjective() {
+    return lastObjective;
+  }
+
+  @Override
+  public boolean hadTimeout() {
+    return this.timedOut;
+  }
+}
diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPDirectSolver.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPDirectSolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c3eaaa43ba2f267af8552d4a3718c30ea672d12
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPDirectSolver.java
@@ -0,0 +1,427 @@
+package de.tudresden.inf.st.mquat.solving.ilp;
+
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import de.tudresden.inf.st.mquat.solving.SolvingException;
+import de.tudresden.inf.st.mquat.utils.LoggingProxyForStdOut;
+import de.tudresden.inf.st.mquat.utils.StopWatch;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.gnu.glpk.*;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class ILPDirectSolver extends AbstractILPSolver {
+
+  private boolean writeFiles;
+  private Path lp, solutionReadable;
+  private glp_prob prob;
+  private int timeoutInMillis;
+
+  private static boolean listenerAddedToGlpk = false;
+
+  /**
+   * Create a new solver with default settings.
+   * Default is:
+   * <ul>
+   *   <li>1 minute timeout</li>
+   *   <li>Do not write out ILP and solution files</li>
+   * </ul>
+   * @see ILPDirectSolver#setWriteFiles(boolean)
+   */
+  public ILPDirectSolver() {
+    super(LogManager.getLogger(ILPDirectSolver.class));
+    setWriteFiles(false);
+  }
+
+  private GlpkTerminalListener redirectToLogger(final Logger logger, final Level logLevel) {
+    return str -> {
+      logger.log(logLevel, str.substring(0, str.length() - 1));  // substring to avoid trailing linebreak
+      return false;
+    };
+  }
+
+  public ILPDirectSolver setWriteFiles(boolean writeFiles) {
+    this.writeFiles = writeFiles;
+    return this;
+  }
+
+  @Override
+  protected void recomputeTimeoutInSeconds() {
+    super.recomputeTimeoutInSeconds();
+    // store timeout in milliseconds, if small enough
+    long timeoutInMillis = this.timeoutInSeconds * 1000;
+    // if smaller than zero, an overflow has occurred
+    this.timeoutInMillis = timeoutInMillis > 0 && timeoutInMillis < Integer.MAX_VALUE ? (int) timeoutInMillis : 0;
+  }
+
+  @Override
+  protected void reset() {
+    super.reset();
+    this.prob = null;
+  }
+
+  protected double solve0(Root model, StopWatch watch, List<IlpVariable> variablesSetToOne) throws SolvingException {
+    ILP ilp = model.getILP();
+
+    if (logger.isTraceEnabled()) {
+      logger.trace(ilp.printIlp().toString());
+    }
+
+    // Create temporary files (if requested)
+    if (this.writeFiles) {
+      try {
+        lp = Files.createTempFile("direct-ilp", null);
+        solutionReadable = Files.createTempFile("direct-sol-read", null);
+      } catch (IOException e) { throw new SolvingException("Can not create lp or solution file", e); }
+    }
+
+    // test if listener is already added to GLPK
+    // no atomic get and set needed, as solve() method is synchronized
+    if (!listenerAddedToGlpk) {
+      GlpkTerminal.addListener(redirectToLogger(logger, Level.DEBUG));
+      listenerAddedToGlpk = true;
+    }
+
+    // create a glp_prob
+    prob = GLPK.glp_create_prob();
+    GLPK.glp_set_prob_name(prob, model.description());
+    // only add variables not being ignored (which are remaining in the info object)
+    GLPK.glp_add_cols(prob, ilp.getInfo().vars.size());
+
+    // helper structure, map IlpVariable to its index
+    Map<IlpVariable, Integer> varToIndex = new HashMap<>(ilp.getNumIlpVariable());
+
+    // create bounds
+    int colCount = ilp.getNumIlpBound();
+    final Set<IlpVariable> toIgnore = new HashSet<>();
+    for (int index = 1; index <= ilp.getNumIlpBound(); index++) {
+      IlpBound bound = ilp.getIlpBound(index - 1);
+      varToIndex.put(bound.getRef(), index);
+      switch (bound.getType()) {
+        case BINARY:
+          GLPK.glp_set_col_kind(prob, index, GLPKConstants.GLP_BV);
+          break;
+        case ZERO:
+          toIgnore.add(bound.getRef());
+          --colCount;
+          continue;
+        default:  // >= 0
+          GLPK.glp_set_col_kind(prob, index, GLPKConstants.GLP_IV);
+          GLPK.glp_set_col_bnds(prob, index, GLPKConstants.GLP_LO, 0, 0);
+          break;
+      }
+      GLPK.glp_set_col_name(prob, index, bound.getRef().getName());
+    }
+
+    // create objective
+    GLPK.glp_set_obj_name(prob, model.getObjective().getPropertyRef().getName().getName());
+    GLPK.glp_set_obj_dir(prob, ilp.getIlpObjective().getKind() == IlpObjectiveKind.MINIMIZE ?
+        GLPKConstants.GLP_MIN : GLPKConstants.GLP_MAX);
+    // TODO only variables mentioned in objective are set to a value. Do the others need to be set to zero?
+    for (IlpTerm term : ilp.getIlpObjective().getIlpLeftHandSide().getIlpTermList()) {
+      if (!toIgnore.contains(term.getRef())) {
+        GLPK.glp_set_obj_coef(prob, varToIndex.get(term.getRef()), term.getValue());
+      }
+    }
+
+    // create a row for each constraint
+    int start = GLPK.glp_add_rows(prob, ilp.getNumIlpConstraint());
+
+    for (int rowCounter = start; rowCounter < ilp.getNumIlpConstraint() + start; rowCounter++) {
+
+      IlpConstraint constraint = ilp.getIlpConstraint(rowCounter - start);
+      if (logger.isTraceEnabled()) {
+        logger.trace("Preparing at {} - {}", rowCounter, constraint.printIlp());
+      }
+      if (constraint.getIlpLeftHandSide().getNumIlpTerm() == 0) {
+        logger.debug("Skipping empty constraint: {}", constraint.printIlp());
+        continue;
+      }
+      // TODO maybe use constraint.getIlpLeftHandSide().getNumIlpTerm() instead of colCount
+      SWIGTYPE_p_int ind = GLPK.new_intArray(colCount + 1);
+      SWIGTYPE_p_double val = GLPK.new_doubleArray(colCount + 1);
+      GLPK.glp_set_row_name(prob, rowCounter, constraint.getName());
+      int glpk_kind;
+      switch (constraint.getClauseComparator()) {
+        case EQ: glpk_kind = GLPKConstants.GLP_FX; break;
+        case GE: glpk_kind = GLPKConstants.GLP_LO; break;
+        case GT:
+          glpk_kind = GLPKConstants.GLP_LO;
+          logger.warn("Relaxing constraint to '>= in " + constraint.printIlp().toString());
+          break;
+        case LE: glpk_kind = GLPKConstants.GLP_UP; break;
+        case LT:
+          glpk_kind = GLPKConstants.GLP_UP;
+          logger.warn("Relaxing constraint to '>= in " + constraint.printIlp().toString());
+          break;
+        case NE: throw new SolvingException("Can not handle inequality constraint in " + constraint.printIlp().toString());
+        default:
+          logger.warn("Unknown clause comparator " + constraint.printIlp().toString());
+          glpk_kind = 0;
+      }
+      GLPK.glp_set_row_bnds(prob, rowCounter, glpk_kind, constraint.getRightHandSide(), constraint.getRightHandSide());
+      IlpLeftHandSide lhs = constraint.getIlpLeftHandSide();
+      int colIndex = 1;
+      for (int termIndex = 0; termIndex < lhs.getNumIlpTerm(); termIndex++) {
+        IlpTerm term = lhs.getIlpTerm(termIndex);
+        if (toIgnore.contains(term.getRef())) {
+          continue;
+        }
+        GLPK.intArray_setitem(ind, colIndex, varToIndex.get(term.getRef()));
+        GLPK.doubleArray_setitem(val, colIndex, term.getValue());
+        if (logger.isTraceEnabled()) {
+          logger.trace("Set ind[{}]={} ({}) and val[{}]={}",
+              colIndex, varToIndex.get(term.getRef()), term.getRef().getName(),
+              colIndex, term.getValue());
+        }
+        ++colIndex;
+      }
+      if (colIndex > 1) {
+        GLPK.glp_set_mat_row(prob, rowCounter, colIndex - 1, ind, val);
+      } else {
+        logger.debug("Skipping constraint with only ignored terms: {}", constraint.printIlp());
+      }
+      GLPK.delete_intArray(ind);
+      GLPK.delete_doubleArray(val);
+    }
+
+    // write out the generated problem
+    if (this.writeFiles) {
+      logger.info("Writing ILP to {}", lp.toAbsolutePath());
+      int returnCode = GLPK.glp_write_lp(prob, null, lp.toAbsolutePath().toString());
+      if (returnCode != 0) {
+        cleanup(watch);
+        throw new SolvingException("Could not write to lp file (error code: " + returnCode + ")");
+      }
+    }
+
+    // now the generation is really finish, note the time and add it to the other generation time
+    lastGeneration += watch.time(TimeUnit.MILLISECONDS);
+    watch.reset();
+
+    // Setup Parameters. See http://www.maximalsoftware.com/solvopt/optglpk.html
+    glp_smcp simplexParam = new glp_smcp();
+    GLPK.glp_init_smcp(simplexParam);
+    glp_iocp param = new glp_iocp();
+    GLPK.glp_init_iocp(param);
+
+    if (logger.isDebugEnabled()) {
+      logger.debug("Default simplex parameters: {}", printGetter(simplexParam));
+      logger.debug("Default mip parameters: {}", printGetter(param));
+    }
+    if(timeoutInMillis > 0) {
+      logger.debug("Set simplex timeout to {}ms.", timeoutInMillis);
+      simplexParam.setTm_lim(timeoutInMillis);
+    }
+
+    // TODO maybe presolve is not needed in one of the solvers -- need to be checked
+    simplexParam.setPresolve(GLPKConstants.GLP_ON);
+//    param.setPresolve(GLPKConstants.GLP_ON);
+
+    GLPK.glp_scale_prob(prob, GLPKConstants.GLP_SF_AUTO);
+
+    // TODO binarize may be needed
+//    parm.setBinarize(GLPKConstants.GLP_ON);
+
+    // -- Msg_lev --
+    // No output (0)	No output.
+    // Error messages (1)	Display error messages only.
+    // Normal (2)	Normal output.
+    // Complete (3)	Complete output, includes informational messages. (default)
+    simplexParam.setMsg_lev(GLPKConstants.GLP_MSG_ALL);
+    param.setMsg_lev(GLPKConstants.GLP_MSG_ALL);
+
+    // Solve the generated problem
+    int returnCode;
+    // First construct basis. TODO maybe not be needed in the end?
+//    GLPK.glp_std_basis(prob);
+    GLPK.glp_adv_basis(prob, 0);
+
+    // Second, solve the problem, finding an optimal solution
+    logger.debug("Start simplex solving");
+
+    returnCode = GLPK.glp_simplex(prob, simplexParam);
+    if (returnCode == GLPKConstants.GLP_ETMLIM) {
+      logger.info("Simplex Solving was stopped after time limit was reached.");
+    } else if (returnCode != 0) {
+      cleanup(watch);
+      // abuse objective to save return code
+      lastObjective = -1000 - returnCode;
+      throw new SolvingException("Solving did not finish correctly, reason: " + translateSimplexReturnError(returnCode));
+    }
+
+    if (timeoutInMillis > 0) {
+      // check how much time is left for MIP after simplex has finished
+      int remaining = timeoutInMillis;
+      remaining -= watch.time(TimeUnit.MILLISECONDS);
+      if (remaining < 0) {
+        cleanup(watch);
+        this.timedOut = true;
+        throw new SolvingException("No time left for MIP solver.");
+      }
+      logger.debug("Set MIP timeout to {}ms.", remaining);
+      param.setTm_lim(remaining);
+    }
+
+
+    // Finally, solve the integer problem
+    logger.debug("Start MIP solving");
+    returnCode = GLPK.glp_intopt(prob, param);
+
+    if (returnCode == GLPKConstants.GLP_ETMLIM) {
+      logger.info("MIP Solving was stopped after time limit was reached.");
+      this.timedOut = true;
+    } else if (returnCode != 0) {
+      cleanup(watch);
+      // abuse objective to save return code
+      lastObjective = -2000 - returnCode;
+      throw new SolvingException("Solving did not finish correctly, reason: " + translateMIPReturnError(returnCode));
+    }
+
+    if (this.writeFiles) {
+      // write out the found solution
+      logger.debug("Solution at {} (readable form)", solutionReadable.toAbsolutePath());
+      if (GLPK.glp_print_sol(prob, solutionReadable.toAbsolutePath().toString()) != 0) {
+        logger.warn("Could not write solution to " + solutionReadable.toAbsolutePath());
+      }
+    }
+
+    logMipStatus(prob);
+
+    // Construct the solution
+    for (int i = 1; i <= colCount; i++) {
+      String name = GLPK.glp_get_col_name(prob, i);
+      double val  = GLPK.glp_mip_col_val(prob, i);
+      logger.trace("{} (at index {}) = {}", name, i, val);
+      if (val == 1) {
+        variablesSetToOne.add(ilp.getInfo().vars.get(name));
+      }
+    }
+
+    return GLPK.glp_mip_obj_val(prob);
+  }
+
+  private void logMipStatus(glp_prob prob) {
+    int mipStatus = GLPK.glp_mip_status(prob);
+    if (mipStatus == GLPKConstants.GLP_UNDEF) {
+      logger.error("MIP solution is undefined");
+    } else if (mipStatus == GLPKConstants.GLP_OPT) {
+      logger.debug("MIP solution is integer optimal");
+    } else if (mipStatus == GLPKConstants.GLP_FEAS) {
+      logger.warn("MIP solution is integer feasible, however, its optimality (or non-optimality) has " +
+          "not been proven, perhaps due to premature termination of the search");
+    } else if (mipStatus == GLPKConstants.GLP_NOFEAS) {
+      logger.error("problem has no integer feasible solution (proven by the solver)");
+    }
+  }
+
+  private String translateSimplexReturnError(int returnCode) {
+    if (returnCode == GLPKConstants.GLP_EBADB) {
+      return "Unable to start the search, because the initial basis specified in the problem object " +
+          "is invalid: the number of basic (auxiliary and structural) variables is not the same" +
+          "as the number of rows in the problem object.";
+    }
+    if (returnCode == GLPKConstants.GLP_ESING) {
+      return "Unable to start the search, because the basis matrix corresponding to the initial " +
+          "basis is singular within the working precision.";
+    }
+    if (returnCode == GLPKConstants.GLP_ECOND) {
+      return "Unable to start the search, because the basis matrix corresponding to the initial " +
+          "basis is ill-conditioned, i.e. its condition number is too large.";
+    }
+    if (returnCode == GLPKConstants.GLP_EBOUND) {
+      return "Unable to start the search, because some double-bounded (auxiliary or structural) " +
+          "variables have incorrect bounds.";
+    }
+    if (returnCode == GLPKConstants.GLP_EFAIL) {
+      return "The search was prematurely terminated due to the solver failure.";
+    }
+    if (returnCode == GLPKConstants.GLP_EOBJLL) {
+      return "The search was prematurely terminated, because the objective function being maximized " +
+      "has reached its lower limit and continues decreasing (the dual simplex only).";
+    }
+    if (returnCode == GLPKConstants.GLP_EOBJUL) {
+      return "The search was prematurely terminated, because the objective function being minimized " +
+          "has reached its upper limit and continues increasing (the dual simplex only).";
+    }
+    if (returnCode == GLPKConstants.GLP_EITLIM) {
+      return "The search was prematurely terminated, because the simplex iteration limit has been exceeded.";
+    }
+    if (returnCode == GLPKConstants.GLP_ENOPFS) {
+      return "The LP problem instance has no primal feasible solution.";
+    }
+    if (returnCode == GLPKConstants.GLP_ENODFS) {
+      return "The LP problem instance has no dual feasible solution.";
+    }
+    return "Unknown error code for simplex: " + returnCode;
+  }
+
+  private String translateMIPReturnError(int returnCode) {
+    if (returnCode == GLPKConstants.GLP_EBOUND) {
+      return "Unable to start the search, because some double-bounded variables have incorrect " +
+          "bounds or some integer variables have non-integer (fractional) bounds.";
+    }
+    if (returnCode == GLPKConstants.GLP_EROOT) {
+      return "Unable to start the search, because optimal basis for initial LP relaxation is not provided.";
+    }
+    if (returnCode == GLPKConstants.GLP_ENOPFS) {
+      return "Unable to start the search, because LP relaxation of the MIP problem instance has " +
+          "no primal feasible solution.";
+    }
+    if (returnCode == GLPKConstants.GLP_ENODFS) {
+      return "Unable to start the search, because LP relaxation of the MIP problem instance has " +
+          "no dual feasible solution. In other word, this code means that if the LP relaxation " +
+          "has at least one primal feasible solution, its optimal solution is unbounded, so if the " +
+          "MIP problem has at least one integer feasible solution, its (integer) optimal solution " +
+          "is also unbounded.";
+    }
+    if (returnCode == GLPKConstants.GLP_EFAIL) {
+      return "The search was prematurely terminated due to the solver failure.";
+    }
+    if (returnCode == GLPKConstants.GLP_EMIPGAP) {
+      return "The search was prematurely terminated, because the relative mip gap tolerance has " +
+          "been reached.";
+    }
+    if (returnCode == GLPKConstants.GLP_ESTOP) {
+      return "The search was prematurely terminated by application.";
+    }
+    return "Unknown error code for MIP: " + returnCode;
+  }
+
+  private String printGetter(Object parm) {
+    StringBuilder sb = new StringBuilder();
+    for (Method method : parm.getClass().getMethods()) {
+      if (method.getName().startsWith("get")) {
+        sb.append(method.getName()).append('=');
+        try {
+          Object result = method.invoke(parm);
+          sb.append(result).append(',');
+        } catch (IllegalAccessException | InvocationTargetException e) {
+          // silently ignore exception
+        }
+      }
+    }
+    sb.setCharAt(sb.length() - 1, '.');
+    return sb.toString();
+  }
+
+  @Override
+  protected void cleanup(StopWatch watch) {
+    super.cleanup(watch);
+    GLPK.glp_delete_prob(prob);
+    prob = null;
+  }
+
+  @Override
+  public String getName() {
+    return "ilp-direct";
+  }
+}
diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPExternalSolver.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPExternalSolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..03385221053416aa341d16c794f42131b57161e4
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPExternalSolver.java
@@ -0,0 +1,205 @@
+package de.tudresden.inf.st.mquat.solving.ilp;
+
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import de.tudresden.inf.st.mquat.solving.SolvingException;
+import de.tudresden.inf.st.mquat.utils.StopWatch;
+import org.apache.logging.log4j.LogManager;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class ILPExternalSolver extends AbstractILPSolver {
+
+  private boolean deleteFilesOnExit;
+  private Path lp, solutionReadable;
+
+  /**
+   * Create a new solver with default settings.
+   * Default is:
+   * <ul>
+   *   <li>1 minute timeout</li>
+   *   <li>delete temporary files on exit.</li>
+   * </ul>
+   * @see ILPExternalSolver#setDeleteFilesOnExit(boolean)
+   */
+  public ILPExternalSolver() {
+    super(LogManager.getLogger(ILPExternalSolver.class));
+    deleteFilesOnExit = true;
+  }
+
+  public ILPExternalSolver setDeleteFilesOnExit(boolean deleteFilesOnExit) {
+    this.deleteFilesOnExit = deleteFilesOnExit;
+    return this;
+  }
+
+  /**
+   * Log stdout (always to logger.debug) and stderr (if existing to logger.warn)
+   * @param process the given process to inspect
+   */
+  private void printFromProcess(Process process) {
+    try (Scanner s = new Scanner(process.getInputStream())) {
+      logger.debug(s.useDelimiter("\\A").hasNext() ? s.next() : "<no output>");
+    }
+    try (Scanner s = new Scanner(process.getErrorStream())) {
+      if (s.useDelimiter("\\A").hasNext()) {
+        logger.warn(s.next());
+      }
+    }
+  }
+
+  @Override
+  protected void cleanup(StopWatch watch) {
+    super.cleanup(watch);
+    if (deleteFilesOnExit) {
+      if (lp.toFile().exists() && !lp.toFile().delete()) {
+        logger.warn("Could not delete ILP file {}", lp.toAbsolutePath());
+      }
+      if (solutionReadable.toFile().exists() && !solutionReadable.toFile().delete()) {
+        logger.warn("Could not delete solution file {}", solutionReadable.toAbsolutePath());
+      }
+    }
+  }
+
+  protected double solve0(Root model, StopWatch watch, List<IlpVariable> variablesSetToOne) throws SolvingException {
+    // Create temporary files
+    try {
+      lp = Files.createTempFile("ilp", null);
+//      solution = Files.createTempFile("solution", null);
+      solutionReadable = Files.createTempFile("sol-read", null);
+    } catch (IOException e) { throw new SolvingException("Can not create lp or solution file", e); }
+    if (!deleteFilesOnExit) {
+      logger.info("Writing ILP to {}, solving now", lp.toAbsolutePath());
+    }
+
+    // write out lp file
+    IlpString output = model.getILP().printIlp();
+    try (BufferedWriter writer = Files.newBufferedWriter(
+        lp, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
+      writer.write(output.toString());
+    } catch (IOException e) { cleanup(watch); throw new SolvingException("Could not write to lp file", e); }
+
+    // start GLPK to solve the lp file just written, writing out the solution
+    Process process;
+    String command = "glpsol --lp " + lp.toAbsolutePath() +
+//        " -w " + solution.toAbsolutePath() +
+        " --tmlim " + timeoutInSeconds +
+        " -o " + solutionReadable.toAbsolutePath();
+    logger.debug("Call: '{}'", command);
+    try {
+      process = Runtime.getRuntime().exec(command,null, new File("."));
+    } catch (IOException e) { cleanup(watch); throw new SolvingException("Problem calling glpsol. Is it installed?", e); }
+    boolean finishedInTime;
+    try {
+      finishedInTime = process.waitFor(timeoutInSeconds, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      cleanup(watch);
+      throw new SolvingException("Interrupted while waiting for result", e);
+    }
+    if (!finishedInTime) {
+      // solver already had a timeout, so wait at least 2 seconds longer to let it write a solution file
+      this.timedOut = true;
+      try {
+        process.waitFor(2, TimeUnit.SECONDS);
+      } catch (InterruptedException ignored) { }
+      // then destroy the process
+      process.destroyForcibly();
+      if (!solutionReadable.toFile().exists()) {
+        cleanup(watch);
+        throw new SolvingException("Solving did not finish within " + timeoutValue + " " + timeoutUnit.toString());
+      }
+      // if there is a solution file, move on and check its content
+    }
+    printFromProcess(process);
+    if (!solutionReadable.toFile().exists()) {
+      cleanup(watch);
+      throw new SolvingException("No solution file was created.");
+    }
+    logger.debug("Solution at {}", solutionReadable);
+
+    // read the solution file
+    ILPSolution result = new ILPSolution(model);
+
+//    readFromPrintableSolution(ilp, solution, result, variablesSetToOne);
+    readFromPlainTextSolution(model.getILP().getInfo(), solutionReadable, result, variablesSetToOne);
+    return result.getObjective();
+  }
+
+  private static void readFromPlainTextSolution(IlpVarInfo info, Path solution, ILPSolution result,
+                                                List<IlpVariable> variablesSetToOne) throws SolvingException {
+    List<String> varNamesSetToOne = new ArrayList<>();
+    String name = null;
+    int phase = 1;
+    try (Stream<String> lines = Files.lines(solution)) {
+      for (String line : lines.collect(Collectors.toList())) {
+        if (phase < 3) {
+          if (line.startsWith("Objective")) {
+            int equalsIndex = line.indexOf('=');
+            int bracketIndex = line.lastIndexOf('(');
+            result.setObjective(Double.valueOf(line.substring(equalsIndex + 1, bracketIndex).trim()));
+          }
+          if (line.startsWith("---")) {
+            phase += 1;
+          }
+          continue;
+        }
+        line = line.trim();
+        if (line.isEmpty()) {
+          continue;
+        }
+        String[] tokens = line.split("\\s+");
+        if (tokens.length == 6) {
+          // tokens: index, name, star, activity, lb, rb
+          if(Integer.valueOf(tokens[3]) == 1) {
+            varNamesSetToOne.add(tokens[1]);
+          }
+          phase = 3;
+        } else if (phase == 3) {
+          if(line.startsWith("Integer")) {
+            break;
+          }
+          // tokens: index, name
+          name = tokens[1];
+          phase = 4;
+        } else if (phase == 4) {
+          // tokens: star, activity, lb, rb
+          if (name == null) {
+            throw new SolvingException("Error in parsing solution. Name is null. Tokens: " + Arrays.toString(tokens));
+          }
+          if (Integer.valueOf(tokens[1]) == 1) {
+            varNamesSetToOne.add(name);
+            name = null;
+          }
+          phase = 3;
+        }
+      }
+    } catch (IOException e) {
+      throw new SolvingException("Could not open solution file", e);
+    } catch (NumberFormatException | IndexOutOfBoundsException e) {
+      throw new SolvingException("Could not parse solution file", e);
+    }
+    for (String varName : varNamesSetToOne) {
+      IlpVariable variable = info.vars.get(varName);
+      if (variable == null) {
+        throw new SolvingException("Could not find variable with name " + varName);
+      }
+      variablesSetToOne.add(variable);
+    }
+  }
+
+  @Override
+  public String getName() {
+    return "ilp-external";
+  }
+
+}
diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPMain.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPMain.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc8b5f2761be6d9367e16530dd52af52bacba405
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPMain.java
@@ -0,0 +1,99 @@
+package de.tudresden.inf.st.mquat.solving.ilp;
+
+import de.tudresden.inf.st.mquat.generator.ScenarioDescription;
+import de.tudresden.inf.st.mquat.generator.ScenarioGenerator;
+import de.tudresden.inf.st.mquat.jastadd.model.ILP;
+import de.tudresden.inf.st.mquat.jastadd.model.MquatWriteSettings;
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+import de.tudresden.inf.st.mquat.jastadd.model.Solution;
+import de.tudresden.inf.st.mquat.solving.Solver;
+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 org.gnu.glpk.GLPK;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
+
+import static de.tudresden.inf.st.mquat.Main.write;
+
+public class ILPMain {
+
+  private static void printFromProcess(Process process, boolean printError) {
+    try (Scanner s = new Scanner(process.getInputStream())) {
+      System.out.println(s.useDelimiter("\\A").hasNext() ? s.next() : "");
+    }
+    if (printError) {
+      try (Scanner s = new Scanner(process.getErrorStream())) {
+        System.err.println(s.useDelimiter("\\A").hasNext() ? s.next() : "");
+      }
+    }
+  }
+
+  private static ILP generateILP(Root generatedModel) throws IOException {
+    StopWatch watch = StopWatch.start();
+    ILP ilp = generatedModel.getILP();
+    System.out.flush();
+    System.err.flush();
+//    System.out.println("---");
+//    System.out.println(ilp.printIlp());
+//    System.out.println("---");
+//    System.out.println(ilp.printIlp());
+//    System.out.println("---");
+    write(ilp, null, "src/main/resources/sample.lp");
+    System.out.println("Generation took " + watch.time(TimeUnit.MILLISECONDS) + "ms.");
+    return ilp;
+  }
+
+  private static void solveILP(ILP ilp) throws IOException, InterruptedException {
+    StopWatch watch = StopWatch.start();
+    Process process;
+    String solutionPath = Paths.get("src", "main", "resources", "solution.txt").toAbsolutePath().toString();
+    process = Runtime.getRuntime().exec(
+        "glpsol --lp src/main/resources/sample.lp -o " + solutionPath + " -w " + solutionPath + ".mr",
+        null, new File("."));
+    if (!process.waitFor(1, TimeUnit.MINUTES)) {
+      process.destroyForcibly();
+      System.out.println("Timeout for solving!");
+    } else {
+      System.out.println(process.exitValue());
+      printFromProcess(process, false);
+    }
+    System.out.println("Solving took " + watch.time(TimeUnit.MILLISECONDS) + "ms.");
+
+    // parse the solution and print variables not assigned zero
+    process = Runtime.getRuntime().exec(
+        "src/main/python/parse_solution.py " + solutionPath,
+        null, new File("."));
+    process.waitFor();
+    printFromProcess(process, true);
+  }
+
+  private static void solveILPWithSolver(Root model) throws SolvingException {
+    ILPExternalSolver solver = new ILPExternalSolver();
+    Solution solution = solver.solve(model);
+    System.out.println(solution);
+  }
+
+  public static void main(String[] args) throws Exception {
+//    System.out.println("Solving tiny model");
+//    Optional<Root> tinyModel = loadModel("tiny.txt");
+//    ILP tinyIlp = generateILP(tinyModel.orElseThrow(RuntimeException::new));
+//    solveILP(tinyIlp);
+//    solveILPWithSolver(tinyModel.orElseThrow(RuntimeException::new));
+    Logger logger = LogManager.getLogger(ILPMain.class);
+    String version = GLPK.glp_version();
+    System.out.println(version);
+    ScenarioGenerator gen = new ScenarioGenerator(new ScenarioDescription(1, 2, 0, 0, 0, 2, 2, 2.5, 3, 1, 0));
+    Root model = gen.generate();
+    Solver external = new ILPExternalSolver().setDeleteFilesOnExit(false);
+    Solution solution = external.solve(model);
+    logger.info(model.print(new MquatWriteSettings(" ")));
+    solution.explain();
+  }
+
+}
diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPSolution.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPSolution.java
new file mode 100644
index 0000000000000000000000000000000000000000..b26ad71c98505a8e7f7b82dee80edffd344c8ebe
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPSolution.java
@@ -0,0 +1,22 @@
+package de.tudresden.inf.st.mquat.solving.ilp;
+
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+import de.tudresden.inf.st.mquat.jastadd.model.Solution;
+
+import java.util.Collections;
+
+public class ILPSolution extends Solution {
+  private double objective;
+
+  public ILPSolution(Root model) {
+    setModel(model);
+  }
+
+  public double getObjective() {
+    return objective;
+  }
+
+  public void setObjective(double objective) {
+    this.objective = objective;
+  }
+}
diff --git a/jastadd-mquat-solver-ilp/src/main/python/parse_solution.py b/jastadd-mquat-solver-ilp/src/main/python/parse_solution.py
new file mode 100755
index 0000000000000000000000000000000000000000..7befd83eb0891572eefad6c39c259729a1be9f30
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/main/python/parse_solution.py
@@ -0,0 +1,54 @@
+#!/usr/bin/python2
+import collections
+import sys
+
+filename = sys.argv[1]
+phase = 1
+solution = collections.OrderedDict()
+
+print 'parse_solution.py:'
+with open(filename) as fdr:
+    for line in fdr:
+        if phase < 3:
+            if line.startswith('Objective'):
+                print line.strip()
+            if line.startswith('---'):
+                phase += 1
+            continue
+        if not line.strip():
+            continue
+        tokens = line.split()
+        if len(tokens) == 6:
+            try:
+                index, name, star, activity, lb, rb = tokens
+                solution[name] = int(activity)
+            except ValueError:
+                print 'Bad name+value tokens:', tokens
+            finally:
+                phase = 3
+        elif phase == 3:
+            if line.startswith('Integer'):
+                break
+            try:
+                index, name = tokens
+            except ValueError:
+                print 'Bad name tokens:', tokens
+            finally:
+                phase = 4
+        elif phase == 4:
+            try:
+                star, activity, lb, rb = tokens
+                solution[name] = int(activity)
+            except ValueError:
+                print 'Bad value tokens:', tokens
+            finally:
+                phase = 3
+
+print 'Read', len(solution), 'variables.'
+all_zero = True
+for key, value in solution.iteritems():
+    if value == 1:
+        print key, '=', value
+        all_zero = False
+if all_zero:
+    print 'No variable has value 1'
diff --git a/jastadd-mquat-solver-ilp/src/main/resources/tiny.txt b/jastadd-mquat-solver-ilp/src/main/resources/tiny.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2551d0e02a72fcdbdfafd0bcd5ac9e9e6ee032b5
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/main/resources/tiny.txt
@@ -0,0 +1,84 @@
+// Expected solution
+// config_0i0m0 -> r0 + cpu0_0
+// config_1i0m0 -> r1 + cpu0_1
+
+container resource type ComputeNode {
+    resource type CPU {
+        static property frequency [Hz]
+        runtime property load [%]
+    }
+    derived property flops [ops/s]
+    runtime property STATE []
+}
+resource r0:ComputeNode {
+    resource cpu0_0:CPU {
+        frequency = 2930
+        load = 30
+    }
+    flops = 293000
+}
+resource r1:ComputeNode {
+    resource cpu1_0:CPU {
+        frequency = 930
+        load = 10
+    }
+    flops = 93000
+}
+meta size
+runtime property energy [J]
+runtime property quality [%]
+
+component c0 {
+    using property quality
+    contract impl0i0 {
+        requires component other of type c1
+        requires resource compute_resource_0 of type ComputeNode
+        requires resource cpu_1 of type CPU
+        requiring other.quality >= 95
+        mode config_0i0m0 {
+            // can run only on r0
+            requiring cpu_1.frequency >= 2159
+            providing quality = 300
+            providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+        }
+        mode config_0i0m1 {
+            // not satisfied at all
+            requiring cpu_1.frequency >= 14159
+            providing quality = 90
+            providing energy = ((0.11*(size^2))+(0.94*compute_resource_0.flops))
+        }
+    }
+}
+
+component c1 {
+    using property quality
+    contract impl1i0 {
+        requires resource compute_resource_0 of type ComputeNode
+        requires resource cpu_1 of type CPU
+        mode config_1i0m0 {
+            // can run on both, r0 and r1
+            requiring cpu_1.load <= 80
+            // fulfills c0 requirement
+            providing quality = 1004
+            providing energy = ((0.45*(size^2))+(0.34*compute_resource_0.flops))
+        }
+        mode config_1i0m1 {
+            // could run on r1
+            requiring cpu_1.load <= 20
+            // does not fulfill c0 requirement
+            providing quality = 3
+            providing energy = ((0.25*(size^2))+(0.34*compute_resource_0.flops))
+        }
+        mode config_1i0m2 {
+            // not satisfied at all
+            requiring cpu_1.load <= 1
+            providing quality = 200
+            providing energy = ((0.02*(size^2))+(0.71*compute_resource_0.flops))
+        }
+    }
+}
+request c0 {
+    meta size = 6
+    requiring quality >= 35
+}
+minimize sum(energy)
diff --git a/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/GLPKTest.java b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/GLPKTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff80441490e619b0932ab6f4b8fcecbf1df95f70
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/GLPKTest.java
@@ -0,0 +1,13 @@
+package de.tudresden.inf.st.mquat.solving;
+
+import org.gnu.glpk.GLPK;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GLPKTest {
+
+  @Test
+  public void glpkJavaInstalled() {
+    Assert.assertNotNull(GLPK.glp_version());
+  }
+}
diff --git a/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPDirectHandwrittenTest.java b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPDirectHandwrittenTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..81a7e44188ceb849e50bc6773b0e69e656ddfaac
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPDirectHandwrittenTest.java
@@ -0,0 +1,11 @@
+package de.tudresden.inf.st.mquat.solving;
+
+import de.tudresden.inf.st.mquat.solving.ilp.ILPDirectSolver;
+
+public class ILPDirectHandwrittenTest extends HandwrittenTestSuite {
+  @Override
+  protected Solver getSolver() {
+    // set to true for debugging
+    return new ILPDirectSolver().setWriteFiles(false);
+  }
+}
diff --git a/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPExternalHandwrittenTest.java b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPExternalHandwrittenTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2abeb4dbdfe7b1f766d040c7826d984b98968b3e
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPExternalHandwrittenTest.java
@@ -0,0 +1,11 @@
+package de.tudresden.inf.st.mquat.solving;
+
+import de.tudresden.inf.st.mquat.solving.ilp.ILPExternalSolver;
+
+public class ILPExternalHandwrittenTest extends HandwrittenTestSuite {
+  @Override
+  protected Solver getSolver() {
+    // set to false for debugging
+    return new ILPExternalSolver().setDeleteFilesOnExit(true);
+  }
+}
diff --git a/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPObjectiveTest.java b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPObjectiveTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e5c761bb7d2b829ad0db0cb75864e80bcb48a3e
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPObjectiveTest.java
@@ -0,0 +1,44 @@
+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 de.tudresden.inf.st.mquat.solving.ilp.ILPExternalSolver;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ILPObjectiveTest {
+
+  private static Logger logger;
+
+  @BeforeClass
+  public static void initLogger() {
+    logger = LogManager.getLogger(ILPObjectiveTest.class);
+  }
+
+  @Test
+  public void test_config_01() throws SolvingException {
+    int tlc = 1;
+    int iac = 1;
+    int isd = 0;
+    int cac = 0;
+    int csd = 0;
+    int dep = 2;
+    int imp = 2;
+    int res = 10;
+    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();
+    ILPExternalSolver solver = new ILPExternalSolver().setDeleteFilesOnExit(false);
+    Solution solution = solver.solve(model);
+    Assert.assertTrue(solution.isValid());
+    logger.info("Solution (objective={}): {}", solution.computeObjective(), solution);
+  }
+}
diff --git a/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPSolveTest.java b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPSolveTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..63ac7cbd3e402be32cbc1150ede363c0871994fc
--- /dev/null
+++ b/jastadd-mquat-solver-ilp/src/test/java/de/tudresden/inf/st/mquat/solving/ILPSolveTest.java
@@ -0,0 +1,160 @@
+package de.tudresden.inf.st.mquat.solving;
+
+import de.tudresden.inf.st.mquat.data.TestGeneratorSettings;
+import de.tudresden.inf.st.mquat.generator.ScenarioGenerator;
+import de.tudresden.inf.st.mquat.utils.TestUtils;
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+import de.tudresden.inf.st.mquat.jastadd.model.Solution;
+import de.tudresden.inf.st.mquat.solving.ilp.ILPDirectSolver;
+import de.tudresden.inf.st.mquat.solving.ilp.ILPExternalSolver;
+import de.tudresden.inf.st.mquat.utils.StopWatch;
+import de.tudresden.inf.st.mquat.utils.TestGenerator;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.*;
+import org.junit.rules.ErrorCollector;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+
+@RunWith(Parameterized.class)
+public class ILPSolveTest {
+
+  private static Logger logger;
+  private static TestGeneratorSettings settings = new TestGeneratorSettings() {{
+    minTopLevelComponents = 1;
+    maxTopLevelComponents = 3;
+
+    minAvgNumImplSubComponents = 0;
+    maxAvgNumImplSubComponents = 2;
+
+    minImplSubComponentDerivation = 0;
+    maxImplSubComponentDerivation = 1;
+
+    minAvgNumCompSubComponents = 0;
+    maxAvgNumCompSubComponents = 2;
+
+    minCompSubComponentDerivation = 0;
+    maxCompSubComponentDerivation = 1;
+
+    minComponentDepth = 1;
+    maxComponentDepth = 3;
+
+    minNumImplementations = 1;
+    maxNumImplementations = 2;
+
+    minResourceRatio = 1d;
+    maxResourceRatio = 2d;
+    stepResourceRatio = .1d;
+
+    minRequests = 0;
+    maxRequests = 100;
+    stepRequests = 25;
+
+    minCpus = 1;
+    maxCpus = 3;
+
+    seed = 0;
+    verbose = false;
+    shouldExitOnWarnings = true;
+  }};
+  private static Integer[] testIdsToSkip = {
+      298,
+      343, 352, 355, 357, 358,
+      477, 478, 479,
+      519, 520, 521, 522, 523, 524, 531, 532, 533, 534, 535, 536, 537, 538};
+  private static Set<Integer> testIdsToSkipAsSet;
+  private static final int startingTestId = 506;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static Collection<Object[]> data() {
+    StopWatch watch = StopWatch.start();
+    List<Object[]> result = new ArrayList<>();
+    TestGenerator generator = new TestGenerator(settings);
+    System.out.println("*** Generating test generator");
+    generator.generateScenarioGenerator((gen, testId) -> {
+      if (testId > 150) { return false; } // skip other test-cases for now
+//      if (testId < startingTestId) { return false; }
+      Root model = gen.generate();
+      String name = testId + model.description();
+      result.add(new Object[]{name, testId, model, gen});
+      return true;
+    });
+    long diff = watch.time(TimeUnit.MILLISECONDS);
+    System.out.println("Generation took " + diff + "ms.");
+    return result;
+  }
+
+  @BeforeClass
+  public static void initLogger() {
+    Assume.assumeTrue(TestUtils.shouldTestLongRunning());
+    logger = LogManager.getLogger(ILPSolveTest.class);
+    testIdsToSkipAsSet = new HashSet<>(Arrays.asList(testIdsToSkip));
+  }
+
+  @Rule
+  public ErrorCollector collector = new ErrorCollector();
+
+  @Before
+  public void setup() {
+    System.gc();
+  }
+
+  private Solver externalSolver() {
+    // set to false to analyse created temporary files
+    return new ILPExternalSolver().setDeleteFilesOnExit(true).setTimeout(10, TimeUnit.SECONDS);
+  }
+
+  private Solver directSolver() {
+    // set to true to analyse created temporary files
+    return new ILPDirectSolver().setWriteFiles(false).setTimeout(10, TimeUnit.SECONDS);
+  }
+
+  private String name;
+  private int testId;
+  private Root model;
+  private ScenarioGenerator gen;
+
+  public ILPSolveTest(String name, int testId, Root model, ScenarioGenerator gen) {
+    this.name = name;
+    this.testId = testId;
+    this.model = model;
+    this.gen = gen;
+  }
+
+  @Test
+  public void testWithExternal() {
+    testWith(externalSolver());
+  }
+
+  @Test
+  public void testWithDirect() {
+    testWith(directSolver());
+  }
+
+  private void testWith(Solver solver) {
+    Assume.assumeTrue(TestUtils.shouldTestLongRunning());
+    Assume.assumeFalse("Skipping complicated test case " + testId, testIdsToSkipAsSet.contains(testId));
+    System.out.println("name=" + name);
+    Solution solution;
+    try {
+      solution = solver.solve(model);
+    } catch (SolvingException e) {
+      collector.addError(e);
+      return;
+    }
+    logger.debug("Start validation");
+    collector.checkThat("Test" + name + " failed", true, equalTo(solution.isValid()));
+    logger.debug("End validation, begin compute objective");
+    double actualObjective = solution.computeObjective();
+    double initialObjective = gen.getInitialSolution().computeObjective();
+    logger.debug("End compute objective");
+    if (actualObjective != initialObjective) {
+      logger.info("Different objective: {}. Initial was {}", actualObjective, initialObjective);
+    }
+  }
+}
diff --git a/jastadd-mquat-solver-simple/.gitignore b/jastadd-mquat-solver-simple/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..567609b1234a9b8806c5a05da6c866e480aa148d
--- /dev/null
+++ b/jastadd-mquat-solver-simple/.gitignore
@@ -0,0 +1 @@
+build/
diff --git a/jastadd-mquat-solver-simple/build.gradle b/jastadd-mquat-solver-simple/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..3e180690f12cb0f3da70298777a3ac432156ebc8
--- /dev/null
+++ b/jastadd-mquat-solver-simple/build.gradle
@@ -0,0 +1,17 @@
+
+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')
+    testCompile group: 'junit', name: 'junit', version: '4.12'
+    testCompile project(path: ':jastadd-mquat-solver', configuration: 'testArtifacts')
+}
diff --git a/jastadd-mquat-solver-simple/src/main/java/de/tudresden/inf/st/mquat/solving/simple/SimpleSolver.java b/jastadd-mquat-solver-simple/src/main/java/de/tudresden/inf/st/mquat/solving/simple/SimpleSolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7129090c1da8afd3e91d3600b66e68dbd905ea5
--- /dev/null
+++ b/jastadd-mquat-solver-simple/src/main/java/de/tudresden/inf/st/mquat/solving/simple/SimpleSolver.java
@@ -0,0 +1,192 @@
+package de.tudresden.inf.st.mquat.solving.simple;
+
+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 java.util.*;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class SimpleSolver implements BenchmarkableSolver {
+
+  private static final Logger logger = LogManager.getLogger(SimpleSolver.class);
+
+  private Solution lastSolution;
+  private long lastSolvingTime;
+
+  private int solutionCounter;
+
+  private StopWatch stopWatch;
+
+  private long maxSolvingTime;
+  private boolean timedOut;
+
+  public SimpleSolver() {
+    this(Long.MAX_VALUE);
+  }
+
+  public SimpleSolver(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);
+    }
+    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);
+//    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-simple/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleHandwrittenTest.java b/jastadd-mquat-solver-simple/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleHandwrittenTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed3e2782a27c12f1c61dd402098f064af9d7102c
--- /dev/null
+++ b/jastadd-mquat-solver-simple/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleHandwrittenTest.java
@@ -0,0 +1,11 @@
+package de.tudresden.inf.st.mquat.solving;
+
+import de.tudresden.inf.st.mquat.solving.simple.SimpleSolver;
+
+public class SimpleHandwrittenTest extends HandwrittenTestSuite {
+
+  @Override
+  protected Solver getSolver() {
+    return new SimpleSolver(10000);
+  }
+}
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
new file mode 100644
index 0000000000000000000000000000000000000000..7647d3e01efa490e23754e80ac4097ce18947842
--- /dev/null
+++ b/jastadd-mquat-solver-simple/src/test/java/de/tudresden/inf/st/mquat/solving/SimpleSolverTest.java
@@ -0,0 +1,54 @@
+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 de.tudresden.inf.st.mquat.solving.simple.SimpleSolver;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SimpleSolverTest {
+
+  private static Logger logger;
+
+  @BeforeClass
+  public static void initLogger() {
+    logger = LogManager.getLogger(SimpleSolverTest.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 = 3;
+    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();
+    SimpleSolver solver = new SimpleSolver(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());
+
+  }
+}
diff --git a/jastadd-mquat-solver/.gitignore b/jastadd-mquat-solver/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..567609b1234a9b8806c5a05da6c866e480aa148d
--- /dev/null
+++ b/jastadd-mquat-solver/.gitignore
@@ -0,0 +1 @@
+build/
diff --git a/jastadd-mquat-solver/build.gradle b/jastadd-mquat-solver/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..0bb16f68259d42fb29a7cada3c745f1f6e90f38e
--- /dev/null
+++ b/jastadd-mquat-solver/build.gradle
@@ -0,0 +1,15 @@
+
+apply plugin: 'java'
+
+sourceCompatibility = 1.8
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    testCompile group: 'junit', name: 'junit', version: '4.12'
+    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')
+}
diff --git a/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/BenchmarkableSolver.java b/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/BenchmarkableSolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..57c2c07c21110214fdddfdfac00a7ba20d611143
--- /dev/null
+++ b/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/BenchmarkableSolver.java
@@ -0,0 +1,45 @@
+package de.tudresden.inf.st.mquat.solving;
+
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+
+public interface BenchmarkableSolver extends Solver {
+
+  /**
+   * @return a descriptive, unique, short name, e.g., "ilp"
+   */
+  String getName();
+
+  /**
+   * @return whether this solver generates an intermediate model. Defaults to <code>false</code>.
+   * Solvers returning <code>true</code> here, should also override {@link #getLastGenerationTime()}.
+   */
+  default boolean doesGeneration() {
+    return false;
+  }
+
+  /**
+   * Return the generation time in milliseconds for the last finished call of {@link #solve(Root)}.
+   * Defaults to returning zero for all solvers that do not generate.
+   * Ignored, if {@link #doesGeneration()} is <code>false</code>.
+   * @return generation time in milliseconds
+   */
+  default long getLastGenerationTime() {
+    return 0;
+  }
+
+  /**
+   * @return solving time in milliseconds for the last finished call of {@link #solve(Root)}.
+   */
+  long getLastSolvingTime();
+
+  /**
+   * @return objective value for the last finished call of {@link #solve(Root)}.
+   */
+  double getLastObjective();
+
+  /**
+   * @return whether this solver reached the timeout for the last finished call of {@link #solve(Root)}.
+   */
+  boolean hadTimeout();
+
+}
diff --git a/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/Solver.java b/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/Solver.java
new file mode 100644
index 0000000000000000000000000000000000000000..1227f10e9b0994e4818d4ad3c405e395af36aa9e
--- /dev/null
+++ b/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/Solver.java
@@ -0,0 +1,29 @@
+package de.tudresden.inf.st.mquat.solving;
+
+import de.tudresden.inf.st.mquat.jastadd.model.Root;
+import de.tudresden.inf.st.mquat.jastadd.model.Solution;
+
+import java.util.concurrent.TimeUnit;
+
+public interface Solver {
+
+  /**
+   * Solve the given model.
+   * @param model the model to solve
+   * @return a solution w.r.t. the model
+   * @throws SolvingException if something went wrong
+   */
+  Solution solve(Root model) throws SolvingException;
+
+  /**
+   * Set the maximum amount of time for calls to {@link Solver#solve(Root)}.
+   * Defaults to ignoring the specified timeout.
+   * @param timeoutValue value for the timeout
+   * @param timeoutUnit  used unit for the timeout
+   * @return this
+   */
+  default Solver setTimeout(long timeoutValue, TimeUnit timeoutUnit) {
+    return this;
+  }
+
+}
diff --git a/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/SolverUtils.java b/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/SolverUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..70af777030622b04bc7574b529c5c7c92d110c19
--- /dev/null
+++ b/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/SolverUtils.java
@@ -0,0 +1,117 @@
+package de.tudresden.inf.st.mquat.solving;
+
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import de.tudresden.inf.st.mquat.utils.StopWatch;
+import org.apache.logging.log4j.Logger;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@SuppressWarnings("Duplicates")
+public class SolverUtils {
+
+  public static void populateResourceMapping(ResourceMapping mapping, ResourceRequirement requirement, Resource resource) {
+
+    for (ResourceRequirement subRequirement : requirement.getResourceRequirementList()) {
+      int fittingResourceCount = 0;
+      for (int currentInstance = 0; currentInstance < subRequirement.getNumInstance(); currentInstance++) {
+        Instance instance = subRequirement.getInstance(currentInstance);
+        for (int currentResource = 0; currentResource < resource.getNumSubResource(); currentResource++) {
+          Resource subResource = resource.getSubResource(currentResource);
+          if (subResource.getType().getRef() == subRequirement.getResourceTypeRef().getRef()) {
+            if (currentInstance == fittingResourceCount) {
+              ResourceMapping newMapping = new ResourceMapping(instance, subResource, new de.tudresden.inf.st.mquat.jastadd.model.List<>());
+              mapping.addResourceMapping(newMapping);
+              populateResourceMapping(newMapping, subRequirement, subResource);
+              fittingResourceCount++;
+            }
+            currentInstance++;
+          }
+        }
+      }
+    }
+  }
+
+  public static long populateSolution(List<Assignment> listOfInitialAssignments, Solution result, Logger logger)
+      throws SolvingException {
+    StopWatch watch = StopWatch.start();
+    Map<Tuple<Request, Component>, Assignment> tupleAssignmentMap = new HashMap<>();
+
+    for (Assignment assignment : listOfInitialAssignments) {
+      Implementation impl = assignment.getImplementation();
+      Resource resource = assignment.getResource();
+
+      ResourceMapping mapping = new ResourceMapping(impl.getResourceRequirement().getInstance(0), resource, new de.tudresden.inf.st.mquat.jastadd.model.List<>());
+      populateResourceMapping(mapping, impl.getResourceRequirement(), resource);
+      assignment.setResourceMapping(mapping);
+
+//      for (ResourceRequirement rr : impl.getResourceRequirementList()) {
+//        ResourceType requiredType = rr.getResourceTypeRef().getRef();
+//        if (requiredType.equals(resource.getType().getRef())) {
+//          // computeNode
+//          assignment.addResourceMapping(new ResourceMapping(rr.getInstance(0), resource));
+//        } else {
+//          // cpu, ram, disk, network
+//          for (int i = 0; i < rr.getNumInstance(); i++) {
+//            // find in resource the i-th sub-resource with matching type
+//            int remaining = i + 1;
+//            int subI;
+//            for (subI = 0; subI < resource.getNumSubResource(); subI++) {
+//              if (resource.getSubResource(subI).getType().getRef().equals(requiredType)) {
+//                if (--remaining == 0) {
+//                  break;
+//                }
+//              }
+//            }
+//            if (remaining > 0) {
+//              throw new SolvingException("Could not find the " + (i + 1) + "-th sub-resource in " +
+//                  resource.getIlpName() +
+//                  " with type " + requiredType + ". Only found " + (i + 1 - remaining));
+//            }
+//            Resource subResource = resource.getSubResource(subI);
+//            if (subResource == null) {
+//              throw new SolvingException("Could not find the " + (i + 1) + "-th sub-resource in " +
+//                  resource.getIlpName() +
+//                  " with type " + requiredType.getIlpName() + ". Tried with " + (subI + 1) + "-th one.");
+//            }
+//            assignment.addResourceMapping(new ResourceMapping(rr.getInstance(i), subResource));
+//          }
+//        }
+//      }
+      tupleAssignmentMap.put(Tuple.of(assignment.getRequest(), impl.containingComponent()), assignment);
+    }
+
+    // set componentRequirementAssignments and add assignments to result
+    // assignments are not final upon adding, thus should not be validated before loop exits
+    for (Assignment assignment : tupleAssignmentMap.values()) {
+      Implementation impl = assignment.getImplementation();
+      for (ComponentRequirement cr : impl.getComponentRequirementList()) {
+        Component requiredComponent = cr.getComponentRef().getRef();
+        Assignment providingAssignment = tupleAssignmentMap.get(Tuple.of(assignment.getRequest(), requiredComponent));
+        if (providingAssignment == null) {
+          logger.warn("No assignment found for component {} at {} required in {}",
+              requiredComponent.getIlpName(), assignment.getRequest().getIlpName(), impl.getIlpName());
+          continue;
+        }
+        assignment.addComponentMapping(new ComponentMapping(cr.getInstance(0), providingAssignment));
+        if (cr.getNumInstance() > 1) {
+          logger.warn("Can not handle more than one required instance for {} in impl {}. Skipping all but first.",
+              requiredComponent.getIlpName(), impl.getIlpName());
+        }
+      }
+
+      if (impl.containingComponent().equals(assignment.getRequest().getTarget().getRef())) {
+        assignment.setTopLevel(true);
+        result.addAssignment(assignment);
+      } else {
+        assignment.setTopLevel(false);
+      }
+    }
+    long solutionCreation = watch.time(TimeUnit.MILLISECONDS);
+    logger.debug("Solution creation took {}ms.", solutionCreation);
+    return solutionCreation;
+
+  }
+}
diff --git a/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/SolvingException.java b/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/SolvingException.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e81b436d44adc45b56f8473b6bac7896595d668
--- /dev/null
+++ b/jastadd-mquat-solver/src/main/java/de/tudresden/inf/st/mquat/solving/SolvingException.java
@@ -0,0 +1,11 @@
+package de.tudresden.inf.st.mquat.solving;
+
+public class SolvingException extends Exception {
+  public SolvingException(String message) {
+    super(message);
+  }
+
+  public SolvingException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}
diff --git a/jastadd-mquat-solver/src/test/java/de/tudresden/inf/st/mquat/solving/HandwrittenTestSuite.java b/jastadd-mquat-solver/src/test/java/de/tudresden/inf/st/mquat/solving/HandwrittenTestSuite.java
new file mode 100644
index 0000000000000000000000000000000000000000..c519b14b8cade4462c70356b38360031d3b6c840
--- /dev/null
+++ b/jastadd-mquat-solver/src/test/java/de/tudresden/inf/st/mquat/solving/HandwrittenTestSuite.java
@@ -0,0 +1,155 @@
+package de.tudresden.inf.st.mquat.solving;
+
+import beaver.Parser;
+import de.tudresden.inf.st.mquat.jastadd.model.*;
+import de.tudresden.inf.st.mquat.utils.ParserUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.*;
+import org.junit.rules.ErrorCollector;
+
+import java.io.*;
+import java.net.URL;
+import java.util.Iterator;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public abstract class HandwrittenTestSuite {
+  private static Logger logger;
+  private Solver solver;
+
+  @Rule
+  public ErrorCollector collector = new ErrorCollector();
+
+  @BeforeClass
+  public static void setupClass() {
+    logger = LogManager.getLogger(HandwrittenTestSuite.class);
+  }
+
+  @Before
+  public void setupSolverForTest() {
+    this.solver = getSolver();
+  }
+
+  /**
+   * Create and return the solver to use in this test suite
+   * @return a solver instance
+   */
+  protected abstract Solver getSolver();
+
+  private Tuple<Root, Solution> loadAndSolve(String filename) throws IOException, Parser.Exception, SolvingException {
+    Root model = ParserUtils.load(filename, HandwrittenTestSuite.class);
+    Solution solution = solver.solve(model);
+    if (logger.isDebugEnabled()) {
+      MquatString out = solution.print(new MquatWriteSettings(" "));
+      logger.debug("Solution:\n{}", out);
+    }
+    return new Tuple<>(model, solution);
+  }
+
+  private Assignment assertAssignment(Tuple<Root, Solution> modelAndSolution,
+                                      int request, String impl, String resource) {
+    Root model = modelAndSolution.getFirstElement();
+    Assignment expectedAssignment = new Assignment();
+    expectedAssignment.setRequest(model.getRequest(request));
+    expectedAssignment.setImplementation(model.findImplementationByName(impl));
+    expectedAssignment.setResourceMapping(new ResourceMapping(expectedAssignment.getImplementation().getResourceRequirement().getInstance(0), model.findResourceByName(resource), new List<>()));
+    // check if assignment matches (partly) one listed in the solution
+    Iterator<Assignment> assignmentIterator = modelAndSolution.getSecondElement().assignmentIterator();
+    while (assignmentIterator.hasNext()) {
+      Assignment actualAssignment = assignmentIterator.next();
+      if (matches(actualAssignment, expectedAssignment)) {
+        Assert.assertNotNull(actualAssignment);
+        return actualAssignment;
+      }
+    }
+    Assert.fail(String.format("Did not find match of assignment: %s on %s for request%s",
+        impl, resource, request));
+    throw new AssertionError();
+  }
+
+  private void assertComponentRequirement(Assignment requiringAssignment,
+                                          String instanceName, Assignment expectedProvidingAssignment) {
+    Instance instance = requiringAssignment.getImplementation().findInstanceByName(instanceName);
+    Assignment actualProvidingAssignment = requiringAssignment.mappedAssignment(instance);
+    Assert.assertEquals(String.format("Not matching assignment for %s", instanceName),
+        expectedProvidingAssignment, actualProvidingAssignment);
+  }
+
+  /**
+   * Check if request, configuration and resource of the given assignments are equal
+   * @param actualAssignment   assignment in the computed solution
+   * @param expectedAssignment expected assignment defined in the test case
+   * @return <code>true</code> if both match, <code>false</code> otherwise
+   */
+  private boolean matches(Assignment actualAssignment, Assignment expectedAssignment) {
+    return actualAssignment.getRequest().equals(expectedAssignment.getRequest()) &&
+        actualAssignment.getImplementation().equals(expectedAssignment.getImplementation()) &&
+        actualAssignment.getResource().equals(expectedAssignment.getResource());
+  }
+
+  private void assertValidSolution(Tuple<Root, Solution> modelAndSolution) {
+//    Assert.assertTrue("Solution is not valid", modelAndSolution.getSecondElement().isValid());
+    collector.checkThat("Solution is not valid", true,
+        equalTo(modelAndSolution.getSecondElement().isValid()));
+  }
+
+  @Test
+  public void test_01() throws IOException, Parser.Exception, SolvingException {
+    Tuple<Root, Solution> modelAndSolution = loadAndSolve("test_01.txt");
+    Assignment config_0i0m0 = assertAssignment(modelAndSolution, 0, "config_0i0m0", "r0");
+    Assignment config_1i0m0 = assertAssignment(modelAndSolution, 0, "config_1i0m0", "r1");
+    assertComponentRequirement(config_0i0m0,"other", config_1i0m0);
+    assertValidSolution(modelAndSolution);
+  }
+
+  @Test
+  public void test_02() throws IOException, Parser.Exception, SolvingException {
+    Tuple<Root, Solution> modelAndSolution = loadAndSolve("test_02.txt");
+    Assignment config_0i0m0 = assertAssignment(modelAndSolution, 0, "config_0i0m0", "r0");
+    Assignment config_1i0m0 = assertAssignment(modelAndSolution, 0, "config_1i0m0", "r1");
+    assertComponentRequirement(config_0i0m0,"other", config_1i0m0);
+    assertValidSolution(modelAndSolution);
+  }
+
+  @Test
+  public void test_03() throws IOException, Parser.Exception, SolvingException {
+    Tuple<Root, Solution> modelAndSolution = loadAndSolve("test_03.txt");
+    assertValidSolution(modelAndSolution);
+    Assignment r0config_0i0m0 = assertAssignment(modelAndSolution, 0, "config_0i0m0", "r0");
+    Assignment r0config_1i0m0 = assertAssignment(modelAndSolution, 0, "config_1i0m0", "r1");
+    assertAssignment(modelAndSolution, 1, "config_1i0m0", "r2");
+    assertComponentRequirement(r0config_0i0m0,"other", r0config_1i0m0);
+  }
+
+  @Test
+  public void test_04() throws IOException, Parser.Exception, SolvingException {
+    Tuple<Root, Solution> modelAndSolution = loadAndSolve("test_04.txt");
+    assertValidSolution(modelAndSolution);
+    Assignment config_0i0m0 = assertAssignment(modelAndSolution, 0, "config_0i0m0", "r0");
+    Assignment config_1i0m0 = assertAssignment(modelAndSolution, 0, "config_1i0m0", "r1");
+    Assignment config_2i0m0 = assertAssignment(modelAndSolution, 0, "config_2i0m0", "r2");
+    assertComponentRequirement(config_0i0m0,"alpha", config_1i0m0);
+    assertComponentRequirement(config_0i0m0,"beta", config_2i0m0);
+  }
+
+  @Test
+  public void test_05() throws IOException, Parser.Exception, SolvingException {
+    Tuple<Root, Solution> modelAndSolution = loadAndSolve("test_05.txt");
+    assertValidSolution(modelAndSolution);
+    Assignment configA = assertAssignment(modelAndSolution, 0, "configA0", "r0");
+    Assignment configB = assertAssignment(modelAndSolution, 0, "configB0", "r1");
+    Assignment configC = assertAssignment(modelAndSolution, 0, "configC0", "r4");
+    Assignment configD = assertAssignment(modelAndSolution, 0, "configD0", "r3");
+    Assignment configE = assertAssignment(modelAndSolution, 0, "configE0", "r2");
+    Assignment configF = assertAssignment(modelAndSolution, 0, "configF0", "r5");
+    Assignment configG = assertAssignment(modelAndSolution, 0, "configG0", "r6");
+    assertComponentRequirement(configA,"beta", configB);
+    assertComponentRequirement(configA,"epsilon", configE);
+    assertComponentRequirement(configB,"chi", configC);
+    assertComponentRequirement(configB,"delta", configD);
+    assertComponentRequirement(configE,"phi", configF);
+    assertComponentRequirement(configE,"gamma", configG);
+  }
+
+}
diff --git a/jastadd-mquat-solver/src/test/resources/test_01.txt b/jastadd-mquat-solver/src/test/resources/test_01.txt
new file mode 100644
index 0000000000000000000000000000000000000000..090557820539ec1f646971bdf452f8ee877716d7
--- /dev/null
+++ b/jastadd-mquat-solver/src/test/resources/test_01.txt
@@ -0,0 +1,92 @@
+// One request, two simple components, first requires second one
+// Expected solution
+// config_0i0m0 -> r0 + cpu0_0
+// config_1i0m0 -> r1 + cpu0_1
+
+container resource type ComputeNode {
+    resource type CPU {
+        property frequency [Hz]
+        property load [%]
+    }
+    property flops [ops/s]
+}
+resource r0:ComputeNode {
+    resource cpu0_0:CPU {
+        frequency = 2930
+        load = 30
+    }
+    flops = 293000
+}
+resource r1:ComputeNode {
+    resource cpu1_0:CPU {
+        frequency = 930
+        load = 10
+    }
+    flops = 93000
+}
+meta size
+property energy [J]
+property quality [%]
+
+component c0 {
+    using property quality
+    contract config_0i0m0 {
+        // can run only on r0
+        requires component other of type c1
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring other.quality >= 95
+        requiring compute_resource_0.cpu_1.frequency >= 2159
+        providing quality = 300
+        providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+    }
+    contract config_0i0m1 {
+        // not satisfied at all
+        requires component other of type c1
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring other.quality >= 95
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.94*compute_resource_0.flops))
+    }
+}
+component c1 {
+    using property quality
+    contract config_1i0m0 {
+        // can run on both, r0 and r1
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= 80
+        // fulfills c0 requirement
+        providing quality = 1004
+        providing energy = ((0.45*(size^2))+(0.34*compute_resource_0.flops))
+    }
+    contract config_1i0m1 {
+        // could run on r1
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= 20
+        // does not fulfill c0 requirement
+        providing quality = 3
+        providing energy = ((0.25*(size^2))+(0.34*compute_resource_0.flops))
+    }
+    contract config_1i0m2 {
+        // not satisfied at all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= 1
+        providing quality = 200
+        providing energy = ((0.02*(size^2))+(0.71*compute_resource_0.flops))
+    }
+}
+request c0 {
+    meta size = 6
+    requiring quality >= 35
+}
+minimize sum(energy)
diff --git a/jastadd-mquat-solver/src/test/resources/test_02.txt b/jastadd-mquat-solver/src/test/resources/test_02.txt
new file mode 100644
index 0000000000000000000000000000000000000000..08a3dc501979ae5f04de8426c69097b99be49c65
--- /dev/null
+++ b/jastadd-mquat-solver/src/test/resources/test_02.txt
@@ -0,0 +1,95 @@
+// One request, two simple components, first requires second one
+//  Using metaparameter size in clauses
+// Expected solution
+// Request0:
+//  config_0i0m0 -> r0 + cpu0_0
+//  config_1i0m0 -> r1 + cpu0_1
+
+container resource type ComputeNode {
+    resource type CPU {
+        property frequency [Hz]
+        property load [%]
+    }
+    property flops [ops/s]
+}
+resource r0:ComputeNode {
+    resource cpu0_0:CPU {
+        frequency = 2930
+        load = 30
+    }
+    flops = 293000
+}
+resource r1:ComputeNode {
+    resource cpu1_0:CPU {
+        frequency = 930
+        load = 10
+    }
+    flops = 93000
+}
+meta size
+property energy [J]
+property quality [%]
+
+component c0 {
+    using property quality
+    contract config_0i0m0 {
+        // can run only on r0
+        requires component other of type c1
+        requires resource compute_resource_0 of type ComputeNode with {
+          cpu_1 of type CPU
+        }
+        requiring other.quality >= 95
+        requiring compute_resource_0.cpu_1.frequency >= 2159
+        providing quality = 300
+        providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+    }
+    contract config_0i0m1 {
+        // not satisfied at all
+        requires component other of type c1
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring other.quality >= 95
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.94*compute_resource_0.flops))
+    }
+}
+
+component c1 {
+    using property quality
+    contract config_1i0m0 {
+        // can run on both, r0 and r1
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= (80 * size)
+        // fulfills c0 requirement
+        providing quality = 1004
+        providing energy = ((0.45*(size^2))+(0.34*compute_resource_0.flops))
+    }
+    contract config_1i0m1 {
+        // could run on r1
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= (20 * size)
+        // does not fulfill c0 requirement
+        providing quality = 3
+        providing energy = ((0.25*(size^2))+(0.34*compute_resource_0.flops))
+    }
+    contract config_1i0m2 {
+        // not satisfied at all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= (1 * size)
+        providing quality = 200
+        providing energy = ((0.02*(size^2))+(0.71*compute_resource_0.flops))
+    }
+}
+request c0 {
+    meta size = 1
+    requiring quality >= 35
+}
+minimize sum(energy)
diff --git a/jastadd-mquat-solver/src/test/resources/test_03.txt b/jastadd-mquat-solver/src/test/resources/test_03.txt
new file mode 100644
index 0000000000000000000000000000000000000000..89501f1c9e0ec4cd420eb26a94cae072dedaacbe
--- /dev/null
+++ b/jastadd-mquat-solver/src/test/resources/test_03.txt
@@ -0,0 +1,115 @@
+// Two requests, two components, first requires second one, request target different one
+//  Using metaparameter size in clauses with different values in requests
+// Expected solution
+// Request0:
+//  config_0i0m0 -> r0 + cpu0_0
+//  config_1i0m0 -> r1 + cpu1_0
+// Request1:
+//  config_1i0m0 -> r2 + cpu2_0
+
+container resource type ComputeNode {
+    resource type CPU {
+        property frequency [Hz]
+        property load [%]
+    }
+    property flops [ops/s]
+    property STATE []
+}
+resource r0:ComputeNode {
+    resource cpu0_0:CPU {
+        frequency = 2930
+        load = 30
+    }
+    flops = 293000
+}
+resource r1:ComputeNode {
+    resource cpu1_0:CPU {
+        frequency = 930
+        load = 10
+    }
+    flops = 93000
+}
+resource r2:ComputeNode {
+    resource cpu2_0:CPU {
+        frequency = 930
+        load = 2
+    }
+    flops = 93000
+}
+meta size
+property energy [J]
+property quality [%]
+
+component c0 {
+    using property quality
+    contract config_0i0m0 {
+        // can run only on r0
+        requires component other of type c1
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring other.quality >= 95
+        requiring compute_resource_0.cpu_1.frequency >= 2159
+        providing quality = 300
+        providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+    }
+    contract config_0i0m1 {
+        // not satisfied at all
+        requires component other of type c1
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring other.quality >= 95
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.94*compute_resource_0.flops))
+    }
+}
+
+component c1 {
+    using property quality
+    contract config_1i0m0 {
+        // req0: can run on all
+        // req1: can only run on r2
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= (90 / size)
+        // req0: fulfills c0 requirement
+        // req1: fulfills req requirement
+        providing quality = 1004
+        providing energy = ((0.45*(size^2))+(0.34*compute_resource_0.flops))
+    }
+    contract config_1i0m1 {
+        // req0: could run on r1
+        // req1: can not run on any
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= (20 / size)
+        // req0: does not fulfill c0 requirement
+        // req1: does not fulfill req requirement
+        providing quality = 3
+        providing energy = ((0.25*(size^2))+(0.34*compute_resource_0.flops))
+    }
+    contract config_1i0m2 {
+        // req0: not satisfied at all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= (1 / size)
+        // req0: would fulfill c0 requirement
+        // req1: would fulfill req requirement
+        providing quality = 200
+        providing energy = ((0.02*(size^2))+(0.71*compute_resource_0.flops))
+    }
+}
+request c0 {
+    meta size = 1
+    requiring quality >= 35
+}
+request c1 {
+    meta size = 40
+    requiring quality >= 35
+}
+minimize sum(energy)
diff --git a/jastadd-mquat-solver/src/test/resources/test_04.txt b/jastadd-mquat-solver/src/test/resources/test_04.txt
new file mode 100644
index 0000000000000000000000000000000000000000..24a42b82184abe2166b5a6fecd7b201fa8f95205
--- /dev/null
+++ b/jastadd-mquat-solver/src/test/resources/test_04.txt
@@ -0,0 +1,131 @@
+// One request, target component requires two different components
+// Expected solution
+// Request0:
+//  config_0i0m0 -> r0 + cpu0_0
+//  config_1i0m0 -> r1 + cpu1_0
+//  config_2i0m0 -> r2 + cpu2_0
+
+container resource type ComputeNode {
+    resource type CPU {
+        property frequency [Hz]
+        property load [%]
+    }
+    property flops [ops/s]
+    property STATE []
+}
+resource r0:ComputeNode {
+    resource cpu0_0:CPU {
+        frequency = 2930
+        load = 30
+    }
+    flops = 293000
+}
+resource r1:ComputeNode {
+    resource cpu1_0:CPU {
+        frequency = 930
+        load = 10
+    }
+    flops = 93000
+}
+resource r2:ComputeNode {
+    resource cpu2_0:CPU {
+        frequency = 930
+        load = 2
+    }
+    flops = 93000
+}
+meta size
+property energy [J]
+property quality [%]
+
+component c0 {
+    using property quality
+    contract config_0i0m0 {
+        // can run only on r0
+        requires component alpha of type c1
+        requires component beta of type c2
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring alpha.quality >= 95
+        requiring beta.quality >= 55
+        requiring compute_resource_0.cpu_1.frequency >= 2159
+        providing quality = 300
+        providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+    }
+    contract config_0i0m1 {
+        // not satisfied at all
+        requires component alpha of type c1
+        requires component beta of type c2
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring alpha.quality >= 95
+        requiring beta.quality >= 55
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.34*compute_resource_0.flops))
+    }
+}
+
+component c1 {
+    using property quality
+    contract config_1i0m0 {
+        // can run on all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= (90 / size)
+        // fulfills c0 requirement
+        providing quality = 1004
+        providing energy = ((0.45*(size^2))+(0.34*compute_resource_0.flops))
+    }
+    contract config_1i0m1 {
+        // could run on r1 and r2
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= (20 / size)
+        // does not fulfill c0 requirement
+        providing quality = 3
+        providing energy = ((0.25*(size^2))+(0.14*compute_resource_0.flops))
+    }
+    contract config_1i0m2 {
+        // not satisfied at all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.load <= (1 / size)
+        // would fulfill c0 requirement
+        providing quality = 200
+        providing energy = ((0.02*(size^2))+(0.11*compute_resource_0.flops))
+    }
+}
+component c2 {
+    using property quality
+    contract config_2i0m0 {
+        // can run only on r2
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency <= 1500
+        requiring compute_resource_0.cpu_1.load <= (size + 4)
+        providing quality = 70
+        providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+    }
+    contract config_2i0m1 {
+        // not satisfied at all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.14*compute_resource_0.flops))
+    }
+}
+
+request c0 {
+    meta size = 2
+    requiring quality >= 35
+}
+minimize sum(energy)
diff --git a/jastadd-mquat-solver/src/test/resources/test_05.txt b/jastadd-mquat-solver/src/test/resources/test_05.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3f5806eee76eabe62928d2679a302588c592eb4b
--- /dev/null
+++ b/jastadd-mquat-solver/src/test/resources/test_05.txt
@@ -0,0 +1,233 @@
+// One request, target component requires two different components, each requiring two other components
+//  Also more resources than needed
+// Expected solution
+// Request0:
+//  configA0 ->         r0 + cpu0_0
+//   |- configB0 ->     r1 + cpu1_0
+//   |   |- configC0 -> r4 + cpu1_0
+//   |   |- configD0 -> r3 + cpu1_0
+//   |- configE0 ->     r2 + cpu2_0
+//   |   |- configF0 -> r5 + cpu2_0
+//   |   |- configG0 -> r6 + cpu2_0
+
+container resource type ComputeNode {
+    resource type CPU {
+        property frequency [Hz]
+        property load [%]
+    }
+    property flops [ops/s]
+    property STATE []
+}
+resource r0:ComputeNode { resource cpu0_0:CPU { frequency = 2930 load = 30 } flops =   3000 }
+resource r1:ComputeNode { resource cpu1_0:CPU { frequency =  930 load = 10 } flops =   3100 }
+resource r2:ComputeNode { resource cpu2_0:CPU { frequency =  930 load =  2 } flops =   3200 }
+resource r3:ComputeNode { resource cpu0_0:CPU { frequency = 2430 load = 30 } flops =   3300 }
+resource r4:ComputeNode { resource cpu0_0:CPU { frequency = 1830 load = 40 } flops =   3400 }
+resource r5:ComputeNode { resource cpu0_0:CPU { frequency =  430 load =  5 } flops =   3500 }
+resource r6:ComputeNode { resource cpu0_0:CPU { frequency = 3330 load = 30 } flops =   3600 }
+resource r7:ComputeNode { resource cpu0_0:CPU { frequency = 4230 load = 75 } flops = 423000 }
+
+meta size
+property energy [J]
+property quality [%]
+
+component A {
+    using property quality
+    contract configA0 {
+        // can run only on r0, r3, r6, r7
+        requires component beta of type B
+        requires component epsilon of type E
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring beta.quality >= 95
+        requiring epsilon.quality >= 55
+        requiring compute_resource_0.cpu_1.frequency >= 2159
+        providing quality = 300
+        providing energy = (((0.59*(size^2))+(0.89*compute_resource_0.flops))+compute_resource_0.cpu_1.frequency)
+    }
+    contract configA1 {
+        // not satisfied at all
+        requires component beta of type B
+        requires component epsilon of type E
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring beta.quality >= 95
+        requiring epsilon.quality >= 55
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.34*compute_resource_0.flops))
+    }
+}
+
+component B {
+    using property quality
+    contract configB0 {
+        // can run on all but r7
+        requires component chi of type C
+        requires component delta of type D
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring chi.quality >= 950
+        requiring delta.quality >= 550
+        requiring compute_resource_0.cpu_1.load <= (90 / size)
+        // fulfills A requirement
+        providing quality = 1004
+        providing energy = ((0.45*(size^2))+(0.34*compute_resource_0.flops))
+    }
+    contract configB1 {
+        // could run on r1, r2, r5
+        requires component chi of type C
+        requires component delta of type D
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring chi.quality >= 950
+        requiring delta.quality >= 550
+        requiring compute_resource_0.cpu_1.load <= (20 / size)
+        // does not fulfill A requirement
+        providing quality = 3
+        providing energy = ((0.25*(size^2))+(0.14*compute_resource_0.flops))
+    }
+    contract configB2 {
+        // not satisfied at all
+        requires component chi of type C
+        requires component delta of type D
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring chi.quality >= 950
+        requiring delta.quality >= 550
+        requiring compute_resource_0.cpu_1.load <= (1 / size)
+        // would fulfill A requirement
+        providing quality = 200
+        providing energy = ((0.02*(size^2))+(0.11*compute_resource_0.flops))
+    }
+}
+
+component C {
+    using property quality
+    contract configC0 {
+        // can run only on r0, r3, r4, r6,r7
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency >= 1759
+        providing quality = 3000
+        providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+    }
+    contract configC1 {
+        // not satisfied at all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 900
+        providing energy = ((0.11*(size^2))+(0.34*compute_resource_0.flops))
+    }
+}
+
+component D {
+    using property quality
+    contract configD0 {
+        // can run only on r0, r3, r6,r7
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency >= 2159
+        providing quality = 3000
+        providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.cpu_1.frequency))
+    }
+    contract configD1 {
+        // not satisfied at all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.34*compute_resource_0.cpu_1.frequency))
+    }
+}
+
+component E {
+    using property quality
+    contract configE0 {
+        // can run only on r1, r2, r5
+        requires component phi of type F
+        requires component gamma of type G
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring phi.quality >= 9500
+        requiring gamma.quality >= 5500
+        requiring compute_resource_0.cpu_1.frequency <= 1500
+        requiring compute_resource_0.cpu_1.load <= (size + 4)
+        providing quality = 70
+        providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+    }
+    contract configE1 {
+        // not satisfied at all
+        requires component phi of type F
+        requires component gamma of type G
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring phi.quality >= 9500
+        requiring gamma.quality >= 5500
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.14*compute_resource_0.flops))
+    }
+}
+
+component F {
+    using property quality
+    contract configF0 {
+        // can run only on r1, r2, r5
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency <= 1159
+        providing quality = 30000
+        providing energy = (((0.59*(size^2))+(0.89*compute_resource_0.flops))+(2*compute_resource_0.cpu_1.frequency))
+    }
+    contract configF1 {
+        // not satisfied at all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.34*compute_resource_0.flops))
+    }
+}
+
+component G {
+    using property quality
+    contract configG0 {
+        // can run only on r0, r3, r6,r7
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency >= 2159
+        providing quality = 30000
+        providing energy = ((0.59*(size^2))+(0.89*compute_resource_0.flops))
+    }
+    contract configG1 {
+        // not satisfied at all
+        requires resource compute_resource_0 of type ComputeNode with {
+            cpu_1 of type CPU
+        }
+        requiring compute_resource_0.cpu_1.frequency >= 14159
+        providing quality = 90
+        providing energy = ((0.11*(size^2))+(0.34*compute_resource_0.flops))
+    }
+}
+
+request A {
+    meta size = 2
+    requiring quality >= 35
+}
+minimize sum(energy)
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..00ff37f0ee12bb9f694350d30e9c45f27ed3ef0f
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,8 @@
+rootProject.name = 'jastadd-mquat'
+
+include ':jastadd-mquat-base'
+include ':jastadd-mquat-benchmark'
+include ':jastadd-mquat-solver'
+include ':jastadd-mquat-solver-ilp'
+include ':jastadd-mquat-solver-simple'
+