Skip to content

Commit

Permalink
updated drt accessibility calculations to be stop-based.
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobrehmann committed May 17, 2024
1 parent 8e7d1c3 commit 2059f9c
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 59 deletions.
12 changes: 12 additions & 0 deletions contribs/accessibility/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,17 @@
<artifactId>gt-jdbc-postgis</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.matsim.contrib</groupId>
<artifactId>dvrp</artifactId>
<version>16.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.matsim.contrib</groupId>
<artifactId>drt</artifactId>
<version>16.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,10 @@ public ControlerListener get() {
} else if ( TransportMode.pt.equals( mode ) ){
calculator = new SwissRailRaptorAccessibilityContributionCalculator( mode, config.scoring(), scenario );
} else if ( Modes4Accessibility.estimatedDrt.name().equals( mode )) {
final TravelTime travelTime = travelTimes.get(TransportMode.drt);
final TravelDisutilityFactory travelDisutilityFactory = travelDisutilityFactories.get(TransportMode.drt);
calculator = new EstimatedDrtAccessibilityContributionCalculator(mode, travelTime, travelDisutilityFactory, scenario);
// final TravelTime travelTime = travelTimes.get("dvrp_estimated"); //TODO
final TravelTime travelTime = travelTimes.get(TransportMode.car); //TODO
final TravelDisutilityFactory travelDisutilityFactory = travelDisutilityFactories.get(TransportMode.car); //TODO
calculator = new EstimatedDrtAccessibilityContributionCalculator(mode, travelTime, travelDisutilityFactory, scenario, tripRouter);
} else if ( Modes4Accessibility.matrixBasedPt.name().equals( mode ) ) {
throw new RuntimeException("currently not supported because implementation not consistent with guice grapher. kai, sep'19") ;
// calculator = new LeastCostPathCalculatorAccessibilityContributionCalculator(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
package org.matsim.contrib.accessibility;

import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.BasicLocation;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.*;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.network.Node;
import org.matsim.api.core.v01.population.Leg;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.PlanElement;
import org.matsim.contrib.accessibility.utils.*;
import org.matsim.contrib.drt.routing.DrtStopFacility;
import org.matsim.contrib.dvrp.router.DvrpRoutingModule;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.config.groups.NetworkConfigGroup;
import org.matsim.core.config.groups.ScoringConfigGroup;
import org.matsim.core.gbl.Gbl;
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.network.algorithms.TransportModeNetworkFilter;
import org.matsim.core.population.PopulationUtils;
import org.matsim.core.router.*;
import org.matsim.core.router.costcalculators.TravelDisutilityFactory;
import org.matsim.core.router.speedy.SpeedyALTFactory;
import org.matsim.core.router.util.LeastCostPathCalculator;
import org.matsim.core.router.util.TravelDisutility;
import org.matsim.core.router.util.TravelTime;
import org.matsim.facilities.ActivityFacilities;
import org.matsim.facilities.ActivityFacility;
import org.matsim.facilities.Facility;
import org.matsim.matrices.Entry;
import org.matsim.pt.transitSchedule.api.TransitStopFacility;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
* @author thibautd, dziemke
Expand All @@ -43,9 +52,10 @@ final class EstimatedDrtAccessibilityContributionCalculator implements Accessibi

private Network subNetwork;

private final double betaWalkTT;
private final double betaWalkTT_h;

private final double betaDrtTT;
private final double betaDrtTT_h;
private final double betaDrtDist_m;
private final double walkSpeed_m_s;

private Node fromNode = null;
Expand All @@ -54,27 +64,28 @@ final class EstimatedDrtAccessibilityContributionCalculator implements Accessibi
private Map<Id<? extends BasicLocation>, AggregationObject> aggregatedOpportunities;

private final LeastCostPathCalculator router;
TripRouter tripRouter ;// TODO: this Getter is a temporary hack. Talk to TS about other ways of accessing the stopFinder
private DvrpRoutingModule.AccessEgressFacilityFinder stopFinder;


public EstimatedDrtAccessibilityContributionCalculator(String mode, final TravelTime travelTime, final TravelDisutilityFactory travelDisutilityFactory, Scenario scenario) {
public EstimatedDrtAccessibilityContributionCalculator(String mode, final TravelTime travelTime, final TravelDisutilityFactory travelDisutilityFactory, Scenario scenario, TripRouter tripRouter) {
this.mode = mode;
this.travelTime = travelTime;
this.travelDisutilityFactory = travelDisutilityFactory;
this.scenario = scenario;
this.scoringConfigGroup = scenario.getConfig().scoring();
this.networkConfigGroup = scenario.getConfig().network();
this.tripRouter = tripRouter;

Gbl.assertNotNull(travelDisutilityFactory);
this.travelDisutility = travelDisutilityFactory.createTravelDisutility(travelTime);
this.router = new SpeedyALTFactory().createPathCalculator(scenario.getNetwork(), travelDisutility, travelTime);



betaWalkTT = scoringConfigGroup.getModes().get(TransportMode.walk).getMarginalUtilityOfTraveling() - scoringConfigGroup.getPerforming_utils_hr();
betaDrtTT = scoringConfigGroup.getModes().get(TransportMode.drt).getMarginalUtilityOfTraveling() - scoringConfigGroup.getPerforming_utils_hr();

betaWalkTT_h = scoringConfigGroup.getModes().get(TransportMode.walk).getMarginalUtilityOfTraveling() - scoringConfigGroup.getPerforming_utils_hr();
betaDrtTT_h = scoringConfigGroup.getModes().get(TransportMode.drt).getMarginalUtilityOfTraveling() - scoringConfigGroup.getPerforming_utils_hr();
betaDrtDist_m = scoringConfigGroup.getModes().get(TransportMode.drt).getMarginalUtilityOfDistance();
this.walkSpeed_m_s = scenario.getConfig().routing().getTeleportedModeSpeeds().get(TransportMode.walk);

stopFinder = ((DvrpRoutingModule) tripRouter.getRoutingModule(TransportMode.drt)).getStopFinder();// todo
// this.drtEstimator = new EuclideanDistanceBasedDrtEstimator(scenario.getNetwork(), 1.2, 0.0842928, 337.1288522, 5 * 60, 0, 0, 0);
// this.drtEstimator = DetourBasedDrtEstimator.normalDistributed(337.1288522, 0.0842928, 0., 0. * 60, 0);

Expand All @@ -85,6 +96,9 @@ public EstimatedDrtAccessibilityContributionCalculator(String mode, final Travel

@Override
public void initialize(ActivityFacilities measuringPoints, ActivityFacilities opportunities) {



LOG.warn("Initializing calculator for mode " + mode + "...");
LOG.warn("Full network has " + scenario.getNetwork().getNodes().size() + " nodes.");
subNetwork = NetworkUtils.createNetwork(networkConfigGroup);
Expand All @@ -98,7 +112,10 @@ public void initialize(ActivityFacilities measuringPoints, ActivityFacilities op
LOG.warn("sub-network for mode " + modeSet + " now has " + subNetwork.getNodes().size() + " nodes.");

this.aggregatedMeasurePoints = AccessibilityUtils.aggregateMeasurePointsWithSameNearestNode(measuringPoints, subNetwork);
this.aggregatedOpportunities = AccessibilityUtils.aggregateOpportunitiesWithSameNearestNode(opportunities, subNetwork, scenario.getConfig());
// this.aggregatedOpportunities = AccessibilityUtils.aggregateOpportunitiesWithSameNearestNode(opportunities, subNetwork, scenario.getConfig());

// this.aggregatedMeasurePoints = measuringPoints;
this.aggregatedOpportunities = aggregateOpportunitiesWithSameNearestDrtStop(opportunities, subNetwork, scenario.getConfig());


}
Expand All @@ -117,64 +134,54 @@ public double computeContributionOfOpportunity(ActivityFacility origin,
Map<Id<? extends BasicLocation>, AggregationObject> aggregatedOpportunities, Double departureTime) {
double expSum = 0.;

Optional<Pair<Facility, Facility>> facilities = stopFinder.findFacilities(origin, origin, null); //todo: cleanup
Facility nearestStopAccess = facilities.get().getKey();

// Access
// new ClosestAccessEgressFacilityFinder(2000, scenario.getNetwork(), facilityQuadTree);

// DRT Trip
List<? extends PlanElement> planElementsAccess = tripRouter.calcRoute(TransportMode.walk, origin, nearestStopAccess, departureTime, null, null);

double accessTime_h = ((Leg) planElementsAccess.get(0)).getTravelTime().seconds() / 3600;

// Egress
double utility_access = accessTime_h * betaWalkTT_h;


double utilityDrtConstant = AccessibilityUtils.getModeSpecificConstantForAccessibilities(TransportMode.drt, scoringConfigGroup);

// Old Approach: nearest link...
Link nearestLink = NetworkUtils.getNearestLinkExactly(subNetwork, origin.getCoord());
Distances distance = NetworkUtil.getDistances2NodeViaGivenLink(origin.getCoord(), nearestLink, fromNode);
double walkTravelTimeMeasuringPoint2Road_h = distance.getDistancePoint2Intersection() / (this.walkSpeed_m_s * 3600);
// Orthogonal walk to nearest link
double walkUtilityMeasuringPoint2Road = (walkTravelTimeMeasuringPoint2Road_h * betaWalkTT);
// Travel on section of first link to first node
double distanceFraction = distance.getDistanceIntersection2Node() / nearestLink.getLength();
double congestedCarUtilityRoad2Node = -travelDisutility.getLinkTravelDisutility(nearestLink, departureTime, null, null) * distanceFraction;

// Combine all utility components (using the identity: exp(a+b) = exp(a) * exp(b))
double modeSpecificConstant = AccessibilityUtils.getModeSpecificConstantForAccessibilities(TransportMode.drt, scoringConfigGroup); // TODO: update from car to drt
for (AggregationObject destination : aggregatedOpportunities.values()) {

for (final AggregationObject destination : aggregatedOpportunities.values()) {
// Calculate main drt leg:
Facility nearestStopEgress = (Facility) destination.getNearestBasicLocation();

// utility during DRT ride
// DrtEstimator.Estimate estimate = drtEstimator.estimate(origin.getCoord(), destination.getNearestBasicLocation().getCoord(), OptionalTime.defined(departureTime));
// Doesn't work because we need a person... //TODO: replace actual person with a fake person, or find workaround.
List<? extends PlanElement> planElementsMain = tripRouter.calcRoute(TransportMode.car, nearestStopAccess, nearestStopEgress, 10 * 3600, scenario.getPopulation().getPersons().get(Id.createPersonId("1213")), null);

// DrtRoute route = new DrtRoute(Id.createLinkId("xxx"), Id.createLinkId("yyy"));
double directRideDistance_m = ((Leg) planElementsMain.get(2)).getRoute().getDistance();

Node destinationNode = (Node) destination.getNearestBasicLocation();
// double directRideTime = VrpPaths.calcAndCreatePath(nearestLink, toLink, departureTime, router, travelTime).getTravelTime();

// LeastCostPathCalculator.Path vrpPath = router.calcLeastCostPath(nearestLink.getToNode(), toLink.getFromNode(), departureTime, null, null);
LeastCostPathCalculator.Path vrpPath = router.calcLeastCostPath(nearestLink.getToNode(), destinationNode, departureTime, null, null);

List<Link> links = vrpPath.links;
// links.add(toLink); TODO: do we need this?
double directRideDistance = links.stream().mapToDouble(Link::getLength).sum();
double waitTime_s = 103.34; //TODO
double rideTime_s = 47.84 + 0.1087 * directRideDistance_m;
double totalTime_h = (waitTime_s + rideTime_s) / 3600;
double utilityDrtTime = betaDrtTT_h * totalTime_h;
double utilityDrtDistance = betaDrtDist_m * directRideDistance_m;

// route.setDirectRideTime(directRideTime);
// route.setDistance(directRideDistance);
// route.setStartLinkId(nearestLink.getId());
// route.setEndLinkId(toLink.getId());
// DrtEstimator.Estimate estimate = drtEstimator.estimate(route, OptionalTime.defined(departureTime));

double waitTime = 103.34;
double rideTime = 47.84 + 0.1087 * directRideDistance;
double totalTime = (waitTime + rideTime) / 3600;
double utilityDrt = betaDrtTT * totalTime;

// Pre-computed effect of all opportunities reachable from destination network node
double sumExpVjkWalk = destination.getSum();


System.out.println("___________________________________");
System.out.println("Measuring Point: " + origin.getId().toString());
System.out.println("utility access: " + utility_access + " ----- =" + betaWalkTT_h + " * " + accessTime_h);
System.out.println("utility drt (time): " + utilityDrtTime + " ----- =" + betaDrtTT_h + " * " + totalTime_h);
System.out.println("utility drt (distance): " + utilityDrtDistance + " ----- =" + betaDrtDist_m + " * " + directRideDistance_m);
System.out.println("utility drt (constant): " + utilityDrtConstant);
System.out.println("utility egress: " + Math.log(sumExpVjkWalk));
// System.out.println("utility egress: (sumExpVjkWalk) exponential of utility, sum over all opportunities near stop: : " + sumExpVjkWalk);

expSum += Math.exp(this.scoringConfigGroup.getBrainExpBeta() *
(walkUtilityMeasuringPoint2Road + modeSpecificConstant
+ congestedCarUtilityRoad2Node + utilityDrt))
(utility_access + utilityDrtTime + utilityDrtDistance + utilityDrtConstant ))
* sumExpVjkWalk;
}
return expSum;
Expand All @@ -185,9 +192,9 @@ public double computeContributionOfOpportunity(ActivityFacility origin,
public EstimatedDrtAccessibilityContributionCalculator duplicate() {
LOG.info("Creating another EstimatedDrtAccessibilityContributionCalculator object.");
EstimatedDrtAccessibilityContributionCalculator estimatedDrtAccessibilityContributionCalculator =
new EstimatedDrtAccessibilityContributionCalculator(this.mode, this.travelTime, this.travelDisutilityFactory, this.scenario);
new EstimatedDrtAccessibilityContributionCalculator(this.mode, this.travelTime, this.travelDisutilityFactory, this.scenario, tripRouter);
estimatedDrtAccessibilityContributionCalculator.subNetwork = this.subNetwork;
estimatedDrtAccessibilityContributionCalculator.aggregatedMeasurePoints = this.aggregatedMeasurePoints;
// estimatedDrtAccessibilityContributionCalculator.aggregatedMeasurePoints = this.aggregatedMeasurePoints;
estimatedDrtAccessibilityContributionCalculator.aggregatedOpportunities = this.aggregatedOpportunities;
return estimatedDrtAccessibilityContributionCalculator;
}
Expand All @@ -203,4 +210,50 @@ public Map<Id<? extends BasicLocation>, ArrayList<ActivityFacility>> getAggregat
public Map<Id<? extends BasicLocation>, AggregationObject> getAgregatedOpportunities() {
return aggregatedOpportunities;
}


public final Map<Id<? extends BasicLocation>, AggregationObject> aggregateOpportunitiesWithSameNearestDrtStop(
final ActivityFacilities opportunities, Network network, Config config ) {
// yyyy this method ignores the "capacities" of the facilities. kai, mar'14
// for now, we decided not to add "capacities" as it is not needed for current projects. dz, feb'16

// double walkSpeed_m_h = config.routing().getTeleportedModeSpeeds().get(TransportMode.walk) * 3600.;
AccessibilityConfigGroup acg = ConfigUtils.addOrGetModule(config, AccessibilityConfigGroup.GROUP_NAME, AccessibilityConfigGroup.class);

LOG.info("Aggregating " + opportunities.getFacilities().size() + " opportunities with same nearest node...");
Map<Id<? extends BasicLocation>, AggregationObject> opportunityClusterMap = new ConcurrentHashMap<>();

for (ActivityFacility opportunity : opportunities.getFacilities().values()) {

Optional<Pair<Facility, Facility>> facilities = stopFinder.findFacilities(opportunity, opportunity, null);
DrtStopFacility nearestStop = (DrtStopFacility) facilities.get().getKey();

List<? extends PlanElement> planElements = tripRouter.calcRoute(TransportMode.walk, nearestStop, opportunity, 10 * 3600., null, null);// departure time should matter for walk
double egressTime_s = ((Leg) planElements.get(0)).getTravelTime().seconds();

double VjkWalkTravelTime = egressTime_s / 3600 * betaWalkTT_h; // a.k.a utility_egress

double expVjk = Math.exp(config.scoring().getBrainExpBeta() * VjkWalkTravelTime);


// add Vjk to sum
AggregationObject jco = opportunityClusterMap.get(nearestStop.getId()); // Why "jco"?
if (jco == null) {
jco = new AggregationObject(opportunity.getId(), null, null, nearestStop, 0.);
opportunityClusterMap.put(nearestStop.getId(), jco);
}
if (acg.isUseOpportunityWeights()) {
if (opportunity.getAttributes().getAttribute( Labels.WEIGHT ) == null) {
throw new RuntimeException("If option \"useOpportunityWeights\" is used, the facilities must have an attribute with key " + Labels.WEIGHT + ".");
} else {
double weight = Double.parseDouble(opportunity.getAttributes().getAttribute( Labels.WEIGHT ).toString() );
jco.addObject(opportunity.getId(), expVjk * Math.pow(weight, acg.getWeightExponent()));
}
} else {
jco.addObject(opportunity.getId(), expVjk);
}
}
LOG.info("Aggregated " + opportunities.getFacilities().size() + " opportunities to " + opportunityClusterMap.size() + " nodes.");
return opportunityClusterMap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ public DvrpRoutingModule(RoutingModule mainRouter, RoutingModule accessRouter, R
this.timeInterpretation = timeInterpretation;
}

public AccessEgressFacilityFinder getStopFinder() {
return stopFinder;
}

@Override
public List<? extends PlanElement> calcRoute(RoutingRequest request) {
final Facility fromFacility = request.getFromFacility();
Expand Down

0 comments on commit 2059f9c

Please sign in to comment.