Skip to content

Commit

Permalink
Simpler disutility function & JIBE disutility model
Browse files Browse the repository at this point in the history
  • Loading branch information
CorinStaves committed Nov 27, 2023
1 parent 959432d commit bd9ed0a
Show file tree
Hide file tree
Showing 19 changed files with 536 additions and 87 deletions.
7 changes: 7 additions & 0 deletions src/main/java/accessibility/RunAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import resources.Resources;

import org.apache.log4j.Logger;
import routing.disutility.JibeDisutility4;

import java.io.IOException;
import java.util.Map;
Expand Down Expand Up @@ -74,6 +75,12 @@ private static void runAnalysis(String propertiesFilepath) throws IOException {
Vehicle veh = AccessibilityResources.instance.getVehicle();
TravelDisutility td = AccessibilityResources.instance.getTravelDisutility();

if(td instanceof JibeDisutility4) {
((JibeDisutility4) td).setNetwork(network);
((JibeDisutility4) td).setVehicle(veh);
((JibeDisutility4) td).precalculateDisutility();
}

// Inputs/outputs
String endLocationsFilename = AccessibilityResources.instance.getString(AccessibilityProperties.END_LOCATIONS);
String outputNodesFilename = AccessibilityResources.instance.getString(AccessibilityProperties.OUTPUT_NODES);
Expand Down
21 changes: 12 additions & 9 deletions src/main/java/accessibility/resources/AccessibilityResources.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import org.matsim.vehicles.Vehicle;
import routing.Bicycle;
import routing.disutility.DistanceDisutility;
import routing.disutility.JibeDisutility;
import routing.disutility.JibeDisutility4;
import routing.travelTime.WalkTravelTime;
import trip.Purpose;

Expand All @@ -25,14 +25,12 @@ public class AccessibilityResources {
public static AccessibilityResources instance;
private final Properties properties;
private final Path baseDirectory;

private Config config;
private String mode;
private Vehicle veh;
private TravelTime tt;
private TravelDisutility td;


private Boolean fwd;

public AccessibilityResources(Properties properties, String baseDirectory) {
this.properties = properties;
Expand Down Expand Up @@ -74,13 +72,18 @@ public static void initializeResources(String propertiesFile) {
default:
throw new RuntimeException("Mode " + instance.mode + " not supported for accessibility calculations!");
}

// Direction
instance.fwd = Boolean.parseBoolean(properties.getProperty(AccessibilityProperties.FORWARD));

} catch (IOException e) {
e.printStackTrace();
}
}

private void setActiveDisutility() {
String type = properties.getProperty(AccessibilityProperties.IMPEDANCE);
boolean dayOverride = false;
switch(type) {
case "shortest":
case "short":
Expand All @@ -90,14 +93,14 @@ private void setActiveDisutility() {
case "fast":
td = new OnlyTimeDependentTravelDisutility(tt);
break;
case "jibe":
double mcTime = getMarginalCostOrDefault(mode, resources.Properties.TIME);
double mcDist = getMarginalCostOrDefault(mode, resources.Properties.DISTANCE);
case "jibe_day":
dayOverride = true;
case "jibe_night":
double mcGrad = getMarginalCostOrDefault(mode, resources.Properties.GRADIENT);
double mcComfort = getMarginalCostOrDefault(mode, resources.Properties.COMFORT);
double mcAmbience = getMarginalCostOrDefault(mode, resources.Properties.AMBIENCE);
double mcStress = getMarginalCostOrDefault(mode, resources.Properties.STRESS);
td = new JibeDisutility(mode,tt,mcTime,mcDist,mcGrad,mcComfort,mcAmbience,mcStress);
td = new JibeDisutility4(mode,tt,dayOverride,mcGrad,mcComfort,mcAmbience,mcStress);
break;
default:
throw new RuntimeException("Disutility type " + type + " not recognised for mode " + mode);
Expand All @@ -117,7 +120,7 @@ public synchronized String getMode() {
return this.mode;
}

public synchronized boolean fwdCalculation() { return Boolean.parseBoolean(AccessibilityProperties.FORWARD); }
public synchronized boolean fwdCalculation() { return this.fwd; }

public synchronized Vehicle getVehicle() {
return this.veh;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ch/sbb/matsim/graph/LeastCostPathTree2.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void calculate(int startNode, double startTime, Person person, Vehicle ve
pq.decreaseKey(toNode, newCost);
setData(toNode, newCost, newTime, currDistance + link.getLength(), newLinksUsed);
for(int i = 0 ; i < attributeCount ; i++) {
double newAttr = currAttr[i] + this.ta[i].getTravelAttribute(link,td);
double newAttr = currAttr[i] + this.ta[i].getTravelAttribute(link,td,tt);
setAttribute(toNode, i, newAttr);
}
this.comingFromNode[toNode] = nodeIdx;
Expand All @@ -110,7 +110,7 @@ public void calculate(int startNode, double startTime, Person person, Vehicle ve
} else {
setData(toNode, newCost, newTime, currDistance + link.getLength(), newLinksUsed);
for(int i = 0 ; i < attributeCount ; i++) {
double newAttr = currAttr[i] + this.ta[i].getTravelAttribute(link,td);
double newAttr = currAttr[i] + this.ta[i].getTravelAttribute(link,td,tt);
setAttribute(toNode, i, newAttr);
}
pq.insert(toNode);
Expand Down
70 changes: 70 additions & 0 deletions src/main/java/demand/WriteHourlyVolumes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package demand;

import demand.volumes.HourlyVolumeEventHandler;
import io.ioUtils;
import network.CreateMatsimNetworkRoad;
import network.NetworkUtils2;
import org.apache.log4j.Logger;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.events.EventsManagerImpl;
import org.matsim.core.events.EventsUtils;
import resources.Properties;
import resources.Resources;

import java.io.File;
import java.io.PrintWriter;

public class WriteHourlyVolumes {

private final static Logger log = Logger.getLogger(CreateMatsimNetworkRoad.class);

public static void main(String[] args) {

if(args.length != 2) {
throw new RuntimeException("Program requires 2 arguments: \n" +
"(0) Properties file \n" +
"(1) Output csv file");
}

Resources.initializeResources(args[0]);
String outputCsv = args[1];

Network network = NetworkUtils2.readFullNetwork();

log.info("Estimating volumes from events...");
int scaleFactor = (int) (1 / Resources.instance.getDouble(Properties.MATSIM_TFGM_OUTPUT_SCALE_FACTOR));
log.info("Multiplying all volumes from events file by a factor of " + scaleFactor);

EventsManager eventsManager = new EventsManagerImpl();
HourlyVolumeEventHandler hourlyVolumeEventHandler = new HourlyVolumeEventHandler(Resources.instance.getString(Properties.MATSIM_TFGM_OUTPUT_VEHICLES));
eventsManager.addHandler(hourlyVolumeEventHandler);
EventsUtils.readEvents(eventsManager,Resources.instance.getString(Properties.MATSIM_TFGM_OUTPUT_EVENTS));

PrintWriter out = ioUtils.openFileForSequentialWriting(new File(outputCsv),false);
assert out != null;

log.info("Writing csv...");
// Write header
out.println("linkId,edgeId,osmId,hour,cars,trucks");

// Write table
for(Link link : network.getLinks().values()) {
String linkId = link.getId().toString();
int edgeId = (int) link.getAttributes().getAttribute("edgeID");
int osmId = (int) link.getAttributes().getAttribute("osmID");
int[] carVolumes = hourlyVolumeEventHandler.getCarVolumes().getOrDefault(link.getId(),new int[24]);
int[] truckVolumes = hourlyVolumeEventHandler.getTruckVolumes().getOrDefault(link.getId(),new int[24]);

for(int i = 0 ; i < 24 ; i++) {
out.println(linkId + "," + edgeId + "," + osmId + "," + i + "," +
(carVolumes[i] * scaleFactor) + "," + (truckVolumes[i] * scaleFactor));
}
}

// Close
out.close();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
import org.matsim.api.core.v01.network.Link;
import org.matsim.vehicles.*;

public class VolumeEventHandler implements LinkEnterEventHandler {
public class DailyVolumeEventHandler implements LinkEnterEventHandler {

Vehicles vehicles = VehicleUtils.createVehiclesContainer();

public VolumeEventHandler(String vehiclesFile) {
public DailyVolumeEventHandler(String vehiclesFile) {
MatsimVehicleReader.VehicleReader reader = new MatsimVehicleReader.VehicleReader(vehicles);
reader.readFile(vehiclesFile);
}
Expand Down
54 changes: 54 additions & 0 deletions src/main/java/demand/volumes/HourlyVolumeEventHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package demand.volumes;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.IdMap;
import org.matsim.api.core.v01.events.LinkEnterEvent;
import org.matsim.api.core.v01.events.handler.LinkEnterEventHandler;
import org.matsim.api.core.v01.network.Link;
import org.matsim.vehicles.MatsimVehicleReader;
import org.matsim.vehicles.VehicleUtils;
import org.matsim.vehicles.Vehicles;

public class HourlyVolumeEventHandler implements LinkEnterEventHandler {

Vehicles vehicles = VehicleUtils.createVehiclesContainer();

public HourlyVolumeEventHandler(String vehiclesFile) {
MatsimVehicleReader.VehicleReader reader = new MatsimVehicleReader.VehicleReader(vehicles);
reader.readFile(vehiclesFile);
}

private final IdMap<Link, int[]> carVolumes = new IdMap<>(Link.class);
private final IdMap<Link, int[]> truckVolumes = new IdMap<>(Link.class);

@Override
public void handleEvent(LinkEnterEvent event) {
Id<Link> linkId = event.getLinkId();

String vehicleType = vehicles.getVehicles().get(event.getVehicleId()).getType().getId().toString();

int hour = ((int) (event.getTime() / 3600.)) % 24;

String mode = event.getAttributes().get("networkMode");

if(vehicleType.equals("car")) {
int[] linkVolumes = carVolumes.getOrDefault(linkId,new int[24]);
linkVolumes[hour]++;
carVolumes.put(linkId,linkVolumes);
} else if (vehicleType.equals("truck")) {
int[] linkVolumes = truckVolumes.getOrDefault(linkId,new int[24]);
linkVolumes[hour]++;
truckVolumes.put(linkId, linkVolumes);
} else {
throw new RuntimeException("Unrecognised vehicle type " + mode);
}
}

public IdMap<Link, int[]> getCarVolumes() {
return carVolumes;
}

public IdMap<Link, int[]> getTruckVolumes() {
return truckVolumes;
}
}
12 changes: 6 additions & 6 deletions src/main/java/network/CreateMatsimNetworkRoad.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package network;

import com.google.common.collect.Sets;
import demand.volumes.VolumeEventHandler;
import demand.volumes.DailyVolumeEventHandler;
import gis.GpkgReader;
import org.apache.log4j.Logger;
import org.locationtech.jts.geom.Point;
Expand Down Expand Up @@ -432,18 +432,18 @@ private static void addSimulationVolumes(Network network) {
log.info("Multiplying all volumes from events file by a factor of " + scaleFactor);

EventsManager eventsManager = new EventsManagerImpl();
VolumeEventHandler volumeEventHandler = new VolumeEventHandler(Resources.instance.getString(Properties.MATSIM_TFGM_OUTPUT_VEHICLES));
eventsManager.addHandler(volumeEventHandler);
DailyVolumeEventHandler dailyVolumeEventHandler = new DailyVolumeEventHandler(Resources.instance.getString(Properties.MATSIM_TFGM_OUTPUT_VEHICLES));
eventsManager.addHandler(dailyVolumeEventHandler);
EventsUtils.readEvents(eventsManager,Resources.instance.getString(Properties.MATSIM_TFGM_OUTPUT_EVENTS));

// Print diagonstics
int carEvents = volumeEventHandler.getCarVolumes().values().stream().mapToInt(e -> e).sum();
int truckEvents = volumeEventHandler.getTruckVolumes().values().stream().mapToInt(e -> e).sum();
int carEvents = dailyVolumeEventHandler.getCarVolumes().values().stream().mapToInt(e -> e).sum();
int truckEvents = dailyVolumeEventHandler.getTruckVolumes().values().stream().mapToInt(e -> e).sum();
log.info("Identified " + carEvents + " car link enter events.");
log.info("Identified " + truckEvents + " truck link enter events.");

// Add forward AADT
network.getLinks().forEach((id,link) -> link.getAttributes().putAttribute("aadtFwd",volumeEventHandler.getAdjVolumes().getOrDefault(id,0) * scaleFactor));
network.getLinks().forEach((id,link) -> link.getAttributes().putAttribute("aadtFwd", dailyVolumeEventHandler.getAdjVolumes().getOrDefault(id,0) * scaleFactor));

// Add forward + opposing AADT
for(Link link : network.getLinks().values()) {
Expand Down
8 changes: 3 additions & 5 deletions src/main/java/network/WriteNetworkGpkg.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@
import routing.Bicycle;
import routing.Gradient;
import routing.disutility.JibeDisutility;
import routing.disutility.components.*;
import routing.travelTime.WalkTravelTime;
import routing.disutility.components.Crossing;
import routing.disutility.components.CycleProtection;
import routing.disutility.components.LinkAmbience;
import routing.disutility.components.JctStress;
import routing.disutility.components.LinkStress;
import com.google.common.math.LongMath;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.log4j.Logger;
Expand Down Expand Up @@ -145,6 +141,7 @@ private static SimpleFeatureType createFeatureType() throws FactoryException {
builder.add("f_freightPOIs",Double.class);
builder.add("f_ambience_day",Double.class);
builder.add("f_ambience_night",Double.class);
builder.add("f_bikeStressDiscrete",String.class);
builder.add("f_bikeStress",Double.class);
builder.add("f_bikeStressJct",Double.class);
builder.add("f_walkStress",Double.class);
Expand Down Expand Up @@ -292,6 +289,7 @@ public static void write(Network network, String outputEdgesFilePath) throws IOE
featureBuilder.add(LinkStress.getFreightPoiFactor(link));
featureBuilder.add(LinkAmbience.getDayAmbience(link));
featureBuilder.add(LinkAmbience.getNightAmbience(link));
featureBuilder.add(link.getAllowedModes().contains(TransportMode.bike) ? LinkStressDiscrete.getCycleStress(link).toString() : "null");
featureBuilder.add(LinkStress.getStress(link, TransportMode.bike));
featureBuilder.add(JctStress.getStress(link,TransportMode.bike));
featureBuilder.add(LinkStress.getStress(link,TransportMode.walk));
Expand Down
Loading

0 comments on commit bd9ed0a

Please sign in to comment.