diff --git a/jastadd-mquat-base/src/main/jastadd/mquat.parser b/jastadd-mquat-base/src/main/jastadd/mquat.parser index ba0955b37e9de64fb0ce8262b11075c5fa025ef0..6819523559d7da1b874f5971a13f609bd260cdfa 100644 --- a/jastadd-mquat-base/src/main/jastadd/mquat.parser +++ b/jastadd-mquat-base/src/main/jastadd/mquat.parser @@ -215,10 +215,21 @@ ResourceTypeRef resource_type_ref = ; Resource resource = - RESOURCE name.n COLON resource_type_ref.r LB_CURLY RB_CURLY + RESOURCE name.n COLON resource_type_ref.r MULT INTEGER.amount LB_CURLY RB_CURLY + {: + return new MultiResource(n, r, new List<>(), new List<>(), Integer.parseInt(amount)); + :} + | 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 MULT INTEGER.amount LB_CURLY resource_body.b RB_CURLY + {: + b.setName(n); + b.setType(r); + b.setAmount(Integer.parseInt(amount)); + return b; + :} | RESOURCE name.n COLON resource_type_ref.r LB_CURLY resource_body.b RB_CURLY {: b.setName(n); @@ -227,11 +238,11 @@ Resource resource = :} ; -Resource resource_body = +MultiResource 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)); :} + | resource.r {: return new MultiResource(null, null, new List<>(r), new List<>(), 1); :} + | current_resource_value.v {: return new MultiResource(null, null, new List<>(), new List<>(v), 1); :} ; CurrentResourceValue current_resource_value = diff --git a/jastadd-mquat-base/src/main/jastadd/solution/Checking.jadd b/jastadd-mquat-base/src/main/jastadd/solution/Checking.jadd index 64e64e03d7c066fdd91c4ab9ea3cc21d6c78410b..0c8198f72614e821f01159b948af8d21fd322895 100644 --- a/jastadd-mquat-base/src/main/jastadd/solution/Checking.jadd +++ b/jastadd-mquat-base/src/main/jastadd/solution/Checking.jadd @@ -1,5 +1,6 @@ aspect Checking { public void Solution.explain() { + // TODO fix for multiresource Set<Request> requestSet = new HashSet<>(); Map<Resource, Assignment> resourceSet = new HashMap<>(); logger.info(this.toString()); diff --git a/jastadd-mquat-base/src/main/jastadd/solution/Checking.jrag b/jastadd-mquat-base/src/main/jastadd/solution/Checking.jrag index fc587981b331ad854188dec5f323404c1fc0b217..8f61ea35f395e316946c45a7ae8bd4f1b1448d41 100644 --- a/jastadd-mquat-base/src/main/jastadd/solution/Checking.jrag +++ b/jastadd-mquat-base/src/main/jastadd/solution/Checking.jrag @@ -2,7 +2,7 @@ aspect Checking { syn boolean Solution.isValid() { Set<Request> requestSet = new HashSet<>(); - Set<Resource> resourceSet = new HashSet<>(); + Map<Resource, Integer> resourceMap = new HashMap<>(); // check assignments Iterator<Assignment> assignmentIterator = this.assignmentIterator(); @@ -15,10 +15,12 @@ aspect Checking { assignment.getRequest().getTarget().getRef()) { requestSet.add(assignment.getRequest()); } - if (resourceSet.contains(assignment.getResource())) { + int num = resourceMap.getOrDefault(assignment.getResource(), 0); + resourceMap.put(assignment.getResource(), num + 1); + + if (resourceMap.get(assignment.getResource()) > assignment.getResource().amount()) { return false; } - resourceSet.add(assignment.getResource()); } } diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.ast b/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.ast new file mode 100644 index 0000000000000000000000000000000000000000..bfb583fe7c93bb574dd753f2a47f898b6489432c --- /dev/null +++ b/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.ast @@ -0,0 +1 @@ +MultiResource:Resource ::= <Amount:int> ; \ No newline at end of file diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.jrag b/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.jrag new file mode 100644 index 0000000000000000000000000000000000000000..5140d678e2efd0a3bf41c4129b3b3a789ff86d5e --- /dev/null +++ b/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.jrag @@ -0,0 +1,9 @@ +aspect AI { + + syn boolean Resource.isMultiResource() = false; + eq MultiResource.isMultiResource() = true; + + syn int Resource.amount() = 1; + eq MultiResource.amount() = getAmount(); + +} \ No newline at end of file diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jadd b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jadd index e95048cbe2ff84e63c3f43333f822fa287378aac..e0fb837955c81af237a0731565b9192d14efc22c 100644 --- a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jadd +++ b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jadd @@ -54,7 +54,7 @@ aspect ILP { IlpConstraint resourceConstraint = resourceConstraints.get(resource); if (resourceConstraint == null) { resourceConstraint = new IlpConstraint("one_on_" + resource.getIlpName(), new IlpLeftHandSide(), - ClauseComparator.LE, 1); + ClauseComparator.LE, resource.amount()); resourceConstraints.put(resource, resourceConstraint); } if (result == null) { 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 index 83a18ee3387257e996afb08f53cf56587b33f25d..c1d261693fa2b23d717626f62a1f9ed9fc0c946c 100644 --- 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 @@ -44,7 +44,7 @@ public class SimpleSolver implements BenchmarkableSolver { assignment.setResourceMapping(mapping); } - private int checkAssignment(Solution solution, List<Solution> solutions, List<Assignment> assignments, List<Set<Resource>> possibleResources, int index, Stack<Resource> usedResources) { + private int checkAssignment(Solution solution, List<Solution> solutions, List<Assignment> assignments, List<Set<Resource>> possibleResources, int index, Map<Resource, Integer> usedResources) { int checkCounter = 0; Assignment assignment = assignments.get(index); @@ -54,9 +54,12 @@ public class SimpleSolver implements BenchmarkableSolver { return checkCounter; } - if (usedResources.contains(resource)) continue; + int currentNumber = usedResources.getOrDefault(resource, 0); + + if (currentNumber >= resource.amount()) continue; + assignResource(assignment, resource); - usedResources.push(resource); + usedResources.put(resource, currentNumber + 1); checkCounter++; if (index == assignments.size() - 1) { if (solution.isValid()) { @@ -71,7 +74,7 @@ public class SimpleSolver implements BenchmarkableSolver { } else { checkCounter += checkAssignment(solution, solutions, assignments, possibleResources, index + 1, usedResources); } - usedResources.pop(); + usedResources.put(resource, currentNumber); } return checkCounter; } @@ -123,7 +126,7 @@ public class SimpleSolver implements BenchmarkableSolver { possibleResources.add(resourceList); } - numAssignments += checkAssignment(currentSolution, solutions, assignments, possibleResources, 0, new Stack<>()); + numAssignments += checkAssignment(currentSolution, solutions, assignments, possibleResources, 0, new HashMap<>()); } if (stopWatch.time(TimeUnit.MILLISECONDS) > maxSolvingTime) { 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 index b15bc10983ea3f192f24141216015ae80f7e32ca..a5b8874a5f080caaab4a961bde6df667dcc873e9 100644 --- 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 @@ -165,4 +165,13 @@ public abstract class HandwrittenTestSuite { modelAndSolution.getSecondElement().computeObjective(), 0.01); } + @Test + public void test_multi_01() throws IOException, Parser.Exception, SolvingException { + Tuple<Root, Solution> modelAndSolution = loadAndSolve("test_multi_01.txt"); + assertValidSolution(modelAndSolution); + Assignment config_0i0m0 = assertAssignment(modelAndSolution, 0, "config_0i0m0", "r0"); + Assignment config_1i0m0 = assertAssignment(modelAndSolution, 0, "config_1i0m0", "r0"); + assertComponentRequirement(config_0i0m0,"other", config_1i0m0); + } + } diff --git a/jastadd-mquat-solver/src/test/resources/test_multi_01.txt b/jastadd-mquat-solver/src/test/resources/test_multi_01.txt new file mode 100644 index 0000000000000000000000000000000000000000..6f410971fd1141902f4daa82127aeb58e4f041b8 --- /dev/null +++ b/jastadd-mquat-solver/src/test/resources/test_multi_01.txt @@ -0,0 +1,85 @@ +// 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 * 5 { + resource cpu0_0:CPU { + frequency = 2930 + load = 30 + } + flops = 293000 +} +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 for c0 { + meta size = 6 + requiring quality >= 35 +} +minimize sum(energy)