diff --git a/contribs/accessibility/pom.xml b/contribs/accessibility/pom.xml index 300f8fb1bd1..c8eab124745 100644 --- a/contribs/accessibility/pom.xml +++ b/contribs/accessibility/pom.xml @@ -83,5 +83,17 @@ gt-jdbc-postgis ${geotools.version} + + org.matsim.contrib + dvrp + 16.0-SNAPSHOT + compile + + + org.matsim.contrib + drt + 16.0-SNAPSHOT + compile + diff --git a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityModule.java b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityModule.java index 459198164a4..7acd374f3e0 100644 --- a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityModule.java +++ b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/AccessibilityModule.java @@ -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( diff --git a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/EstimatedDrtAccessibilityContributionCalculator.java b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/EstimatedDrtAccessibilityContributionCalculator.java index 532e4f6a834..bad2e6abbb3 100644 --- a/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/EstimatedDrtAccessibilityContributionCalculator.java +++ b/contribs/accessibility/src/main/java/org/matsim/contrib/accessibility/EstimatedDrtAccessibilityContributionCalculator.java @@ -1,21 +1,26 @@ 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; @@ -23,8 +28,12 @@ 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 @@ -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; @@ -54,27 +64,28 @@ final class EstimatedDrtAccessibilityContributionCalculator implements Accessibi private Map, 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); @@ -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); @@ -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()); } @@ -117,64 +134,54 @@ public double computeContributionOfOpportunity(ActivityFacility origin, Map, AggregationObject> aggregatedOpportunities, Double departureTime) { double expSum = 0.; + Optional> facilities = stopFinder.findFacilities(origin, origin, null); //todo: cleanup + Facility nearestStopAccess = facilities.get().getKey(); - // Access -// new ClosestAccessEgressFacilityFinder(2000, scenario.getNetwork(), facilityQuadTree); - - // DRT Trip + List 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 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 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; @@ -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; } @@ -203,4 +210,50 @@ public Map, ArrayList> getAggregat public Map, AggregationObject> getAgregatedOpportunities() { return aggregatedOpportunities; } + + + public final Map, 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, AggregationObject> opportunityClusterMap = new ConcurrentHashMap<>(); + + for (ActivityFacility opportunity : opportunities.getFacilities().values()) { + + Optional> facilities = stopFinder.findFacilities(opportunity, opportunity, null); + DrtStopFacility nearestStop = (DrtStopFacility) facilities.get().getKey(); + + List 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; + } } diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpRoutingModule.java b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpRoutingModule.java index 678039145d1..a3cf450ba34 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpRoutingModule.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/dvrp/router/DvrpRoutingModule.java @@ -69,6 +69,10 @@ public DvrpRoutingModule(RoutingModule mainRouter, RoutingModule accessRouter, R this.timeInterpretation = timeInterpretation; } + public AccessEgressFacilityFinder getStopFinder() { + return stopFinder; + } + @Override public List calcRoute(RoutingRequest request) { final Facility fromFacility = request.getFromFacility();