Commit 2ecd7c2b authored by René Schöne's avatar René Schöne
Browse files

Added ACO solution from https://github.com/Ariyanic/TTC18

parent d72f50dc
......@@ -12,6 +12,7 @@ repositories {
dependencies {
compile project(':jastadd-mquat-base')
compile project(':jastadd-mquat-solver')
compile project(':jastadd-mquat-solver-aco')
compile project(':jastadd-mquat-solver-ilp')
compile project(':jastadd-mquat-solver-emfer')
compile project(':jastadd-mquat-solver-simple')
......
......@@ -4,6 +4,7 @@ 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 ir.ac.ui.eng.ACOSolver;
import uniks.EMFeRSolver;
import java.util.Map;
......@@ -23,6 +24,7 @@ public class SolverFactory {
private static Map<String, BenchmarkableSolver> createAvailableSolversIfNeeded() {
if (availableSolvers == null) {
availableSolvers = Stream.of(
new ACOSolver(),
new EMFeRSolver(),
new ILPExternalSolver(),
new ILPDirectSolver(),
......
......@@ -2,9 +2,10 @@
"path": "results",
"logLevel": "info",
"solvers": [
"aco",
"emfer",
"ilp-direct",
// "ilp-external",
"emfer",
"simple"
],
"timeoutValue": 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')
compile project(':jastadd-mquat-solver')
testCompile project(path: ':jastadd-mquat-solver', configuration: 'testArtifacts')
}
package ir.ac.ui.eng;
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.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
/**
* @author Samaneh Hoseindoost
* @author Meysan Karimi
* @author Shekoufeh Kolahdouz-Rahimi
* @author Bahman Zamani
*/
public class ACOSolver implements BenchmarkableSolver {
int population_size = 100000;
int iteration_size = 20;
private static final Logger logger = LogManager.getLogger(ACOSolver.class);
private Solution lastSolution;
private long lastSolvingTime;
private int solutionCounter;
private long maxSolvingTime;
private StopWatch stopWatch;
private boolean timedOut;
int numAssignments = 0;
public ACOSolver() {
this(Long.MAX_VALUE);
}
public ACOSolver(long maxSolvingTime) {
this.maxSolvingTime = maxSolvingTime;
reset();
}
public Assignment ACOCreateSoftwareAssignment(Request request, Component component, boolean topLevel, int i) {
Assignment assignment = new Assignment();
assignment.setRequest(request);
assignment.setTopLevel(topLevel);
Implementation implementation = component.getImplementation(i);
assignment.setImplementation(implementation);
for (ComponentRequirement requirement : implementation.getComponentRequirementList()) {
for (Instance instance : requirement.getInstanceList()) {
int rangeMin = 0;
int rangeMax = requirement.getComponentRef().getRef().getImplementationList().getNumChild();
Assignment ass = null;
do{
int randomNum = ThreadLocalRandom.current().nextInt(rangeMin, rangeMax);
ass = ACOCreateSoftwareAssignment(request, requirement.getComponentRef().getRef(), false, randomNum);
}while(!ass.isSoftwareValid());
assignment.addComponentMapping(new ComponentMapping(instance, ass));
}
}
for (Instance instance : implementation.getResourceRequirement().getInstanceList()) {
assignment.setResourceMapping(new ResourceMapping(instance, null, new de.tudresden.inf.st.mquat.jastadd.model.List<>()));
}
return assignment;
}
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);
}
@Override
public Solution solve(Root model) throws SolvingException {
reset();
if (model.getNumRequest() == 0) {
return Solution.emptySolutionOf(model);
}
int numSoftwareSolutions = 0;
int numTotalSoftwareSolutions = 0;
stopWatch = StopWatch.start();
List<Solution> solutions = new ArrayList<>();
List<Solution> currentSolutions = new ArrayList<>();
List<List<Set<Resource>>> currentPossibleResources = new ArrayList<>();
List<List<List<Double>>> currentTau = new ArrayList<>(); // Pheromone for each resources
List<List<List<Double>>> currentEta = new ArrayList<>(); // Objective for each resources
List<List<Double>> currentDenominatorP = new ArrayList<>();
List<List<List<Double>>> currentNumeratorP = new ArrayList<>();
List<Map<Integer, List<Integer>>> currentSort = new ArrayList<>();
for (int pop = 0; pop < population_size; pop++) {
System.out.println("pop: " + pop);
Solution currentSolution = new Solution();
currentSolution.setModel(model);
de.tudresden.inf.st.mquat.jastadd.model.List<Request> requests = model.getRequests();
for(Request request: requests){
int rangeMin = 0;
int rangeMax = request.getTarget().getRef().getImplementationList().getNumChild();
Assignment ass = null;
do{
int randomNum = ThreadLocalRandom.current().nextInt(rangeMin, rangeMax);
ass = ACOCreateSoftwareAssignment(request, request.getTarget().getRef(), true, randomNum);
}while(!ass.isSoftwareValid());
currentSolution.addAssignment(ass);
}
de.tudresden.inf.st.mquat.jastadd.model.List<Resource> resources = model.getHardwareModel().getResources();
numTotalSoftwareSolutions++;
List<Assignment> assignments = currentSolution.allAssignments();
List<Set<Resource>> possibleResources = new ArrayList<>(assignments.size());
boolean isHardwareValid = true;
double tau0 = 1;
List<List<Double>> tau = new ArrayList<>(); // Pheromone for each resources
List<List<Double>> eta = new ArrayList<>(); // Objective
double alpha = 1;
double beta = 1;
List<List<Double>> numeratorP = new ArrayList<>(); // soorate Probability
List<Double> denominatorP = new ArrayList<>(); // makhraje Probability
Map<Integer, List<Integer>> SortIndexByPossibleResource = new HashMap<>();
int index = 0;
for (Assignment assignment : assignments) {
Set<Resource> resourceList = new HashSet<>();
List<Double> taui = new ArrayList<>();
List<Double> etai = new ArrayList<>();
List<Double> numeratorPi = new ArrayList<>();
double sum = 0;
int i = 0;
for (Resource resource : resources) {
assignResource(assignment, resource);
if (assignment.isValid()) {
resourceList.add(resource);
taui.add(tau0); // Pheromone on antSolution.allAssignments().allResources;
etai.add(1 / assignment.computeObjective());
numeratorPi.add((taui.get(i) * alpha) + (etai.get(i) * beta));
sum += numeratorPi.get(i);
i++;
}
}
if(i == 0){
isHardwareValid = false;
break;
}
possibleResources.add(resourceList);
tau.add(taui);
eta.add(etai);
numeratorP.add(numeratorPi);
denominatorP.add(sum);
SortIndexByPossibleResource.computeIfAbsent(i, k -> new ArrayList<>()).add(index);
index++;
}
if(isHardwareValid == true){
numSoftwareSolutions++;
System.out.println("valid:" + numSoftwareSolutions);
Solution clone = currentSolution.deepCopy();
currentSolutions.add(clone);
currentPossibleResources.add(possibleResources);
currentTau.add(tau);
currentEta.add(eta);
currentNumeratorP.add(numeratorP);
currentDenominatorP.add(denominatorP);
currentSort.add(SortIndexByPossibleResource);
}
}
for (int iteration = 0; iteration < iteration_size; iteration++) {
List<Ant> population = new ArrayList<>();
for (int i = 0; i < currentSolutions.size(); i++) {
Ant ant = new Ant(i, currentSolutions.get(i), currentPossibleResources.get(i), currentEta.get(i), currentSort.get(i), numAssignments);
population.add(ant);
}
Parallel.ForEach(population, new LoopBody<Ant>() {
@Override
public void run(Ant ant) {
int ant_Number = ant.id;
List<List<Double>> tau = currentTau.get(ant_Number); ///////////// BEFORE RUN
List<List<Double>> numeratorP = currentNumeratorP.get(ant_Number);
List<Double> denominatorP = currentDenominatorP.get(ant_Number);
Solution antSolution = ant.run(tau, numeratorP, denominatorP); //////////// Tau CHANGE AFTER RUN.
if (antSolution != null) {
currentTau.set(ant_Number, tau); ///////////// AFTER RUN
currentNumeratorP.set(ant_Number, numeratorP);
currentDenominatorP.set(ant_Number, denominatorP);
numAssignments += ant.numAssignments;
solutionCounter++;
if (solutions.isEmpty() || antSolution.computeObjective() < solutions
.get(solutions.size() - 1).computeObjective()) {
Solution clone = antSolution.deepCopy();
solutions.add(clone);
logger.info("found a better solution with an objective of {}.",
antSolution.computeObjective());
}
}
ant = null;
}
});
population = null;
System.gc();
}
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 "aco";
}
@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;
}
}
package ir.ac.ui.eng;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Stack;
import de.tudresden.inf.st.mquat.jastadd.model.Assignment;
import de.tudresden.inf.st.mquat.jastadd.model.Implementation;
import de.tudresden.inf.st.mquat.jastadd.model.Resource;
import de.tudresden.inf.st.mquat.jastadd.model.ResourceMapping;
import de.tudresden.inf.st.mquat.jastadd.model.Solution;
import de.tudresden.inf.st.mquat.solving.SolverUtils;
/**
* @author Samaneh Hoseindoost
* @author Meysan Karimi
* @author Shekoufeh Kolahdouz-Rahimi
* @author Bahman Zamani
*/
public class Ant {
int id;
Solution currentSolution;
List<Set<Resource>> possibleResources;
List<List<Double>> eta;
Map<Integer, List<Integer>> Sort;
int numAssignments;
Ant(int i, Solution solu, List<Set<Resource>> pr, List<List<Double>> et, Map<Integer, List<Integer>> Sr, int a) {
id = i;
currentSolution = solu;
possibleResources = pr;
eta = et;
Sort = Sr;
numAssignments = a;
}
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);
}
public int RoleteWhileSelection(double[] c) {
double rangeMin = 0.0f;
double rangeMax = c[c.length-1];
Random r = new Random();
double createdRanNum = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
int i;
for (i = 0; i < c.length-1; i++) {
if (createdRanNum <= c[i + 1])
break;
}
return i;
}
public Solution run(List<List<Double>> tau, List<List<Double>> numeratorP, List<Double> denominatorP) {
List<Assignment> assignments = currentSolution.allAssignments();
Stack<Resource> usedResources = new Stack<>();
double alpha = 1;
double beta = 1;
double rho = 0.1; // Evaporation rate
double Q = 2;
List<Integer> keys = new ArrayList<Integer>(Sort.keySet());
Collections.sort(keys); // "keys" are number of possible resources
// "values" are index of the assignments
for (Integer key: keys) {
int siz = Sort.get(key).size();
for (int i = 0; i < siz; i++) {
int index = Sort.get(key).get(i);
Assignment assignment = assignments.get(index);
List<Resource> resources = new ArrayList<Resource>(possibleResources.get(index));
/*
System.out.print("Ant_" + id + " ");
System.out.print("assignment " + assignment.name() + " ");
System.out.print("possible resources: " + resources.size() + " ");
for (int j = 0; j < resources.size(); j++) {
System.out.println("po: " + resources.get(j).getName());
}
*/
int remove = 0;
for (Iterator<Resource> resIt = resources.iterator(); resIt.hasNext();) {
Resource resource = resIt.next();
if (usedResources.contains(resource)) {
remove++;
}
}
if (resources.size() == remove) {
return null;
}
List<Double> numerator = numeratorP.get(index);
double denominator = denominatorP.get(index);
int size = resources.size();
double[] p = new double[size];
double[] c = new double[size + 1];
c[0] = 0;
for(int j=0; j<size; j++ ){
p[j] = numerator.get(j)/denominator;
c[j + 1] = c[j] + p[j];
}
int select = RoleteWhileSelection(c);
Resource resource = resources.get(select);
while (usedResources.contains(resource)) {
select = RoleteWhileSelection(c);
resource = resources.get(select);
}
// System.out.println("selected resource: " + resource.getName());
assignResource(assignment, resource);
usedResources.push(resource);
denominatorP.set(index, denominatorP.get(index) - numeratorP.get(index).get(select));
// tau[index][select] = tau[index][select] + (Q /assignment.computeObjective());
// tau[index][select] = (1 - rho) * tau[index][select];
List<Double> taui = tau.get(index);
// Upadte Pheromone
taui.set(select, taui.get(select) + (Q / assignment.computeObjective()));
// Evaporation on Pheromone of antSolution.allAssignments();
taui.set(select, (1 - rho) * taui.get(select));
tau.set(index, taui);
// p[index][select] = (tau[index][select] * alpha) + (eta[index][select] * beta);
List<Double> sIndex = numeratorP.get(index);
sIndex.set(select, (tau.get(index).get(select) * alpha) + (eta.get(index).get(select) * beta));
numeratorP.set(index, sIndex);
denominatorP.set(index, denominatorP.get(index) + numeratorP.get(index).get(select));
}
}
numAssignments++;
return currentSolution;
}
}
package ir.ac.ui.eng;
/**
* @author Samaneh Hoseindoost
* @author Meysan Karimi
* @author Shekoufeh Kolahdouz-Rahimi
* @author Bahman Zamani
*/
public interface LoopBody <T>
{
void run(T i);
}
package ir.ac.ui.eng;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @author Samaneh Hoseindoost
* @author Meysan Karimi
* @author Shekoufeh Kolahdouz-Rahimi
* @author Bahman Zamani
*/
public class Parallel {
static final int iCPU = Runtime.getRuntime().availableProcessors();
public static <T> void ForEach(Iterable<T> parameters, final LoopBody<T> loopBody) {
ExecutorService executor = Executors.newFixedThreadPool(iCPU);
List<Future<?>> futures = new LinkedList<Future<?>>();
for (final T param : parameters) {
Future<?> future = executor.submit(new Runnable() {
public void run() {
loopBody.run(param);
}
});
futures.add(future);
}
for (Future<?> f : futures) {
try {
f.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
}
executor.shutdown();
}
public static void For(int start, int stop, final LoopBody<Integer> loopBody) {
ExecutorService executor = Executors.newFixedThreadPool(iCPU);
List<Future<?>> futures = new LinkedList<Future<?>>();
for (int i = start; i < stop; i++) {
final Integer k = i;
Future<?> future = executor.submit(new Runnable() {
public void run() {
loopBody.run(k);
}
});
futures.add(future);
}
for (Future<?> f : futures) {