|
|
@@ -0,0 +1,153 @@
|
|
|
+package com.deliveryproject.easydelivery;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Random;
|
|
|
+
|
|
|
+public class AntColony {
|
|
|
+
|
|
|
+ private int numStops;
|
|
|
+ private int numAnts;
|
|
|
+ private double alpha;
|
|
|
+ private double beta;
|
|
|
+ private double evaporationRate;
|
|
|
+ private double initialPheromone;
|
|
|
+
|
|
|
+ private double[][] pheromoneMatrix;
|
|
|
+ private double[][] distanceMatrix;
|
|
|
+
|
|
|
+ private List<Integer> bestSolution;
|
|
|
+ private double bestSolutionDistance;
|
|
|
+
|
|
|
+ public AntColony(int numStops, int numAnts, double alpha, double beta, double evaporationRate, double initialPheromone) {
|
|
|
+ this.numStops = numStops;
|
|
|
+ this.numAnts = numAnts;
|
|
|
+ this.alpha = alpha;
|
|
|
+ this.beta = beta;
|
|
|
+ this.evaporationRate = evaporationRate;
|
|
|
+ this.initialPheromone = initialPheromone;
|
|
|
+
|
|
|
+ this.pheromoneMatrix = new double[numStops][numStops];
|
|
|
+ this.distanceMatrix = new double[numStops][numStops];
|
|
|
+
|
|
|
+ this.bestSolution = null;
|
|
|
+ this.bestSolutionDistance = Double.MAX_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void initializePheromoneMatrix() {
|
|
|
+ double initialPheromoneValue = initialPheromone;
|
|
|
+
|
|
|
+ for (int i = 0; i < numStops; i++) {
|
|
|
+ for (int j = 0; j < numStops; j++) {
|
|
|
+ if (i != j) {
|
|
|
+ pheromoneMatrix[i][j] = initialPheromoneValue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void constructSolutions() {
|
|
|
+ for (int ant = 0; ant < numAnts; ant++) {
|
|
|
+ List<Integer> solution = constructSolution(ant);
|
|
|
+ double solutionDistance = calculateSolutionDistance(solution);
|
|
|
+
|
|
|
+ if (solutionDistance < bestSolutionDistance) {
|
|
|
+ bestSolution = solution;
|
|
|
+ bestSolutionDistance = solutionDistance;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Integer> constructSolution(int ant) {
|
|
|
+ boolean[] visited = new boolean[numStops];
|
|
|
+ int startCity = new Random().nextInt(numStops);
|
|
|
+
|
|
|
+ List<Integer> solution = new ArrayList<>();
|
|
|
+ solution.add(startCity);
|
|
|
+ visited[startCity] = true;
|
|
|
+
|
|
|
+ for (int i = 1; i < numStops; i++) {
|
|
|
+ int nextCity = selectNextCity(ant, solution, visited);
|
|
|
+ solution.add(nextCity);
|
|
|
+ visited[nextCity] = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return solution;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int selectNextCity(int ant, List<Integer> solution, boolean[] visited) {
|
|
|
+ int currentCity = solution.get(solution.size() - 1);
|
|
|
+
|
|
|
+ double totalWeight = 0.0;
|
|
|
+ double[] probabilities = new double[numStops];
|
|
|
+
|
|
|
+ for (int city = 0; city < numStops; city++) {
|
|
|
+ if (!visited[city]) {
|
|
|
+ double pheromone = Math.pow(pheromoneMatrix[currentCity][city], alpha);
|
|
|
+ double distance = 1.0 / Math.pow(distanceMatrix[currentCity][city], beta);
|
|
|
+ probabilities[city] = pheromone * distance;
|
|
|
+ totalWeight += probabilities[city];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ double randomValue = new Random().nextDouble();
|
|
|
+ double cumulativeProbability = 0.0;
|
|
|
+
|
|
|
+ for (int city = 0; city < numStops; city++) {
|
|
|
+ if (!visited[city]) {
|
|
|
+ probabilities[city] /= totalWeight;
|
|
|
+ cumulativeProbability += probabilities[city];
|
|
|
+ if (randomValue <= cumulativeProbability) {
|
|
|
+ return city;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Choose an unvisited city randomly
|
|
|
+ for (int city = 0; city < numStops; city++) {
|
|
|
+ if (!visited[city]) {
|
|
|
+ return city;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void updatePheromoneMatrix() {
|
|
|
+ // Evaporate pheromone on all edges
|
|
|
+ for (int i = 0; i < numStops; i++) {
|
|
|
+ for (int j = 0; j < numStops; j++) {
|
|
|
+ if (i != j) {
|
|
|
+ pheromoneMatrix[i][j] *= (1.0 - evaporationRate);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Deposit pheromone on edges of the best solution
|
|
|
+ for (int i = 0; i < numStops - 1; i++) {
|
|
|
+ int stop1 = bestSolution.get(i);
|
|
|
+ int stop2 = bestSolution.get(i + 1);
|
|
|
+ pheromoneMatrix[stop1][stop2] += (1.0 / bestSolutionDistance);
|
|
|
+ pheromoneMatrix[stop2][stop1] += (1.0 / bestSolutionDistance);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Integer> getBestSolution() {
|
|
|
+ return bestSolution;
|
|
|
+ }
|
|
|
+
|
|
|
+ private double calculateSolutionDistance(List<Integer> solution) {
|
|
|
+ double distance = 0.0;
|
|
|
+
|
|
|
+ for (int i = 0; i < numStops - 1; i++) {
|
|
|
+ int stop1 = solution.get(i);
|
|
|
+ int stop2 = solution.get(i + 1);
|
|
|
+ distance += distanceMatrix[stop1][stop2];
|
|
|
+ }
|
|
|
+ return distance;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setDistanceMatrix(double[][] distanceMatrix) {
|
|
|
+ this.distanceMatrix = distanceMatrix;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|