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; import com.deliveryproject.easydelivery.Utils.AntColony; import com.deliveryproject.easydelivery.Utils.SimulatedAnnealing; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.web.bind.annotation.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; @CrossOrigin @RestController public class MainController { //@PreAuthorize("hasRole('User')") @GetMapping("/route/nodes") @ResponseBody public ArrayList> getNodesBetweenTwoCoordinates(@RequestParam double lon1, @RequestParam double lat1, @RequestParam double lon2, @RequestParam double lat2) throws IOException { System.out.println(lon1); String url = "http://router.project-osrm.org/route/v1/driving/" + lon1 + "," + lat1 + ";" + lon2 + "," + lat2 + "?steps=true&geometries=geojson"; System.out.println(url); URL osrmEndpoint = new URL(url); HttpURLConnection connection = (HttpURLConnection) osrmEndpoint.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-Type", "application/json"); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String inputLine; StringBuilder response = new StringBuilder(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); ObjectMapper om = new ObjectMapper(); Root root = om.readValue(response.toString(), Root.class); ArrayList steps = root.routes.get(0).legs.get(0).steps; ArrayList> coordinates = new ArrayList<>(); for (Step step : steps) { ArrayList intersections = step.intersections; for (Intersection intersection : intersections) { ArrayList location = new ArrayList<>(); location.add(intersection.location.get(1)); location.add(intersection.location.get(0)); coordinates.add(location); } } System.out.println(coordinates); return coordinates; } @RequestMapping("/optimize-delivery-route") @ResponseBody public List optimizeDeliveryRoute(@RequestBody List coordinates) { List optimizedRoute = new ArrayList<>(); List optimizedRouteCoordinates = new ArrayList<>(); boolean[] visited = new boolean[coordinates.size()]; int currentCoordinateIndex = 0; optimizedRoute.add(currentCoordinateIndex); visited[currentCoordinateIndex] = true; while (optimizedRoute.size() < coordinates.size()) { double minDistance = Double.MAX_VALUE; int nearestCoordinateIndex = -1; for (int i = 0; i < coordinates.size(); i++) { if (!visited[i]) { double distance = calculateDistance(coordinates.get(currentCoordinateIndex), coordinates.get(i)); if (distance < minDistance) { minDistance = distance; nearestCoordinateIndex = i; } } } optimizedRoute.add(nearestCoordinateIndex); visited[nearestCoordinateIndex] = true; currentCoordinateIndex = nearestCoordinateIndex; } for (Integer integer : optimizedRoute) { optimizedRouteCoordinates.add(coordinates.get(integer)); } return optimizedRouteCoordinates; } @RequestMapping("/intersections-between-multiple-coordinates/{algorithm}") @ResponseBody public List getIntersectionsBetweenCoordinates(@PathVariable("algorithm") String algorithm, @RequestBody List coordinates) throws IOException { List optimizedRouteCoordinates = null; if (algorithm.equals("Brute-Force")) { optimizedRouteCoordinates = optimizeDeliveryRoute(coordinates); System.out.println("Brute-Force"); } else if (algorithm.equals("Ant")){ optimizedRouteCoordinates = optimizeDeliveryRouteACO(coordinates); System.out.println("ANT"); } else if (algorithm.equals("Annealing")){ optimizedRouteCoordinates = optimizeDeliveryRouteAnnealing(coordinates); System.out.println("Annealing"); } ArrayList nodes = new ArrayList<>(); for (int i = 0; i < optimizedRouteCoordinates.size(); i++) { ArrayList> 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 node: nodesBetweenTwoCoordinates) { nodes.add(new Coordinate(node.get(0), node.get(1))); } } return nodes; } @GetMapping("/optimize-delivery-route-aco") @ResponseBody public List optimizeDeliveryRouteACO(@RequestBody List coordinates) throws IOException { 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).getLat(); double y1 = coordinates.get(i).getLon(); double x2 = coordinates.get(j).getLat(); double y2 = coordinates.get(j).getLon(); double distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); distanceMatrix[i][j] = distance; } } } // 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(); } // Get the best solution from AntColony and convert it to a list of coordinates List bestRoute = antColony.getBestSolution(coordinates); // Iterate over the bestRoute list List optimizedRoute = new ArrayList<>(); for (int i = 0; i < bestRoute.size() - 1; i++) { Coordinate currentCoordinate = bestRoute.get(i); Coordinate nextCoordinate = bestRoute.get(i + 1); // Get the nodes between the current and next coordinates ArrayList> nodesBetweenCoordinates = getNodesBetweenTwoCoordinates( currentCoordinate.getLat(), currentCoordinate.getLon(), nextCoordinate.getLat(), nextCoordinate.getLon() ); // Convert the nodes to Coordinate objects and add them to the optimizedRoute for (ArrayList node : nodesBetweenCoordinates) { double lon = node.get(1); double lat = node.get(0); optimizedRoute.add(new Coordinate(lon, lat)); } } // Add the last coordinate to the optimizedRoute optimizedRoute.add(bestRoute.get(bestRoute.size() - 1)); return optimizedRoute; } private double calculateDistance(Coordinate c1, Coordinate c2) { ArrayList> nodes; try { nodes = getNodesBetweenTwoCoordinates(c1.lon, c1.lat, c2.lon, c2.lat); } catch (IOException e) { e.printStackTrace(); return Double.MAX_VALUE; } double sumDistance = 0.0; for (int i = 0; i < nodes.size() - 1; i++) { ArrayList current = nodes.get(i); ArrayList next = nodes.get(i + 1); double dx = next.get(0) - current.get(0); double dy = next.get(1) - current.get(1); double distance = Math.sqrt(dx * dx + dy * dy); sumDistance += distance; } return sumDistance; } @GetMapping("/optimize-delivery-route-annealing") @ResponseBody public List optimizeDeliveryRouteAnnealing(List coordinates) { SimulatedAnnealing annealing = new SimulatedAnnealing(); List currentSolution = new ArrayList<>(coordinates); double initialTemperature = 500.0; // Initial temperature double coolingRate = 0.85; // Cooling rate int numIterations = 1000; // Number of iterations currentSolution = annealing.optimize(currentSolution, initialTemperature, coolingRate, numIterations); return currentSolution; } }