Skip to content

Commit

Permalink
Updated multirouter for mode choice LCP method
Browse files Browse the repository at this point in the history
  • Loading branch information
CorinStaves committed Jan 9, 2024
1 parent 8ef190c commit 57ea79b
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 87 deletions.
41 changes: 18 additions & 23 deletions src/main/java/diary/RunMultiRouter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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" +
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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();

Expand All @@ -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<Id<Link>> 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<Link> linkId : path) {
Expand All @@ -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++;
}
Expand Down
112 changes: 49 additions & 63 deletions src/main/java/routing/disutility/JibeDisutility2.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,103 +23,91 @@ 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();
}

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());
}
Expand All @@ -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;
}

}
2 changes: 1 addition & 1 deletion src/main/java/trip/Trip.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class Trip {
private final Map<String, Map<String,Object>> routeAttributes = new LinkedHashMap<>();
private final Map<String,Integer> routePathIndices = new LinkedHashMap<>();
private final List<Route> routes = new ArrayList<>();
private final List<List<Id<Link>>> 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<List<Id<Link>>> paths = new ArrayList<>();

public Trip(String householdId, int personId, int tripId, int startTime,
String mainMode, Purpose startPurpose, Purpose endPurpose, Map<Place, String> zones, Map<Place,Coord> coords, Map<Place,Boolean> coordsInsideBoundary) {
Expand Down

0 comments on commit 57ea79b

Please sign in to comment.