package com.chkris.service;
import com.chkris.ant.model.AntAlgorithmSettings;
import com.chkris.ant.model.Ant;
import graph.Graph;
import graph.model.Edge;
import graph.model.Vertex;
import java.util.*;
public class AntDecisionAlgorithm {
private List<Ant> antList = new ArrayList<>();
private AntAlgorithmSettings antAlgorithmSettings;
public AntDecisionAlgorithm(AntAlgorithmSettings antAlgorithmSettings) {
this.antAlgorithmSettings = antAlgorithmSettings;
}
public double p(Vertex startVertex, Vertex endVertex, Graph graph, Ant ant) {
double sum = 0;
for(Edge edge : getNotVisitedEdgesByAnt(graph, startVertex, ant)) {
sum += d(edge);
}
Edge edge = graph.getEdgeBetweenToVertices(startVertex, endVertex);
return d(edge) / sum;
}
public double d(Edge edge) {
return Math.pow(edge.getPheromone(), antAlgorithmSettings.getAlpha()) * Math.pow((1 / (double) edge.getWeight()), antAlgorithmSettings.getBeta());
}
public Vertex chosePath(Vertex iVertex, Graph graph, Ant ant) {
TreeMap<Double, Vertex> prob = new TreeMap<>();
for (Edge edge : getNotVisitedEdgesByAnt(graph, iVertex, ant)) {
double pp = p(iVertex, edge.getSource(), graph, ant);
prob.put(pp, edge.getSource());
}
return prob.firstEntry().getValue();
}
public List<Edge> getNotVisitedEdgesByAnt(Graph graph, Vertex vertex, Ant ant) {
List<Edge> notVisitedEdges = new ArrayList<>();
for (Edge edge : graph.getEdgesPointingToVertex(vertex)) {
if (! ant.getListOfVisitedVertices().contains(edge.getSource())) {
notVisitedEdges.add(edge);
}
}
return notVisitedEdges;
}
public void sendAnt(Graph graph, Ant ant) {
Vertex startingVertex = graph.getRandomVertex();
int numberOfVertices = graph.getVertices().size();
List<Vertex> visitedVertex = null;
int size = 0;
while (size + 1 < numberOfVertices) {
Vertex chosenVertex = chosePath(startingVertex, graph, ant);
ant.addVisitedVertex(startingVertex);
ant.addToTour(graph.getEdgeBetweenToVertices(startingVertex, chosenVertex).getWeight());
ant.addEdge(graph.getEdgeBetweenToVertices(startingVertex, chosenVertex));
startingVertex = chosenVertex;
visitedVertex = ant.getListOfVisitedVertices();
size = visitedVertex.size();
}
}
public void sentAllAnts(Graph graph) {
for(int i=0; i < antAlgorithmSettings.getMaximalNumberOfAnts(); i++) {
antList.add(new Ant());
}
for (Ant ant : antList) {
sendAnt(graph, ant);
pheromoneEvaporation(graph, ant);
}
}
public void pheromoneEvaporation(Graph graph, Ant ant) {
for (Edge edge : ant.getEdges()) {
double coef = antAlgorithmSettings.getEvaporationCoefficient();
graph.getEdgeBetweenToVertices(edge.getSource(), edge.getDestination()).setPheromone((1 - coef) * graph.getEdgeBetweenToVertices(edge.getSource(), edge.getDestination()).getPheromone() + updatePheromone(graph.getEdgeBetweenToVertices(edge.getSource(), edge.getDestination())));
graph.getEdgeBetweenToVertices(edge.getDestination(), edge.getSource()).setPheromone((1 - coef) * graph.getEdgeBetweenToVertices(edge.getDestination(), edge.getSource()).getPheromone() + updatePheromone(graph.getEdgeBetweenToVertices(edge.getSource(), edge.getDestination())));
}
}
public double updatePheromone() {
double sum = 0;
for (Ant ant : antList) {
if (ant.getTour() > 0) {
sum += 1/(double)ant.getTour();
}
}
return sum;
}
public double updatePheromone(Edge edge) {
return 1 / edge.getWeight();
}
}