Skip to content
Snippets Groups Projects
Commit bd0c5096 authored by Johannes Mey's avatar Johannes Mey
Browse files

fixed KMeans for test cases, prepared eval functions for clusters

parent 57a74af8
Branches
No related tags found
No related merge requests found
Showing
with 359 additions and 95 deletions
......@@ -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) {
......
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));
}
......@@ -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
......@@ -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* ;
......
......@@ -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);
......
......@@ -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) {
......
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;
......@@ -21,24 +24,45 @@ import java.util.Map;
* @version 0.1
*/
public class KMeans {
private static final Logger logger = LogManager.getLogger(KMeans.class);
// dataset
private Instances resources;
// number of clusters
private int k;
// 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<Attribute>();
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);
......@@ -76,19 +100,24 @@ public class KMeans{
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<>();
for (int i = 0; i < k; i ++)
for (int i = 0; i < numClusters; i++)
Clusters.put(i, new ArrayList<>());
try {
algorithm.setNumClusters(k);
algorithm.setNumClusters(numClusters);
algorithm.setPreserveInstancesOrder(true);
algorithm.buildClusterer(resources);
......@@ -101,6 +130,13 @@ public class KMeans{
} 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;
}
}
......@@ -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);
......
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());
}
}
}
}
......@@ -14,4 +14,9 @@ public class ConcreteILPTransformer implements ILPTransformer {
public String getSuffix() {
return "";
}
@Override
public void prepareModel(Root model) {
// do nothing
}
}
......@@ -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(" ")));
......
......@@ -7,4 +7,6 @@ public interface ILPTransformer {
ILP getILP(Root model);
String getSuffix();
void prepareModel(Root model);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment