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 < max, or min > max if step < 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": "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\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' +