Explorar o código

Ant Colony Algorithm

wpfat23-1 %!s(int64=2) %!d(string=hai) anos
pai
achega
d9feeed9b0

+ 153 - 0
src/main/java/com/deliveryproject/easydelivery/AntColony.java

@@ -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;
+    }
+}
+

+ 54 - 20
src/main/java/com/deliveryproject/easydelivery/MainController.java

@@ -1,6 +1,5 @@
 package com.deliveryproject.easydelivery;
 
-import com.deliveryproject.easydelivery.Models.Coordinate;
 import com.deliveryproject.easydelivery.Models.OSMRClass.Intersection;
 import com.deliveryproject.easydelivery.Models.OSMRClass.Root;
 import com.deliveryproject.easydelivery.Models.OSMRClass.Step;
@@ -53,15 +52,13 @@ public class MainController {
                 location.add(intersection.location.get(0));
                 coordinates.add(location);
             }
-
         }
         System.out.println(coordinates);
         return coordinates;
     }
-
-    @RequestMapping("/optimize-delivery-route")
+    @GetMapping("/optimize-delivery-route")
     @ResponseBody
-    public List<Coordinate> optimizeDeliveryRoute(@RequestBody List<Coordinate> coordinates) {
+    public List<Coordinate> optimizeDeliveryRoute(List<Coordinate> coordinates) {
 
         List<Integer> optimizedRoute = new ArrayList<>();
         List<Coordinate> optimizedRouteCoordinates = new ArrayList<>();
@@ -93,29 +90,56 @@ public class MainController {
         }
         return optimizedRouteCoordinates;
     }
-
-    @RequestMapping("/intersections-between-multiple-coordinates")
+    @GetMapping("/optimize-delivery-route-aco")
     @ResponseBody
-    public List<Coordinate> getIntersectionsBetweenCoordinates(@RequestBody List<Coordinate> coordinates) throws IOException {
-        List<Coordinate> optimizedRouteCoordinates = optimizeDeliveryRoute(coordinates);
-
-        ArrayList<Coordinate> nodes = new ArrayList<>();
-        for (int i = 0; i < optimizedRouteCoordinates.size(); i++) {
-            ArrayList<ArrayList<Double>> nodesBetweenTwoCoordinates;
-            if (i == optimizedRouteCoordinates.size() - 1) nodesBetweenTwoCoordinates = getNodesBetweenTwoCoordinates(optimizedRouteCoordinates.get(i).lon, optimizedRouteCoordinates.get(i).lat,optimizedRouteCoordinates.get(0).lon, optimizedRouteCoordinates.get(0).lat);
-            else nodesBetweenTwoCoordinates = getNodesBetweenTwoCoordinates(optimizedRouteCoordinates.get(i).lon, optimizedRouteCoordinates.get(i).lat,optimizedRouteCoordinates.get(i+1).lon, optimizedRouteCoordinates.get(i+1).lat);
-            System.out.println("Drop off");
-            for (ArrayList <Double> node: nodesBetweenTwoCoordinates) {
-                nodes.add(new Coordinate(node.get(0), node.get(1)));
+    public List<Integer> optimizeDeliveryRouteACO(@RequestBody List<Coordinate> coordinates) {
+        int numAnts = 10;
+        int numIterations = 100;
+        double alpha = 1.0;
+        double beta = 2.0;
+        double evaporationRate = 0.5;
+        double initialPheromone = 0.1;
+        int numStops = coordinates.size();
+        AntColony antColony = new AntColony(coordinates.size(), numAnts, alpha, beta, evaporationRate, initialPheromone);
+
+        // Populate the distance matrix
+        double[][] distanceMatrix = new double[numStops][numStops];
+        for (int i = 0; i < numStops; i++) {
+            for (int j = 0; j < numStops; j++) {
+                if (i == j) {
+                    distanceMatrix[i][j] = 0.0;
+                } else {
+                    double x1 = coordinates.get(i).x;
+                    double y1 = coordinates.get(i).y;
+                    double x2 = coordinates.get(j).x;
+                    double y2 = coordinates.get(j).y;
+
+                    double distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
+                    distanceMatrix[i][j] = distance;
+                }
             }
         }
-        return nodes;
+
+        // Set the distance matrix in the AntColony instance
+        antColony.setDistanceMatrix(distanceMatrix);
+
+        antColony.initializePheromoneMatrix();
+
+        // Ant colony optimization for the specified number of iterations
+        for (int iteration = 0; iteration < numIterations; iteration++) {
+            antColony.constructSolutions();
+            antColony.updatePheromoneMatrix();
+        }
+
+        List<Integer> bestSolution = antColony.getBestSolution();
+
+        return bestSolution;
     }
 
     private double calculateDistance(Coordinate c1, Coordinate c2) {
         ArrayList<ArrayList<Double>> nodes;
         try {
-            nodes = getNodesBetweenTwoCoordinates(c1.lon, c1.lat, c2.lon, c2.lat);
+            nodes = getNodesBetweenTwoCoordinates(c1.x, c1.y, c2.x, c2.y);
         } catch (IOException e) {
             e.printStackTrace();
             return Double.MAX_VALUE;
@@ -135,6 +159,16 @@ public class MainController {
         return sumDistance;
     }
 
+
+    class Coordinate {
+        double x;
+        double y;
+        public Coordinate(double x, double y) {
+            this.x = x;
+            this.y = y;
+        }
+
+    }
 }