diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java b/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java index 8bb0107..ed9dde6 100644 --- a/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java +++ b/src/main/java/fr/u_paris/gla/project/itinerary/Connection.java @@ -1,6 +1,7 @@ package fr.u_paris.gla.project.itinerary; import java.util.ArrayList; +import java.util.Collections; public class Connection{ // Destination of the connection between the two stops @@ -9,8 +10,10 @@ public class Connection{ // The line used for this connection private final String lineName; + //Distance between the two stops private final double distance; + //Travel time between the two stops private final int time; private final ArrayList schedules; @@ -51,6 +54,10 @@ public class Connection{ this.schedules.add(hours); } + public void sortSchedule() { + Collections.sort(this.schedules); + } + public ArrayList getSchedules() { return this.schedules; } @@ -58,4 +65,35 @@ public class Connection{ public int getBifurcation() { return this.bifurcation; } + + public double getCost() { + return this.time; + } + + public double getNextTime(double currentTime) { + if(this.schedules.size() == 0) { + return currentTime; + } + + int i = 0; + while(i < this.schedules.size() && this.schedules.get(i) < currentTime) { + i++; + } + if(i < this.schedules.size()) { + return this.schedules.get(i); + } + return this.schedules.get(0); + } + + public double getCost(double currentTime) { + if(this.schedules.size() == 0) { + if(this.lineName.equals("WALK")) { + return this.time; + } + return this.time + 900; + } + double nextTime = this.getNextTime(currentTime); + if(nextTime < currentTime) { nextTime += 86400;} + return nextTime - currentTime + this.time; + } } diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/Finder.java b/src/main/java/fr/u_paris/gla/project/itinerary/Finder.java index 5f837f2..1e557b3 100644 --- a/src/main/java/fr/u_paris/gla/project/itinerary/Finder.java +++ b/src/main/java/fr/u_paris/gla/project/itinerary/Finder.java @@ -9,6 +9,8 @@ public class Finder { } public List findPath(Stop startNode, Stop goalNode) { + double startTime = 43200; //12h + PriorityQueue openSet = new PriorityQueue<>(Comparator.comparingDouble(GraphNode::getF)); HashSet closedSet = new HashSet<>(); HashMap cameFrom = new HashMap<>(); @@ -21,16 +23,15 @@ public class Finder { fScore.put(node, Double.POSITIVE_INFINITY); } - // The cost of going from start to start is zero - gScore.put(startNode, 0.0); + // The cost of going from start to start is the start time + gScore.put(startNode, startTime); // For the first node, fScore = gScore + heuristic fScore.put(startNode, startNode.getHeuristicCost(goalNode)); openSet.add(startNode); while (!openSet.isEmpty()) { Stop current = openSet.poll(); - //System.out.println(current); - //System.out.println(graph.getConnections(current)); + double currentTime = gScore.get(current); if (current.equals(goalNode)) { return reconstructPath(cameFrom, current); @@ -42,19 +43,15 @@ public class Finder { continue; } - for (Connection connection : graph.getConnections(current) ) { + for (Connection connection : graph.getConnections(current)) { Stop neighbor = connection.getStop(); if (closedSet.contains(neighbor)) { continue; // Ignore the neighbor which is already evaluated. } - double tentativeGScore = gScore.get(current) + connection.getDistance(); + double tentativeGScore = currentTime + connection.getCost(currentTime); - if (!openSet.contains(neighbor)) { - openSet.add(neighbor); - updatePriority(openSet, neighbor, fScore.get(neighbor)); - - } else if (tentativeGScore >= gScore.get(neighbor)) { + if (tentativeGScore >= gScore.get(neighbor)) { continue; // This is not a better path. } @@ -62,7 +59,14 @@ public class Finder { cameFrom.put(neighbor, current); gScore.put(neighbor, tentativeGScore); fScore.put(neighbor, tentativeGScore + neighbor.getHeuristicCost(goalNode)); - neighbor.setF(fScore.get(neighbor)); + + if (!openSet.contains(neighbor)) { + neighbor.setF(fScore.get(neighbor)); + openSet.add(neighbor); + } + else { + updatePriority(openSet, neighbor, fScore.get(neighbor)); + } } } diff --git a/src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java b/src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java index ca72f53..f2ebe85 100644 --- a/src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java +++ b/src/main/java/fr/u_paris/gla/project/itinerary/ItineraryCalculator.java @@ -38,6 +38,11 @@ public class ItineraryCalculator { private static final double ERROR_MARGIN = 1.; + //The time public vehicles spend at each stop in seconds. + private static final int STOP_TIME = 30; + + //Walking speed in m/s + private static final double WALK_SPEED = 1.; /** * Returns the coordinates from a String to a double array: @@ -59,11 +64,12 @@ public class ItineraryCalculator { * @param lineId the line the stop is on * @return the Stop object */ - private static Stop getOrCreateStop(HashSet nodes, HashMap> tmp, String name, String gps, String lineId) { + private static Stop getOrCreateStop(HashSet nodes, HashMap> tmp, String name, String gps, String lineId, HashMap> connections) { ArrayList stopList = tmp.get(name); double[] coords = getCoords(gps); // First we search by name, and then compare the coordinates since multiple stations can have the same name. A margin of error is necessary since stops can have multiple GPS coordinates + ArrayList lineChanges = new ArrayList<>(); if (stopList != null) { for(Stop stop : stopList) { @@ -73,7 +79,7 @@ public class ItineraryCalculator { return stop; } if(dist < ERROR_MARGIN) { - + lineChanges.add(stop); } } } @@ -83,6 +89,15 @@ public class ItineraryCalculator { stopList = stopList == null ? new ArrayList<>() : stopList; stopList.add(newStop); tmp.put(name, stopList); + for(Stop s : lineChanges) { + double dist = GPS.distance(coords[0], coords[1], s.getLatitude(), s.getLongitude()); + int time = (int) (dist*1000/WALK_SPEED); + Connection c1 = new Connection(s, "WALK", dist, time); + connections.computeIfAbsent(newStop, k -> new HashSet<>()).add(c1); + + Connection c2 = new Connection(newStop, "WALK", dist, time); + connections.computeIfAbsent(s, k -> new HashSet<>()).add(c2); + } return newStop; } @@ -94,8 +109,8 @@ public class ItineraryCalculator { * @param connections */ private static void addLine(String[] line, HashSet nodes, HashMap> tmp, HashMap> connections) { - Stop fromStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_FROM_INDEX], line[IDFM_TRACE_FROM_GPS_INDEX], line[IDFM_TRACE_ID_INDEX]); - Stop toStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_TO_INDEX], line[IDFM_TRACE_TO_GPS_INDEX], line[IDFM_TRACE_ID_INDEX]); + Stop fromStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_FROM_INDEX], line[IDFM_TRACE_FROM_GPS_INDEX], line[IDFM_TRACE_ID_INDEX], connections); + Stop toStop = getOrCreateStop(nodes, tmp, line[IDFM_TRACE_TO_INDEX], line[IDFM_TRACE_TO_GPS_INDEX], line[IDFM_TRACE_ID_INDEX], connections); String[] timeString = line[IDFM_TRACE_TIME_INDEX].split(":"); String time0WithoutComma = timeString[0].replace(",", ""); @@ -176,7 +191,7 @@ public class ItineraryCalculator { String name = input[2]; String[] timeString = input[3].split(":"); - int time = Integer.parseInt(timeString[0]) * 3600 + Integer.parseInt(timeString[1])*60; + int time = Integer.parseInt(timeString[0]) * 3600 + Integer.parseInt(timeString[1])*60 + STOP_TIME; ArrayList stops = stopsHashSet.get(name); @@ -206,6 +221,12 @@ public class ItineraryCalculator { CSVTools.readCSVFromFile(HOURS_FILE_NAME, (String[] line) -> addSchedule(line, tmp, connections)); + for(Set set : connections.values()) { + for(Connection c : set) { + c.sortSchedule(); + } + } + Stop porteivry = tmp.get("Porte d'Ivry").get(0); Stop repu = tmp.get("République").get(0); @@ -224,7 +245,6 @@ public class ItineraryCalculator { Finder finder = new Finder(graph); List res = finder.findPath(porteivry, chatelet); - for (Stop element : res) { System.out.println(element); }