From 57ea79b5b9b2a84d8bff9ebbc814390975451e2f Mon Sep 17 00:00:00 2001 From: Corin Staves Date: Tue, 9 Jan 2024 21:50:01 +0000 Subject: [PATCH] Updated multirouter for mode choice LCP method --- src/main/java/diary/RunMultiRouter.java | 41 +++---- .../routing/disutility/JibeDisutility2.java | 112 ++++++++---------- src/main/java/trip/Trip.java | 2 +- 3 files changed, 68 insertions(+), 87 deletions(-) diff --git a/src/main/java/diary/RunMultiRouter.java b/src/main/java/diary/RunMultiRouter.java index b2f05b9..f315832 100644 --- a/src/main/java/diary/RunMultiRouter.java +++ b/src/main/java/diary/RunMultiRouter.java @@ -42,9 +42,6 @@ public class RunMultiRouter { private final static String SEP = ","; - // Equivalent MC of distance for bike = 0.002, walk = 0.005 - // (see travelDiaryProcessing/Manchester/calcAvgSpeed.csv) - public static void main(String[] args) throws IOException, FactoryException { if (args.length != 5) { throw new RuntimeException("Program requires 5 arguments: \n" + @@ -121,10 +118,10 @@ public static void main(String[] args) throws IOException, FactoryException { // GENERATE RANDOM NUMBERS AND WRITE SAMPLES logger.info("Randomly sampling " + SAMPLES + " sets of marginal cost values."); - double[] mcGradient = random.doubles(SAMPLES,0,0.1).toArray(); - double[] mcVgviLight = random.doubles(SAMPLES,0,0.02).toArray(); - double[] mcStressLink = random.doubles(SAMPLES,0,0.02).toArray(); - double[] mcStressJct = random.doubles(SAMPLES,0,0.02).toArray(); + double[] mcGradient = random.doubles(SAMPLES,0,20).toArray(); + double[] mcVgvi = random.doubles(SAMPLES,0,10).toArray(); + double[] mcStressLink = random.doubles(SAMPLES,0,10).toArray(); + double[] mcStressJct = random.doubles(SAMPLES,0,10).toArray(); int[] newPathCount = new int[SAMPLES]; // ESTIMATE PATHS @@ -133,8 +130,8 @@ public static void main(String[] args) throws IOException, FactoryException { LogitDataCalculator calc = new LogitDataCalculator(selectedTrips); for (int i = 0 ; i < SAMPLES ; i++) { logger.info("Estimating path for sample " + (i+1) + "..."); - JibeDisutility2 disutility = new JibeDisutility2(network,null,veh,mode,tt,0.00667,0, - mcGradient[i],mcVgviLight[i],mcStressLink[i],mcStressJct[i]); + JibeDisutility2 disutility = new JibeDisutility2(network,veh,mode,tt,mcGradient[i], + mcVgvi[i],mcStressLink[i],mcStressJct[i]); calc.calculate(veh,network,disutility,tt); int thisPathCount = selectedTrips.stream().mapToInt(t -> t.getPaths().size()).sum(); newPathCount[i] = thisPathCount - currPathCount; @@ -150,10 +147,10 @@ public static void main(String[] args) throws IOException, FactoryException { PrintWriter out = ioUtils.openFileForSequentialWriting(mcCsvFile,true); assert out != null; if(writeHeader) { - out.println("mcGradient" + SEP + "mcVgviLight" + SEP + "mcStressLink" + SEP + "mcStressJct" + SEP + "newPathCount"); + out.println("mcGradient" + SEP + "mcVgvi" + SEP + "mcStressLink" + SEP + "mcStressJct" + SEP + "newPathCount"); } for(int i = 0 ; i < SAMPLES ; i++) { - out.println(mcGradient[i] + SEP + mcVgviLight[i] + SEP + mcStressLink[i] + SEP + mcStressJct[i] + SEP + newPathCount[i]); + out.println(mcGradient[i] + SEP + mcVgvi[i] + SEP + mcStressLink[i] + SEP + mcStressJct[i] + SEP + newPathCount[i]); } out.close(); @@ -164,19 +161,18 @@ public static void main(String[] args) throws IOException, FactoryException { // Write header out.println("IDNumber" + SEP + "PersonNumber" + SEP + "TripNumber" + SEP + "path" + SEP + - "distance" + SEP + "travelTime" + SEP + "gradient" + SEP + "vgviLight" + SEP + + "distance" + SEP + "travelTime" + SEP + "gradient" + SEP + "vgvi" + SEP + "stressLink" + SEP + "stressJct" + SEP + "links"); - // Write routes todo: make part of disutility, otherwise we'll have problems... + // Write routes for(Trip trip : selectedTrips) { - boolean day = trip.getStartTime() >= 21600 && trip.getStartTime() < 72000; int pathId = 0; for(List> path : trip.getPaths()) { StringBuilder links = new StringBuilder(); double distance = 0.; double travelTime = 0.; double gradient = 0.; - double vgviLight = 0.; + double vgvi = 0.; double stressLink = 0.; double stressJct = 0.; for(Id linkId : path) { @@ -186,18 +182,17 @@ public static void main(String[] args) throws IOException, FactoryException { double linkTime = tt.getLinkTravelTime(link,trip.getStartTime(),null,veh); distance += linkLength; travelTime += linkTime; - gradient += Math.max(Math.min(Gradient.getGradient(link),0.5),0.) * linkLength; - if(day) { - vgviLight += LinkAmbience.getVgviFactor(link) * linkLength; - } else { - vgviLight += LinkAmbience.getDarknessFactor(link) * linkLength; + gradient += linkTime * Math.max(Math.min(Gradient.getGradient(link),0.5),0.); + vgvi += linkTime * Math.max(0.,0.81 - LinkAmbience.getVgviFactor(link)); + stressLink += linkTime * LinkStress.getStress(link,mode); + if((boolean) link.getAttributes().getAttribute("crossVehicles")) { + double junctionWidth = Math.min(linkLength,(double) link.getAttributes().getAttribute("crossWidth")); + stressJct += linkTime * (junctionWidth / linkLength) * JctStress.getStress(link,mode); } - stressLink += LinkStress.getStress(link,mode) * linkLength; - stressJct += JctStress.getStress(link,mode) * (double) link.getAttributes().getAttribute("crossWidth"); } links.deleteCharAt(links.length() - 1); out.println(trip.getHouseholdId() + SEP + trip.getPersonId() + SEP + trip.getTripId() + SEP + pathId + SEP + - distance + SEP + travelTime + SEP + gradient + SEP + vgviLight + SEP + stressLink + SEP + stressJct + SEP + + distance + SEP + travelTime + SEP + gradient + SEP + vgvi + SEP + stressLink + SEP + stressJct + SEP + links); pathId++; } diff --git a/src/main/java/routing/disutility/JibeDisutility2.java b/src/main/java/routing/disutility/JibeDisutility2.java index 1b5aeb1..825e935 100644 --- a/src/main/java/routing/disutility/JibeDisutility2.java +++ b/src/main/java/routing/disutility/JibeDisutility2.java @@ -23,40 +23,32 @@ public class JibeDisutility2 implements TravelDisutility { private final static Logger logger = Logger.getLogger(JibeDisutility2.class); private final String mode; - private final double mcTime_s; - private final double mcDistance_m; - private final double mcGradient_m_100m; - private final double mcVgviLight; - private final double mcStressLink; - private final double mcStressJct; + private final double marginalCostGradient; + private final double marginalCostVgvi; + private final double marginalCostLinkStress; + private final double marginalCostJctStress; private final TravelTime timeCalculator; private final Network network; - private final Person person; private final Vehicle vehicle; - - private final double[] disutilities = new double[Id.getNumberOfIds(Link.class) * 2]; + private final double[] disutilities = new double[Id.getNumberOfIds(Link.class)]; // Custom parameters - public JibeDisutility2(Network network, Person person, Vehicle vehicle, String mode, TravelTime tt, - double mcTime_s, double mcDistance_m, - double mcGradient_m_100m, double mcVgviLight, - double mcStressLink, double mcStressJct) { + public JibeDisutility2(Network network, Vehicle vehicle, String mode, TravelTime tt, + double marginalCostGradient, double marginalCostVgvi, + double marginalCostLinkStress, double marginalCostJctStress) { if(!mode.equals(TransportMode.bike) && !mode.equals(TransportMode.walk)) { throw new RuntimeException("Mode " + mode + " not supported for JIBE disutility."); } this.network = network; - this.person = person; this.vehicle = vehicle; this.mode = mode; this.timeCalculator = tt; - this.mcTime_s = mcTime_s; - this.mcDistance_m = mcDistance_m; - this.mcGradient_m_100m = mcGradient_m_100m; - this.mcVgviLight = mcVgviLight; - this.mcStressLink = mcStressLink; - this.mcStressJct = mcStressJct; + this.marginalCostGradient = marginalCostGradient; + this.marginalCostVgvi = marginalCostVgvi; + this.marginalCostLinkStress = marginalCostLinkStress; + this.marginalCostJctStress = marginalCostJctStress; printMarginalCosts(); precalculateDisutility(); } @@ -64,62 +56,58 @@ public JibeDisutility2(Network network, Person person, Vehicle vehicle, String m private void printMarginalCosts() { logger.info("Initialised JIBE disutility with the following parameters:" + "\nMode: " + this.mode + - "\nMarginal cost of time (/s): " + this.mcTime_s + - "\nMarginal cost of distance (/m): " + this.mcDistance_m + - "\nMarginal cost of gradient (m/100m): " + this.mcGradient_m_100m + - "\nMarginal cost of lighting/vgvi (/m): " + this.mcVgviLight + - "\nMarginal cost of LINK stress (/m): " + this.mcStressLink + - "\nMarginal cost of JCT stress (/m): " + this.mcStressJct); + "\nMarginal cost of gradient (/s): " + this.marginalCostGradient + + "\nMarginal cost of vgvi (/s): " + this.marginalCostVgvi + + "\nMarginal cost of link stress (/s): " + this.marginalCostLinkStress + + "\nMarginal cost of jct stress (/s): " + this.marginalCostJctStress); } - private void precalculateDisutility() { + public void precalculateDisutility() { logger.info("precalculating disutilities..."); for(Link link : network.getLinks().values()) { - disutilities[link.getId().index() * 2] = calculateDisutility(link,true,person,vehicle); - disutilities[link.getId().index() * 2 + 1] = calculateDisutility(link,false,person,vehicle); + disutilities[link.getId().index()] = calculateDisutility(link); } } - private double calculateDisutility(Link link, boolean day, Person person, Vehicle vehicle) { - + private double calculateDisutility(Link link) { if(link.getAllowedModes().contains(this.mode)) { - double travelTime = timeCalculator.getLinkTravelTime(link, 0., person, vehicle); + double linkTime = timeCalculator.getLinkTravelTime(link, 0., null, vehicle); + double linkLength = link.getLength(); - double distance = link.getLength(); + // Gradient factor + double gradient = Math.max(Math.min(Gradient.getGradient(link),0.5),0.); - // Travel time disutility - double disutility = mcTime_s * travelTime; + // VGVI + double vgvi = Math.max(0.,0.81 - LinkAmbience.getVgviFactor(link)); - // Distance disutility (0 by default) - disutility += mcDistance_m * distance; + // Link stress + double linkStress = LinkStress.getStress(link,mode); - // Gradient factor - double gradient = Gradient.getGradient(link); - if(gradient < 0.) gradient = 0.; - disutility += mcGradient_m_100m * gradient * distance; - - // Lighting / VGVI - double vgviLight; - if(day) { - // Daytime - use VGVI - vgviLight = LinkAmbience.getVgviFactor(link); - } else { - // Nighttime - use Street Lighting - vgviLight = LinkAmbience.getDarknessFactor(link); + // Junction stress + double jctStress = 0; + if((boolean) link.getAttributes().getAttribute("crossVehicles")) { + double junctionWidth = Math.min(linkLength,(double) link.getAttributes().getAttribute("crossWidth")); + jctStress = (junctionWidth / linkLength) * JctStress.getStress(link,mode); } - disutility += mcVgviLight * vgviLight * distance; - // Link Stress - double linkStress = LinkStress.getStress(link,mode); - disutility += mcStressLink * linkStress * distance; + // Link disutility + double disutility = linkTime * (1 + + marginalCostGradient * gradient + + marginalCostVgvi * vgvi + + marginalCostLinkStress * linkStress + + marginalCostJctStress * jctStress); // Junction stress factor - double junctionStress = JctStress.getStress(link,mode); - double crossingWidth = (double) link.getAttributes().getAttribute("crossWidth"); - disutility += mcStressJct * junctionStress * crossingWidth; + if((boolean) link.getAttributes().getAttribute("crossVehicles")) { + double junctionStress = JctStress.getStress(link,mode); + double junctionWidth = (double) link.getAttributes().getAttribute("crossWidth"); + if(junctionWidth > linkLength) junctionWidth = linkLength; + double junctionTime = linkTime * (junctionWidth / linkLength); + + disutility += marginalCostJctStress * junctionTime * junctionStress; + } - // Check it's not NAN if(Double.isNaN(disutility)) { throw new RuntimeException("Null JIBE disutility for link " + link.getId().toString()); } @@ -133,14 +121,12 @@ private double calculateDisutility(Link link, boolean day, Person person, Vehicl @Override public double getLinkTravelDisutility(Link link, double time, Person person, Vehicle vehicle) { - int idx = link.getId().index() * 2; - if(time < 21600 || time >= 72000) { - idx += 1; - } - return disutilities[idx]; + return disutilities[link.getId().index()]; } + @Override public double getLinkMinimumTravelDisutility(Link link) { return 0; } + } diff --git a/src/main/java/trip/Trip.java b/src/main/java/trip/Trip.java index 59de302..27ad605 100644 --- a/src/main/java/trip/Trip.java +++ b/src/main/java/trip/Trip.java @@ -26,7 +26,7 @@ public class Trip { private final Map> routeAttributes = new LinkedHashMap<>(); private final Map routePathIndices = new LinkedHashMap<>(); private final List routes = new ArrayList<>(); - private final List>> paths = new ArrayList<>(); // todo: just use routes instead if not too much impact on runtime. Probably, it will be faster if I can check distance first. + private final List>> paths = new ArrayList<>(); public Trip(String householdId, int personId, int tripId, int startTime, String mainMode, Purpose startPurpose, Purpose endPurpose, Map zones, Map coords, Map coordsInsideBoundary) {