diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd b/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd index 6294668e9b8ef58b9a2fbfe811ff1e9dccb923c8..c5653a728f575d08c87b1f26f4807d96dde43695 100644 --- a/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd +++ b/jastadd-mquat-base/src/main/jastadd/solvers/Helpers.jadd @@ -15,6 +15,21 @@ aspect Helpers { return assignment; } + uncache Clause.simpleClusterAssignment(Request request, ResourceClass resource); + syn Assignment Clause.simpleClusterAssignment(Request request, ResourceClass resourceClass) { + Assignment assignment = new Assignment(); + assignment.setRequest(request); + Implementation impl = containingImplementation(); + if (impl != null) { + assignment.setImplementation(impl); + + ResourceClassMapping mapping = new ResourceClassMapping(impl.getResourceRequirement().getInstance(0),new List<>(),resourceClass); + // Resource.populateResourceMapping(mapping,impl.getResourceRequirement(),resource); + assignment.setResourceMapping(mapping); + } + return assignment; + } + public Solution Root.createRandomSolution(java.util.Random random) { diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ai/AbstractEval.jrag b/jastadd-mquat-base/src/main/jastadd/solvers/ai/AbstractEval.jrag new file mode 100644 index 0000000000000000000000000000000000000000..a8db7a5e8456d0b73b7897bc771b8f2a32d0d266 --- /dev/null +++ b/jastadd-mquat-base/src/main/jastadd/solvers/ai/AbstractEval.jrag @@ -0,0 +1,10 @@ +aspect eval { + + + uncache Clause.checkUsing(Request request, ResourceClass resourceClass); + syn boolean Clause.checkUsing(Request request, ResourceClass resourceClass) = checkUsing(simpleClusterAssignment(request, resourceClass)); + + uncache Clause.evalUsing(Request request, ResourceClass target); + syn double Clause.evalUsing(Request request, ResourceClass target) = evalUsing(simpleClusterAssignment(request, target)); + +} diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.jrag b/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.jrag index 9fd4c96c5f628bc9441303a40d8e35f8cf36d2f8..1beae7881ba65c5ce851ba0aafb8ad687f662bb2 100644 --- a/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.jrag +++ b/jastadd-mquat-base/src/main/jastadd/solvers/ai/ai.jrag @@ -6,8 +6,160 @@ aspect AI { syn int Resource.amount() = 1; eq MultiResource.amount() = getAmount(); + syn int ResourceClass.amount() { + int amount = 0; + for (ResourceRef ref : getResourceRefList()) { + amount += ref.getRef().amount(); + } + return amount; + } + + /** + * the non-terminal attribute to compute the abstract ILP subtree + */ syn ILP Root.getAbstractILP() { - return null; + de.tudresden.inf.st.mquat.utils.StopWatch stopWatch = de.tudresden.inf.st.mquat.utils.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 (ResourceClass resourceClass : this.getHardwareModel().getResourceClassList()) { + // r1#c2#i3#hw4 + IlpTerm term = new IlpTerm(); + IlpVariable var = info.getIlpVariable(request, impl, resourceClass); + term.setRef(var); + Optional<Clause> providingObjectiveClause = impl.findFirstProvidingClause(getObjective().getPropertyRef().getRef()); + if (providingObjectiveClause.isPresent()) { + term.setValue(providingObjectiveClause.get().evalUsing(request, resourceClass)); + } else { + term.setValue(0); + } + olhs.addIlpTerm(term); + oneImplLhs.addIlpTerm(new IlpTerm(1, var)); + } + 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 (ResourceClass resourceClass : this.getHardwareModel().getResourceClassList()) { + reqLhs.addIlpTerm(new IlpTerm(providingClause.evalUsing(request, resourceClass), + info.getIlpVariable(request, providingImpl, resourceClass))); + } + } + for (ResourceClass resourceClass : this.getHardwareModel().getResourceClassList()) { + // we always use negative eval-value to get the required value on the right side (literally) + reqLhs.addIlpTerm(new IlpTerm(makeNegative(reqClause.evalUsing(request, resourceClass)), + info.getIlpVariable(request, impl, resourceClass))); + } + // 2b. non-functional requirements of required components + 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 (ResourceClass resourceClass : this.getHardwareModel().getResourceClassList()) { + // check if constraint is fulfilled, otherwise remember this illegal combination + if (!reqClause.checkUsing(request, resourceClass)) { + info.getIlpVariable(request, impl, resourceClass).setIllegal(true); + } + } + } + } + + oneImplLhs.addIlpTerm(new IlpTerm(-1, info.getIlpVariable(request, impl))); + // implementation variable definition + result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_single_" + impl.getIlpName(), + oneImplLhs, ClauseComparator.EQ, 0)); + 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))); + // 1c. required components + result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_" + impl.getIlpName() + + "_req_" + req.getComponentRef().getRef().getIlpName(), + reqImplLhs, ClauseComparator.GE, 0)); + } + } + // 1b. + result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_opc_" + comp.getIlpName(), + oneCompLhs, ClauseComparator.LE, 1)); + } + IlpLeftHandSide targetLhs = new IlpLeftHandSide(); + for (Implementation impl : request.getTarget().getRef().getImplementationList()) { + IlpVariable var = info.getIlpVariable(request, impl); + targetLhs.addIlpTerm(new IlpTerm(1, var)); + } + // 1a. functional requirement of the request + result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_target", targetLhs, ClauseComparator.EQ, 1)); + for (Clause requiredClause : request.getConstraintList()) { + IlpLeftHandSide reqLhs = new IlpLeftHandSide(); + Property requiredProperty = requiredClause.getDesignator().asSoftwareDesignator().getPropertyRef().getRef(); + for(Implementation impl : request.getTarget().getRef().getImplementationList()) { + for (ResourceClass resourceClass : this.getHardwareModel().getResourceClassList()) { + Optional<Clause> providingClause = impl.findFirstProvidingClause(requiredProperty); + if (providingClause.isPresent()) { + IlpVariable var = info.getIlpVariable(request, impl, resourceClass); + reqLhs.addIlpTerm(new IlpTerm(providingClause.get().evalUsing(request, resourceClass), var)); + } + } + } + // 2a. non-functional requirement of the request + result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_req_" + requiredProperty.getIlpName(), + reqLhs, requiredClause.getClauseComparator(), + requiredClause.evalUsing(request, (ResourceClass) 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()) { + // 1d. + result.addIlpConstraint(constraint); + } + + // variables + for (IlpVariable var : info.vars.values()) { + result.addIlpVariable(var); + } + + return result; } } \ 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 index fc06d7cdc801f2c9df118794b1e6bae890832813..7384d30650b85946e076626dcc6d309c36373621 100644 --- a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.ast +++ b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.ast @@ -9,6 +9,7 @@ IlpConstraint ::= <Name:String> IlpLeftHandSide <ClauseComparator:ClauseComparat abstract IlpVariable ::= <Name:String> <Request:Request> <Impl:Implementation> <Illegal:boolean>; IlpAllResourcesVariable:IlpVariable ; IlpMappingVariable:IlpVariable ::= <Resource:Resource> ; +IlpClassMappingVariable:IlpVariable ::= <ResourceClass:ResourceClass> ; // sum of terms IlpLeftHandSide ::= IlpTerm* ; 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 e0fb837955c81af237a0731565b9192d14efc22c..eb19a31f697b56813e36a3b7cdc1c50c50620d02 100644 --- a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jadd +++ b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jadd @@ -42,10 +42,12 @@ aspect ILP { public class IlpVarInfo { public java.util.Map<String, IlpVariable> vars; public java.util.Map<Resource, IlpConstraint> resourceConstraints; + public java.util.Map<ResourceClass, IlpConstraint> resourceClassConstraints; public IlpVarInfo() { vars = new java.util.TreeMap<>(); resourceConstraints = new java.util.HashMap<>(); + resourceClassConstraints = new java.util.HashMap<>(); } public IlpVariable getIlpVariable(Request request, Implementation impl, Resource resource) { @@ -65,6 +67,23 @@ aspect ILP { return result; } + public IlpVariable getIlpVariable(Request request, Implementation impl, ResourceClass resourceClass) { + String varName = request.getIlpName() + "#" + impl.getIlpName() + "#" + resourceClass.getIlpName(); + IlpVariable result = vars.get(varName); + IlpConstraint resourceClassConstraint = resourceClassConstraints.get(resourceClass); + if (resourceClassConstraint == null) { + resourceClassConstraint = new IlpConstraint("one_on_" + resourceClass.getIlpName(), new IlpLeftHandSide(), + ClauseComparator.LE, resourceClass.amount()); + resourceClassConstraints.put(resourceClass, resourceClassConstraint); + } + if (result == null) { + result = new IlpClassMappingVariable(varName, request, impl, false, resourceClass); + vars.put(varName, result); + resourceClassConstraint.getIlpLeftHandSide().addIlpTerm(new IlpTerm(1, result)); + } + return result; + } + public IlpVariable getIlpVariable(Request request, Implementation impl) { String varName = request.getIlpName() + "#" + impl.getIlpName(); IlpVariable result = vars.get(varName); diff --git a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jrag b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jrag index f8d8c9898ac066aca6cdb3f4511f307956ff839a..951aa253efbd97cce1bfe1a2c9183fd0d0e2156b 100644 --- a/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jrag +++ b/jastadd-mquat-base/src/main/jastadd/solvers/ilp/ILP.jrag @@ -159,7 +159,7 @@ aspect ILP { // 2a. non-functional requirement of the request result.addIlpConstraint(new IlpConstraint(request.getIlpName() + "_req_" + requiredProperty.getIlpName(), reqLhs, requiredClause.getClauseComparator(), - requiredClause.evalUsing(request, null))); + requiredClause.evalUsing(request, (Resource) null))); } } if (stopWatch.time() > timeoutNanos) { diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/clustering/HardwareComponent.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/clustering/HardwareComponent.java index 5f334aafebf7769a311fffff28899a9e13ab04a9..4e9e2e52773a0b8e05242b65baa855ed74da3d1c 100644 --- a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/clustering/HardwareComponent.java +++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/clustering/HardwareComponent.java @@ -9,27 +9,27 @@ import weka.core.Instance; */ public class HardwareComponent { - private Resource resource; - private Instance instance; + private Resource resource; + private Instance instance; - public HardwareComponent(Resource resource, int attributes_number) { - this.resource = resource; - this.instance = new DenseInstance(attributes_number); - } + public HardwareComponent(Resource resource, int attributes_number) { + this.resource = resource; + this.instance = new DenseInstance(attributes_number); + } - public Resource getResource() { - return resource; - } + public Resource getResource() { + return resource; + } - public void setResource(Resource resource) { - this.resource = resource; - } + public void setResource(Resource resource) { + this.resource = resource; + } - public Instance getInstance() { - return instance; - } + public Instance getInstance() { + return instance; + } - public void setInstance(Instance instance) { - this.instance = instance; - } + public void setInstance(Instance instance) { + this.instance = instance; + } } diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/clustering/KMeans.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/clustering/KMeans.java index 04ea64d311d9ef28b6a7bb9e4017636ecf6c6a59..59a7a8c74d683b9f4a6ea018f07202f2d208f737 100644 --- a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/clustering/KMeans.java +++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/clustering/KMeans.java @@ -1,8 +1,11 @@ package de.tudresden.inf.st.mquat.solving.clustering; import de.tudresden.inf.st.mquat.jastadd.model.Resource; +import de.tudresden.inf.st.mquat.jastadd.model.ResourceType; import de.tudresden.inf.st.mquat.jastadd.model.Root; -import weka.clusterers.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import weka.clusterers.SimpleKMeans; import weka.core.Attribute; import weka.core.Instances; @@ -20,87 +23,120 @@ import java.util.Map; * @author Dmytro Pukhkaiev * @version 0.1 */ -public class KMeans{ - // dataset - private Instances resources; - // number of clusters - private int k; - // list of resources - private ArrayList<HardwareComponent> hardwareComponentList = new ArrayList<>(); - - public KMeans(Root model) { - // create attributes for instances - Attribute cpu = new Attribute("cpu"); - Attribute ram = new Attribute("ram"); - Attribute disk = new Attribute("disk"); - Attribute network = new Attribute("network"); - ArrayList<Attribute> attributeList = new ArrayList<Attribute>(); - attributeList.add(cpu); - attributeList.add(ram); - attributeList.add(disk); - attributeList.add(network); - - // create a dataset - resources = new Instances("resources", attributeList, 0); - - //instantiate items in the dataset - for (Resource resource : model.getHardwareModel().getResourceList()) { - if (resource.getType().getName().getName().equals("ComputeNode")) { - HardwareComponent hardwareComponent = new HardwareComponent(resource, resource.getNumSubResource()); - hardwareComponent.getInstance().setDataset(resources); - - for (Resource sub : resource.getSubResourceList()) { - String typeName = sub.getType().getName().getName(); - switch (typeName) { - case "CPU": - hardwareComponent.getInstance().setValue(cpu, sub.getCurrentValueByPropertyName("frequency")); - break; - case "RAM": - hardwareComponent.getInstance().setValue(ram, sub.getCurrentValueByPropertyName("total")); - break; - case "DISK": - hardwareComponent.getInstance().setValue(disk, sub.getCurrentValueByPropertyName("total")); - break; - case "NETWORK": - hardwareComponent.getInstance().setValue(network, sub.getCurrentValueByPropertyName("throughput")); - break; - default: - throw new RuntimeException("Unable to transform unknown resource of type" + typeName); - } - } - - hardwareComponentList.add(hardwareComponent); - } +public class KMeans { + private static final Logger logger = LogManager.getLogger(KMeans.class); + + // dataset + private Instances resources; + + // the model + private Root model; + + // list of resources + private ArrayList<HardwareComponent> hardwareComponentList = new ArrayList<>(); + + public KMeans(Root model) { + + this.model = model; + + // create attributes for instances + Attribute cpu = new Attribute("cpu"); + Attribute ram = new Attribute("ram"); + Attribute disk = new Attribute("disk"); + Attribute network = new Attribute("network"); + + ArrayList<Attribute> attributeList = new ArrayList<>(); + + // we expect one top-level resource type and consider at most four sub-resources of the following names + for (ResourceType resourceType : model.getHardwareModel().getResourceType(0).getSubTypeList()) { + switch (resourceType.name().toLowerCase()) { + case "cpu": + attributeList.add(cpu); + break; + case "ram": + attributeList.add(ram); + break; + case "disk": + attributeList.add(disk); + break; + case "network": + attributeList.add(network); + } + } + + // create a dataset + resources = new Instances("resources", attributeList, 0); + + //instantiate items in the dataset + for (Resource resource : model.getHardwareModel().getResourceList()) { + if (resource.getType().getName().getName().equals("ComputeNode")) { + HardwareComponent hardwareComponent = new HardwareComponent(resource, resource.getNumSubResource()); + hardwareComponent.getInstance().setDataset(resources); + + for (Resource sub : resource.getSubResourceList()) { + String typeName = sub.getType().getName().getName(); + switch (typeName) { + case "CPU": + hardwareComponent.getInstance().setValue(cpu, sub.getCurrentValueByPropertyName("frequency")); + break; + case "RAM": + hardwareComponent.getInstance().setValue(ram, sub.getCurrentValueByPropertyName("total")); + break; + case "DISK": + hardwareComponent.getInstance().setValue(disk, sub.getCurrentValueByPropertyName("total")); + break; + case "NETWORK": + hardwareComponent.getInstance().setValue(network, sub.getCurrentValueByPropertyName("throughput")); + break; + default: + throw new RuntimeException("Unable to transform unknown resource of type" + typeName); + } } - for (HardwareComponent hwc : hardwareComponentList) - resources.add(hwc.getInstance()); + hardwareComponentList.add(hardwareComponent); + } + } + + for (HardwareComponent hwc : hardwareComponentList) + resources.add(hwc.getInstance()); + + } - k = (int) (0.2 * model.getHardwareModel().getResourceList().asJavaCollection().size()); + public Map<Integer, ArrayList<Resource>> buildClusters(int numClusters) { + if (numClusters < 1) { + logger.error("Unable to cluster the model in less than one cluster (numClusters was " + numClusters + ")"); + throw new RuntimeException(); } - public Map<Integer, ArrayList<Resource>> buildClusters(){ + logger.info("Clustering " + model.getHardwareModel().getNumResource() + " resources in " + numClusters + " clusters"); - SimpleKMeans algorithm = new SimpleKMeans(); - Map<Integer, ArrayList<Resource>> Clusters = new HashMap<>(); + SimpleKMeans algorithm = new SimpleKMeans(); + Map<Integer, ArrayList<Resource>> Clusters = new HashMap<>(); - for (int i = 0; i < k; i ++) - Clusters.put(i, new ArrayList<>()); - try { - algorithm.setNumClusters(k); - algorithm.setPreserveInstancesOrder(true); - algorithm.buildClusterer(resources); + for (int i = 0; i < numClusters; i++) + Clusters.put(i, new ArrayList<>()); + try { + algorithm.setNumClusters(numClusters); + algorithm.setPreserveInstancesOrder(true); + algorithm.buildClusterer(resources); - int[] assignments = algorithm.getAssignments(); + int[] assignments = algorithm.getAssignments(); - for (int i = 0; i < assignments.length; i++){ - Clusters.get(assignments[i]).add(hardwareComponentList.get(i).getResource()); - } + for (int i = 0; i < assignments.length; i++) { + Clusters.get(assignments[i]).add(hardwareComponentList.get(i).getResource()); + } - } catch (Exception e) { - e.printStackTrace(); - } - return Clusters; + } catch (Exception e) { + e.printStackTrace(); + } + + // print cluster statistics + logger.info("Clusters:"); + for (int c = 0; c < numClusters; c++) { + logger.info("Cluster " + c + ": " + Clusters.get(c).size() + " resources"); } + + return Clusters; + } } 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 index 59cb830d2a2f5a6f23064c40c7a89e030243e4ee..b7d0e40b132c627aae0d3686573b74855dcb0741 100644 --- 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 @@ -61,6 +61,8 @@ public abstract class AbstractILPSolver implements BenchmarkableSolver { public synchronized Solution solve(Root model) throws SolvingException { StopWatch watch = StopWatch.start(); + transformer.prepareModel(model); + reset(); if (model.getNumRequest() == 0) { return Solution.emptySolutionOf(model); diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/AbstractILPTransformer.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/AbstractILPTransformer.java index 46049ad706d86c213b09774842a086b1986803f0..08d99277def6195a90d45599a52d7be10148de37 100644 --- a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/AbstractILPTransformer.java +++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/AbstractILPTransformer.java @@ -1,7 +1,10 @@ package de.tudresden.inf.st.mquat.solving.ilp; -import de.tudresden.inf.st.mquat.jastadd.model.ILP; -import de.tudresden.inf.st.mquat.jastadd.model.Root; +import de.tudresden.inf.st.mquat.jastadd.model.*; +import de.tudresden.inf.st.mquat.solving.clustering.KMeans; + +import java.util.ArrayList; +import java.util.Map; public class AbstractILPTransformer implements ILPTransformer { @@ -15,5 +18,24 @@ public class AbstractILPTransformer implements ILPTransformer { return "-abstract"; } + @Override + public void prepareModel(Root model) { + int numClusters = Math.max(2,model.getHardwareModel().getNumResource()/5); + KMeans kmeans = new KMeans(model); + + Map<Integer, ArrayList<Resource>> clusters = kmeans.buildClusters(numClusters); + + for (int clusterId : clusters.keySet()) { + + ResourceClass resourceClass = new ResourceClass(); + resourceClass.setName(new Name("class_" + clusterId)); + + for (Resource resource : clusters.get(clusterId)) { + resource.setResourceClassRef(resourceClass.createRef()); + resourceClass.addResourceRef(resource.createRef()); + } + } + } + } diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ConcreteILPTransformer.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ConcreteILPTransformer.java index 0ba3cfc5c983d6483c97926e640d877cf29aa5f4..eacb97c2006d5caba745896b89299d3deae3c95f 100644 --- a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ConcreteILPTransformer.java +++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ConcreteILPTransformer.java @@ -14,4 +14,9 @@ public class ConcreteILPTransformer implements ILPTransformer { public String getSuffix() { return ""; } + + @Override + public void prepareModel(Root model) { + // do nothing + } } 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 index cb99848e7a313b5abc14df936495e46eb3fbac74..70e621a8542ac03b574e662cedec02e6075528ab 100644 --- 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 @@ -91,7 +91,7 @@ public class ILPMain { ScenarioGenerator gen = new ScenarioGenerator(new ScenarioDescription(1, 2, 0, 0, 0, 2, 2, 2.5, 3, 1, 0)); Root model = gen.generate(); KMeans kMeans = new KMeans(model); - Map<Integer, ArrayList<Resource>> clusters = kMeans.buildClusters(); + Map<Integer, ArrayList<Resource>> clusters = kMeans.buildClusters(model.getHardwareModel().getNumResource()/5); Solver external = new GLPKSolver().setDeleteFilesOnExit(false); Solution solution = external.solve(model); logger.info(model.print(new MquatWriteSettings(" "))); diff --git a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPTransformer.java b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPTransformer.java index 8c75aeedcb4ff25d02a527dc049678bf26c5caf3..da5a1a703ccac6a6df6dcac2edf933de8fd8c1a1 100644 --- a/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPTransformer.java +++ b/jastadd-mquat-solver-ilp/src/main/java/de/tudresden/inf/st/mquat/solving/ilp/ILPTransformer.java @@ -7,4 +7,6 @@ public interface ILPTransformer { ILP getILP(Root model); String getSuffix(); + + void prepareModel(Root model); }